3 Copyright (c) 2010 - 2016, 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
);
33 BOOLEAN mSmmConfigurationTableInstalled
= FALSE
;
36 This function return SmmLockBox context from SMST.
38 @return SmmLockBox context from SMST.
40 SMM_LOCK_BOX_CONTEXT
*
41 InternalGetSmmLockBoxContext (
48 // Check if gEfiSmmLockBoxCommunicationGuid is installed by someone
50 for (Index
= 0; Index
< gSmst
->NumberOfTableEntries
; Index
++) {
51 if (CompareGuid (&gSmst
->SmmConfigurationTable
[Index
].VendorGuid
, &gEfiSmmLockBoxCommunicationGuid
)) {
53 // Found. That means some other library instance is already run.
54 // No need to install again, just return.
56 return (SMM_LOCK_BOX_CONTEXT
*)gSmst
->SmmConfigurationTable
[Index
].VendorTable
;
67 Constructor for SmmLockBox library.
68 This is used to set SmmLockBox context, which will be used in PEI phase in S3 boot path later.
70 @param[in] ImageHandle Image handle of this driver.
71 @param[in] SystemTable A Pointer to the EFI System Table.
74 @return Others Some error occurs.
78 SmmLockBoxSmmConstructor (
79 IN EFI_HANDLE ImageHandle
,
80 IN EFI_SYSTEM_TABLE
*SystemTable
84 SMM_LOCK_BOX_CONTEXT
*SmmLockBoxContext
;
86 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SmmLockBoxSmmConstructor - Enter\n"));
89 // Check if gEfiSmmLockBoxCommunicationGuid is installed by someone
91 SmmLockBoxContext
= InternalGetSmmLockBoxContext ();
92 if (SmmLockBoxContext
!= NULL
) {
94 // Find it. That means some other library instance is already run.
95 // No need to install again, just return.
97 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SmmLockBoxContext - already installed\n"));
98 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SmmLockBoxSmmConstructor - Exit\n"));
103 // If no one install this, it means this is first instance. Install it.
105 if (sizeof(UINTN
) == sizeof(UINT64
)) {
106 mSmmLockBoxContext
.Signature
= SMM_LOCK_BOX_SIGNATURE_64
;
108 mSmmLockBoxContext
.Signature
= SMM_LOCK_BOX_SIGNATURE_32
;
110 mSmmLockBoxContext
.LockBoxDataAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)&mLockBoxQueue
;
112 Status
= gSmst
->SmmInstallConfigurationTable (
114 &gEfiSmmLockBoxCommunicationGuid
,
116 sizeof(mSmmLockBoxContext
)
118 ASSERT_EFI_ERROR (Status
);
119 mSmmConfigurationTableInstalled
= TRUE
;
121 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SmmLockBoxContext - %x\n", (UINTN
)&mSmmLockBoxContext
));
122 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib LockBoxDataAddress - %x\n", (UINTN
)&mLockBoxQueue
));
123 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SmmLockBoxSmmConstructor - Exit\n"));
129 Destructor for SmmLockBox library.
130 This is used to uninstall SmmLockBoxCommunication configuration table
131 if it has been installed in Constructor.
133 @param[in] ImageHandle Image handle of this driver.
134 @param[in] SystemTable A Pointer to the EFI System Table.
136 @retval EFI_SUCEESS The destructor always returns EFI_SUCCESS.
141 SmmLockBoxSmmDestructor (
142 IN EFI_HANDLE ImageHandle
,
143 IN EFI_SYSTEM_TABLE
*SystemTable
148 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SmmLockBoxSmmDestructor in %a module\n", gEfiCallerBaseName
));
150 if (mSmmConfigurationTableInstalled
) {
151 Status
= gSmst
->SmmInstallConfigurationTable (
153 &gEfiSmmLockBoxCommunicationGuid
,
157 ASSERT_EFI_ERROR (Status
);
158 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib uninstall SmmLockBoxCommunication configuration table\n"));
165 This function return SmmLockBox queue address.
167 @return SmmLockBox queue address.
170 InternalGetLockBoxQueue (
174 SMM_LOCK_BOX_CONTEXT
*SmmLockBoxContext
;
176 SmmLockBoxContext
= InternalGetSmmLockBoxContext ();
177 ASSERT (SmmLockBoxContext
!= NULL
);
178 if (SmmLockBoxContext
== NULL
) {
181 return (LIST_ENTRY
*)(UINTN
)SmmLockBoxContext
->LockBoxDataAddress
;
185 This function find LockBox by GUID.
187 @param Guid The guid to indentify the LockBox
192 InternalFindLockBoxByGuid (
197 SMM_LOCK_BOX_DATA
*LockBox
;
198 LIST_ENTRY
*LockBoxQueue
;
200 LockBoxQueue
= InternalGetLockBoxQueue ();
201 ASSERT (LockBoxQueue
!= NULL
);
203 for (Link
= LockBoxQueue
->ForwardLink
;
204 Link
!= LockBoxQueue
;
205 Link
= Link
->ForwardLink
) {
211 if (CompareGuid (&LockBox
->Guid
, Guid
)) {
219 This function will save confidential information to lockbox.
221 @param Guid the guid to identify the confidential information
222 @param Buffer the address of the confidential information
223 @param Length the length of the confidential information
225 @retval RETURN_SUCCESS the information is saved successfully.
226 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0
227 @retval RETURN_ALREADY_STARTED the requested GUID already exist.
228 @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information.
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 implementaion.
241 SMM_LOCK_BOX_DATA
*LockBox
;
242 EFI_PHYSICAL_ADDRESS SmramBuffer
;
244 LIST_ENTRY
*LockBoxQueue
;
246 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SaveLockBox - Enter\n"));
251 if ((Guid
== NULL
) || (Buffer
== NULL
) || (Length
== 0)) {
252 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER
));
253 return EFI_INVALID_PARAMETER
;
259 LockBox
= InternalFindLockBoxByGuid (Guid
);
260 if (LockBox
!= NULL
) {
261 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_ALREADY_STARTED
));
262 return EFI_ALREADY_STARTED
;
266 // Allocate SMRAM buffer
268 Status
= gSmst
->SmmAllocatePages (
270 EfiRuntimeServicesData
,
271 EFI_SIZE_TO_PAGES (Length
),
274 ASSERT_EFI_ERROR (Status
);
275 if (EFI_ERROR (Status
)) {
276 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES
));
277 return EFI_OUT_OF_RESOURCES
;
283 Status
= gSmst
->SmmAllocatePool (
284 EfiRuntimeServicesData
,
288 ASSERT_EFI_ERROR (Status
);
289 if (EFI_ERROR (Status
)) {
290 gSmst
->SmmFreePages (SmramBuffer
, EFI_SIZE_TO_PAGES (Length
));
291 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES
));
292 return EFI_OUT_OF_RESOURCES
;
298 CopyMem ((VOID
*)(UINTN
)SmramBuffer
, (VOID
*)(UINTN
)Buffer
, Length
);
301 // Insert LockBox to queue
303 LockBox
->Signature
= SMM_LOCK_BOX_DATA_SIGNATURE
;
304 CopyMem (&LockBox
->Guid
, Guid
, sizeof(EFI_GUID
));
305 LockBox
->Buffer
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Buffer
;
306 LockBox
->Length
= (UINT64
)Length
;
307 LockBox
->Attributes
= 0;
308 LockBox
->SmramBuffer
= SmramBuffer
;
312 "LockBoxGuid - %g, SmramBuffer - 0x%lx, Length - 0x%lx\n",
314 LockBox
->SmramBuffer
,
318 LockBoxQueue
= InternalGetLockBoxQueue ();
319 ASSERT (LockBoxQueue
!= NULL
);
320 InsertTailList (LockBoxQueue
, &LockBox
->Link
);
325 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_SUCCESS
));
330 This function will set lockbox attributes.
332 @param Guid the guid to identify the confidential information
333 @param Attributes the attributes of the lockbox
335 @retval RETURN_SUCCESS the information is saved successfully.
336 @retval RETURN_INVALID_PARAMETER attributes is invalid.
337 @retval RETURN_NOT_FOUND the requested GUID not found.
338 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
339 @retval RETURN_NOT_STARTED it is too early to invoke this interface
340 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
344 SetLockBoxAttributes (
349 SMM_LOCK_BOX_DATA
*LockBox
;
351 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SetLockBoxAttributes - Enter\n"));
356 if ((Guid
== NULL
) ||
357 ((Attributes
& ~LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
) != 0)) {
358 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_INVALID_PARAMETER
));
359 return EFI_INVALID_PARAMETER
;
365 LockBox
= InternalFindLockBoxByGuid (Guid
);
366 if (LockBox
== NULL
) {
367 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_NOT_FOUND
));
368 return EFI_NOT_FOUND
;
374 LockBox
->Attributes
= Attributes
;
379 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_SUCCESS
));
384 This function will update confidential information to lockbox.
386 @param Guid the guid to identify the original confidential information
387 @param Offset the offset of the original confidential information
388 @param Buffer the address of the updated confidential information
389 @param Length the length of the updated confidential information
391 @retval RETURN_SUCCESS the information is saved successfully.
392 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0.
393 @retval RETURN_NOT_FOUND the requested GUID not found.
394 @retval RETURN_BUFFER_TOO_SMALL the original buffer to too small to hold new information.
395 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
396 @retval RETURN_NOT_STARTED it is too early to invoke this interface
397 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
408 SMM_LOCK_BOX_DATA
*LockBox
;
410 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib UpdateLockBox - Enter\n"));
415 if ((Guid
== NULL
) || (Buffer
== NULL
) || (Length
== 0)) {
416 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER
));
417 return EFI_INVALID_PARAMETER
;
423 LockBox
= InternalFindLockBoxByGuid (Guid
);
424 if (LockBox
== NULL
) {
425 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_NOT_FOUND
));
426 return EFI_NOT_FOUND
;
432 if (LockBox
->Length
< Offset
+ Length
) {
433 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL
));
434 return EFI_BUFFER_TOO_SMALL
;
436 ASSERT ((UINTN
)LockBox
->SmramBuffer
<= (MAX_ADDRESS
- Offset
));
437 CopyMem ((VOID
*)((UINTN
)LockBox
->SmramBuffer
+ Offset
), Buffer
, Length
);
442 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_SUCCESS
));
447 This function will restore confidential information from lockbox.
449 @param Guid the guid to identify the confidential information
450 @param Buffer the address of the restored confidential information
451 NULL means restored to original address, Length MUST be NULL at same time.
452 @param Length the length of the restored confidential information
454 @retval RETURN_SUCCESS the information is restored successfully.
455 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and Length is NULL.
456 @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox has no
457 LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute.
458 @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the confidential information.
459 @retval RETURN_NOT_FOUND the requested GUID not found.
460 @retval RETURN_NOT_STARTED it is too early to invoke this interface
461 @retval RETURN_ACCESS_DENIED not allow to restore to the address
462 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
468 IN VOID
*Buffer
, OPTIONAL
469 IN OUT UINTN
*Length OPTIONAL
472 SMM_LOCK_BOX_DATA
*LockBox
;
475 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Enter\n"));
478 // Restore this, Buffer and Length MUST be both NULL or both non-NULL
480 if ((Guid
== NULL
) ||
481 ((Buffer
== NULL
) && (Length
!= NULL
)) ||
482 ((Buffer
!= NULL
) && (Length
== NULL
))) {
483 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER
));
484 return EFI_INVALID_PARAMETER
;
490 LockBox
= InternalFindLockBoxByGuid (Guid
);
491 if (LockBox
== NULL
) {
495 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_NOT_FOUND
));
496 return EFI_NOT_FOUND
;
502 if (Buffer
!= NULL
) {
504 // restore to new buffer
506 RestoreBuffer
= Buffer
;
509 // restore to original buffer
511 if ((LockBox
->Attributes
& LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
) == 0) {
512 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_WRITE_PROTECTED
));
513 return EFI_WRITE_PROTECTED
;
515 RestoreBuffer
= (VOID
*)(UINTN
)LockBox
->Buffer
;
521 if (Length
!= NULL
) {
522 if (*Length
< (UINTN
)LockBox
->Length
) {
524 // Input buffer is too small to hold all data.
526 *Length
= (UINTN
)LockBox
->Length
;
527 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL
));
528 return EFI_BUFFER_TOO_SMALL
;
530 *Length
= (UINTN
)LockBox
->Length
;
536 CopyMem (RestoreBuffer
, (VOID
*)(UINTN
)LockBox
->SmramBuffer
, (UINTN
)LockBox
->Length
);
541 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_SUCCESS
));
546 This function will restore confidential information from all lockbox which have RestoreInPlace attribute.
548 @retval RETURN_SUCCESS the information is restored successfully.
549 @retval RETURN_NOT_STARTED it is too early to invoke this interface
550 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
554 RestoreAllLockBoxInPlace (
558 SMM_LOCK_BOX_DATA
*LockBox
;
560 LIST_ENTRY
*LockBoxQueue
;
562 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Enter\n"));
564 LockBoxQueue
= InternalGetLockBoxQueue ();
565 ASSERT (LockBoxQueue
!= NULL
);
568 // Restore all, Buffer and Length MUST be NULL
570 for (Link
= LockBoxQueue
->ForwardLink
;
571 Link
!= LockBoxQueue
;
572 Link
= Link
->ForwardLink
) {
578 if ((LockBox
->Attributes
& LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
) != 0) {
582 CopyMem ((VOID
*)(UINTN
)LockBox
->Buffer
, (VOID
*)(UINTN
)LockBox
->SmramBuffer
, (UINTN
)LockBox
->Length
);
588 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Exit (%r)\n", EFI_SUCCESS
));