1 /** @file
2 
3 Copyright (c) 2010 - 2011, 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 <PiPei.h>
17 #include <PiDxe.h>
18 #include <PiSmm.h>
19 #include <Library/PeiServicesTablePointerLib.h>
20 #include <Library/PeiServicesLib.h>
21 #include <Library/BaseLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/LockBoxLib.h>
24 #include <Library/HobLib.h>
25 #include <Library/DebugLib.h>
26 #include <Library/PcdLib.h>
27 #include <Protocol/SmmCommunication.h>
28 #include <Ppi/SmmCommunication.h>
29 #include <Ppi/SmmAccess.h>
30 #include <Guid/AcpiS3Context.h>
31 #include <Guid/SmmLockBox.h>
32 
33 #include "SmmLockBoxLibPrivate.h"
34 
35 #if defined (MDE_CPU_IA32)
36 typedef struct _LIST_ENTRY64 LIST_ENTRY64;
37 struct _LIST_ENTRY64 {
38   LIST_ENTRY64  *ForwardLink;
39   UINT32        Reserved1;
40   LIST_ENTRY64  *BackLink;
41   UINT32        Reserved2;
42 };
43 
44 typedef struct {
45   EFI_TABLE_HEADER    Hdr;
46   UINT64              SmmFirmwareVendor;
47   UINT64              SmmFirmwareRevision;
48   UINT64              SmmInstallConfigurationTable;
49   UINT64              SmmIoMemRead;
50   UINT64              SmmIoMemWrite;
51   UINT64              SmmIoIoRead;
52   UINT64              SmmIoIoWrite;
53   UINT64              SmmAllocatePool;
54   UINT64              SmmFreePool;
55   UINT64              SmmAllocatePages;
56   UINT64              SmmFreePages;
57   UINT64              SmmStartupThisAp;
58   UINT64              CurrentlyExecutingCpu;
59   UINT64              NumberOfCpus;
60   UINT64              CpuSaveStateSize;
61   UINT64              CpuSaveState;
62   UINT64              NumberOfTableEntries;
63   UINT64              SmmConfigurationTable;
64 } EFI_SMM_SYSTEM_TABLE2_64;
65 
66 typedef struct {
67   EFI_GUID                          VendorGuid;
68   UINT64                            VendorTable;
69 } EFI_CONFIGURATION_TABLE64;
70 #endif
71 
72 #if defined (MDE_CPU_X64)
73 typedef LIST_ENTRY LIST_ENTRY64;
74 typedef EFI_SMM_SYSTEM_TABLE2 EFI_SMM_SYSTEM_TABLE2_64;
75 typedef EFI_CONFIGURATION_TABLE EFI_CONFIGURATION_TABLE64;
76 #endif
77 
78 /**
79   This function return first node of LinkList queue.
80 
81   @param LockBoxQueue  LinkList queue
82 
83   @return first node of LinkList queue
84 **/
85 LIST_ENTRY *
InternalInitLinkDxe(IN LIST_ENTRY * LinkList)86 InternalInitLinkDxe (
87   IN LIST_ENTRY *LinkList
88   )
89 {
90   if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) {
91     //
92     // 32 PEI + 64 DXE
93     //
94     return (LIST_ENTRY *)(((LIST_ENTRY64 *)LinkList)->ForwardLink);
95   } else {
96     return LinkList->ForwardLink;
97   }
98 }
99 
100 /**
101   This function return next node of LinkList.
102 
103   @param Link  LinkList node
104 
105   @return next node of LinkList
106 **/
107 LIST_ENTRY *
InternalNextLinkDxe(IN LIST_ENTRY * Link)108 InternalNextLinkDxe (
109   IN LIST_ENTRY *Link
110   )
111 {
112   if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) {
113     //
114     // 32 PEI + 64 DXE
115     //
116     return (LIST_ENTRY *)(((LIST_ENTRY64 *)Link)->ForwardLink);
117   } else {
118     return Link->ForwardLink;
119   }
120 }
121 
122 /**
123   This function find LockBox by GUID from SMRAM.
124 
125   @param LockBoxQueue The LockBox queue in SMRAM
126   @param Guid         The guid to indentify the LockBox
127 
128   @return LockBoxData
129 **/
130 SMM_LOCK_BOX_DATA *
InternalFindLockBoxByGuidFromSmram(IN LIST_ENTRY * LockBoxQueue,IN EFI_GUID * Guid)131 InternalFindLockBoxByGuidFromSmram (
132   IN LIST_ENTRY *LockBoxQueue,
133   IN EFI_GUID   *Guid
134   )
135 {
136   LIST_ENTRY                    *Link;
137   SMM_LOCK_BOX_DATA             *LockBox;
138 
139   for (Link = InternalInitLinkDxe (LockBoxQueue);
140        Link != LockBoxQueue;
141        Link = InternalNextLinkDxe (Link)) {
142     LockBox = BASE_CR (
143                 Link,
144                 SMM_LOCK_BOX_DATA,
145                 Link
146                 );
147     if (CompareGuid (&LockBox->Guid, Guid)) {
148       return LockBox;
149     }
150   }
151   return NULL;
152 }
153 
154 /**
155   Get VendorTable by VendorGuid in Smst.
156 
157   @param Signature  Signature of SMM_S3_RESUME_STATE
158   @param Smst       SMM system table
159   @param VendorGuid vendor guid
160 
161   @return vendor table.
162 **/
163 VOID *
InternalSmstGetVendorTableByGuid(IN UINT64 Signature,IN EFI_SMM_SYSTEM_TABLE2 * Smst,IN EFI_GUID * VendorGuid)164 InternalSmstGetVendorTableByGuid (
165   IN UINT64                                        Signature,
166   IN EFI_SMM_SYSTEM_TABLE2                         *Smst,
167   IN EFI_GUID                                      *VendorGuid
168   )
169 {
170   EFI_CONFIGURATION_TABLE                       *SmmConfigurationTable;
171   UINTN                                         NumberOfTableEntries;
172   UINTN                                         Index;
173   EFI_SMM_SYSTEM_TABLE2_64                      *Smst64;
174   EFI_CONFIGURATION_TABLE64                     *SmmConfigurationTable64;
175 
176   if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode))) {
177     //
178     // 32 PEI + 64 DXE
179     //
180     Smst64 = (EFI_SMM_SYSTEM_TABLE2_64 *)Smst;
181     SmmConfigurationTable64 = (EFI_CONFIGURATION_TABLE64 *)(UINTN)Smst64->SmmConfigurationTable;
182     NumberOfTableEntries = (UINTN)Smst64->NumberOfTableEntries;
183     for (Index = 0; Index < NumberOfTableEntries; Index++) {
184       if (CompareGuid (&SmmConfigurationTable64[Index].VendorGuid, VendorGuid)) {
185         return (VOID *)(UINTN)SmmConfigurationTable64[Index].VendorTable;
186       }
187     }
188     return NULL;
189   } else {
190     SmmConfigurationTable = Smst->SmmConfigurationTable;
191     NumberOfTableEntries = Smst->NumberOfTableEntries;
192     for (Index = 0; Index < NumberOfTableEntries; Index++) {
193       if (CompareGuid (&SmmConfigurationTable[Index].VendorGuid, VendorGuid)) {
194         return (VOID *)SmmConfigurationTable[Index].VendorTable;
195       }
196     }
197     return NULL;
198   }
199 }
200 
201 /**
202   Get SMM LockBox context.
203 
204   @return SMM LockBox context.
205 **/
206 SMM_LOCK_BOX_CONTEXT *
InternalGetSmmLockBoxContext(VOID)207 InternalGetSmmLockBoxContext (
208   VOID
209   )
210 {
211   EFI_SMRAM_DESCRIPTOR                          *SmramDescriptor;
212   SMM_S3_RESUME_STATE                           *SmmS3ResumeState;
213   VOID                                          *GuidHob;
214   SMM_LOCK_BOX_CONTEXT                          *SmmLockBoxContext;
215 
216   GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);
217   ASSERT (GuidHob != NULL);
218   SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);
219   SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;
220 
221   SmmLockBoxContext = (SMM_LOCK_BOX_CONTEXT *)InternalSmstGetVendorTableByGuid (
222                                                 SmmS3ResumeState->Signature,
223                                                 (EFI_SMM_SYSTEM_TABLE2 *)(UINTN)SmmS3ResumeState->Smst,
224                                                 &gEfiSmmLockBoxCommunicationGuid
225                                                 );
226   ASSERT (SmmLockBoxContext != NULL);
227 
228   return SmmLockBoxContext;
229 }
230 
231 /**
232   This function will restore confidential information from lockbox in SMRAM directly.
233 
234   @param Guid   the guid to identify the confidential information
235   @param Buffer the address of the restored confidential information
236                 NULL means restored to original address, Length MUST be NULL at same time.
237   @param Length the length of the restored confidential information
238 
239   @retval RETURN_SUCCESS            the information is restored successfully.
240   @retval RETURN_WRITE_PROTECTED    Buffer and Length are NULL, but the LockBox has no
241                                     LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute.
242   @retval RETURN_BUFFER_TOO_SMALL   the Length is too small to hold the confidential information.
243   @retval RETURN_NOT_FOUND          the requested GUID not found.
244 **/
245 EFI_STATUS
InternalRestoreLockBoxFromSmram(IN GUID * Guid,IN VOID * Buffer,OPTIONAL IN OUT UINTN * Length OPTIONAL)246 InternalRestoreLockBoxFromSmram (
247   IN  GUID                        *Guid,
248   IN  VOID                        *Buffer, OPTIONAL
249   IN  OUT UINTN                   *Length  OPTIONAL
250   )
251 {
252   PEI_SMM_ACCESS_PPI             *SmmAccess;
253   UINTN                          Index;
254   EFI_STATUS                     Status;
255   SMM_LOCK_BOX_CONTEXT           *SmmLockBoxContext;
256   LIST_ENTRY                     *LockBoxQueue;
257   SMM_LOCK_BOX_DATA              *LockBox;
258   VOID                           *RestoreBuffer;
259 
260   //
261   // Get needed resource
262   //
263   Status = PeiServicesLocatePpi (
264              &gPeiSmmAccessPpiGuid,
265              0,
266              NULL,
267              (VOID **)&SmmAccess
268              );
269   if (!EFI_ERROR (Status)) {
270     for (Index = 0; !EFI_ERROR (Status); Index++) {
271       Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
272     }
273   }
274 
275   //
276   // Get LockBox context
277   //
278   SmmLockBoxContext = InternalGetSmmLockBoxContext ();
279   LockBoxQueue = (LIST_ENTRY *)(UINTN)SmmLockBoxContext->LockBoxDataAddress;
280 
281   //
282   // We do NOT check Buffer address in SMRAM, because if SMRAM not locked, we trust the caller.
283   //
284 
285   //
286   // Restore this, Buffer and Length MUST be both NULL or both non-NULL
287   //
288 
289   //
290   // Find LockBox
291   //
292   LockBox = InternalFindLockBoxByGuidFromSmram (LockBoxQueue, Guid);
293   if (LockBox == NULL) {
294     //
295     // Not found
296     //
297     return EFI_NOT_FOUND;
298   }
299 
300   //
301   // Set RestoreBuffer
302   //
303   if (Buffer != NULL) {
304     //
305     // restore to new buffer
306     //
307     RestoreBuffer = Buffer;
308   } else {
309     //
310     // restore to original buffer
311     //
312     if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) == 0) {
313       return EFI_WRITE_PROTECTED;
314     }
315     RestoreBuffer = (VOID *)(UINTN)LockBox->Buffer;
316   }
317 
318   //
319   // Set RestoreLength
320   //
321   if (Length != NULL) {
322     if (*Length < (UINTN)LockBox->Length) {
323       //
324       // Input buffer is too small to hold all data.
325       //
326       *Length = (UINTN)LockBox->Length;
327       return EFI_BUFFER_TOO_SMALL;
328     }
329     *Length = (UINTN)LockBox->Length;
330   }
331 
332   //
333   // Restore data
334   //
335   CopyMem (RestoreBuffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);
336 
337   //
338   // Done
339   //
340   return EFI_SUCCESS;
341 }
342 
343 /**
344   This function will restore confidential information from all lockbox which have RestoreInPlace attribute.
345 
346   @retval RETURN_SUCCESS            the information is restored successfully.
347 **/
348 EFI_STATUS
InternalRestoreAllLockBoxInPlaceFromSmram(VOID)349 InternalRestoreAllLockBoxInPlaceFromSmram (
350   VOID
351   )
352 {
353   PEI_SMM_ACCESS_PPI             *SmmAccess;
354   UINTN                          Index;
355   EFI_STATUS                     Status;
356   SMM_LOCK_BOX_CONTEXT           *SmmLockBoxContext;
357   LIST_ENTRY                     *LockBoxQueue;
358   SMM_LOCK_BOX_DATA              *LockBox;
359   LIST_ENTRY                     *Link;
360 
361   //
362   // Get needed resource
363   //
364   Status = PeiServicesLocatePpi (
365              &gPeiSmmAccessPpiGuid,
366              0,
367              NULL,
368              (VOID **)&SmmAccess
369              );
370   if (!EFI_ERROR (Status)) {
371     for (Index = 0; !EFI_ERROR (Status); Index++) {
372       Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
373     }
374   }
375 
376   //
377   // Get LockBox context
378   //
379   SmmLockBoxContext = InternalGetSmmLockBoxContext ();
380   LockBoxQueue = (LIST_ENTRY *)(UINTN)SmmLockBoxContext->LockBoxDataAddress;
381 
382   //
383   // We do NOT check Buffer address in SMRAM, because if SMRAM not locked, we trust the caller.
384   //
385 
386   //
387   // Restore all, Buffer and Length MUST be NULL
388   //
389   for (Link = InternalInitLinkDxe (LockBoxQueue);
390        Link != LockBoxQueue;
391        Link = InternalNextLinkDxe (Link)) {
392     LockBox = BASE_CR (
393                 Link,
394                 SMM_LOCK_BOX_DATA,
395                 Link
396                 );
397     if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) {
398       //
399       // Restore data
400       //
401       CopyMem ((VOID *)(UINTN)LockBox->Buffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);
402     }
403   }
404   //
405   // Done
406   //
407   return EFI_SUCCESS;
408 }
409 
410 /**
411   This function will save confidential information to lockbox.
412 
413   @param Guid       the guid to identify the confidential information
414   @param Buffer     the address of the confidential information
415   @param Length     the length of the confidential information
416 
417   @retval RETURN_SUCCESS            the information is saved successfully.
418   @retval RETURN_INVALID_PARAMETER  the Guid is NULL, or Buffer is NULL, or Length is 0
419   @retval RETURN_ALREADY_STARTED    the requested GUID already exist.
420   @retval RETURN_OUT_OF_RESOURCES   no enough resource to save the information.
421   @retval RETURN_ACCESS_DENIED      it is too late to invoke this interface
422   @retval RETURN_NOT_STARTED        it is too early to invoke this interface
423   @retval RETURN_UNSUPPORTED        the service is not supported by implementaion.
424 **/
425 RETURN_STATUS
426 EFIAPI
SaveLockBox(IN GUID * Guid,IN VOID * Buffer,IN UINTN Length)427 SaveLockBox (
428   IN  GUID                        *Guid,
429   IN  VOID                        *Buffer,
430   IN  UINTN                       Length
431   )
432 {
433   ASSERT (FALSE);
434 
435   //
436   // No support to save at PEI phase
437   //
438   return RETURN_UNSUPPORTED;
439 }
440 
441 /**
442   This function will set lockbox attributes.
443 
444   @param Guid       the guid to identify the confidential information
445   @param Attributes the attributes of the lockbox
446 
447   @retval RETURN_SUCCESS            the information is saved successfully.
448   @retval RETURN_INVALID_PARAMETER  attributes is invalid.
449   @retval RETURN_NOT_FOUND          the requested GUID not found.
450   @retval RETURN_ACCESS_DENIED      it is too late to invoke this interface
451   @retval RETURN_NOT_STARTED        it is too early to invoke this interface
452   @retval RETURN_UNSUPPORTED        the service is not supported by implementaion.
453 **/
454 RETURN_STATUS
455 EFIAPI
SetLockBoxAttributes(IN GUID * Guid,IN UINT64 Attributes)456 SetLockBoxAttributes (
457   IN  GUID                        *Guid,
458   IN  UINT64                      Attributes
459   )
460 {
461   ASSERT (FALSE);
462 
463   //
464   // No support to save at PEI phase
465   //
466   return RETURN_UNSUPPORTED;
467 }
468 
469 /**
470   This function will update confidential information to lockbox.
471 
472   @param Guid   the guid to identify the original confidential information
473   @param Offset the offset of the original confidential information
474   @param Buffer the address of the updated confidential information
475   @param Length the length of the updated confidential information
476 
477   @retval RETURN_SUCCESS            the information is saved successfully.
478   @retval RETURN_INVALID_PARAMETER  the Guid is NULL, or Buffer is NULL, or Length is 0.
479   @retval RETURN_NOT_FOUND          the requested GUID not found.
480   @retval RETURN_BUFFER_TOO_SMALL   the original buffer to too small to hold new information.
481   @retval RETURN_ACCESS_DENIED      it is too late to invoke this interface
482   @retval RETURN_NOT_STARTED        it is too early to invoke this interface
483   @retval RETURN_UNSUPPORTED        the service is not supported by implementaion.
484 **/
485 RETURN_STATUS
486 EFIAPI
UpdateLockBox(IN GUID * Guid,IN UINTN Offset,IN VOID * Buffer,IN UINTN Length)487 UpdateLockBox (
488   IN  GUID                        *Guid,
489   IN  UINTN                       Offset,
490   IN  VOID                        *Buffer,
491   IN  UINTN                       Length
492   )
493 {
494   ASSERT (FALSE);
495 
496   //
497   // No support to update at PEI phase
498   //
499   return RETURN_UNSUPPORTED;
500 }
501 
502 /**
503   This function will restore confidential information from lockbox.
504 
505   @param Guid   the guid to identify the confidential information
506   @param Buffer the address of the restored confidential information
507                 NULL means restored to original address, Length MUST be NULL at same time.
508   @param Length the length of the restored confidential information
509 
510   @retval RETURN_SUCCESS            the information is restored successfully.
511   @retval RETURN_INVALID_PARAMETER  the Guid is NULL, or one of Buffer and Length is NULL.
512   @retval RETURN_WRITE_PROTECTED    Buffer and Length are NULL, but the LockBox has no
513                                     LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute.
514   @retval RETURN_BUFFER_TOO_SMALL   the Length is too small to hold the confidential information.
515   @retval RETURN_NOT_FOUND          the requested GUID not found.
516   @retval RETURN_NOT_STARTED        it is too early to invoke this interface
517   @retval RETURN_ACCESS_DENIED      not allow to restore to the address
518   @retval RETURN_UNSUPPORTED        the service is not supported by implementaion.
519 **/
520 RETURN_STATUS
521 EFIAPI
RestoreLockBox(IN GUID * Guid,IN VOID * Buffer,OPTIONAL IN OUT UINTN * Length OPTIONAL)522 RestoreLockBox (
523   IN  GUID                        *Guid,
524   IN  VOID                        *Buffer, OPTIONAL
525   IN  OUT UINTN                   *Length  OPTIONAL
526   )
527 {
528   EFI_STATUS                         Status;
529   EFI_PEI_SMM_COMMUNICATION_PPI      *SmmCommunicationPpi;
530   EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *LockBoxParameterRestore;
531   EFI_SMM_COMMUNICATE_HEADER         *CommHeader;
532   UINT8                              CommBuffer[sizeof(EFI_GUID) + sizeof(UINT64) + sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE)];
533   UINTN                              CommSize;
534   UINT64                             MessageLength;
535 
536   //
537   // Please aware that there is UINTN in EFI_SMM_COMMUNICATE_HEADER. It might be UINT64 in DXE, while it is UINT32 in PEI.
538   // typedef struct {
539   //   EFI_GUID  HeaderGuid;
540   //   UINTN     MessageLength;
541   //   UINT8     Data[1];
542   // } EFI_SMM_COMMUNICATE_HEADER;
543   //
544 
545   DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib RestoreLockBox - Enter\n"));
546 
547   //
548   // Basic check
549   //
550   if ((Guid == NULL) ||
551       ((Buffer == NULL) && (Length != NULL)) ||
552       ((Buffer != NULL) && (Length == NULL))) {
553     return EFI_INVALID_PARAMETER;
554   }
555 
556   //
557   // Get needed resource
558   //
559   Status = PeiServicesLocatePpi (
560              &gEfiPeiSmmCommunicationPpiGuid,
561              0,
562              NULL,
563              (VOID **)&SmmCommunicationPpi
564              );
565   if (EFI_ERROR (Status)) {
566     DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib LocatePpi - (%r)\n", Status));
567     Status = InternalRestoreLockBoxFromSmram (Guid, Buffer, Length);
568     DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib RestoreLockBox - Exit (%r)\n", Status));
569     return Status;
570   }
571 
572   //
573   // Prepare parameter
574   //
575   CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];
576   CopyMem (&CommHeader->HeaderGuid, &gEfiSmmLockBoxCommunicationGuid, sizeof(gEfiSmmLockBoxCommunicationGuid));
577   if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) {
578     MessageLength = sizeof(*LockBoxParameterRestore);
579     CopyMem (&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength)], &MessageLength, sizeof(MessageLength));
580   } else {
581     CommHeader->MessageLength = sizeof(*LockBoxParameterRestore);
582   }
583 
584   DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib CommBuffer - %x\n", &CommBuffer[0]));
585   if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) {
586     LockBoxParameterRestore = (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength) + sizeof(UINT64)];
587   } else {
588     LockBoxParameterRestore = (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength) + sizeof(UINTN)];
589   }
590   DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib LockBoxParameterRestore - %x\n", LockBoxParameterRestore));
591   LockBoxParameterRestore->Header.Command    = EFI_SMM_LOCK_BOX_COMMAND_RESTORE;
592   LockBoxParameterRestore->Header.DataLength = sizeof(*LockBoxParameterRestore);
593   LockBoxParameterRestore->Header.ReturnStatus = (UINT64)-1;
594   if (Guid != 0) {
595     CopyMem (&LockBoxParameterRestore->Guid, Guid, sizeof(*Guid));
596   } else {
597     ZeroMem (&LockBoxParameterRestore->Guid, sizeof(*Guid));
598   }
599   LockBoxParameterRestore->Buffer = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
600   if (Length != NULL) {
601     LockBoxParameterRestore->Length = (EFI_PHYSICAL_ADDRESS)*Length;
602   } else {
603     LockBoxParameterRestore->Length = 0;
604   }
605 
606   //
607   // Send command
608   //
609   CommSize = sizeof(CommBuffer);
610   Status = SmmCommunicationPpi->Communicate (
611                                   SmmCommunicationPpi,
612                                   &CommBuffer[0],
613                                   &CommSize
614                                   );
615   if (Status == EFI_NOT_STARTED) {
616     //
617     // Pei SMM communication not ready yet, so we access SMRAM directly
618     //
619     DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib Communicate - (%r)\n", Status));
620     Status = InternalRestoreLockBoxFromSmram (Guid, Buffer, Length);
621     LockBoxParameterRestore->Header.ReturnStatus = (UINT64)Status;
622     if (Length != NULL) {
623       LockBoxParameterRestore->Length = (UINT64)*Length;
624     }
625   }
626   ASSERT_EFI_ERROR (Status);
627 
628   if (Length != NULL) {
629     *Length = (UINTN)LockBoxParameterRestore->Length;
630   }
631 
632   Status = (EFI_STATUS)LockBoxParameterRestore->Header.ReturnStatus;
633   if (Status != EFI_SUCCESS) {
634     // Need or MAX_BIT, because there might be case that SMM is X64 while PEI is IA32.
635     Status |= MAX_BIT;
636   }
637 
638   DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib RestoreLockBox - Exit (%r)\n", Status));
639 
640   //
641   // Done
642   //
643   return Status;
644 }
645 
646 /**
647   This function will restore confidential information from all lockbox which have RestoreInPlace attribute.
648 
649   @retval RETURN_SUCCESS            the information is restored successfully.
650   @retval RETURN_NOT_STARTED        it is too early to invoke this interface
651   @retval RETURN_UNSUPPORTED        the service is not supported by implementaion.
652 **/
653 RETURN_STATUS
654 EFIAPI
RestoreAllLockBoxInPlace(VOID)655 RestoreAllLockBoxInPlace (
656   VOID
657   )
658 {
659   EFI_STATUS                                      Status;
660   EFI_PEI_SMM_COMMUNICATION_PPI                   *SmmCommunicationPpi;
661   EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *LockBoxParameterRestoreAllInPlace;
662   EFI_SMM_COMMUNICATE_HEADER                      *CommHeader;
663   UINT8                                           CommBuffer[sizeof(EFI_GUID) + sizeof(UINT64) + sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE)];
664   UINTN                                           CommSize;
665   UINT64                                          MessageLength;
666 
667   //
668   // Please aware that there is UINTN in EFI_SMM_COMMUNICATE_HEADER. It might be UINT64 in DXE, while it is UINT32 in PEI.
669   // typedef struct {
670   //   EFI_GUID  HeaderGuid;
671   //   UINTN     MessageLength;
672   //   UINT8     Data[1];
673   // } EFI_SMM_COMMUNICATE_HEADER;
674   //
675 
676   DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib RestoreAllLockBoxInPlace - Enter\n"));
677 
678   //
679   // Get needed resource
680   //
681   Status = PeiServicesLocatePpi (
682              &gEfiPeiSmmCommunicationPpiGuid,
683              0,
684              NULL,
685              (VOID **)&SmmCommunicationPpi
686              );
687   if (EFI_ERROR (Status)) {
688     DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib LocatePpi - (%r)\n", Status));
689     Status = InternalRestoreAllLockBoxInPlaceFromSmram ();
690     DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib RestoreAllLockBoxInPlace - Exit (%r)\n", Status));
691     return Status;
692   }
693 
694   //
695   // Prepare parameter
696   //
697   CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];
698   CopyMem (&CommHeader->HeaderGuid, &gEfiSmmLockBoxCommunicationGuid, sizeof(gEfiSmmLockBoxCommunicationGuid));
699   if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) {
700     MessageLength = sizeof(*LockBoxParameterRestoreAllInPlace);
701     CopyMem (&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength)], &MessageLength, sizeof(MessageLength));
702   } else {
703     CommHeader->MessageLength = sizeof(*LockBoxParameterRestoreAllInPlace);
704   }
705 
706   if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) {
707     LockBoxParameterRestoreAllInPlace = (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength) + sizeof(UINT64)];
708   } else {
709     LockBoxParameterRestoreAllInPlace = (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength) + sizeof(UINTN)];
710   }
711   LockBoxParameterRestoreAllInPlace->Header.Command    = EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE;
712   LockBoxParameterRestoreAllInPlace->Header.DataLength = sizeof(*LockBoxParameterRestoreAllInPlace);
713   LockBoxParameterRestoreAllInPlace->Header.ReturnStatus = (UINT64)-1;
714 
715   //
716   // Send command
717   //
718   CommSize = sizeof(CommBuffer);
719   Status = SmmCommunicationPpi->Communicate (
720                                   SmmCommunicationPpi,
721                                   &CommBuffer[0],
722                                   &CommSize
723                                   );
724   if (Status == EFI_NOT_STARTED) {
725     //
726     // Pei SMM communication not ready yet, so we access SMRAM directly
727     //
728     DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib Communicate - (%r)\n", Status));
729     Status = InternalRestoreAllLockBoxInPlaceFromSmram ();
730     LockBoxParameterRestoreAllInPlace->Header.ReturnStatus = (UINT64)Status;
731   }
732   ASSERT_EFI_ERROR (Status);
733 
734   Status = (EFI_STATUS)LockBoxParameterRestoreAllInPlace->Header.ReturnStatus;
735   if (Status != EFI_SUCCESS) {
736     // Need or MAX_BIT, because there might be case that SMM is X64 while PEI is IA32.
737     Status |= MAX_BIT;
738   }
739 
740   DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib RestoreAllLockBoxInPlace - Exit (%r)\n", Status));
741 
742   //
743   // Done
744   //
745   return Status;
746 }
747 
748