3 Library implementing the LockBox interface for OVMF
5 Copyright (C) 2013, Red Hat, Inc.
6 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
8 This program and the accompanying materials are licensed and made available
9 under the terms and conditions of the BSD License which accompanies this
10 distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
14 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/LockBoxLib.h>
22 #include <Library/PcdLib.h>
23 #include <LockBoxLib.h>
28 EFI_PHYSICAL_ADDRESS OrigAddress
;
29 EFI_PHYSICAL_ADDRESS CopyAddress
;
35 LOCK_BOX_GLOBAL
*mLockBoxGlobal
= NULL
;
36 STATIC LOCK_BOX_ENTRY
*StartOfEntries
= NULL
;
37 STATIC LOCK_BOX_ENTRY
*EndOfEntries
= NULL
;
41 LockBoxLibInitialize (
47 if (PcdGet32 (PcdOvmfLockBoxStorageSize
) < sizeof (LOCK_BOX_GLOBAL
)) {
48 return RETURN_UNSUPPORTED
;
51 mLockBoxGlobal
= (LOCK_BOX_GLOBAL
*)(UINTN
) PcdGet32 (PcdOvmfLockBoxStorageBase
);
52 StartOfEntries
= ((LOCK_BOX_ENTRY
*) (mLockBoxGlobal
+ 1));
53 NumEntries
= ((PcdGet32 (PcdOvmfLockBoxStorageSize
) - sizeof (LOCK_BOX_GLOBAL
)) /
54 sizeof (LOCK_BOX_ENTRY
));
55 EndOfEntries
= StartOfEntries
+ NumEntries
;
56 if (mLockBoxGlobal
->Signature
!= LOCK_BOX_GLOBAL_SIGNATURE
) {
58 // Note: This code depends on the lock box being cleared in early
59 // PEI before usage, so the SubPageBuffer and SubPageRemaining
60 // fields don't need to be set to 0.
62 mLockBoxGlobal
->Signature
= LOCK_BOX_GLOBAL_SIGNATURE
;
64 return RETURN_SUCCESS
;
69 Find LockBox entry based on GUID.
71 @param[in] Guid The GUID to search for.
73 @return Address of the LOCK_BOX_ENTRY found.
75 If NULL, then the item was not found, and there is no space
76 left to store a new item.
78 If non-NULL and LOCK_BOX_ENTRY.Size == 0, then the item was not
79 found, but a new item can be inserted at the returned location.
81 If non-NULL and LOCK_BOX_ENTRY.Size > 0, then the item was found.
87 IN CONST EFI_GUID
*Guid
90 LOCK_BOX_ENTRY
*Header
;
92 for (Header
= StartOfEntries
; Header
< EndOfEntries
; Header
++) {
93 if (Header
->Size
== 0 || CompareGuid (Guid
, &Header
->Guid
)) {
103 This function will save confidential information to lockbox.
105 @param Guid the guid to identify the confidential information
106 @param Buffer the address of the confidential information
107 @param Length the length of the confidential information
109 @retval RETURN_SUCCESS the information is saved successfully.
110 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or
112 @retval RETURN_ALREADY_STARTED the requested GUID already exist.
113 @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information.
114 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
115 @retval RETURN_NOT_STARTED it is too early to invoke this interface
116 @retval RETURN_UNSUPPORTED the service is not supported by
127 LOCK_BOX_ENTRY
*Header
;
130 DEBUG ((DEBUG_VERBOSE
, "%a: Guid=%g Buffer=%p Length=0x%x\n", __FUNCTION__
,
131 Guid
, Buffer
, (UINT32
) Length
));
133 if (Guid
== NULL
|| Buffer
== NULL
|| Length
== 0) {
134 return RETURN_INVALID_PARAMETER
;
137 if (Length
> 0xFFFFFFFF) {
138 return RETURN_OUT_OF_RESOURCES
;
141 Header
= FindHeaderByGuid (Guid
);
142 if (Header
== NULL
) {
143 return RETURN_OUT_OF_RESOURCES
;
146 if (Header
->Size
> 0) {
147 return RETURN_ALREADY_STARTED
;
150 CopyBuffer
= AllocateAcpiNvsPool (Length
);
151 if (CopyBuffer
== NULL
) {
152 return RETURN_OUT_OF_RESOURCES
;
156 // overwrite the current terminator header with new metadata
158 CopyGuid (&Header
->Guid
, Guid
);
159 Header
->OrigAddress
= (UINTN
) Buffer
;
160 Header
->CopyAddress
= (UINTN
) CopyBuffer
;
161 Header
->Size
= (UINT32
) Length
;
162 Header
->Attributes
= 0;
167 CopyMem (CopyBuffer
, Buffer
, Length
);
169 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
;
196 DEBUG ((DEBUG_VERBOSE
, "%a: Guid=%g Attributes=0x%Lx\n", __FUNCTION__
, Guid
,
200 return RETURN_INVALID_PARAMETER
;
203 Header
= FindHeaderByGuid (Guid
);
204 if (!Header
|| Header
->Size
== 0) {
205 return RETURN_NOT_FOUND
;
207 Header
->Attributes
= Attributes
;
209 return RETURN_SUCCESS
;
214 This function will update confidential information to lockbox.
216 @param Guid the guid to identify the original confidential information
217 @param Offset the offset of the original confidential information
218 @param Buffer the address of the updated confidential information
219 @param Length the length of the updated confidential information
221 @retval RETURN_SUCCESS the information is saved successfully.
222 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or
224 @retval RETURN_NOT_FOUND the requested GUID not found.
225 @retval RETURN_BUFFER_TOO_SMALL the original buffer to too small to hold
227 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
228 @retval RETURN_NOT_STARTED it is too early to invoke this interface
229 @retval RETURN_UNSUPPORTED the service is not supported by
241 LOCK_BOX_ENTRY
*Header
;
243 DEBUG ((DEBUG_VERBOSE
, "%a: Guid=%g Offset=0x%x Length=0x%x\n", __FUNCTION__
,
244 Guid
, (UINT32
) Offset
, (UINT32
) Length
));
246 if (Guid
== NULL
|| Buffer
== NULL
|| Length
== 0) {
247 return RETURN_INVALID_PARAMETER
;
250 Header
= FindHeaderByGuid (Guid
);
251 if (!Header
|| Header
->Size
== 0) {
252 return RETURN_NOT_FOUND
;
255 if (Header
->Size
< Offset
||
256 Length
> Header
->Size
- Offset
) {
257 return RETURN_BUFFER_TOO_SMALL
;
260 CopyMem ((UINT8
*)(UINTN
) (Header
->CopyAddress
) + Offset
, Buffer
, Length
);
262 return RETURN_SUCCESS
;
267 This function will restore confidential information from lockbox.
269 @param Guid the guid to identify the confidential information
270 @param Buffer the address of the restored confidential information
271 NULL means restored to original address, Length MUST be NULL at
273 @param Length the length of the restored confidential information
275 @retval RETURN_SUCCESS the information is restored successfully.
276 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and
278 @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox
279 has no LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
281 @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the
282 confidential information.
283 @retval RETURN_NOT_FOUND the requested GUID not found.
284 @retval RETURN_NOT_STARTED it is too early to invoke this interface
285 @retval RETURN_ACCESS_DENIED not allow to restore to the address
286 @retval RETURN_UNSUPPORTED the service is not supported by
293 IN VOID
*Buffer
, OPTIONAL
294 IN OUT UINTN
*Length OPTIONAL
297 LOCK_BOX_ENTRY
*Header
;
299 DEBUG ((DEBUG_VERBOSE
, "%a: Guid=%g Buffer=%p\n", __FUNCTION__
, Guid
,
302 if ((Guid
== NULL
) ||
303 ((Buffer
== NULL
) && (Length
!= NULL
)) ||
304 ((Buffer
!= NULL
) && (Length
== NULL
))) {
305 return EFI_INVALID_PARAMETER
;
308 Header
= FindHeaderByGuid (Guid
);
309 if (!Header
|| Header
->Size
== 0) {
310 return RETURN_NOT_FOUND
;
313 if (Buffer
== NULL
) {
314 if (!(Header
->Attributes
& LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
)) {
315 return RETURN_WRITE_PROTECTED
;
317 if (Header
->OrigAddress
+ (Header
->Size
- 1) > MAX_ADDRESS
) {
318 return RETURN_UNSUPPORTED
;
320 Buffer
= (VOID
*)(UINTN
) Header
->OrigAddress
;
326 if (Length
!= NULL
) {
327 if (Header
->Size
> *Length
) {
329 // Input buffer is too small to hold all data.
331 *Length
= Header
->Size
;
332 return EFI_BUFFER_TOO_SMALL
;
334 *Length
= Header
->Size
;
337 CopyMem (Buffer
, (VOID
*)(UINTN
) Header
->CopyAddress
, Header
->Size
);
339 return RETURN_SUCCESS
;
344 This function will restore confidential information from all lockbox which
345 have RestoreInPlace attribute.
347 @retval RETURN_SUCCESS the information is restored successfully.
348 @retval RETURN_NOT_STARTED it is too early to invoke this interface
349 @retval RETURN_UNSUPPORTED the service is not supported by
354 RestoreAllLockBoxInPlace (
358 LOCK_BOX_ENTRY
*Header
;
360 for (Header
= StartOfEntries
;
361 Header
< EndOfEntries
&& Header
->Size
> 0;
363 if (Header
->Attributes
& LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
) {
366 if (Header
->OrigAddress
+ (Header
->Size
- 1) > MAX_ADDRESS
) {
367 return RETURN_UNSUPPORTED
;
369 Buffer
= (VOID
*)(UINTN
) Header
->OrigAddress
;
370 CopyMem (Buffer
, (VOID
*)(UINTN
)Header
->CopyAddress
, Header
->Size
);
371 DEBUG ((DEBUG_VERBOSE
, "%a: Guid=%g Buffer=%p\n", __FUNCTION__
,
372 &Header
->Guid
, Buffer
));
375 return RETURN_SUCCESS
;