3 Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions
7 of the BSD License which accompanies this distribution. The
8 full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/SmmServicesTableLib.h>
18 #include <Library/BaseLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/LockBoxLib.h>
21 #include <Library/DebugLib.h>
22 #include <Guid/SmmLockBox.h>
24 #include "SmmLockBoxLibPrivate.h"
27 We need handle this library carefully. Only one library instance will construct the environment.
28 Below 2 global variable can only be used in constructor. They should NOT be used in any other library functions.
30 SMM_LOCK_BOX_CONTEXT mSmmLockBoxContext
;
31 LIST_ENTRY mLockBoxQueue
= INITIALIZE_LIST_HEAD_VARIABLE (mLockBoxQueue
);
34 This function return SmmLockBox context from SMST.
36 @return SmmLockBox context from SMST.
38 SMM_LOCK_BOX_CONTEXT
*
39 InternalGetSmmLockBoxContext (
46 // Check if gEfiSmmLockBoxCommunicationGuid is installed by someone
48 for (Index
= 0; Index
< gSmst
->NumberOfTableEntries
; Index
++) {
49 if (CompareGuid (&gSmst
->SmmConfigurationTable
[Index
].VendorGuid
, &gEfiSmmLockBoxCommunicationGuid
)) {
51 // Found. That means some other library instance is already run.
52 // No need to install again, just return.
54 return (SMM_LOCK_BOX_CONTEXT
*)gSmst
->SmmConfigurationTable
[Index
].VendorTable
;
65 Constructor for SmmLockBox library.
66 This is used to set SmmLockBox context, which will be used in PEI phase in S3 boot path later.
68 @param[in] ImageHandle Image handle of this driver.
69 @param[in] SystemTable A Pointer to the EFI System Table.
72 @return Others Some error occurs.
76 SmmLockBoxSmmConstructuor (
77 IN EFI_HANDLE ImageHandle
,
78 IN EFI_SYSTEM_TABLE
*SystemTable
82 SMM_LOCK_BOX_CONTEXT
*SmmLockBoxContext
;
84 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SmmLockBoxSmmConstructuor - Enter\n"));
87 // Check if gEfiSmmLockBoxCommunicationGuid is installed by someone
89 SmmLockBoxContext
= InternalGetSmmLockBoxContext ();
90 if (SmmLockBoxContext
!= NULL
) {
92 // Find it. That means some other library instance is already run.
93 // No need to install again, just return.
95 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SmmLockBoxContext - already installed\n"));
96 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SmmLockBoxSmmConstructuor - Exit\n"));
101 // If no one install this, it means this is first instance. Install it.
103 if (sizeof(UINTN
) == sizeof(UINT64
)) {
104 mSmmLockBoxContext
.Signature
= SMM_LOCK_BOX_SIGNATURE_64
;
106 mSmmLockBoxContext
.Signature
= SMM_LOCK_BOX_SIGNATURE_32
;
108 mSmmLockBoxContext
.LockBoxDataAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)&mLockBoxQueue
;
110 Status
= gSmst
->SmmInstallConfigurationTable (
112 &gEfiSmmLockBoxCommunicationGuid
,
114 sizeof(mSmmLockBoxContext
)
116 ASSERT_EFI_ERROR (Status
);
118 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SmmLockBoxContext - %x\n", (UINTN
)&mSmmLockBoxContext
));
119 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib LockBoxDataAddress - %x\n", (UINTN
)&mLockBoxQueue
));
120 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SmmLockBoxSmmConstructuor - Exit\n"));
126 This function return SmmLockBox queue address.
128 @return SmmLockBox queue address.
131 InternalGetLockBoxQueue (
135 SMM_LOCK_BOX_CONTEXT
*SmmLockBoxContext
;
137 SmmLockBoxContext
= InternalGetSmmLockBoxContext ();
138 ASSERT (SmmLockBoxContext
!= NULL
);
139 if (SmmLockBoxContext
== NULL
) {
142 return (LIST_ENTRY
*)(UINTN
)SmmLockBoxContext
->LockBoxDataAddress
;
146 This function find LockBox by GUID.
148 @param Guid The guid to indentify the LockBox
153 InternalFindLockBoxByGuid (
158 SMM_LOCK_BOX_DATA
*LockBox
;
159 LIST_ENTRY
*LockBoxQueue
;
161 LockBoxQueue
= InternalGetLockBoxQueue ();
162 ASSERT (LockBoxQueue
!= NULL
);
164 for (Link
= LockBoxQueue
->ForwardLink
;
165 Link
!= LockBoxQueue
;
166 Link
= Link
->ForwardLink
) {
172 if (CompareGuid (&LockBox
->Guid
, Guid
)) {
180 This function will save confidential information to lockbox.
182 @param Guid the guid to identify the confidential information
183 @param Buffer the address of the confidential information
184 @param Length the length of the confidential information
186 @retval RETURN_SUCCESS the information is saved successfully.
187 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0
188 @retval RETURN_ALREADY_STARTED the requested GUID already exist.
189 @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information.
190 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
191 @retval RETURN_NOT_STARTED it is too early to invoke this interface
192 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
202 SMM_LOCK_BOX_DATA
*LockBox
;
203 EFI_PHYSICAL_ADDRESS SmramBuffer
;
205 LIST_ENTRY
*LockBoxQueue
;
207 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SaveLockBox - Enter\n"));
212 if ((Guid
== NULL
) || (Buffer
== NULL
) || (Length
== 0)) {
213 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER
));
214 return EFI_INVALID_PARAMETER
;
220 LockBox
= InternalFindLockBoxByGuid (Guid
);
221 if (LockBox
!= NULL
) {
222 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_ALREADY_STARTED
));
223 return EFI_ALREADY_STARTED
;
227 // Allocate SMRAM buffer
229 Status
= gSmst
->SmmAllocatePages (
231 EfiRuntimeServicesData
,
232 EFI_SIZE_TO_PAGES (Length
),
235 ASSERT_EFI_ERROR (Status
);
236 if (EFI_ERROR (Status
)) {
237 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES
));
238 return EFI_OUT_OF_RESOURCES
;
244 Status
= gSmst
->SmmAllocatePool (
245 EfiRuntimeServicesData
,
249 ASSERT_EFI_ERROR (Status
);
250 if (EFI_ERROR (Status
)) {
251 gSmst
->SmmFreePages (SmramBuffer
, EFI_SIZE_TO_PAGES (Length
));
252 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES
));
253 return EFI_OUT_OF_RESOURCES
;
259 CopyMem ((VOID
*)(UINTN
)SmramBuffer
, (VOID
*)(UINTN
)Buffer
, Length
);
262 // Insert LockBox to queue
264 LockBox
->Signature
= SMM_LOCK_BOX_DATA_SIGNATURE
;
265 CopyMem (&LockBox
->Guid
, Guid
, sizeof(EFI_GUID
));
266 LockBox
->Buffer
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Buffer
;
267 LockBox
->Length
= (UINT64
)Length
;
268 LockBox
->Attributes
= 0;
269 LockBox
->SmramBuffer
= SmramBuffer
;
271 LockBoxQueue
= InternalGetLockBoxQueue ();
272 ASSERT (LockBoxQueue
!= NULL
);
273 InsertTailList (LockBoxQueue
, &LockBox
->Link
);
278 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_SUCCESS
));
283 This function will set lockbox attributes.
285 @param Guid the guid to identify the confidential information
286 @param Attributes the attributes of the lockbox
288 @retval RETURN_SUCCESS the information is saved successfully.
289 @retval RETURN_INVALID_PARAMETER attributes is invalid.
290 @retval RETURN_NOT_FOUND the requested GUID not found.
291 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
292 @retval RETURN_NOT_STARTED it is too early to invoke this interface
293 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
297 SetLockBoxAttributes (
302 SMM_LOCK_BOX_DATA
*LockBox
;
304 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SetLockBoxAttributes - Enter\n"));
309 if ((Guid
== NULL
) ||
310 ((Attributes
& ~LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
) != 0)) {
311 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_INVALID_PARAMETER
));
312 return EFI_INVALID_PARAMETER
;
318 LockBox
= InternalFindLockBoxByGuid (Guid
);
319 if (LockBox
== NULL
) {
320 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_NOT_FOUND
));
321 return EFI_NOT_FOUND
;
327 LockBox
->Attributes
= Attributes
;
332 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_SUCCESS
));
337 This function will update confidential information to lockbox.
339 @param Guid the guid to identify the original confidential information
340 @param Offset the offset of the original confidential information
341 @param Buffer the address of the updated confidential information
342 @param Length the length of the updated confidential information
344 @retval RETURN_SUCCESS the information is saved successfully.
345 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0.
346 @retval RETURN_NOT_FOUND the requested GUID not found.
347 @retval RETURN_BUFFER_TOO_SMALL the original buffer to too small to hold new information.
348 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
349 @retval RETURN_NOT_STARTED it is too early to invoke this interface
350 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
361 SMM_LOCK_BOX_DATA
*LockBox
;
363 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib UpdateLockBox - Enter\n"));
368 if ((Guid
== NULL
) || (Buffer
== NULL
) || (Length
== 0)) {
369 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER
));
370 return EFI_INVALID_PARAMETER
;
376 LockBox
= InternalFindLockBoxByGuid (Guid
);
377 if (LockBox
== NULL
) {
378 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_NOT_FOUND
));
379 return EFI_NOT_FOUND
;
385 if (LockBox
->Length
< Offset
+ Length
) {
386 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL
));
387 return EFI_BUFFER_TOO_SMALL
;
389 CopyMem ((VOID
*)((UINTN
)LockBox
->SmramBuffer
+ Offset
), Buffer
, Length
);
394 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_SUCCESS
));
399 This function will restore confidential information from lockbox.
401 @param Guid the guid to identify the confidential information
402 @param Buffer the address of the restored confidential information
403 NULL means restored to original address, Length MUST be NULL at same time.
404 @param Length the length of the restored confidential information
406 @retval RETURN_SUCCESS the information is restored successfully.
407 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and Length is NULL.
408 @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox has no
409 LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute.
410 @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the confidential information.
411 @retval RETURN_NOT_FOUND the requested GUID not found.
412 @retval RETURN_NOT_STARTED it is too early to invoke this interface
413 @retval RETURN_ACCESS_DENIED not allow to restore to the address
414 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
420 IN VOID
*Buffer
, OPTIONAL
421 IN OUT UINTN
*Length OPTIONAL
424 SMM_LOCK_BOX_DATA
*LockBox
;
427 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Enter\n"));
430 // Restore this, Buffer and Length MUST be both NULL or both non-NULL
432 if ((Guid
== NULL
) ||
433 ((Buffer
== NULL
) && (Length
!= NULL
)) ||
434 ((Buffer
!= NULL
) && (Length
== NULL
))) {
435 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER
));
436 return EFI_INVALID_PARAMETER
;
442 LockBox
= InternalFindLockBoxByGuid (Guid
);
443 if (LockBox
== NULL
) {
447 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_NOT_FOUND
));
448 return EFI_NOT_FOUND
;
454 if (Buffer
!= NULL
) {
456 // restore to new buffer
458 RestoreBuffer
= Buffer
;
461 // restore to original buffer
463 if ((LockBox
->Attributes
& LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
) == 0) {
464 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_WRITE_PROTECTED
));
465 return EFI_WRITE_PROTECTED
;
467 RestoreBuffer
= (VOID
*)(UINTN
)LockBox
->Buffer
;
473 if (Length
!= NULL
) {
474 if (*Length
< (UINTN
)LockBox
->Length
) {
476 // Input buffer is too small to hold all data.
478 *Length
= (UINTN
)LockBox
->Length
;
479 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL
));
480 return EFI_BUFFER_TOO_SMALL
;
482 *Length
= (UINTN
)LockBox
->Length
;
488 CopyMem (RestoreBuffer
, (VOID
*)(UINTN
)LockBox
->SmramBuffer
, (UINTN
)LockBox
->Length
);
493 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_SUCCESS
));
498 This function will restore confidential information from all lockbox which have RestoreInPlace attribute.
500 @retval RETURN_SUCCESS the information is restored successfully.
501 @retval RETURN_NOT_STARTED it is too early to invoke this interface
502 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
506 RestoreAllLockBoxInPlace (
510 SMM_LOCK_BOX_DATA
*LockBox
;
512 LIST_ENTRY
*LockBoxQueue
;
514 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Enter\n"));
516 LockBoxQueue
= InternalGetLockBoxQueue ();
517 ASSERT (LockBoxQueue
!= NULL
);
520 // Restore all, Buffer and Length MUST be NULL
522 for (Link
= LockBoxQueue
->ForwardLink
;
523 Link
!= LockBoxQueue
;
524 Link
= Link
->ForwardLink
) {
530 if ((LockBox
->Attributes
& LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
) != 0) {
534 CopyMem ((VOID
*)(UINTN
)LockBox
->Buffer
, (VOID
*)(UINTN
)LockBox
->SmramBuffer
, (UINTN
)LockBox
->Length
);
540 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Exit (%r)\n", EFI_SUCCESS
));