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