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
;
61 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
)) {
98 This function will save confidential information to lockbox.
100 @param Guid the guid to identify the confidential information
101 @param Buffer the address of the confidential information
102 @param Length the length of the confidential information
104 @retval RETURN_SUCCESS the information is saved successfully.
105 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or
107 @retval RETURN_ALREADY_STARTED the requested GUID already exist.
108 @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information.
109 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
110 @retval RETURN_NOT_STARTED it is too early to invoke this interface
111 @retval RETURN_UNSUPPORTED the service is not supported by
122 LOCK_BOX_ENTRY
*Header
;
127 "%a: Guid=%g Buffer=%p Length=0x%x\n",
134 if ((Guid
== NULL
) || (Buffer
== NULL
) || (Length
== 0)) {
135 return RETURN_INVALID_PARAMETER
;
138 if (Length
> 0xFFFFFFFF) {
139 return RETURN_OUT_OF_RESOURCES
;
142 Header
= FindHeaderByGuid (Guid
);
143 if (Header
== NULL
) {
144 return RETURN_OUT_OF_RESOURCES
;
147 if (Header
->Size
> 0) {
148 return RETURN_ALREADY_STARTED
;
151 CopyBuffer
= AllocateAcpiNvsPool (Length
);
152 if (CopyBuffer
== NULL
) {
153 return RETURN_OUT_OF_RESOURCES
;
157 // overwrite the current terminator header with new metadata
159 CopyGuid (&Header
->Guid
, Guid
);
160 Header
->OrigAddress
= (UINTN
)Buffer
;
161 Header
->CopyAddress
= (UINTN
)CopyBuffer
;
162 Header
->Size
= (UINT32
)Length
;
163 Header
->Attributes
= 0;
168 CopyMem (CopyBuffer
, Buffer
, Length
);
170 return RETURN_SUCCESS
;
174 This function will set lockbox attributes.
176 @param Guid the guid to identify the confidential information
177 @param Attributes the attributes of the lockbox
179 @retval RETURN_SUCCESS the information is saved successfully.
180 @retval RETURN_INVALID_PARAMETER attributes is invalid.
181 @retval RETURN_NOT_FOUND the requested GUID not found.
182 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
183 @retval RETURN_NOT_STARTED it is too early to invoke this interface
184 @retval RETURN_UNSUPPORTED the service is not supported by
189 SetLockBoxAttributes (
194 LOCK_BOX_ENTRY
*Header
;
198 "%a: Guid=%g Attributes=0x%Lx\n",
205 return RETURN_INVALID_PARAMETER
;
208 Header
= FindHeaderByGuid (Guid
);
209 if (!Header
|| (Header
->Size
== 0)) {
210 return RETURN_NOT_FOUND
;
213 Header
->Attributes
= Attributes
;
215 return RETURN_SUCCESS
;
219 This function will update confidential information to lockbox.
221 @param Guid the guid to identify the original confidential information
222 @param Offset the offset of the original confidential information
223 @param Buffer the address of the updated confidential information
224 @param Length the length of the updated confidential information
226 @retval RETURN_SUCCESS the information is saved successfully.
227 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or
229 @retval RETURN_NOT_FOUND the requested GUID not found.
230 @retval RETURN_BUFFER_TOO_SMALL for lockbox without attribute
231 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY, the
232 original buffer to too small to hold new
234 @retval RETURN_OUT_OF_RESOURCES for lockbox with attribute
235 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY, no
236 enough resource to save the information.
237 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
238 @retval RETURN_NOT_STARTED it is too early to invoke this interface
239 @retval RETURN_UNSUPPORTED the service is not supported by
251 LOCK_BOX_ENTRY
*Header
;
255 "%a: Guid=%g Offset=0x%x Length=0x%x\n",
262 if ((Guid
== NULL
) || (Buffer
== NULL
) || (Length
== 0)) {
263 return RETURN_INVALID_PARAMETER
;
266 Header
= FindHeaderByGuid (Guid
);
267 if (!Header
|| (Header
->Size
== 0)) {
268 return RETURN_NOT_FOUND
;
271 if ((Header
->Size
< Offset
) ||
272 (Length
> Header
->Size
- Offset
))
274 return RETURN_BUFFER_TOO_SMALL
;
277 CopyMem ((UINT8
*)(UINTN
)(Header
->CopyAddress
) + Offset
, Buffer
, Length
);
279 return RETURN_SUCCESS
;
283 This function will restore confidential information from lockbox.
285 @param Guid the guid to identify the confidential information
286 @param Buffer the address of the restored confidential information
287 NULL means restored to original address, Length MUST be NULL at
289 @param Length the length of the restored confidential information
291 @retval RETURN_SUCCESS the information is restored successfully.
292 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and
294 @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox
295 has no LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
297 @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the
298 confidential information.
299 @retval RETURN_NOT_FOUND the requested GUID not found.
300 @retval RETURN_NOT_STARTED it is too early to invoke this interface
301 @retval RETURN_ACCESS_DENIED not allow to restore to the address
302 @retval RETURN_UNSUPPORTED the service is not supported by
309 IN VOID
*Buffer OPTIONAL
,
310 IN OUT UINTN
*Length OPTIONAL
313 LOCK_BOX_ENTRY
*Header
;
317 "%a: Guid=%g Buffer=%p\n",
323 if ((Guid
== NULL
) ||
324 ((Buffer
== NULL
) && (Length
!= NULL
)) ||
325 ((Buffer
!= NULL
) && (Length
== NULL
)))
327 return EFI_INVALID_PARAMETER
;
330 Header
= FindHeaderByGuid (Guid
);
331 if (!Header
|| (Header
->Size
== 0)) {
332 return RETURN_NOT_FOUND
;
335 if (Buffer
== NULL
) {
336 if (!(Header
->Attributes
& LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
)) {
337 return RETURN_WRITE_PROTECTED
;
340 if (Header
->OrigAddress
+ (Header
->Size
- 1) > MAX_ADDRESS
) {
341 return RETURN_UNSUPPORTED
;
344 Buffer
= (VOID
*)(UINTN
)Header
->OrigAddress
;
350 if (Length
!= NULL
) {
351 if (Header
->Size
> *Length
) {
353 // Input buffer is too small to hold all data.
355 *Length
= Header
->Size
;
356 return EFI_BUFFER_TOO_SMALL
;
359 *Length
= Header
->Size
;
362 CopyMem (Buffer
, (VOID
*)(UINTN
)Header
->CopyAddress
, Header
->Size
);
364 return RETURN_SUCCESS
;
368 This function will restore confidential information from all lockbox which
369 have RestoreInPlace attribute.
371 @retval RETURN_SUCCESS the information is restored successfully.
372 @retval RETURN_NOT_STARTED it is too early to invoke this interface
373 @retval RETURN_UNSUPPORTED the service is not supported by
378 RestoreAllLockBoxInPlace (
382 LOCK_BOX_ENTRY
*Header
;
384 for (Header
= StartOfEntries
;
385 Header
< EndOfEntries
&& Header
->Size
> 0;
388 if (Header
->Attributes
& LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
) {
391 if (Header
->OrigAddress
+ (Header
->Size
- 1) > MAX_ADDRESS
) {
392 return RETURN_UNSUPPORTED
;
395 Buffer
= (VOID
*)(UINTN
)Header
->OrigAddress
;
396 CopyMem (Buffer
, (VOID
*)(UINTN
)Header
->CopyAddress
, Header
->Size
);
399 "%a: Guid=%g Buffer=%p\n",
407 return RETURN_SUCCESS
;