]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Library / SmmLockBoxLib / SmmLockBoxSmmLib.c
CommitLineData
1c837cd5 1/** @file\r
2\r
481ffd6f 3Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>\r
1c837cd5 4\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
1c837cd5 6\r
7**/\r
8\r
9#include <PiSmm.h>\r
10#include <Library/SmmServicesTableLib.h>\r
11#include <Library/BaseLib.h>\r
12#include <Library/BaseMemoryLib.h>\r
13#include <Library/LockBoxLib.h>\r
14#include <Library/DebugLib.h>\r
15#include <Guid/SmmLockBox.h>\r
6bd4af30
SZ
16#include <Guid/EndOfS3Resume.h>\r
17#include <Protocol/SmmReadyToLock.h>\r
18#include <Protocol/SmmEndOfDxe.h>\r
19#include <Protocol/SmmSxDispatch2.h>\r
1c837cd5 20\r
21#include "SmmLockBoxLibPrivate.h"\r
22\r
23/**\r
24 We need handle this library carefully. Only one library instance will construct the environment.\r
25 Below 2 global variable can only be used in constructor. They should NOT be used in any other library functions.\r
26**/\r
27SMM_LOCK_BOX_CONTEXT mSmmLockBoxContext;\r
28LIST_ENTRY mLockBoxQueue = INITIALIZE_LIST_HEAD_VARIABLE (mLockBoxQueue);\r
29\r
738df706 30BOOLEAN mSmmConfigurationTableInstalled = FALSE;\r
6bd4af30
SZ
31VOID *mSmmLockBoxRegistrationSmmEndOfDxe = NULL;\r
32VOID *mSmmLockBoxRegistrationSmmReadyToLock = NULL;\r
33VOID *mSmmLockBoxRegistrationEndOfS3Resume = NULL;\r
34BOOLEAN mSmmLockBoxSmmReadyToLock = FALSE;\r
35BOOLEAN mSmmLockBoxDuringS3Resume = FALSE;\r
738df706 36\r
1c837cd5 37/**\r
38 This function return SmmLockBox context from SMST.\r
39\r
40 @return SmmLockBox context from SMST.\r
41**/\r
42SMM_LOCK_BOX_CONTEXT *\r
43InternalGetSmmLockBoxContext (\r
44 VOID\r
45 )\r
46{\r
47 UINTN Index;\r
48\r
49 //\r
50 // Check if gEfiSmmLockBoxCommunicationGuid is installed by someone\r
51 //\r
52 for (Index = 0; Index < gSmst->NumberOfTableEntries; Index++) {\r
53 if (CompareGuid (&gSmst->SmmConfigurationTable[Index].VendorGuid, &gEfiSmmLockBoxCommunicationGuid)) {\r
54 //\r
55 // Found. That means some other library instance is already run.\r
56 // No need to install again, just return.\r
57 //\r
58 return (SMM_LOCK_BOX_CONTEXT *)gSmst->SmmConfigurationTable[Index].VendorTable;\r
59 }\r
60 }\r
61\r
62 //\r
63 // Not found.\r
64 //\r
65 return NULL;\r
66}\r
67\r
6bd4af30
SZ
68/**\r
69 Notification for SMM ReadyToLock protocol.\r
70\r
71 @param[in] Protocol Points to the protocol's unique identifier.\r
72 @param[in] Interface Points to the interface instance.\r
73 @param[in] Handle The handle on which the interface was installed.\r
74\r
75 @retval EFI_SUCCESS Notification runs successfully.\r
76**/\r
77EFI_STATUS\r
78EFIAPI\r
79SmmLockBoxSmmReadyToLockNotify (\r
80 IN CONST EFI_GUID *Protocol,\r
81 IN VOID *Interface,\r
82 IN EFI_HANDLE Handle\r
83 )\r
84{\r
85 mSmmLockBoxSmmReadyToLock = TRUE;\r
86 return EFI_SUCCESS;\r
87}\r
88\r
89/**\r
90 Main entry point for an SMM handler dispatch or communicate-based callback.\r
91\r
92 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
93 @param[in] Context Points to an optional handler context which was specified when the\r
94 handler was registered.\r
95 @param[in,out] CommBuffer A pointer to a collection of data in memory that will\r
96 be conveyed from a non-SMM environment into an SMM environment.\r
97 @param[in,out] CommBufferSize The size of the CommBuffer.\r
98\r
99 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers\r
100 should still be called.\r
101 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should\r
102 still be called.\r
103 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still\r
104 be called.\r
105 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.\r
106**/\r
107EFI_STATUS\r
108EFIAPI\r
109SmmLockBoxS3EntryCallBack (\r
110 IN EFI_HANDLE DispatchHandle,\r
111 IN CONST VOID *Context OPTIONAL,\r
112 IN OUT VOID *CommBuffer OPTIONAL,\r
113 IN OUT UINTN *CommBufferSize OPTIONAL\r
114 )\r
115{\r
116 mSmmLockBoxDuringS3Resume = TRUE;\r
117 return EFI_SUCCESS;\r
118}\r
119\r
120/**\r
121 Notification for SMM EndOfDxe protocol.\r
122\r
123 @param[in] Protocol Points to the protocol's unique identifier.\r
124 @param[in] Interface Points to the interface instance.\r
125 @param[in] Handle The handle on which the interface was installed.\r
126\r
127 @retval EFI_SUCCESS Notification runs successfully.\r
128**/\r
129EFI_STATUS\r
130EFIAPI\r
131SmmLockBoxSmmEndOfDxeNotify (\r
132 IN CONST EFI_GUID *Protocol,\r
133 IN VOID *Interface,\r
134 IN EFI_HANDLE Handle\r
135 )\r
136{\r
137 EFI_STATUS Status;\r
138 EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatch;\r
139 EFI_SMM_SX_REGISTER_CONTEXT EntryRegisterContext;\r
140 EFI_HANDLE S3EntryHandle;\r
141\r
142 //\r
143 // Locate SmmSxDispatch2 protocol.\r
144 //\r
145 Status = gSmst->SmmLocateProtocol (\r
146 &gEfiSmmSxDispatch2ProtocolGuid,\r
147 NULL,\r
148 (VOID **)&SxDispatch\r
149 );\r
150 if (!EFI_ERROR (Status) && (SxDispatch != NULL)) {\r
151 //\r
152 // Register a S3 entry callback function to\r
153 // determine if it will be during S3 resume.\r
154 //\r
155 EntryRegisterContext.Type = SxS3;\r
156 EntryRegisterContext.Phase = SxEntry;\r
157 Status = SxDispatch->Register (\r
158 SxDispatch,\r
159 SmmLockBoxS3EntryCallBack,\r
160 &EntryRegisterContext,\r
161 &S3EntryHandle\r
162 );\r
163 ASSERT_EFI_ERROR (Status);\r
164 }\r
165\r
166 return EFI_SUCCESS;\r
167}\r
168\r
169/**\r
170 Notification for SMM EndOfS3Resume protocol.\r
171\r
172 @param[in] Protocol Points to the protocol's unique identifier.\r
173 @param[in] Interface Points to the interface instance.\r
174 @param[in] Handle The handle on which the interface was installed.\r
175\r
176 @retval EFI_SUCCESS Notification runs successfully.\r
177**/\r
178EFI_STATUS\r
179EFIAPI\r
180SmmLockBoxEndOfS3ResumeNotify (\r
181 IN CONST EFI_GUID *Protocol,\r
182 IN VOID *Interface,\r
183 IN EFI_HANDLE Handle\r
184 )\r
185{\r
186 mSmmLockBoxDuringS3Resume = FALSE;\r
187 return EFI_SUCCESS;\r
188}\r
189\r
1c837cd5 190/**\r
191 Constructor for SmmLockBox library.\r
192 This is used to set SmmLockBox context, which will be used in PEI phase in S3 boot path later.\r
193\r
194 @param[in] ImageHandle Image handle of this driver.\r
195 @param[in] SystemTable A Pointer to the EFI System Table.\r
196\r
d1102dba 197 @retval EFI_SUCEESS\r
1c837cd5 198 @return Others Some error occurs.\r
199**/\r
200EFI_STATUS\r
201EFIAPI\r
da9d39c2 202SmmLockBoxSmmConstructor (\r
1c837cd5 203 IN EFI_HANDLE ImageHandle,\r
204 IN EFI_SYSTEM_TABLE *SystemTable\r
205 )\r
206{\r
207 EFI_STATUS Status;\r
208 SMM_LOCK_BOX_CONTEXT *SmmLockBoxContext;\r
209\r
481ffd6f 210 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxSmmConstructor - Enter\n"));\r
1c837cd5 211\r
6bd4af30
SZ
212 //\r
213 // Register SmmReadyToLock notification.\r
214 //\r
215 Status = gSmst->SmmRegisterProtocolNotify (\r
216 &gEfiSmmReadyToLockProtocolGuid,\r
217 SmmLockBoxSmmReadyToLockNotify,\r
218 &mSmmLockBoxRegistrationSmmReadyToLock\r
219 );\r
220 ASSERT_EFI_ERROR (Status);\r
221\r
222 //\r
223 // Register SmmEndOfDxe notification.\r
224 //\r
225 Status = gSmst->SmmRegisterProtocolNotify (\r
226 &gEfiSmmEndOfDxeProtocolGuid,\r
227 SmmLockBoxSmmEndOfDxeNotify,\r
228 &mSmmLockBoxRegistrationSmmEndOfDxe\r
229 );\r
230 ASSERT_EFI_ERROR (Status);\r
231\r
232 //\r
233 // Register EndOfS3Resume notification.\r
234 //\r
235 Status = gSmst->SmmRegisterProtocolNotify (\r
236 &gEdkiiEndOfS3ResumeGuid,\r
237 SmmLockBoxEndOfS3ResumeNotify,\r
238 &mSmmLockBoxRegistrationEndOfS3Resume\r
239 );\r
240 ASSERT_EFI_ERROR (Status);\r
241\r
1c837cd5 242 //\r
243 // Check if gEfiSmmLockBoxCommunicationGuid is installed by someone\r
244 //\r
245 SmmLockBoxContext = InternalGetSmmLockBoxContext ();\r
246 if (SmmLockBoxContext != NULL) {\r
247 //\r
248 // Find it. That means some other library instance is already run.\r
249 // No need to install again, just return.\r
250 //\r
481ffd6f
HW
251 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxContext - already installed\n"));\r
252 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxSmmConstructor - Exit\n"));\r
1c837cd5 253 return EFI_SUCCESS;\r
254 }\r
255\r
256 //\r
257 // If no one install this, it means this is first instance. Install it.\r
258 //\r
259 if (sizeof(UINTN) == sizeof(UINT64)) {\r
260 mSmmLockBoxContext.Signature = SMM_LOCK_BOX_SIGNATURE_64;\r
261 } else {\r
262 mSmmLockBoxContext.Signature = SMM_LOCK_BOX_SIGNATURE_32;\r
263 }\r
264 mSmmLockBoxContext.LockBoxDataAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)&mLockBoxQueue;\r
265\r
266 Status = gSmst->SmmInstallConfigurationTable (\r
267 gSmst,\r
268 &gEfiSmmLockBoxCommunicationGuid,\r
269 &mSmmLockBoxContext,\r
270 sizeof(mSmmLockBoxContext)\r
271 );\r
272 ASSERT_EFI_ERROR (Status);\r
738df706 273 mSmmConfigurationTableInstalled = TRUE;\r
1c837cd5 274\r
481ffd6f
HW
275 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxContext - %x\n", (UINTN)&mSmmLockBoxContext));\r
276 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib LockBoxDataAddress - %x\n", (UINTN)&mLockBoxQueue));\r
277 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxSmmConstructor - Exit\n"));\r
1c837cd5 278\r
279 return Status;\r
280}\r
281\r
738df706
SZ
282/**\r
283 Destructor for SmmLockBox library.\r
284 This is used to uninstall SmmLockBoxCommunication configuration table\r
285 if it has been installed in Constructor.\r
286\r
287 @param[in] ImageHandle Image handle of this driver.\r
288 @param[in] SystemTable A Pointer to the EFI System Table.\r
289\r
290 @retval EFI_SUCEESS The destructor always returns EFI_SUCCESS.\r
291\r
292**/\r
293EFI_STATUS\r
294EFIAPI\r
295SmmLockBoxSmmDestructor (\r
296 IN EFI_HANDLE ImageHandle,\r
297 IN EFI_SYSTEM_TABLE *SystemTable\r
298 )\r
299{\r
300 EFI_STATUS Status;\r
301\r
481ffd6f 302 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxSmmDestructor in %a module\n", gEfiCallerBaseName));\r
738df706
SZ
303\r
304 if (mSmmConfigurationTableInstalled) {\r
305 Status = gSmst->SmmInstallConfigurationTable (\r
306 gSmst,\r
307 &gEfiSmmLockBoxCommunicationGuid,\r
308 NULL,\r
309 0\r
310 );\r
311 ASSERT_EFI_ERROR (Status);\r
481ffd6f 312 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib uninstall SmmLockBoxCommunication configuration table\n"));\r
738df706
SZ
313 }\r
314\r
6bd4af30
SZ
315 if (mSmmLockBoxRegistrationSmmReadyToLock != NULL) {\r
316 //\r
317 // Unregister SmmReadyToLock notification.\r
318 //\r
319 Status = gSmst->SmmRegisterProtocolNotify (\r
320 &gEfiSmmReadyToLockProtocolGuid,\r
321 NULL,\r
322 &mSmmLockBoxRegistrationSmmReadyToLock\r
323 );\r
324 ASSERT_EFI_ERROR (Status);\r
325 }\r
326 if (mSmmLockBoxRegistrationSmmEndOfDxe != NULL) {\r
327 //\r
328 // Unregister SmmEndOfDxe notification.\r
329 //\r
330 Status = gSmst->SmmRegisterProtocolNotify (\r
331 &gEfiSmmEndOfDxeProtocolGuid,\r
332 NULL,\r
333 &mSmmLockBoxRegistrationSmmEndOfDxe\r
334 );\r
335 ASSERT_EFI_ERROR (Status);\r
336 }\r
337 if (mSmmLockBoxRegistrationEndOfS3Resume != NULL) {\r
338 //\r
339 // Unregister EndOfS3Resume notification.\r
340 //\r
341 Status = gSmst->SmmRegisterProtocolNotify (\r
342 &gEdkiiEndOfS3ResumeGuid,\r
343 NULL,\r
344 &mSmmLockBoxRegistrationEndOfS3Resume\r
345 );\r
346 ASSERT_EFI_ERROR (Status);\r
347 }\r
348\r
738df706
SZ
349 return EFI_SUCCESS;\r
350}\r
351\r
1c837cd5 352/**\r
353 This function return SmmLockBox queue address.\r
354\r
355 @return SmmLockBox queue address.\r
356**/\r
357LIST_ENTRY *\r
358InternalGetLockBoxQueue (\r
359 VOID\r
360 )\r
361{\r
362 SMM_LOCK_BOX_CONTEXT *SmmLockBoxContext;\r
363\r
364 SmmLockBoxContext = InternalGetSmmLockBoxContext ();\r
365 ASSERT (SmmLockBoxContext != NULL);\r
366 if (SmmLockBoxContext == NULL) {\r
367 return NULL;\r
368 }\r
369 return (LIST_ENTRY *)(UINTN)SmmLockBoxContext->LockBoxDataAddress;\r
370}\r
371\r
372/**\r
373 This function find LockBox by GUID.\r
374\r
375 @param Guid The guid to indentify the LockBox\r
376\r
377 @return LockBoxData\r
378**/\r
379SMM_LOCK_BOX_DATA *\r
380InternalFindLockBoxByGuid (\r
381 IN EFI_GUID *Guid\r
382 )\r
383{\r
384 LIST_ENTRY *Link;\r
385 SMM_LOCK_BOX_DATA *LockBox;\r
386 LIST_ENTRY *LockBoxQueue;\r
387\r
388 LockBoxQueue = InternalGetLockBoxQueue ();\r
389 ASSERT (LockBoxQueue != NULL);\r
390\r
391 for (Link = LockBoxQueue->ForwardLink;\r
392 Link != LockBoxQueue;\r
393 Link = Link->ForwardLink) {\r
394 LockBox = BASE_CR (\r
395 Link,\r
396 SMM_LOCK_BOX_DATA,\r
397 Link\r
398 );\r
399 if (CompareGuid (&LockBox->Guid, Guid)) {\r
400 return LockBox;\r
401 }\r
402 }\r
403 return NULL;\r
404}\r
405\r
406/**\r
407 This function will save confidential information to lockbox.\r
408\r
409 @param Guid the guid to identify the confidential information\r
410 @param Buffer the address of the confidential information\r
411 @param Length the length of the confidential information\r
412\r
413 @retval RETURN_SUCCESS the information is saved successfully.\r
414 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0\r
415 @retval RETURN_ALREADY_STARTED the requested GUID already exist.\r
416 @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information.\r
417 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface\r
418 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
419 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.\r
420**/\r
421RETURN_STATUS\r
422EFIAPI\r
423SaveLockBox (\r
424 IN GUID *Guid,\r
425 IN VOID *Buffer,\r
426 IN UINTN Length\r
427 )\r
428{\r
429 SMM_LOCK_BOX_DATA *LockBox;\r
430 EFI_PHYSICAL_ADDRESS SmramBuffer;\r
431 EFI_STATUS Status;\r
432 LIST_ENTRY *LockBoxQueue;\r
433\r
481ffd6f 434 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Enter\n"));\r
1c837cd5 435\r
436 //\r
437 // Basic check\r
438 //\r
439 if ((Guid == NULL) || (Buffer == NULL) || (Length == 0)) {\r
481ffd6f 440 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER));\r
1c837cd5 441 return EFI_INVALID_PARAMETER;\r
442 }\r
443\r
444 //\r
445 // Find LockBox\r
446 //\r
447 LockBox = InternalFindLockBoxByGuid (Guid);\r
448 if (LockBox != NULL) {\r
481ffd6f 449 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_ALREADY_STARTED));\r
1c837cd5 450 return EFI_ALREADY_STARTED;\r
451 }\r
452\r
453 //\r
454 // Allocate SMRAM buffer\r
455 //\r
456 Status = gSmst->SmmAllocatePages (\r
457 AllocateAnyPages,\r
458 EfiRuntimeServicesData,\r
459 EFI_SIZE_TO_PAGES (Length),\r
460 &SmramBuffer\r
461 );\r
462 ASSERT_EFI_ERROR (Status);\r
463 if (EFI_ERROR (Status)) {\r
481ffd6f 464 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES));\r
1c837cd5 465 return EFI_OUT_OF_RESOURCES;\r
466 }\r
467\r
468 //\r
469 // Allocate LockBox\r
470 //\r
471 Status = gSmst->SmmAllocatePool (\r
472 EfiRuntimeServicesData,\r
473 sizeof(*LockBox),\r
474 (VOID **)&LockBox\r
475 );\r
476 ASSERT_EFI_ERROR (Status);\r
477 if (EFI_ERROR (Status)) {\r
478 gSmst->SmmFreePages (SmramBuffer, EFI_SIZE_TO_PAGES (Length));\r
481ffd6f 479 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES));\r
1c837cd5 480 return EFI_OUT_OF_RESOURCES;\r
481 }\r
482\r
483 //\r
484 // Save data\r
485 //\r
486 CopyMem ((VOID *)(UINTN)SmramBuffer, (VOID *)(UINTN)Buffer, Length);\r
487\r
488 //\r
489 // Insert LockBox to queue\r
490 //\r
491 LockBox->Signature = SMM_LOCK_BOX_DATA_SIGNATURE;\r
492 CopyMem (&LockBox->Guid, Guid, sizeof(EFI_GUID));\r
493 LockBox->Buffer = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;\r
494 LockBox->Length = (UINT64)Length;\r
05ca95e2 495 LockBox->Attributes = 0;\r
1c837cd5 496 LockBox->SmramBuffer = SmramBuffer;\r
ef96ba3c
SZ
497\r
498 DEBUG ((\r
481ffd6f 499 DEBUG_INFO,\r
ef96ba3c
SZ
500 "LockBoxGuid - %g, SmramBuffer - 0x%lx, Length - 0x%lx\n",\r
501 &LockBox->Guid,\r
502 LockBox->SmramBuffer,\r
503 LockBox->Length\r
504 ));\r
505\r
1c837cd5 506 LockBoxQueue = InternalGetLockBoxQueue ();\r
507 ASSERT (LockBoxQueue != NULL);\r
508 InsertTailList (LockBoxQueue, &LockBox->Link);\r
509\r
510 //\r
511 // Done\r
512 //\r
481ffd6f 513 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_SUCCESS));\r
1c837cd5 514 return EFI_SUCCESS;\r
515}\r
516\r
517/**\r
518 This function will set lockbox attributes.\r
519\r
520 @param Guid the guid to identify the confidential information\r
521 @param Attributes the attributes of the lockbox\r
522\r
523 @retval RETURN_SUCCESS the information is saved successfully.\r
524 @retval RETURN_INVALID_PARAMETER attributes is invalid.\r
525 @retval RETURN_NOT_FOUND the requested GUID not found.\r
526 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface\r
527 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
528 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.\r
529**/\r
530RETURN_STATUS\r
531EFIAPI\r
532SetLockBoxAttributes (\r
533 IN GUID *Guid,\r
534 IN UINT64 Attributes\r
535 )\r
536{\r
537 SMM_LOCK_BOX_DATA *LockBox;\r
538\r
481ffd6f 539 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Enter\n"));\r
1c837cd5 540\r
541 //\r
542 // Basic check\r
543 //\r
544 if ((Guid == NULL) ||\r
6bd4af30 545 ((Attributes & ~(LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE | LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY)) != 0)) {\r
481ffd6f 546 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_INVALID_PARAMETER));\r
6bd4af30
SZ
547 return EFI_INVALID_PARAMETER;\r
548 }\r
549\r
550 if (((Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) &&\r
551 ((Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0)) {\r
481ffd6f
HW
552 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_INVALID_PARAMETER));\r
553 DEBUG ((DEBUG_INFO, " LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE and LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\n\n"));\r
554 DEBUG ((DEBUG_INFO, " can not be set together\n"));\r
1c837cd5 555 return EFI_INVALID_PARAMETER;\r
556 }\r
557\r
558 //\r
559 // Find LockBox\r
560 //\r
561 LockBox = InternalFindLockBoxByGuid (Guid);\r
562 if (LockBox == NULL) {\r
481ffd6f 563 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_NOT_FOUND));\r
1c837cd5 564 return EFI_NOT_FOUND;\r
565 }\r
566\r
6bd4af30
SZ
567 if ((((Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) &&\r
568 ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0)) ||\r
569 (((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) &&\r
570 ((Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0))) {\r
481ffd6f
HW
571 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes 0x%lx 0x%lx - Exit (%r)\n", LockBox->Attributes, Attributes, EFI_INVALID_PARAMETER));\r
572 DEBUG ((DEBUG_INFO, " LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE and LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\n\n"));\r
573 DEBUG ((DEBUG_INFO, " can not be set together\n"));\r
6bd4af30
SZ
574 return EFI_INVALID_PARAMETER;\r
575 }\r
576\r
1c837cd5 577 //\r
578 // Update data\r
579 //\r
580 LockBox->Attributes = Attributes;\r
581\r
582 //\r
583 // Done\r
584 //\r
481ffd6f 585 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_SUCCESS));\r
1c837cd5 586 return EFI_SUCCESS;\r
587}\r
588\r
589/**\r
590 This function will update confidential information to lockbox.\r
591\r
592 @param Guid the guid to identify the original confidential information\r
593 @param Offset the offset of the original confidential information\r
594 @param Buffer the address of the updated confidential information\r
595 @param Length the length of the updated confidential information\r
596\r
597 @retval RETURN_SUCCESS the information is saved successfully.\r
598 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0.\r
599 @retval RETURN_NOT_FOUND the requested GUID not found.\r
99383667
HW
600 @retval RETURN_BUFFER_TOO_SMALL for lockbox without attribute LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY,\r
601 the original buffer to too small to hold new information.\r
602 @retval RETURN_OUT_OF_RESOURCES for lockbox with attribute LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY,\r
603 no enough resource to save the information.\r
1c837cd5 604 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface\r
605 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
606 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.\r
607**/\r
608RETURN_STATUS\r
609EFIAPI\r
610UpdateLockBox (\r
611 IN GUID *Guid,\r
612 IN UINTN Offset,\r
613 IN VOID *Buffer,\r
614 IN UINTN Length\r
615 )\r
616{\r
617 SMM_LOCK_BOX_DATA *LockBox;\r
99383667
HW
618 EFI_PHYSICAL_ADDRESS SmramBuffer;\r
619 EFI_STATUS Status;\r
1c837cd5 620\r
481ffd6f 621 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Enter\n"));\r
1c837cd5 622\r
623 //\r
624 // Basic check\r
625 //\r
99383667
HW
626 if ((Guid == NULL) || (Buffer == NULL) || (Length == 0) ||\r
627 (Length > MAX_UINTN - Offset)) {\r
481ffd6f 628 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER));\r
1c837cd5 629 return EFI_INVALID_PARAMETER;\r
630 }\r
631\r
632 //\r
633 // Find LockBox\r
634 //\r
635 LockBox = InternalFindLockBoxByGuid (Guid);\r
636 if (LockBox == NULL) {\r
481ffd6f 637 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_NOT_FOUND));\r
1c837cd5 638 return EFI_NOT_FOUND;\r
639 }\r
640\r
641 //\r
642 // Update data\r
643 //\r
644 if (LockBox->Length < Offset + Length) {\r
99383667
HW
645 if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0) {\r
646 //\r
647 // If 'LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY' attribute is set, enlarge the\r
648 // LockBox.\r
649 //\r
650 DEBUG ((\r
651 DEBUG_INFO,\r
652 "SmmLockBoxSmmLib UpdateLockBox - Origin LockBox too small, enlarge.\n"\r
653 ));\r
654\r
655 if (EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES ((UINTN)LockBox->Length)) < Offset + Length) {\r
656 //\r
657 // In SaveLockBox(), the SMRAM buffer allocated for LockBox is of page\r
658 // granularity. Here, if the required size is larger than the origin size\r
659 // of the pages, allocate new buffer from SMRAM to enlarge the LockBox.\r
660 //\r
661 DEBUG ((\r
662 DEBUG_INFO,\r
663 "SmmLockBoxSmmLib UpdateLockBox - Allocate new buffer to enlarge.\n"\r
664 ));\r
665 Status = gSmst->SmmAllocatePages (\r
666 AllocateAnyPages,\r
667 EfiRuntimeServicesData,\r
668 EFI_SIZE_TO_PAGES (Offset + Length),\r
669 &SmramBuffer\r
670 );\r
671 if (EFI_ERROR (Status)) {\r
672 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES));\r
673 return EFI_OUT_OF_RESOURCES;\r
674 }\r
675\r
676 //\r
677 // Copy origin data to the new SMRAM buffer and wipe the content in the\r
678 // origin SMRAM buffer.\r
679 //\r
680 CopyMem ((VOID *)(UINTN)SmramBuffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);\r
681 ZeroMem ((VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);\r
682 gSmst->SmmFreePages (LockBox->SmramBuffer, EFI_SIZE_TO_PAGES ((UINTN)LockBox->Length));\r
683\r
684 LockBox->SmramBuffer = SmramBuffer;\r
685 }\r
686\r
687 //\r
688 // Handle uninitialized content in the LockBox.\r
689 //\r
690 if (Offset > LockBox->Length) {\r
691 ZeroMem (\r
692 (VOID *)((UINTN)LockBox->SmramBuffer + (UINTN)LockBox->Length),\r
693 Offset - (UINTN)LockBox->Length\r
694 );\r
695 }\r
696 LockBox->Length = Offset + Length;\r
697 } else {\r
698 //\r
699 // If 'LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY' attribute is NOT set, return\r
700 // EFI_BUFFER_TOO_SMALL directly.\r
701 //\r
702 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL));\r
703 return EFI_BUFFER_TOO_SMALL;\r
704 }\r
1c837cd5 705 }\r
579b5ef2 706 ASSERT ((UINTN)LockBox->SmramBuffer <= (MAX_ADDRESS - Offset));\r
1c837cd5 707 CopyMem ((VOID *)((UINTN)LockBox->SmramBuffer + Offset), Buffer, Length);\r
708\r
709 //\r
710 // Done\r
711 //\r
481ffd6f 712 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_SUCCESS));\r
1c837cd5 713 return EFI_SUCCESS;\r
714}\r
715\r
716/**\r
717 This function will restore confidential information from lockbox.\r
718\r
719 @param Guid the guid to identify the confidential information\r
720 @param Buffer the address of the restored confidential information\r
721 NULL means restored to original address, Length MUST be NULL at same time.\r
722 @param Length the length of the restored confidential information\r
723\r
724 @retval RETURN_SUCCESS the information is restored successfully.\r
725 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and Length is NULL.\r
d1102dba 726 @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox has no\r
1c837cd5 727 LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute.\r
728 @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the confidential information.\r
729 @retval RETURN_NOT_FOUND the requested GUID not found.\r
730 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
731 @retval RETURN_ACCESS_DENIED not allow to restore to the address\r
732 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.\r
733**/\r
734RETURN_STATUS\r
735EFIAPI\r
736RestoreLockBox (\r
737 IN GUID *Guid,\r
738 IN VOID *Buffer, OPTIONAL\r
739 IN OUT UINTN *Length OPTIONAL\r
740 )\r
741{\r
742 SMM_LOCK_BOX_DATA *LockBox;\r
743 VOID *RestoreBuffer;\r
744\r
481ffd6f 745 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Enter\n"));\r
1c837cd5 746\r
747 //\r
748 // Restore this, Buffer and Length MUST be both NULL or both non-NULL\r
749 //\r
750 if ((Guid == NULL) ||\r
751 ((Buffer == NULL) && (Length != NULL)) ||\r
752 ((Buffer != NULL) && (Length == NULL))) {\r
481ffd6f 753 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER));\r
1c837cd5 754 return EFI_INVALID_PARAMETER;\r
755 }\r
756\r
757 //\r
758 // Find LockBox\r
759 //\r
760 LockBox = InternalFindLockBoxByGuid (Guid);\r
761 if (LockBox == NULL) {\r
762 //\r
763 // Not found\r
764 //\r
481ffd6f 765 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_NOT_FOUND));\r
1c837cd5 766 return EFI_NOT_FOUND;\r
767 }\r
768\r
6bd4af30
SZ
769 if (((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0) &&\r
770 mSmmLockBoxSmmReadyToLock &&\r
771 !mSmmLockBoxDuringS3Resume) {\r
772 //\r
773 // With LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY,\r
774 // this LockBox can be restored in S3 resume only.\r
775 //\r
776 return EFI_ACCESS_DENIED;\r
777 }\r
778\r
1c837cd5 779 //\r
780 // Set RestoreBuffer\r
781 //\r
782 if (Buffer != NULL) {\r
783 //\r
784 // restore to new buffer\r
785 //\r
786 RestoreBuffer = Buffer;\r
787 } else {\r
788 //\r
789 // restore to original buffer\r
790 //\r
791 if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) == 0) {\r
481ffd6f 792 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_WRITE_PROTECTED));\r
1c837cd5 793 return EFI_WRITE_PROTECTED;\r
794 }\r
795 RestoreBuffer = (VOID *)(UINTN)LockBox->Buffer;\r
796 }\r
797\r
798 //\r
799 // Set RestoreLength\r
800 //\r
801 if (Length != NULL) {\r
802 if (*Length < (UINTN)LockBox->Length) {\r
803 //\r
804 // Input buffer is too small to hold all data.\r
805 //\r
806 *Length = (UINTN)LockBox->Length;\r
481ffd6f 807 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL));\r
1c837cd5 808 return EFI_BUFFER_TOO_SMALL;\r
809 }\r
810 *Length = (UINTN)LockBox->Length;\r
811 }\r
812\r
813 //\r
814 // Restore data\r
815 //\r
816 CopyMem (RestoreBuffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);\r
817\r
818 //\r
819 // Done\r
820 //\r
481ffd6f 821 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_SUCCESS));\r
1c837cd5 822 return EFI_SUCCESS;\r
823}\r
824\r
825/**\r
826 This function will restore confidential information from all lockbox which have RestoreInPlace attribute.\r
827\r
828 @retval RETURN_SUCCESS the information is restored successfully.\r
829 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
830 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.\r
831**/\r
832RETURN_STATUS\r
833EFIAPI\r
834RestoreAllLockBoxInPlace (\r
835 VOID\r
836 )\r
837{\r
838 SMM_LOCK_BOX_DATA *LockBox;\r
839 LIST_ENTRY *Link;\r
840 LIST_ENTRY *LockBoxQueue;\r
841\r
481ffd6f 842 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Enter\n"));\r
1c837cd5 843\r
844 LockBoxQueue = InternalGetLockBoxQueue ();\r
845 ASSERT (LockBoxQueue != NULL);\r
846\r
847 //\r
848 // Restore all, Buffer and Length MUST be NULL\r
849 //\r
850 for (Link = LockBoxQueue->ForwardLink;\r
851 Link != LockBoxQueue;\r
852 Link = Link->ForwardLink) {\r
853 LockBox = BASE_CR (\r
854 Link,\r
855 SMM_LOCK_BOX_DATA,\r
856 Link\r
857 );\r
858 if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) {\r
859 //\r
860 // Restore data\r
861 //\r
862 CopyMem ((VOID *)(UINTN)LockBox->Buffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);\r
863 }\r
864 }\r
865 //\r
866 // Done\r
867 //\r
481ffd6f 868 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Exit (%r)\n", EFI_SUCCESS));\r
1c837cd5 869 return EFI_SUCCESS;\r
870}\r
871\r