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