3 Library implementing the LockBox interface for OVMF
5 Copyright (C) 2013, Red Hat, Inc.
6 Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/DebugLib.h>
15 #include <Library/LockBoxLib.h>
16 #include <Library/PcdLib.h>
17 #include <LockBoxLib.h>
22 EFI_PHYSICAL_ADDRESS OrigAddress
;
23 EFI_PHYSICAL_ADDRESS CopyAddress
;
29 LOCK_BOX_GLOBAL
*mLockBoxGlobal
= NULL
;
30 STATIC LOCK_BOX_ENTRY
*StartOfEntries
= NULL
;
31 STATIC LOCK_BOX_ENTRY
*EndOfEntries
= NULL
;
35 LockBoxLibInitialize (
41 ASSERT (!FeaturePcdGet (PcdSmmSmramRequire
));
43 if (PcdGet32 (PcdOvmfLockBoxStorageSize
) < sizeof (LOCK_BOX_GLOBAL
)) {
44 return RETURN_UNSUPPORTED
;
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
) {
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.
58 mLockBoxGlobal
->Signature
= LOCK_BOX_GLOBAL_SIGNATURE
;
60 return RETURN_SUCCESS
;
65 Find LockBox entry based on GUID.
67 @param[in] Guid The GUID to search for.
69 @return Address of the LOCK_BOX_ENTRY found.
71 If NULL, then the item was not found, and there is no space
72 left to store a new item.
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.
77 If non-NULL and LOCK_BOX_ENTRY.Size > 0, then the item was found.
83 IN CONST EFI_GUID
*Guid
86 LOCK_BOX_ENTRY
*Header
;
88 for (Header
= StartOfEntries
; Header
< EndOfEntries
; Header
++) {
89 if (Header
->Size
== 0 || CompareGuid (Guid
, &Header
->Guid
)) {
99 This function will save confidential information to lockbox.
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
105 @retval RETURN_SUCCESS the information is saved successfully.
106 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or
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
123 LOCK_BOX_ENTRY
*Header
;
126 DEBUG ((DEBUG_VERBOSE
, "%a: Guid=%g Buffer=%p Length=0x%x\n", __FUNCTION__
,
127 Guid
, Buffer
, (UINT32
) Length
));
129 if (Guid
== NULL
|| Buffer
== NULL
|| Length
== 0) {
130 return RETURN_INVALID_PARAMETER
;
133 if (Length
> 0xFFFFFFFF) {
134 return RETURN_OUT_OF_RESOURCES
;
137 Header
= FindHeaderByGuid (Guid
);
138 if (Header
== NULL
) {
139 return RETURN_OUT_OF_RESOURCES
;
142 if (Header
->Size
> 0) {
143 return RETURN_ALREADY_STARTED
;
146 CopyBuffer
= AllocateAcpiNvsPool (Length
);
147 if (CopyBuffer
== NULL
) {
148 return RETURN_OUT_OF_RESOURCES
;
152 // overwrite the current terminator header with new metadata
154 CopyGuid (&Header
->Guid
, Guid
);
155 Header
->OrigAddress
= (UINTN
) Buffer
;
156 Header
->CopyAddress
= (UINTN
) CopyBuffer
;
157 Header
->Size
= (UINT32
) Length
;
158 Header
->Attributes
= 0;
163 CopyMem (CopyBuffer
, Buffer
, Length
);
165 return RETURN_SUCCESS
;
170 This function will set lockbox attributes.
172 @param Guid the guid to identify the confidential information
173 @param Attributes the attributes of the lockbox
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
185 SetLockBoxAttributes (
190 LOCK_BOX_ENTRY
*Header
;
192 DEBUG ((DEBUG_VERBOSE
, "%a: Guid=%g Attributes=0x%Lx\n", __FUNCTION__
, Guid
,
196 return RETURN_INVALID_PARAMETER
;
199 Header
= FindHeaderByGuid (Guid
);
200 if (!Header
|| Header
->Size
== 0) {
201 return RETURN_NOT_FOUND
;
203 Header
->Attributes
= Attributes
;
205 return RETURN_SUCCESS
;
210 This function will update confidential information to lockbox.
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
217 @retval RETURN_SUCCESS the information is saved successfully.
218 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or
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
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
242 LOCK_BOX_ENTRY
*Header
;
244 DEBUG ((DEBUG_VERBOSE
, "%a: Guid=%g Offset=0x%x Length=0x%x\n", __FUNCTION__
,
245 Guid
, (UINT32
) Offset
, (UINT32
) Length
));
247 if (Guid
== NULL
|| Buffer
== NULL
|| Length
== 0) {
248 return RETURN_INVALID_PARAMETER
;
251 Header
= FindHeaderByGuid (Guid
);
252 if (!Header
|| Header
->Size
== 0) {
253 return RETURN_NOT_FOUND
;
256 if (Header
->Size
< Offset
||
257 Length
> Header
->Size
- Offset
) {
258 return RETURN_BUFFER_TOO_SMALL
;
261 CopyMem ((UINT8
*)(UINTN
) (Header
->CopyAddress
) + Offset
, Buffer
, Length
);
263 return RETURN_SUCCESS
;
268 This function will restore confidential information from lockbox.
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
274 @param Length the length of the restored confidential information
276 @retval RETURN_SUCCESS the information is restored successfully.
277 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and
279 @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox
280 has no LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
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
294 IN VOID
*Buffer
, OPTIONAL
295 IN OUT UINTN
*Length OPTIONAL
298 LOCK_BOX_ENTRY
*Header
;
300 DEBUG ((DEBUG_VERBOSE
, "%a: Guid=%g Buffer=%p\n", __FUNCTION__
, Guid
,
303 if ((Guid
== NULL
) ||
304 ((Buffer
== NULL
) && (Length
!= NULL
)) ||
305 ((Buffer
!= NULL
) && (Length
== NULL
))) {
306 return EFI_INVALID_PARAMETER
;
309 Header
= FindHeaderByGuid (Guid
);
310 if (!Header
|| Header
->Size
== 0) {
311 return RETURN_NOT_FOUND
;
314 if (Buffer
== NULL
) {
315 if (!(Header
->Attributes
& LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
)) {
316 return RETURN_WRITE_PROTECTED
;
318 if (Header
->OrigAddress
+ (Header
->Size
- 1) > MAX_ADDRESS
) {
319 return RETURN_UNSUPPORTED
;
321 Buffer
= (VOID
*)(UINTN
) Header
->OrigAddress
;
327 if (Length
!= NULL
) {
328 if (Header
->Size
> *Length
) {
330 // Input buffer is too small to hold all data.
332 *Length
= Header
->Size
;
333 return EFI_BUFFER_TOO_SMALL
;
335 *Length
= Header
->Size
;
338 CopyMem (Buffer
, (VOID
*)(UINTN
) Header
->CopyAddress
, Header
->Size
);
340 return RETURN_SUCCESS
;
345 This function will restore confidential information from all lockbox which
346 have RestoreInPlace attribute.
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
355 RestoreAllLockBoxInPlace (
359 LOCK_BOX_ENTRY
*Header
;
361 for (Header
= StartOfEntries
;
362 Header
< EndOfEntries
&& Header
->Size
> 0;
364 if (Header
->Attributes
& LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
) {
367 if (Header
->OrigAddress
+ (Header
->Size
- 1) > MAX_ADDRESS
) {
368 return RETURN_UNSUPPORTED
;
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
));
376 return RETURN_SUCCESS
;