]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - 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
1/** @file\r
2\r
3Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>\r
4\r
5SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9#include <PiMm.h>\r
10#include <Library/MmServicesTableLib.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
16#include <Guid/EndOfS3Resume.h>\r
17#include <Protocol/MmReadyToLock.h>\r
18#include <Protocol/MmEndOfDxe.h>\r
19#include <Protocol/SmmSxDispatch2.h>\r
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
30BOOLEAN mSmmConfigurationTableInstalled = FALSE;\r
31VOID *mSmmLockBoxRegistrationSmmEndOfDxe = NULL;\r
32VOID *mSmmLockBoxRegistrationSmmReadyToLock = NULL;\r
33VOID *mSmmLockBoxRegistrationEndOfS3Resume = NULL;\r
34BOOLEAN mSmmLockBoxSmmReadyToLock = FALSE;\r
35BOOLEAN mSmmLockBoxDuringS3Resume = FALSE;\r
36\r
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 < gMmst->NumberOfTableEntries; Index++) {\r
53 if (CompareGuid (&gMmst->MmConfigurationTable[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 *)gMmst->MmConfigurationTable[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
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 = gMmst->MmLocateProtocol (\r
146 &gEfiMmSxDispatchProtocolGuid,\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
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 @retval EFI_SUCEESS\r
195 @return Others Some error occurs.\r
196**/\r
197EFI_STATUS\r
198SmmLockBoxMmConstructor (\r
199 VOID\r
200 )\r
201{\r
202 EFI_STATUS Status;\r
203 SMM_LOCK_BOX_CONTEXT *SmmLockBoxContext;\r
204\r
205 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxMmConstructor - Enter\n"));\r
206\r
207 //\r
208 // Register SmmReadyToLock notification.\r
209 //\r
210 Status = gMmst->MmRegisterProtocolNotify (\r
211 &gEfiMmReadyToLockProtocolGuid,\r
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
220 Status = gMmst->MmRegisterProtocolNotify (\r
221 &gEfiMmEndOfDxeProtocolGuid,\r
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
230 Status = gMmst->MmRegisterProtocolNotify (\r
231 &gEdkiiEndOfS3ResumeGuid,\r
232 SmmLockBoxEndOfS3ResumeNotify,\r
233 &mSmmLockBoxRegistrationEndOfS3Resume\r
234 );\r
235 ASSERT_EFI_ERROR (Status);\r
236\r
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
246 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxContext - already installed\n"));\r
247 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxMmConstructor - Exit\n"));\r
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
261 Status = gMmst->MmInstallConfigurationTable (\r
262 gMmst,\r
263 &gEfiSmmLockBoxCommunicationGuid,\r
264 &mSmmLockBoxContext,\r
265 sizeof(mSmmLockBoxContext)\r
266 );\r
267 ASSERT_EFI_ERROR (Status);\r
268 mSmmConfigurationTableInstalled = TRUE;\r
269\r
270 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxContext - %x\n", (UINTN)&mSmmLockBoxContext));\r
271 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib LockBoxDataAddress - %x\n", (UINTN)&mLockBoxQueue));\r
272 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxMmConstructor - Exit\n"));\r
273\r
274 return Status;\r
275}\r
276\r
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
282 @retval EFI_SUCEESS The destructor always returns EFI_SUCCESS.\r
283\r
284**/\r
285EFI_STATUS\r
286SmmLockBoxMmDestructor (\r
287 VOID\r
288 )\r
289{\r
290 EFI_STATUS Status;\r
291\r
292 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxMmDestructor in %a module\n", gEfiCallerBaseName));\r
293\r
294 if (mSmmConfigurationTableInstalled) {\r
295 Status = gMmst->MmInstallConfigurationTable (\r
296 gMmst,\r
297 &gEfiSmmLockBoxCommunicationGuid,\r
298 NULL,\r
299 0\r
300 );\r
301 ASSERT_EFI_ERROR (Status);\r
302 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib uninstall SmmLockBoxCommunication configuration table\n"));\r
303 }\r
304\r
305 if (mSmmLockBoxRegistrationSmmReadyToLock != NULL) {\r
306 //\r
307 // Unregister SmmReadyToLock notification.\r
308 //\r
309 Status = gMmst->MmRegisterProtocolNotify (\r
310 &gEfiMmReadyToLockProtocolGuid,\r
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
320 Status = gMmst->MmRegisterProtocolNotify (\r
321 &gEfiMmEndOfDxeProtocolGuid,\r
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
331 Status = gMmst->MmRegisterProtocolNotify (\r
332 &gEdkiiEndOfS3ResumeGuid,\r
333 NULL,\r
334 &mSmmLockBoxRegistrationEndOfS3Resume\r
335 );\r
336 ASSERT_EFI_ERROR (Status);\r
337 }\r
338\r
339 return EFI_SUCCESS;\r
340}\r
341\r
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
424 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Enter\n"));\r
425\r
426 //\r
427 // Basic check\r
428 //\r
429 if ((Guid == NULL) || (Buffer == NULL) || (Length == 0)) {\r
430 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER));\r
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
439 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_ALREADY_STARTED));\r
440 return EFI_ALREADY_STARTED;\r
441 }\r
442\r
443 //\r
444 // Allocate SMRAM buffer\r
445 //\r
446 Status = gMmst->MmAllocatePages (\r
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
454 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES));\r
455 return EFI_OUT_OF_RESOURCES;\r
456 }\r
457\r
458 //\r
459 // Allocate LockBox\r
460 //\r
461 Status = gMmst->MmAllocatePool (\r
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
468 gMmst->MmFreePages (SmramBuffer, EFI_SIZE_TO_PAGES (Length));\r
469 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES));\r
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
485 LockBox->Attributes = 0;\r
486 LockBox->SmramBuffer = SmramBuffer;\r
487\r
488 DEBUG ((\r
489 DEBUG_INFO,\r
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
496 LockBoxQueue = InternalGetLockBoxQueue ();\r
497 ASSERT (LockBoxQueue != NULL);\r
498 InsertTailList (LockBoxQueue, &LockBox->Link);\r
499\r
500 //\r
501 // Done\r
502 //\r
503 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_SUCCESS));\r
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
529 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Enter\n"));\r
530\r
531 //\r
532 // Basic check\r
533 //\r
534 if ((Guid == NULL) ||\r
535 ((Attributes & ~(LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE | LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY)) != 0)) {\r
536 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_INVALID_PARAMETER));\r
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
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
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
553 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_NOT_FOUND));\r
554 return EFI_NOT_FOUND;\r
555 }\r
556\r
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
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
564 return EFI_INVALID_PARAMETER;\r
565 }\r
566\r
567 //\r
568 // Update data\r
569 //\r
570 LockBox->Attributes = Attributes;\r
571\r
572 //\r
573 // Done\r
574 //\r
575 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_SUCCESS));\r
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
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
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
608 EFI_PHYSICAL_ADDRESS SmramBuffer;\r
609 EFI_STATUS Status;\r
610\r
611 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Enter\n"));\r
612\r
613 //\r
614 // Basic check\r
615 //\r
616 if ((Guid == NULL) || (Buffer == NULL) || (Length == 0) ||\r
617 (Length > MAX_UINTN - Offset)) {\r
618 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER));\r
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
627 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_NOT_FOUND));\r
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
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
655 Status = gMmst->MmAllocatePages (\r
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
672 gMmst->MmFreePages (LockBox->SmramBuffer, EFI_SIZE_TO_PAGES ((UINTN)LockBox->Length));\r
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
695 }\r
696 ASSERT ((UINTN)LockBox->SmramBuffer <= (MAX_ADDRESS - Offset));\r
697 CopyMem ((VOID *)((UINTN)LockBox->SmramBuffer + Offset), Buffer, Length);\r
698\r
699 //\r
700 // Done\r
701 //\r
702 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_SUCCESS));\r
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
716 @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox has no\r
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
735 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Enter\n"));\r
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
743 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER));\r
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
755 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_NOT_FOUND));\r
756 return EFI_NOT_FOUND;\r
757 }\r
758\r
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
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
782 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_WRITE_PROTECTED));\r
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
797 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL));\r
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
811 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_SUCCESS));\r
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
832 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Enter\n"));\r
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
858 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Exit (%r)\n", EFI_SUCCESS));\r
859 return EFI_SUCCESS;\r
860}\r
861\r