]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/LockBoxLib/LockBoxLib.c
CryptoPkg/OpensslLib: fix VS2017 build failure
[mirror_edk2.git] / OvmfPkg / Library / LockBoxLib / LockBoxLib.c
1 /** @file
2
3 Library implementing the LockBox interface for OVMF
4
5 Copyright (C) 2013, Red Hat, Inc.
6 Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10 **/
11
12 #include <Uefi.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/DebugLib.h>
15 #include <Library/LockBoxLib.h>
16 #include <Library/PcdLib.h>
17 #include <LockBoxLib.h>
18
19 #pragma pack(1)
20 typedef struct {
21 EFI_GUID Guid;
22 EFI_PHYSICAL_ADDRESS OrigAddress;
23 EFI_PHYSICAL_ADDRESS CopyAddress;
24 UINT32 Size;
25 UINT64 Attributes;
26 } LOCK_BOX_ENTRY;
27 #pragma pack()
28
29 LOCK_BOX_GLOBAL *mLockBoxGlobal = NULL;
30 STATIC LOCK_BOX_ENTRY *StartOfEntries = NULL;
31 STATIC LOCK_BOX_ENTRY *EndOfEntries = NULL;
32
33 RETURN_STATUS
34 EFIAPI
35 LockBoxLibInitialize (
36 VOID
37 )
38 {
39 UINTN NumEntries;
40
41 ASSERT (!FeaturePcdGet (PcdSmmSmramRequire));
42
43 if (PcdGet32 (PcdOvmfLockBoxStorageSize) < sizeof (LOCK_BOX_GLOBAL)) {
44 return RETURN_UNSUPPORTED;
45 }
46
47 mLockBoxGlobal = (LOCK_BOX_GLOBAL *)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageBase);
48 StartOfEntries = ((LOCK_BOX_ENTRY *) (mLockBoxGlobal + 1));
49 NumEntries = ((PcdGet32 (PcdOvmfLockBoxStorageSize) - sizeof (LOCK_BOX_GLOBAL)) /
50 sizeof (LOCK_BOX_ENTRY));
51 EndOfEntries = StartOfEntries + NumEntries;
52 if (mLockBoxGlobal->Signature != LOCK_BOX_GLOBAL_SIGNATURE) {
53 //
54 // Note: This code depends on the lock box being cleared in early
55 // PEI before usage, so the SubPageBuffer and SubPageRemaining
56 // fields don't need to be set to 0.
57 //
58 mLockBoxGlobal->Signature = LOCK_BOX_GLOBAL_SIGNATURE;
59 }
60 return RETURN_SUCCESS;
61 }
62
63
64 /**
65 Find LockBox entry based on GUID.
66
67 @param[in] Guid The GUID to search for.
68
69 @return Address of the LOCK_BOX_ENTRY found.
70
71 If NULL, then the item was not found, and there is no space
72 left to store a new item.
73
74 If non-NULL and LOCK_BOX_ENTRY.Size == 0, then the item was not
75 found, but a new item can be inserted at the returned location.
76
77 If non-NULL and LOCK_BOX_ENTRY.Size > 0, then the item was found.
78 **/
79 STATIC
80 LOCK_BOX_ENTRY *
81 EFIAPI
82 FindHeaderByGuid (
83 IN CONST EFI_GUID *Guid
84 )
85 {
86 LOCK_BOX_ENTRY *Header;
87
88 for (Header = StartOfEntries; Header < EndOfEntries; Header++) {
89 if (Header->Size == 0 || CompareGuid (Guid, &Header->Guid)) {
90 return Header;
91 }
92 }
93
94 return NULL;
95 }
96
97
98 /**
99 This function will save confidential information to lockbox.
100
101 @param Guid the guid to identify the confidential information
102 @param Buffer the address of the confidential information
103 @param Length the length of the confidential information
104
105 @retval RETURN_SUCCESS the information is saved successfully.
106 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or
107 Length is 0
108 @retval RETURN_ALREADY_STARTED the requested GUID already exist.
109 @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information.
110 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
111 @retval RETURN_NOT_STARTED it is too early to invoke this interface
112 @retval RETURN_UNSUPPORTED the service is not supported by
113 implementaion.
114 **/
115 RETURN_STATUS
116 EFIAPI
117 SaveLockBox (
118 IN GUID *Guid,
119 IN VOID *Buffer,
120 IN UINTN Length
121 )
122 {
123 LOCK_BOX_ENTRY *Header;
124 VOID *CopyBuffer;
125
126 DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Buffer=%p Length=0x%x\n", __FUNCTION__,
127 Guid, Buffer, (UINT32) Length));
128
129 if (Guid == NULL || Buffer == NULL || Length == 0) {
130 return RETURN_INVALID_PARAMETER;
131 }
132
133 if (Length > 0xFFFFFFFF) {
134 return RETURN_OUT_OF_RESOURCES;
135 }
136
137 Header = FindHeaderByGuid (Guid);
138 if (Header == NULL) {
139 return RETURN_OUT_OF_RESOURCES;
140 }
141
142 if (Header->Size > 0) {
143 return RETURN_ALREADY_STARTED;
144 }
145
146 CopyBuffer = AllocateAcpiNvsPool (Length);
147 if (CopyBuffer == NULL) {
148 return RETURN_OUT_OF_RESOURCES;
149 }
150
151 //
152 // overwrite the current terminator header with new metadata
153 //
154 CopyGuid (&Header->Guid, Guid);
155 Header->OrigAddress = (UINTN) Buffer;
156 Header->CopyAddress = (UINTN) CopyBuffer;
157 Header->Size = (UINT32) Length;
158 Header->Attributes = 0;
159
160 //
161 // copy contents
162 //
163 CopyMem (CopyBuffer, Buffer, Length);
164
165 return RETURN_SUCCESS;
166 }
167
168
169 /**
170 This function will set lockbox attributes.
171
172 @param Guid the guid to identify the confidential information
173 @param Attributes the attributes of the lockbox
174
175 @retval RETURN_SUCCESS the information is saved successfully.
176 @retval RETURN_INVALID_PARAMETER attributes is invalid.
177 @retval RETURN_NOT_FOUND the requested GUID not found.
178 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
179 @retval RETURN_NOT_STARTED it is too early to invoke this interface
180 @retval RETURN_UNSUPPORTED the service is not supported by
181 implementaion.
182 **/
183 RETURN_STATUS
184 EFIAPI
185 SetLockBoxAttributes (
186 IN GUID *Guid,
187 IN UINT64 Attributes
188 )
189 {
190 LOCK_BOX_ENTRY *Header;
191
192 DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Attributes=0x%Lx\n", __FUNCTION__, Guid,
193 Attributes));
194
195 if (Guid == NULL) {
196 return RETURN_INVALID_PARAMETER;
197 }
198
199 Header = FindHeaderByGuid (Guid);
200 if (!Header || Header->Size == 0) {
201 return RETURN_NOT_FOUND;
202 }
203 Header->Attributes = Attributes;
204
205 return RETURN_SUCCESS;
206 }
207
208
209 /**
210 This function will update confidential information to lockbox.
211
212 @param Guid the guid to identify the original confidential information
213 @param Offset the offset of the original confidential information
214 @param Buffer the address of the updated confidential information
215 @param Length the length of the updated confidential information
216
217 @retval RETURN_SUCCESS the information is saved successfully.
218 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or
219 Length is 0.
220 @retval RETURN_NOT_FOUND the requested GUID not found.
221 @retval RETURN_BUFFER_TOO_SMALL for lockbox without attribute
222 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY, the
223 original buffer to too small to hold new
224 information.
225 @retval RETURN_OUT_OF_RESOURCES for lockbox with attribute
226 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY, no
227 enough resource to save the information.
228 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
229 @retval RETURN_NOT_STARTED it is too early to invoke this interface
230 @retval RETURN_UNSUPPORTED the service is not supported by
231 implementaion.
232 **/
233 RETURN_STATUS
234 EFIAPI
235 UpdateLockBox (
236 IN GUID *Guid,
237 IN UINTN Offset,
238 IN VOID *Buffer,
239 IN UINTN Length
240 )
241 {
242 LOCK_BOX_ENTRY *Header;
243
244 DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Offset=0x%x Length=0x%x\n", __FUNCTION__,
245 Guid, (UINT32) Offset, (UINT32) Length));
246
247 if (Guid == NULL || Buffer == NULL || Length == 0) {
248 return RETURN_INVALID_PARAMETER;
249 }
250
251 Header = FindHeaderByGuid (Guid);
252 if (!Header || Header->Size == 0) {
253 return RETURN_NOT_FOUND;
254 }
255
256 if (Header->Size < Offset ||
257 Length > Header->Size - Offset) {
258 return RETURN_BUFFER_TOO_SMALL;
259 }
260
261 CopyMem ((UINT8 *)(UINTN) (Header->CopyAddress) + Offset, Buffer, Length);
262
263 return RETURN_SUCCESS;
264 }
265
266
267 /**
268 This function will restore confidential information from lockbox.
269
270 @param Guid the guid to identify the confidential information
271 @param Buffer the address of the restored confidential information
272 NULL means restored to original address, Length MUST be NULL at
273 same time.
274 @param Length the length of the restored confidential information
275
276 @retval RETURN_SUCCESS the information is restored successfully.
277 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and
278 Length is NULL.
279 @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox
280 has no LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
281 attribute.
282 @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the
283 confidential information.
284 @retval RETURN_NOT_FOUND the requested GUID not found.
285 @retval RETURN_NOT_STARTED it is too early to invoke this interface
286 @retval RETURN_ACCESS_DENIED not allow to restore to the address
287 @retval RETURN_UNSUPPORTED the service is not supported by
288 implementaion.
289 **/
290 RETURN_STATUS
291 EFIAPI
292 RestoreLockBox (
293 IN GUID *Guid,
294 IN VOID *Buffer, OPTIONAL
295 IN OUT UINTN *Length OPTIONAL
296 )
297 {
298 LOCK_BOX_ENTRY *Header;
299
300 DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Buffer=%p\n", __FUNCTION__, Guid,
301 Buffer));
302
303 if ((Guid == NULL) ||
304 ((Buffer == NULL) && (Length != NULL)) ||
305 ((Buffer != NULL) && (Length == NULL))) {
306 return EFI_INVALID_PARAMETER;
307 }
308
309 Header = FindHeaderByGuid (Guid);
310 if (!Header || Header->Size == 0) {
311 return RETURN_NOT_FOUND;
312 }
313
314 if (Buffer == NULL) {
315 if (!(Header->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE)) {
316 return RETURN_WRITE_PROTECTED;
317 }
318 if (Header->OrigAddress + (Header->Size - 1) > MAX_ADDRESS) {
319 return RETURN_UNSUPPORTED;
320 }
321 Buffer = (VOID *)(UINTN) Header->OrigAddress;
322 }
323
324 //
325 // Set RestoreLength
326 //
327 if (Length != NULL) {
328 if (Header->Size > *Length) {
329 //
330 // Input buffer is too small to hold all data.
331 //
332 *Length = Header->Size;
333 return EFI_BUFFER_TOO_SMALL;
334 }
335 *Length = Header->Size;
336 }
337
338 CopyMem (Buffer, (VOID*)(UINTN) Header->CopyAddress, Header->Size);
339
340 return RETURN_SUCCESS;
341 }
342
343
344 /**
345 This function will restore confidential information from all lockbox which
346 have RestoreInPlace attribute.
347
348 @retval RETURN_SUCCESS the information is restored successfully.
349 @retval RETURN_NOT_STARTED it is too early to invoke this interface
350 @retval RETURN_UNSUPPORTED the service is not supported by
351 implementaion.
352 **/
353 RETURN_STATUS
354 EFIAPI
355 RestoreAllLockBoxInPlace (
356 VOID
357 )
358 {
359 LOCK_BOX_ENTRY *Header;
360
361 for (Header = StartOfEntries;
362 Header < EndOfEntries && Header->Size > 0;
363 Header++) {
364 if (Header->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) {
365 VOID *Buffer;
366
367 if (Header->OrigAddress + (Header->Size - 1) > MAX_ADDRESS) {
368 return RETURN_UNSUPPORTED;
369 }
370 Buffer = (VOID *)(UINTN) Header->OrigAddress;
371 CopyMem (Buffer, (VOID*)(UINTN)Header->CopyAddress, Header->Size);
372 DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Buffer=%p\n", __FUNCTION__,
373 &Header->Guid, Buffer));
374 }
375 }
376 return RETURN_SUCCESS;
377 }