]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxMmLib.c
MdeModulePkg: Fix device path when boot manager menu is from different FV
[mirror_edk2.git] / MdeModulePkg / Library / SmmLockBoxLib / SmmLockBoxMmLib.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
e35fce8a
KQ
9#include <PiMm.h>\r
10#include <Library/MmServicesTableLib.h>\r
1c837cd5 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 16#include <Guid/EndOfS3Resume.h>\r
e35fce8a
KQ
17#include <Protocol/MmReadyToLock.h>\r
18#include <Protocol/MmEndOfDxe.h>\r
6bd4af30 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
e35fce8a
KQ
52 for (Index = 0; Index < gMmst->NumberOfTableEntries; Index++) {\r
53 if (CompareGuid (&gMmst->MmConfigurationTable[Index].VendorGuid, &gEfiSmmLockBoxCommunicationGuid)) {\r
1c837cd5 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
e35fce8a 58 return (SMM_LOCK_BOX_CONTEXT *)gMmst->MmConfigurationTable[Index].VendorTable;\r
1c837cd5 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
e35fce8a
KQ
145 Status = gMmst->MmLocateProtocol (\r
146 &gEfiMmSxDispatchProtocolGuid,\r
6bd4af30
SZ
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
d1102dba 194 @retval EFI_SUCEESS\r
1c837cd5 195 @return Others Some error occurs.\r
196**/\r
197EFI_STATUS\r
e35fce8a
KQ
198SmmLockBoxMmConstructor (\r
199 VOID\r
1c837cd5 200 )\r
201{\r
202 EFI_STATUS Status;\r
203 SMM_LOCK_BOX_CONTEXT *SmmLockBoxContext;\r
204\r
e35fce8a 205 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxMmConstructor - Enter\n"));\r
1c837cd5 206\r
6bd4af30
SZ
207 //\r
208 // Register SmmReadyToLock notification.\r
209 //\r
e35fce8a
KQ
210 Status = gMmst->MmRegisterProtocolNotify (\r
211 &gEfiMmReadyToLockProtocolGuid,\r
6bd4af30
SZ
212 SmmLockBoxSmmReadyToLockNotify,\r
213 &mSmmLockBoxRegistrationSmmReadyToLock\r
214 );\r
215 ASSERT_EFI_ERROR (Status);\r
216\r
217 //\r
218 // Register SmmEndOfDxe notification.\r
219 //\r
e35fce8a
KQ
220 Status = gMmst->MmRegisterProtocolNotify (\r
221 &gEfiMmEndOfDxeProtocolGuid,\r
6bd4af30
SZ
222 SmmLockBoxSmmEndOfDxeNotify,\r
223 &mSmmLockBoxRegistrationSmmEndOfDxe\r
224 );\r
225 ASSERT_EFI_ERROR (Status);\r
226\r
227 //\r
228 // Register EndOfS3Resume notification.\r
229 //\r
e35fce8a 230 Status = gMmst->MmRegisterProtocolNotify (\r
6bd4af30
SZ
231 &gEdkiiEndOfS3ResumeGuid,\r
232 SmmLockBoxEndOfS3ResumeNotify,\r
233 &mSmmLockBoxRegistrationEndOfS3Resume\r
234 );\r
235 ASSERT_EFI_ERROR (Status);\r
236\r
1c837cd5 237 //\r
238 // Check if gEfiSmmLockBoxCommunicationGuid is installed by someone\r
239 //\r
240 SmmLockBoxContext = InternalGetSmmLockBoxContext ();\r
241 if (SmmLockBoxContext != NULL) {\r
242 //\r
243 // Find it. That means some other library instance is already run.\r
244 // No need to install again, just return.\r
245 //\r
481ffd6f 246 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxContext - already installed\n"));\r
e35fce8a 247 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxMmConstructor - Exit\n"));\r
1c837cd5 248 return EFI_SUCCESS;\r
249 }\r
250\r
251 //\r
252 // If no one install this, it means this is first instance. Install it.\r
253 //\r
254 if (sizeof(UINTN) == sizeof(UINT64)) {\r
255 mSmmLockBoxContext.Signature = SMM_LOCK_BOX_SIGNATURE_64;\r
256 } else {\r
257 mSmmLockBoxContext.Signature = SMM_LOCK_BOX_SIGNATURE_32;\r
258 }\r
259 mSmmLockBoxContext.LockBoxDataAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)&mLockBoxQueue;\r
260\r
e35fce8a
KQ
261 Status = gMmst->MmInstallConfigurationTable (\r
262 gMmst,\r
1c837cd5 263 &gEfiSmmLockBoxCommunicationGuid,\r
264 &mSmmLockBoxContext,\r
265 sizeof(mSmmLockBoxContext)\r
266 );\r
267 ASSERT_EFI_ERROR (Status);\r
738df706 268 mSmmConfigurationTableInstalled = TRUE;\r
1c837cd5 269\r
481ffd6f
HW
270 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxContext - %x\n", (UINTN)&mSmmLockBoxContext));\r
271 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib LockBoxDataAddress - %x\n", (UINTN)&mLockBoxQueue));\r
e35fce8a 272 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxMmConstructor - Exit\n"));\r
1c837cd5 273\r
274 return Status;\r
275}\r
276\r
738df706
SZ
277/**\r
278 Destructor for SmmLockBox library.\r
279 This is used to uninstall SmmLockBoxCommunication configuration table\r
280 if it has been installed in Constructor.\r
281\r
738df706
SZ
282 @retval EFI_SUCEESS The destructor always returns EFI_SUCCESS.\r
283\r
284**/\r
285EFI_STATUS\r
e35fce8a
KQ
286SmmLockBoxMmDestructor (\r
287 VOID\r
738df706
SZ
288 )\r
289{\r
290 EFI_STATUS Status;\r
291\r
e35fce8a 292 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxMmDestructor in %a module\n", gEfiCallerBaseName));\r
738df706
SZ
293\r
294 if (mSmmConfigurationTableInstalled) {\r
e35fce8a
KQ
295 Status = gMmst->MmInstallConfigurationTable (\r
296 gMmst,\r
738df706
SZ
297 &gEfiSmmLockBoxCommunicationGuid,\r
298 NULL,\r
299 0\r
300 );\r
301 ASSERT_EFI_ERROR (Status);\r
481ffd6f 302 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib uninstall SmmLockBoxCommunication configuration table\n"));\r
738df706
SZ
303 }\r
304\r
6bd4af30
SZ
305 if (mSmmLockBoxRegistrationSmmReadyToLock != NULL) {\r
306 //\r
307 // Unregister SmmReadyToLock notification.\r
308 //\r
e35fce8a
KQ
309 Status = gMmst->MmRegisterProtocolNotify (\r
310 &gEfiMmReadyToLockProtocolGuid,\r
6bd4af30
SZ
311 NULL,\r
312 &mSmmLockBoxRegistrationSmmReadyToLock\r
313 );\r
314 ASSERT_EFI_ERROR (Status);\r
315 }\r
316 if (mSmmLockBoxRegistrationSmmEndOfDxe != NULL) {\r
317 //\r
318 // Unregister SmmEndOfDxe notification.\r
319 //\r
e35fce8a
KQ
320 Status = gMmst->MmRegisterProtocolNotify (\r
321 &gEfiMmEndOfDxeProtocolGuid,\r
6bd4af30
SZ
322 NULL,\r
323 &mSmmLockBoxRegistrationSmmEndOfDxe\r
324 );\r
325 ASSERT_EFI_ERROR (Status);\r
326 }\r
327 if (mSmmLockBoxRegistrationEndOfS3Resume != NULL) {\r
328 //\r
329 // Unregister EndOfS3Resume notification.\r
330 //\r
e35fce8a 331 Status = gMmst->MmRegisterProtocolNotify (\r
6bd4af30
SZ
332 &gEdkiiEndOfS3ResumeGuid,\r
333 NULL,\r
334 &mSmmLockBoxRegistrationEndOfS3Resume\r
335 );\r
336 ASSERT_EFI_ERROR (Status);\r
337 }\r
338\r
738df706
SZ
339 return EFI_SUCCESS;\r
340}\r
341\r
1c837cd5 342/**\r
343 This function return SmmLockBox queue address.\r
344\r
345 @return SmmLockBox queue address.\r
346**/\r
347LIST_ENTRY *\r
348InternalGetLockBoxQueue (\r
349 VOID\r
350 )\r
351{\r
352 SMM_LOCK_BOX_CONTEXT *SmmLockBoxContext;\r
353\r
354 SmmLockBoxContext = InternalGetSmmLockBoxContext ();\r
355 ASSERT (SmmLockBoxContext != NULL);\r
356 if (SmmLockBoxContext == NULL) {\r
357 return NULL;\r
358 }\r
359 return (LIST_ENTRY *)(UINTN)SmmLockBoxContext->LockBoxDataAddress;\r
360}\r
361\r
362/**\r
363 This function find LockBox by GUID.\r
364\r
365 @param Guid The guid to indentify the LockBox\r
366\r
367 @return LockBoxData\r
368**/\r
369SMM_LOCK_BOX_DATA *\r
370InternalFindLockBoxByGuid (\r
371 IN EFI_GUID *Guid\r
372 )\r
373{\r
374 LIST_ENTRY *Link;\r
375 SMM_LOCK_BOX_DATA *LockBox;\r
376 LIST_ENTRY *LockBoxQueue;\r
377\r
378 LockBoxQueue = InternalGetLockBoxQueue ();\r
379 ASSERT (LockBoxQueue != NULL);\r
380\r
381 for (Link = LockBoxQueue->ForwardLink;\r
382 Link != LockBoxQueue;\r
383 Link = Link->ForwardLink) {\r
384 LockBox = BASE_CR (\r
385 Link,\r
386 SMM_LOCK_BOX_DATA,\r
387 Link\r
388 );\r
389 if (CompareGuid (&LockBox->Guid, Guid)) {\r
390 return LockBox;\r
391 }\r
392 }\r
393 return NULL;\r
394}\r
395\r
396/**\r
397 This function will save confidential information to lockbox.\r
398\r
399 @param Guid the guid to identify the confidential information\r
400 @param Buffer the address of the confidential information\r
401 @param Length the length of the confidential information\r
402\r
403 @retval RETURN_SUCCESS the information is saved successfully.\r
404 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0\r
405 @retval RETURN_ALREADY_STARTED the requested GUID already exist.\r
406 @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information.\r
407 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface\r
408 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
409 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.\r
410**/\r
411RETURN_STATUS\r
412EFIAPI\r
413SaveLockBox (\r
414 IN GUID *Guid,\r
415 IN VOID *Buffer,\r
416 IN UINTN Length\r
417 )\r
418{\r
419 SMM_LOCK_BOX_DATA *LockBox;\r
420 EFI_PHYSICAL_ADDRESS SmramBuffer;\r
421 EFI_STATUS Status;\r
422 LIST_ENTRY *LockBoxQueue;\r
423\r
481ffd6f 424 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Enter\n"));\r
1c837cd5 425\r
426 //\r
427 // Basic check\r
428 //\r
429 if ((Guid == NULL) || (Buffer == NULL) || (Length == 0)) {\r
481ffd6f 430 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER));\r
1c837cd5 431 return EFI_INVALID_PARAMETER;\r
432 }\r
433\r
434 //\r
435 // Find LockBox\r
436 //\r
437 LockBox = InternalFindLockBoxByGuid (Guid);\r
438 if (LockBox != NULL) {\r
481ffd6f 439 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_ALREADY_STARTED));\r
1c837cd5 440 return EFI_ALREADY_STARTED;\r
441 }\r
442\r
443 //\r
444 // Allocate SMRAM buffer\r
445 //\r
e35fce8a 446 Status = gMmst->MmAllocatePages (\r
1c837cd5 447 AllocateAnyPages,\r
448 EfiRuntimeServicesData,\r
449 EFI_SIZE_TO_PAGES (Length),\r
450 &SmramBuffer\r
451 );\r
452 ASSERT_EFI_ERROR (Status);\r
453 if (EFI_ERROR (Status)) {\r
481ffd6f 454 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES));\r
1c837cd5 455 return EFI_OUT_OF_RESOURCES;\r
456 }\r
457\r
458 //\r
459 // Allocate LockBox\r
460 //\r
e35fce8a 461 Status = gMmst->MmAllocatePool (\r
1c837cd5 462 EfiRuntimeServicesData,\r
463 sizeof(*LockBox),\r
464 (VOID **)&LockBox\r
465 );\r
466 ASSERT_EFI_ERROR (Status);\r
467 if (EFI_ERROR (Status)) {\r
e35fce8a 468 gMmst->MmFreePages (SmramBuffer, EFI_SIZE_TO_PAGES (Length));\r
481ffd6f 469 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES));\r
1c837cd5 470 return EFI_OUT_OF_RESOURCES;\r
471 }\r
472\r
473 //\r
474 // Save data\r
475 //\r
476 CopyMem ((VOID *)(UINTN)SmramBuffer, (VOID *)(UINTN)Buffer, Length);\r
477\r
478 //\r
479 // Insert LockBox to queue\r
480 //\r
481 LockBox->Signature = SMM_LOCK_BOX_DATA_SIGNATURE;\r
482 CopyMem (&LockBox->Guid, Guid, sizeof(EFI_GUID));\r
483 LockBox->Buffer = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;\r
484 LockBox->Length = (UINT64)Length;\r
05ca95e2 485 LockBox->Attributes = 0;\r
1c837cd5 486 LockBox->SmramBuffer = SmramBuffer;\r
ef96ba3c
SZ
487\r
488 DEBUG ((\r
481ffd6f 489 DEBUG_INFO,\r
ef96ba3c
SZ
490 "LockBoxGuid - %g, SmramBuffer - 0x%lx, Length - 0x%lx\n",\r
491 &LockBox->Guid,\r
492 LockBox->SmramBuffer,\r
493 LockBox->Length\r
494 ));\r
495\r
1c837cd5 496 LockBoxQueue = InternalGetLockBoxQueue ();\r
497 ASSERT (LockBoxQueue != NULL);\r
498 InsertTailList (LockBoxQueue, &LockBox->Link);\r
499\r
500 //\r
501 // Done\r
502 //\r
481ffd6f 503 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_SUCCESS));\r
1c837cd5 504 return EFI_SUCCESS;\r
505}\r
506\r
507/**\r
508 This function will set lockbox attributes.\r
509\r
510 @param Guid the guid to identify the confidential information\r
511 @param Attributes the attributes of the lockbox\r
512\r
513 @retval RETURN_SUCCESS the information is saved successfully.\r
514 @retval RETURN_INVALID_PARAMETER attributes is invalid.\r
515 @retval RETURN_NOT_FOUND the requested GUID not found.\r
516 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface\r
517 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
518 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.\r
519**/\r
520RETURN_STATUS\r
521EFIAPI\r
522SetLockBoxAttributes (\r
523 IN GUID *Guid,\r
524 IN UINT64 Attributes\r
525 )\r
526{\r
527 SMM_LOCK_BOX_DATA *LockBox;\r
528\r
481ffd6f 529 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Enter\n"));\r
1c837cd5 530\r
531 //\r
532 // Basic check\r
533 //\r
534 if ((Guid == NULL) ||\r
6bd4af30 535 ((Attributes & ~(LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE | LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY)) != 0)) {\r
481ffd6f 536 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_INVALID_PARAMETER));\r
6bd4af30
SZ
537 return EFI_INVALID_PARAMETER;\r
538 }\r
539\r
540 if (((Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) &&\r
541 ((Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0)) {\r
481ffd6f
HW
542 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_INVALID_PARAMETER));\r
543 DEBUG ((DEBUG_INFO, " LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE and LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\n\n"));\r
544 DEBUG ((DEBUG_INFO, " can not be set together\n"));\r
1c837cd5 545 return EFI_INVALID_PARAMETER;\r
546 }\r
547\r
548 //\r
549 // Find LockBox\r
550 //\r
551 LockBox = InternalFindLockBoxByGuid (Guid);\r
552 if (LockBox == NULL) {\r
481ffd6f 553 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_NOT_FOUND));\r
1c837cd5 554 return EFI_NOT_FOUND;\r
555 }\r
556\r
6bd4af30
SZ
557 if ((((Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) &&\r
558 ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0)) ||\r
559 (((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) &&\r
560 ((Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0))) {\r
481ffd6f
HW
561 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes 0x%lx 0x%lx - Exit (%r)\n", LockBox->Attributes, Attributes, EFI_INVALID_PARAMETER));\r
562 DEBUG ((DEBUG_INFO, " LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE and LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\n\n"));\r
563 DEBUG ((DEBUG_INFO, " can not be set together\n"));\r
6bd4af30
SZ
564 return EFI_INVALID_PARAMETER;\r
565 }\r
566\r
1c837cd5 567 //\r
568 // Update data\r
569 //\r
570 LockBox->Attributes = Attributes;\r
571\r
572 //\r
573 // Done\r
574 //\r
481ffd6f 575 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_SUCCESS));\r
1c837cd5 576 return EFI_SUCCESS;\r
577}\r
578\r
579/**\r
580 This function will update confidential information to lockbox.\r
581\r
582 @param Guid the guid to identify the original confidential information\r
583 @param Offset the offset of the original confidential information\r
584 @param Buffer the address of the updated confidential information\r
585 @param Length the length of the updated confidential information\r
586\r
587 @retval RETURN_SUCCESS the information is saved successfully.\r
588 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0.\r
589 @retval RETURN_NOT_FOUND the requested GUID not found.\r
99383667
HW
590 @retval RETURN_BUFFER_TOO_SMALL for lockbox without attribute LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY,\r
591 the original buffer to too small to hold new information.\r
592 @retval RETURN_OUT_OF_RESOURCES for lockbox with attribute LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY,\r
593 no enough resource to save the information.\r
1c837cd5 594 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface\r
595 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
596 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.\r
597**/\r
598RETURN_STATUS\r
599EFIAPI\r
600UpdateLockBox (\r
601 IN GUID *Guid,\r
602 IN UINTN Offset,\r
603 IN VOID *Buffer,\r
604 IN UINTN Length\r
605 )\r
606{\r
607 SMM_LOCK_BOX_DATA *LockBox;\r
99383667
HW
608 EFI_PHYSICAL_ADDRESS SmramBuffer;\r
609 EFI_STATUS Status;\r
1c837cd5 610\r
481ffd6f 611 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Enter\n"));\r
1c837cd5 612\r
613 //\r
614 // Basic check\r
615 //\r
99383667
HW
616 if ((Guid == NULL) || (Buffer == NULL) || (Length == 0) ||\r
617 (Length > MAX_UINTN - Offset)) {\r
481ffd6f 618 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER));\r
1c837cd5 619 return EFI_INVALID_PARAMETER;\r
620 }\r
621\r
622 //\r
623 // Find LockBox\r
624 //\r
625 LockBox = InternalFindLockBoxByGuid (Guid);\r
626 if (LockBox == NULL) {\r
481ffd6f 627 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_NOT_FOUND));\r
1c837cd5 628 return EFI_NOT_FOUND;\r
629 }\r
630\r
631 //\r
632 // Update data\r
633 //\r
634 if (LockBox->Length < Offset + Length) {\r
99383667
HW
635 if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0) {\r
636 //\r
637 // If 'LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY' attribute is set, enlarge the\r
638 // LockBox.\r
639 //\r
640 DEBUG ((\r
641 DEBUG_INFO,\r
642 "SmmLockBoxSmmLib UpdateLockBox - Origin LockBox too small, enlarge.\n"\r
643 ));\r
644\r
645 if (EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES ((UINTN)LockBox->Length)) < Offset + Length) {\r
646 //\r
647 // In SaveLockBox(), the SMRAM buffer allocated for LockBox is of page\r
648 // granularity. Here, if the required size is larger than the origin size\r
649 // of the pages, allocate new buffer from SMRAM to enlarge the LockBox.\r
650 //\r
651 DEBUG ((\r
652 DEBUG_INFO,\r
653 "SmmLockBoxSmmLib UpdateLockBox - Allocate new buffer to enlarge.\n"\r
654 ));\r
e35fce8a 655 Status = gMmst->MmAllocatePages (\r
99383667
HW
656 AllocateAnyPages,\r
657 EfiRuntimeServicesData,\r
658 EFI_SIZE_TO_PAGES (Offset + Length),\r
659 &SmramBuffer\r
660 );\r
661 if (EFI_ERROR (Status)) {\r
662 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES));\r
663 return EFI_OUT_OF_RESOURCES;\r
664 }\r
665\r
666 //\r
667 // Copy origin data to the new SMRAM buffer and wipe the content in the\r
668 // origin SMRAM buffer.\r
669 //\r
670 CopyMem ((VOID *)(UINTN)SmramBuffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);\r
671 ZeroMem ((VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);\r
e35fce8a 672 gMmst->MmFreePages (LockBox->SmramBuffer, EFI_SIZE_TO_PAGES ((UINTN)LockBox->Length));\r
99383667
HW
673\r
674 LockBox->SmramBuffer = SmramBuffer;\r
675 }\r
676\r
677 //\r
678 // Handle uninitialized content in the LockBox.\r
679 //\r
680 if (Offset > LockBox->Length) {\r
681 ZeroMem (\r
682 (VOID *)((UINTN)LockBox->SmramBuffer + (UINTN)LockBox->Length),\r
683 Offset - (UINTN)LockBox->Length\r
684 );\r
685 }\r
686 LockBox->Length = Offset + Length;\r
687 } else {\r
688 //\r
689 // If 'LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY' attribute is NOT set, return\r
690 // EFI_BUFFER_TOO_SMALL directly.\r
691 //\r
692 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL));\r
693 return EFI_BUFFER_TOO_SMALL;\r
694 }\r
1c837cd5 695 }\r
579b5ef2 696 ASSERT ((UINTN)LockBox->SmramBuffer <= (MAX_ADDRESS - Offset));\r
1c837cd5 697 CopyMem ((VOID *)((UINTN)LockBox->SmramBuffer + Offset), Buffer, Length);\r
698\r
699 //\r
700 // Done\r
701 //\r
481ffd6f 702 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_SUCCESS));\r
1c837cd5 703 return EFI_SUCCESS;\r
704}\r
705\r
706/**\r
707 This function will restore confidential information from lockbox.\r
708\r
709 @param Guid the guid to identify the confidential information\r
710 @param Buffer the address of the restored confidential information\r
711 NULL means restored to original address, Length MUST be NULL at same time.\r
712 @param Length the length of the restored confidential information\r
713\r
714 @retval RETURN_SUCCESS the information is restored successfully.\r
715 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and Length is NULL.\r
d1102dba 716 @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox has no\r
1c837cd5 717 LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute.\r
718 @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the confidential information.\r
719 @retval RETURN_NOT_FOUND the requested GUID not found.\r
720 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
721 @retval RETURN_ACCESS_DENIED not allow to restore to the address\r
722 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.\r
723**/\r
724RETURN_STATUS\r
725EFIAPI\r
726RestoreLockBox (\r
727 IN GUID *Guid,\r
728 IN VOID *Buffer, OPTIONAL\r
729 IN OUT UINTN *Length OPTIONAL\r
730 )\r
731{\r
732 SMM_LOCK_BOX_DATA *LockBox;\r
733 VOID *RestoreBuffer;\r
734\r
481ffd6f 735 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Enter\n"));\r
1c837cd5 736\r
737 //\r
738 // Restore this, Buffer and Length MUST be both NULL or both non-NULL\r
739 //\r
740 if ((Guid == NULL) ||\r
741 ((Buffer == NULL) && (Length != NULL)) ||\r
742 ((Buffer != NULL) && (Length == NULL))) {\r
481ffd6f 743 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER));\r
1c837cd5 744 return EFI_INVALID_PARAMETER;\r
745 }\r
746\r
747 //\r
748 // Find LockBox\r
749 //\r
750 LockBox = InternalFindLockBoxByGuid (Guid);\r
751 if (LockBox == NULL) {\r
752 //\r
753 // Not found\r
754 //\r
481ffd6f 755 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_NOT_FOUND));\r
1c837cd5 756 return EFI_NOT_FOUND;\r
757 }\r
758\r
6bd4af30
SZ
759 if (((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0) &&\r
760 mSmmLockBoxSmmReadyToLock &&\r
761 !mSmmLockBoxDuringS3Resume) {\r
762 //\r
763 // With LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY,\r
764 // this LockBox can be restored in S3 resume only.\r
765 //\r
766 return EFI_ACCESS_DENIED;\r
767 }\r
768\r
1c837cd5 769 //\r
770 // Set RestoreBuffer\r
771 //\r
772 if (Buffer != NULL) {\r
773 //\r
774 // restore to new buffer\r
775 //\r
776 RestoreBuffer = Buffer;\r
777 } else {\r
778 //\r
779 // restore to original buffer\r
780 //\r
781 if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) == 0) {\r
481ffd6f 782 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_WRITE_PROTECTED));\r
1c837cd5 783 return EFI_WRITE_PROTECTED;\r
784 }\r
785 RestoreBuffer = (VOID *)(UINTN)LockBox->Buffer;\r
786 }\r
787\r
788 //\r
789 // Set RestoreLength\r
790 //\r
791 if (Length != NULL) {\r
792 if (*Length < (UINTN)LockBox->Length) {\r
793 //\r
794 // Input buffer is too small to hold all data.\r
795 //\r
796 *Length = (UINTN)LockBox->Length;\r
481ffd6f 797 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL));\r
1c837cd5 798 return EFI_BUFFER_TOO_SMALL;\r
799 }\r
800 *Length = (UINTN)LockBox->Length;\r
801 }\r
802\r
803 //\r
804 // Restore data\r
805 //\r
806 CopyMem (RestoreBuffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);\r
807\r
808 //\r
809 // Done\r
810 //\r
481ffd6f 811 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_SUCCESS));\r
1c837cd5 812 return EFI_SUCCESS;\r
813}\r
814\r
815/**\r
816 This function will restore confidential information from all lockbox which have RestoreInPlace attribute.\r
817\r
818 @retval RETURN_SUCCESS the information is restored successfully.\r
819 @retval RETURN_NOT_STARTED it is too early to invoke this interface\r
820 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.\r
821**/\r
822RETURN_STATUS\r
823EFIAPI\r
824RestoreAllLockBoxInPlace (\r
825 VOID\r
826 )\r
827{\r
828 SMM_LOCK_BOX_DATA *LockBox;\r
829 LIST_ENTRY *Link;\r
830 LIST_ENTRY *LockBoxQueue;\r
831\r
481ffd6f 832 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Enter\n"));\r
1c837cd5 833\r
834 LockBoxQueue = InternalGetLockBoxQueue ();\r
835 ASSERT (LockBoxQueue != NULL);\r
836\r
837 //\r
838 // Restore all, Buffer and Length MUST be NULL\r
839 //\r
840 for (Link = LockBoxQueue->ForwardLink;\r
841 Link != LockBoxQueue;\r
842 Link = Link->ForwardLink) {\r
843 LockBox = BASE_CR (\r
844 Link,\r
845 SMM_LOCK_BOX_DATA,\r
846 Link\r
847 );\r
848 if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) {\r
849 //\r
850 // Restore data\r
851 //\r
852 CopyMem ((VOID *)(UINTN)LockBox->Buffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);\r
853 }\r
854 }\r
855 //\r
856 // Done\r
857 //\r
481ffd6f 858 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Exit (%r)\n", EFI_SUCCESS));\r
1c837cd5 859 return EFI_SUCCESS;\r
860}\r
861\r