]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.c
MdeModulePkg/SmmLockBoxLib: Support LockBox enlarge in UpdateLockBox()
[mirror_edk2.git] / MdeModulePkg / Library / SmmLockBoxLib / SmmLockBoxSmmLib.c
1 /** @file
2
3 Copyright (c) 2010 - 2019, 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 ((DEBUG_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 ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxContext - already installed\n"));
259 DEBUG ((DEBUG_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 ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxContext - %x\n", (UINTN)&mSmmLockBoxContext));
283 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib LockBoxDataAddress - %x\n", (UINTN)&mLockBoxQueue));
284 DEBUG ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Enter\n"));
442
443 //
444 // Basic check
445 //
446 if ((Guid == NULL) || (Buffer == NULL) || (Length == 0)) {
447 DEBUG ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 DEBUG_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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes - Exit (%r)\n", EFI_INVALID_PARAMETER));
560 DEBUG ((DEBUG_INFO, " LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE and LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\n\n"));
561 DEBUG ((DEBUG_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 ((DEBUG_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 ((DEBUG_INFO, "SmmLockBoxSmmLib SetLockBoxAttributes 0x%lx 0x%lx - Exit (%r)\n", LockBox->Attributes, Attributes, EFI_INVALID_PARAMETER));
579 DEBUG ((DEBUG_INFO, " LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE and LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\n\n"));
580 DEBUG ((DEBUG_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 ((DEBUG_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 for lockbox without attribute LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY,
608 the original buffer to too small to hold new information.
609 @retval RETURN_OUT_OF_RESOURCES for lockbox with attribute LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY,
610 no enough resource to save the information.
611 @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
612 @retval RETURN_NOT_STARTED it is too early to invoke this interface
613 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
614 **/
615 RETURN_STATUS
616 EFIAPI
617 UpdateLockBox (
618 IN GUID *Guid,
619 IN UINTN Offset,
620 IN VOID *Buffer,
621 IN UINTN Length
622 )
623 {
624 SMM_LOCK_BOX_DATA *LockBox;
625 EFI_PHYSICAL_ADDRESS SmramBuffer;
626 EFI_STATUS Status;
627
628 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Enter\n"));
629
630 //
631 // Basic check
632 //
633 if ((Guid == NULL) || (Buffer == NULL) || (Length == 0) ||
634 (Length > MAX_UINTN - Offset)) {
635 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER));
636 return EFI_INVALID_PARAMETER;
637 }
638
639 //
640 // Find LockBox
641 //
642 LockBox = InternalFindLockBoxByGuid (Guid);
643 if (LockBox == NULL) {
644 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_NOT_FOUND));
645 return EFI_NOT_FOUND;
646 }
647
648 //
649 // Update data
650 //
651 if (LockBox->Length < Offset + Length) {
652 if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0) {
653 //
654 // If 'LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY' attribute is set, enlarge the
655 // LockBox.
656 //
657 DEBUG ((
658 DEBUG_INFO,
659 "SmmLockBoxSmmLib UpdateLockBox - Origin LockBox too small, enlarge.\n"
660 ));
661
662 if (EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES ((UINTN)LockBox->Length)) < Offset + Length) {
663 //
664 // In SaveLockBox(), the SMRAM buffer allocated for LockBox is of page
665 // granularity. Here, if the required size is larger than the origin size
666 // of the pages, allocate new buffer from SMRAM to enlarge the LockBox.
667 //
668 DEBUG ((
669 DEBUG_INFO,
670 "SmmLockBoxSmmLib UpdateLockBox - Allocate new buffer to enlarge.\n"
671 ));
672 Status = gSmst->SmmAllocatePages (
673 AllocateAnyPages,
674 EfiRuntimeServicesData,
675 EFI_SIZE_TO_PAGES (Offset + Length),
676 &SmramBuffer
677 );
678 if (EFI_ERROR (Status)) {
679 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES));
680 return EFI_OUT_OF_RESOURCES;
681 }
682
683 //
684 // Copy origin data to the new SMRAM buffer and wipe the content in the
685 // origin SMRAM buffer.
686 //
687 CopyMem ((VOID *)(UINTN)SmramBuffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);
688 ZeroMem ((VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);
689 gSmst->SmmFreePages (LockBox->SmramBuffer, EFI_SIZE_TO_PAGES ((UINTN)LockBox->Length));
690
691 LockBox->SmramBuffer = SmramBuffer;
692 }
693
694 //
695 // Handle uninitialized content in the LockBox.
696 //
697 if (Offset > LockBox->Length) {
698 ZeroMem (
699 (VOID *)((UINTN)LockBox->SmramBuffer + (UINTN)LockBox->Length),
700 Offset - (UINTN)LockBox->Length
701 );
702 }
703 LockBox->Length = Offset + Length;
704 } else {
705 //
706 // If 'LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY' attribute is NOT set, return
707 // EFI_BUFFER_TOO_SMALL directly.
708 //
709 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL));
710 return EFI_BUFFER_TOO_SMALL;
711 }
712 }
713 ASSERT ((UINTN)LockBox->SmramBuffer <= (MAX_ADDRESS - Offset));
714 CopyMem ((VOID *)((UINTN)LockBox->SmramBuffer + Offset), Buffer, Length);
715
716 //
717 // Done
718 //
719 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib UpdateLockBox - Exit (%r)\n", EFI_SUCCESS));
720 return EFI_SUCCESS;
721 }
722
723 /**
724 This function will restore confidential information from lockbox.
725
726 @param Guid the guid to identify the confidential information
727 @param Buffer the address of the restored confidential information
728 NULL means restored to original address, Length MUST be NULL at same time.
729 @param Length the length of the restored confidential information
730
731 @retval RETURN_SUCCESS the information is restored successfully.
732 @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and Length is NULL.
733 @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox has no
734 LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute.
735 @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the confidential information.
736 @retval RETURN_NOT_FOUND the requested GUID not found.
737 @retval RETURN_NOT_STARTED it is too early to invoke this interface
738 @retval RETURN_ACCESS_DENIED not allow to restore to the address
739 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
740 **/
741 RETURN_STATUS
742 EFIAPI
743 RestoreLockBox (
744 IN GUID *Guid,
745 IN VOID *Buffer, OPTIONAL
746 IN OUT UINTN *Length OPTIONAL
747 )
748 {
749 SMM_LOCK_BOX_DATA *LockBox;
750 VOID *RestoreBuffer;
751
752 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Enter\n"));
753
754 //
755 // Restore this, Buffer and Length MUST be both NULL or both non-NULL
756 //
757 if ((Guid == NULL) ||
758 ((Buffer == NULL) && (Length != NULL)) ||
759 ((Buffer != NULL) && (Length == NULL))) {
760 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER));
761 return EFI_INVALID_PARAMETER;
762 }
763
764 //
765 // Find LockBox
766 //
767 LockBox = InternalFindLockBoxByGuid (Guid);
768 if (LockBox == NULL) {
769 //
770 // Not found
771 //
772 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_NOT_FOUND));
773 return EFI_NOT_FOUND;
774 }
775
776 if (((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY) != 0) &&
777 mSmmLockBoxSmmReadyToLock &&
778 !mSmmLockBoxDuringS3Resume) {
779 //
780 // With LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY,
781 // this LockBox can be restored in S3 resume only.
782 //
783 return EFI_ACCESS_DENIED;
784 }
785
786 //
787 // Set RestoreBuffer
788 //
789 if (Buffer != NULL) {
790 //
791 // restore to new buffer
792 //
793 RestoreBuffer = Buffer;
794 } else {
795 //
796 // restore to original buffer
797 //
798 if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) == 0) {
799 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_WRITE_PROTECTED));
800 return EFI_WRITE_PROTECTED;
801 }
802 RestoreBuffer = (VOID *)(UINTN)LockBox->Buffer;
803 }
804
805 //
806 // Set RestoreLength
807 //
808 if (Length != NULL) {
809 if (*Length < (UINTN)LockBox->Length) {
810 //
811 // Input buffer is too small to hold all data.
812 //
813 *Length = (UINTN)LockBox->Length;
814 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_BUFFER_TOO_SMALL));
815 return EFI_BUFFER_TOO_SMALL;
816 }
817 *Length = (UINTN)LockBox->Length;
818 }
819
820 //
821 // Restore data
822 //
823 CopyMem (RestoreBuffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);
824
825 //
826 // Done
827 //
828 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreLockBox - Exit (%r)\n", EFI_SUCCESS));
829 return EFI_SUCCESS;
830 }
831
832 /**
833 This function will restore confidential information from all lockbox which have RestoreInPlace attribute.
834
835 @retval RETURN_SUCCESS the information is restored successfully.
836 @retval RETURN_NOT_STARTED it is too early to invoke this interface
837 @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
838 **/
839 RETURN_STATUS
840 EFIAPI
841 RestoreAllLockBoxInPlace (
842 VOID
843 )
844 {
845 SMM_LOCK_BOX_DATA *LockBox;
846 LIST_ENTRY *Link;
847 LIST_ENTRY *LockBoxQueue;
848
849 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Enter\n"));
850
851 LockBoxQueue = InternalGetLockBoxQueue ();
852 ASSERT (LockBoxQueue != NULL);
853
854 //
855 // Restore all, Buffer and Length MUST be NULL
856 //
857 for (Link = LockBoxQueue->ForwardLink;
858 Link != LockBoxQueue;
859 Link = Link->ForwardLink) {
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 // Done
874 //
875 DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib RestoreAllLockBoxInPlace - Exit (%r)\n", EFI_SUCCESS));
876 return EFI_SUCCESS;
877 }
878