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 ASSERT (!FeaturePcdGet (PcdSmmSmramRequire
));
49 if (PcdGet32 (PcdOvmfLockBoxStorageSize
) < sizeof (LOCK_BOX_GLOBAL
)) {
50 return RETURN_UNSUPPORTED
;
53 mLockBoxGlobal
= (LOCK_BOX_GLOBAL
*)(UINTN
) PcdGet32 (PcdOvmfLockBoxStorageBase
);
54 StartOfEntries
= ((LOCK_BOX_ENTRY
*) (mLockBoxGlobal
+ 1));
55 NumEntries
= ((PcdGet32 (PcdOvmfLockBoxStorageSize
) - sizeof (LOCK_BOX_GLOBAL
)) /
56 sizeof (LOCK_BOX_ENTRY
));
57 EndOfEntries
= StartOfEntries
+ NumEntries
;
58 if (mLockBoxGlobal
->Signature
!= LOCK_BOX_GLOBAL_SIGNATURE
) {
60 // Note: This code depends on the lock box being cleared in early
61 // PEI before usage, so the SubPageBuffer and SubPageRemaining
62 // fields don't need to be set to 0.
64 mLockBoxGlobal
->Signature
= LOCK_BOX_GLOBAL_SIGNATURE
;
66 return RETURN_SUCCESS
;
71 Find LockBox entry based on GUID.
73 @param[in] Guid The GUID to search for.
75 @return Address of the LOCK_BOX_ENTRY found.
77 If NULL, then the item was not found, and there is no space
78 left to store a new item.
80 If non-NULL and LOCK_BOX_ENTRY.Size == 0, then the item was not
81 found, but a new item can be inserted at the returned location.
83 If non-NULL and LOCK_BOX_ENTRY.Size > 0, then the item was found.
89 IN CONST EFI_GUID
*Guid
92 LOCK_BOX_ENTRY
*Header
;
94 for (Header
= StartOfEntries
; Header
< EndOfEntries
; Header
++) {
95 if (Header
->Size
== 0 || CompareGuid (Guid
, &Header
->Guid
)) {
105 This function will save confidential information to lockbox.
107 @param Guid the guid to identify the confidential information
108 @param Buffer the address of the confidential information
109 @param Length the length of the confidential information
111 @retval RETURN_SUCCESS the information is saved successfully.
112 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or
114 @retval RETURN_ALREADY_STARTED the requested GUID already exist.
115 @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information.
116 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
117 @retval RETURN_NOT_STARTED it is too early to invoke this interface
118 @retval RETURN_UNSUPPORTED the service is not supported by
129 LOCK_BOX_ENTRY
*Header
;
132 DEBUG ((DEBUG_VERBOSE
, "%a: Guid=%g Buffer=%p Length=0x%x\n", __FUNCTION__
,
133 Guid
, Buffer
, (UINT32
) Length
));
135 if (Guid
== NULL
|| Buffer
== NULL
|| Length
== 0) {
136 return RETURN_INVALID_PARAMETER
;
139 if (Length
> 0xFFFFFFFF) {
140 return RETURN_OUT_OF_RESOURCES
;
143 Header
= FindHeaderByGuid (Guid
);
144 if (Header
== NULL
) {
145 return RETURN_OUT_OF_RESOURCES
;
148 if (Header
->Size
> 0) {
149 return RETURN_ALREADY_STARTED
;
152 CopyBuffer
= AllocateAcpiNvsPool (Length
);
153 if (CopyBuffer
== NULL
) {
154 return RETURN_OUT_OF_RESOURCES
;
158 // overwrite the current terminator header with new metadata
160 CopyGuid (&Header
->Guid
, Guid
);
161 Header
->OrigAddress
= (UINTN
) Buffer
;
162 Header
->CopyAddress
= (UINTN
) CopyBuffer
;
163 Header
->Size
= (UINT32
) Length
;
164 Header
->Attributes
= 0;
169 CopyMem (CopyBuffer
, Buffer
, Length
);
171 return RETURN_SUCCESS
;
176 This function will set lockbox attributes.
178 @param Guid the guid to identify the confidential information
179 @param Attributes the attributes of the lockbox
181 @retval RETURN_SUCCESS the information is saved successfully.
182 @retval RETURN_INVALID_PARAMETER attributes is invalid.
183 @retval RETURN_NOT_FOUND the requested GUID not found.
184 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
185 @retval RETURN_NOT_STARTED it is too early to invoke this interface
186 @retval RETURN_UNSUPPORTED the service is not supported by
191 SetLockBoxAttributes (
196 LOCK_BOX_ENTRY
*Header
;
198 DEBUG ((DEBUG_VERBOSE
, "%a: Guid=%g Attributes=0x%Lx\n", __FUNCTION__
, Guid
,
202 return RETURN_INVALID_PARAMETER
;
205 Header
= FindHeaderByGuid (Guid
);
206 if (!Header
|| Header
->Size
== 0) {
207 return RETURN_NOT_FOUND
;
209 Header
->Attributes
= Attributes
;
211 return RETURN_SUCCESS
;
216 This function will update confidential information to lockbox.
218 @param Guid the guid to identify the original confidential information
219 @param Offset the offset of the original confidential information
220 @param Buffer the address of the updated confidential information
221 @param Length the length of the updated confidential information
223 @retval RETURN_SUCCESS the information is saved successfully.
224 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or
226 @retval RETURN_NOT_FOUND the requested GUID not found.
227 @retval RETURN_BUFFER_TOO_SMALL the original buffer to too small to hold
229 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
230 @retval RETURN_NOT_STARTED it is too early to invoke this interface
231 @retval RETURN_UNSUPPORTED the service is not supported by
243 LOCK_BOX_ENTRY
*Header
;
245 DEBUG ((DEBUG_VERBOSE
, "%a: Guid=%g Offset=0x%x Length=0x%x\n", __FUNCTION__
,
246 Guid
, (UINT32
) Offset
, (UINT32
) Length
));
248 if (Guid
== NULL
|| Buffer
== NULL
|| Length
== 0) {
249 return RETURN_INVALID_PARAMETER
;
252 Header
= FindHeaderByGuid (Guid
);
253 if (!Header
|| Header
->Size
== 0) {
254 return RETURN_NOT_FOUND
;
257 if (Header
->Size
< Offset
||
258 Length
> Header
->Size
- Offset
) {
259 return RETURN_BUFFER_TOO_SMALL
;
262 CopyMem ((UINT8
*)(UINTN
) (Header
->CopyAddress
) + Offset
, Buffer
, Length
);
264 return RETURN_SUCCESS
;
269 This function will restore confidential information from lockbox.
271 @param Guid the guid to identify the confidential information
272 @param Buffer the address of the restored confidential information
273 NULL means restored to original address, Length MUST be NULL at
275 @param Length the length of the restored confidential information
277 @retval RETURN_SUCCESS the information is restored successfully.
278 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and
280 @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox
281 has no LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
283 @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the
284 confidential information.
285 @retval RETURN_NOT_FOUND the requested GUID not found.
286 @retval RETURN_NOT_STARTED it is too early to invoke this interface
287 @retval RETURN_ACCESS_DENIED not allow to restore to the address
288 @retval RETURN_UNSUPPORTED the service is not supported by
295 IN VOID
*Buffer
, OPTIONAL
296 IN OUT UINTN
*Length OPTIONAL
299 LOCK_BOX_ENTRY
*Header
;
301 DEBUG ((DEBUG_VERBOSE
, "%a: Guid=%g Buffer=%p\n", __FUNCTION__
, Guid
,
304 if ((Guid
== NULL
) ||
305 ((Buffer
== NULL
) && (Length
!= NULL
)) ||
306 ((Buffer
!= NULL
) && (Length
== NULL
))) {
307 return EFI_INVALID_PARAMETER
;
310 Header
= FindHeaderByGuid (Guid
);
311 if (!Header
|| Header
->Size
== 0) {
312 return RETURN_NOT_FOUND
;
315 if (Buffer
== NULL
) {
316 if (!(Header
->Attributes
& LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
)) {
317 return RETURN_WRITE_PROTECTED
;
319 if (Header
->OrigAddress
+ (Header
->Size
- 1) > MAX_ADDRESS
) {
320 return RETURN_UNSUPPORTED
;
322 Buffer
= (VOID
*)(UINTN
) Header
->OrigAddress
;
328 if (Length
!= NULL
) {
329 if (Header
->Size
> *Length
) {
331 // Input buffer is too small to hold all data.
333 *Length
= Header
->Size
;
334 return EFI_BUFFER_TOO_SMALL
;
336 *Length
= Header
->Size
;
339 CopyMem (Buffer
, (VOID
*)(UINTN
) Header
->CopyAddress
, Header
->Size
);
341 return RETURN_SUCCESS
;
346 This function will restore confidential information from all lockbox which
347 have RestoreInPlace attribute.
349 @retval RETURN_SUCCESS the information is restored successfully.
350 @retval RETURN_NOT_STARTED it is too early to invoke this interface
351 @retval RETURN_UNSUPPORTED the service is not supported by
356 RestoreAllLockBoxInPlace (
360 LOCK_BOX_ENTRY
*Header
;
362 for (Header
= StartOfEntries
;
363 Header
< EndOfEntries
&& Header
->Size
> 0;
365 if (Header
->Attributes
& LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
) {
368 if (Header
->OrigAddress
+ (Header
->Size
- 1) > MAX_ADDRESS
) {
369 return RETURN_UNSUPPORTED
;
371 Buffer
= (VOID
*)(UINTN
) Header
->OrigAddress
;
372 CopyMem (Buffer
, (VOID
*)(UINTN
)Header
->CopyAddress
, Header
->Size
);
373 DEBUG ((DEBUG_VERBOSE
, "%a: Guid=%g Buffer=%p\n", __FUNCTION__
,
374 &Header
->Guid
, Buffer
));
377 return RETURN_SUCCESS
;