Home | History | Annotate | Download | only in SmmLockBoxLib
      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 *
     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 *
    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 *
    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 *
    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 *
    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
    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
    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
    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
    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
    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
    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
    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