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