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