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