3 Copyright (c) 2010, 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
->SmramBuffer
= SmramBuffer
;
270 LockBoxQueue
= InternalGetLockBoxQueue ();
271 ASSERT (LockBoxQueue
!= NULL
);
272 InsertTailList (LockBoxQueue
, &LockBox
->Link
);
277 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_SUCCESS
));
282 This function will set lockbox attributes.
284 @param Guid the guid to identify the confidential information
285 @param Attributes the attributes of the lockbox
287 @retval RETURN_SUCCESS the information is saved successfully.
288 @retval RETURN_INVALID_PARAMETER attributes is invalid.
289 @retval RETURN_NOT_FOUND the requested GUID not found.
290 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
291 @retval RETURN_NOT_STARTED it is too early to invoke this interface
292 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
296 SetLockBoxAttributes (
301 SMM_LOCK_BOX_DATA
*LockBox
;
303 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SetLockBoxAttributes - Enter\n"));
308 if ((Guid
== NULL
) ||
309 ((Attributes
& ~LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
) != 0)) {
310 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_INVALID_PARAMETER
));
311 return EFI_INVALID_PARAMETER
;
317 LockBox
= InternalFindLockBoxByGuid (Guid
);
318 if (LockBox
== NULL
) {
319 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_NOT_FOUND
));
320 return EFI_NOT_FOUND
;
326 LockBox
->Attributes
= Attributes
;
331 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_SUCCESS
));
336 This function will update confidential information to lockbox.
338 @param Guid the guid to identify the original confidential information
339 @param Offset the offset of the original confidential information
340 @param Buffer the address of the updated confidential information
341 @param Length the length of the updated confidential information
343 @retval RETURN_SUCCESS the information is saved successfully.
344 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0.
345 @retval RETURN_NOT_FOUND the requested GUID not found.
346 @retval RETURN_BUFFER_TOO_SMALL the original buffer to too small to hold new information.
347 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
348 @retval RETURN_NOT_STARTED it is too early to invoke this interface
349 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
360 SMM_LOCK_BOX_DATA
*LockBox
;
362 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib UpdateLockBox - Enter\n"));
367 if ((Guid
== NULL
) || (Buffer
== NULL
) || (Length
== 0)) {
368 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER
));
369 return EFI_INVALID_PARAMETER
;
375 LockBox
= InternalFindLockBoxByGuid (Guid
);
376 if (LockBox
== NULL
) {
377 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_NOT_FOUND
));
378 return EFI_NOT_FOUND
;
384 if (LockBox
->Length
< Offset
+ Length
) {
385 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL
));
386 return EFI_BUFFER_TOO_SMALL
;
388 CopyMem ((VOID
*)((UINTN
)LockBox
->SmramBuffer
+ Offset
), Buffer
, Length
);
393 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_SUCCESS
));
398 This function will restore confidential information from lockbox.
400 @param Guid the guid to identify the confidential information
401 @param Buffer the address of the restored confidential information
402 NULL means restored to original address, Length MUST be NULL at same time.
403 @param Length the length of the restored confidential information
405 @retval RETURN_SUCCESS the information is restored successfully.
406 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and Length is NULL.
407 @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox has no
408 LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute.
409 @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the confidential information.
410 @retval RETURN_NOT_FOUND the requested GUID not found.
411 @retval RETURN_NOT_STARTED it is too early to invoke this interface
412 @retval RETURN_ACCESS_DENIED not allow to restore to the address
413 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
419 IN VOID
*Buffer
, OPTIONAL
420 IN OUT UINTN
*Length OPTIONAL
423 SMM_LOCK_BOX_DATA
*LockBox
;
426 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Enter\n"));
429 // Restore this, Buffer and Length MUST be both NULL or both non-NULL
431 if ((Guid
== NULL
) ||
432 ((Buffer
== NULL
) && (Length
!= NULL
)) ||
433 ((Buffer
!= NULL
) && (Length
== NULL
))) {
434 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER
));
435 return EFI_INVALID_PARAMETER
;
441 LockBox
= InternalFindLockBoxByGuid (Guid
);
442 if (LockBox
== NULL
) {
446 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_NOT_FOUND
));
447 return EFI_NOT_FOUND
;
453 if (Buffer
!= NULL
) {
455 // restore to new buffer
457 RestoreBuffer
= Buffer
;
460 // restore to original buffer
462 if ((LockBox
->Attributes
& LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
) == 0) {
463 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_WRITE_PROTECTED
));
464 return EFI_WRITE_PROTECTED
;
466 RestoreBuffer
= (VOID
*)(UINTN
)LockBox
->Buffer
;
472 if (Length
!= NULL
) {
473 if (*Length
< (UINTN
)LockBox
->Length
) {
475 // Input buffer is too small to hold all data.
477 *Length
= (UINTN
)LockBox
->Length
;
478 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL
));
479 return EFI_BUFFER_TOO_SMALL
;
481 *Length
= (UINTN
)LockBox
->Length
;
487 CopyMem (RestoreBuffer
, (VOID
*)(UINTN
)LockBox
->SmramBuffer
, (UINTN
)LockBox
->Length
);
492 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_SUCCESS
));
497 This function will restore confidential information from all lockbox which have RestoreInPlace attribute.
499 @retval RETURN_SUCCESS the information is restored successfully.
500 @retval RETURN_NOT_STARTED it is too early to invoke this interface
501 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
505 RestoreAllLockBoxInPlace (
509 SMM_LOCK_BOX_DATA
*LockBox
;
511 LIST_ENTRY
*LockBoxQueue
;
513 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Enter\n"));
515 LockBoxQueue
= InternalGetLockBoxQueue ();
516 ASSERT (LockBoxQueue
!= NULL
);
519 // Restore all, Buffer and Length MUST be NULL
521 for (Link
= LockBoxQueue
->ForwardLink
;
522 Link
!= LockBoxQueue
;
523 Link
= Link
->ForwardLink
) {
529 if ((LockBox
->Attributes
& LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
) != 0) {
533 CopyMem ((VOID
*)(UINTN
)LockBox
->Buffer
, (VOID
*)(UINTN
)LockBox
->SmramBuffer
, (UINTN
)LockBox
->Length
);
539 DEBUG ((EFI_D_INFO
, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Exit (%r)\n", EFI_SUCCESS
));