Home | History | Annotate | Download | only in TcgPei
      1 /** @file
      2   Initialize TPM device and measure FVs before handing off control to DXE.
      3 
      4 Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include <PiPei.h>
     16 
     17 #include <IndustryStandard/Tpm12.h>
     18 #include <IndustryStandard/UefiTcgPlatform.h>
     19 #include <Ppi/FirmwareVolumeInfo.h>
     20 #include <Ppi/FirmwareVolumeInfo2.h>
     21 #include <Ppi/LockPhysicalPresence.h>
     22 #include <Ppi/TpmInitialized.h>
     23 #include <Ppi/FirmwareVolume.h>
     24 #include <Ppi/EndOfPeiPhase.h>
     25 #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
     26 
     27 #include <Guid/TcgEventHob.h>
     28 #include <Guid/MeasuredFvHob.h>
     29 #include <Guid/TpmInstance.h>
     30 
     31 #include <Library/DebugLib.h>
     32 #include <Library/BaseMemoryLib.h>
     33 #include <Library/PeiServicesLib.h>
     34 #include <Library/PeimEntryPoint.h>
     35 #include <Library/HobLib.h>
     36 #include <Library/PcdLib.h>
     37 #include <Library/PeiServicesTablePointerLib.h>
     38 #include <Library/BaseLib.h>
     39 #include <Library/MemoryAllocationLib.h>
     40 #include <Library/ReportStatusCodeLib.h>
     41 #include <Library/Tpm12DeviceLib.h>
     42 #include <Library/Tpm12CommandLib.h>
     43 #include <Library/BaseCryptLib.h>
     44 
     45 BOOLEAN                 mImageInMemory  = FALSE;
     46 
     47 EFI_PEI_PPI_DESCRIPTOR  mTpmInitializedPpiList = {
     48   EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
     49   &gPeiTpmInitializedPpiGuid,
     50   NULL
     51 };
     52 
     53 EFI_PEI_PPI_DESCRIPTOR  mTpmInitializationDonePpiList = {
     54   EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
     55   &gPeiTpmInitializationDonePpiGuid,
     56   NULL
     57 };
     58 
     59 EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredBaseFvInfo;
     60 UINT32 mMeasuredBaseFvIndex = 0;
     61 
     62 EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredChildFvInfo;
     63 UINT32 mMeasuredChildFvIndex = 0;
     64 
     65 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi;
     66 
     67 /**
     68   Lock physical presence if needed.
     69 
     70   @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
     71   @param[in] NotifyDescriptor  Address of the notification descriptor data structure.
     72   @param[in] Ppi               Address of the PPI that was installed.
     73 
     74   @retval EFI_SUCCESS          Operation completed successfully.
     75 
     76 **/
     77 EFI_STATUS
     78 EFIAPI
     79 PhysicalPresencePpiNotifyCallback (
     80   IN EFI_PEI_SERVICES              **PeiServices,
     81   IN EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor,
     82   IN VOID                          *Ppi
     83   );
     84 
     85 /**
     86   Measure and record the Firmware Volum Information once FvInfoPPI install.
     87 
     88   @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
     89   @param[in] NotifyDescriptor  Address of the notification descriptor data structure.
     90   @param[in] Ppi               Address of the PPI that was installed.
     91 
     92   @retval EFI_SUCCESS          The FV Info is measured and recorded to TPM.
     93   @return Others               Fail to measure FV.
     94 
     95 **/
     96 EFI_STATUS
     97 EFIAPI
     98 FirmwareVolmeInfoPpiNotifyCallback (
     99   IN EFI_PEI_SERVICES              **PeiServices,
    100   IN EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor,
    101   IN VOID                          *Ppi
    102   );
    103 
    104 /**
    105   Record all measured Firmware Volum Information into a Guid Hob
    106 
    107   @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
    108   @param[in] NotifyDescriptor  Address of the notification descriptor data structure.
    109   @param[in] Ppi               Address of the PPI that was installed.
    110 
    111   @retval EFI_SUCCESS          The FV Info is measured and recorded to TPM.
    112   @return Others               Fail to measure FV.
    113 
    114 **/
    115 EFI_STATUS
    116 EFIAPI
    117 EndofPeiSignalNotifyCallBack (
    118   IN EFI_PEI_SERVICES              **PeiServices,
    119   IN EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor,
    120   IN VOID                          *Ppi
    121   );
    122 
    123 EFI_PEI_NOTIFY_DESCRIPTOR           mNotifyList[] = {
    124   {
    125     EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
    126     &gPeiLockPhysicalPresencePpiGuid,
    127     PhysicalPresencePpiNotifyCallback
    128   },
    129   {
    130     EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
    131     &gEfiPeiFirmwareVolumeInfoPpiGuid,
    132     FirmwareVolmeInfoPpiNotifyCallback
    133   },
    134   {
    135     EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
    136     &gEfiPeiFirmwareVolumeInfo2PpiGuid,
    137     FirmwareVolmeInfoPpiNotifyCallback
    138   },
    139   {
    140     (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
    141     &gEfiEndOfPeiSignalPpiGuid,
    142     EndofPeiSignalNotifyCallBack
    143   }
    144 };
    145 
    146 /**
    147   Record all measured Firmware Volum Information into a Guid Hob
    148   Guid Hob payload layout is
    149 
    150      UINT32 *************************** FIRMWARE_BLOB number
    151      EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array
    152 
    153   @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
    154   @param[in] NotifyDescriptor  Address of the notification descriptor data structure.
    155   @param[in] Ppi               Address of the PPI that was installed.
    156 
    157   @retval EFI_SUCCESS          The FV Info is measured and recorded to TPM.
    158   @return Others               Fail to measure FV.
    159 
    160 **/
    161 EFI_STATUS
    162 EFIAPI
    163 EndofPeiSignalNotifyCallBack (
    164   IN EFI_PEI_SERVICES              **PeiServices,
    165   IN EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor,
    166   IN VOID                          *Ppi
    167   )
    168 {
    169   MEASURED_HOB_DATA *MeasuredHobData;
    170 
    171   MeasuredHobData = NULL;
    172 
    173   //
    174   // Create a Guid hob to save all measured Fv
    175   //
    176   MeasuredHobData = BuildGuidHob(
    177                       &gMeasuredFvHobGuid,
    178                       sizeof(UINTN) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex + mMeasuredChildFvIndex)
    179                       );
    180 
    181   if (MeasuredHobData != NULL){
    182     //
    183     // Save measured FV info enty number
    184     //
    185     MeasuredHobData->Num = mMeasuredBaseFvIndex + mMeasuredChildFvIndex;
    186 
    187     //
    188     // Save measured base Fv info
    189     //
    190     CopyMem (MeasuredHobData->MeasuredFvBuf, mMeasuredBaseFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex));
    191 
    192     //
    193     // Save measured child Fv info
    194     //
    195     CopyMem (&MeasuredHobData->MeasuredFvBuf[mMeasuredBaseFvIndex] , mMeasuredChildFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredChildFvIndex));
    196   }
    197 
    198   return EFI_SUCCESS;
    199 }
    200 
    201 /**
    202 Single function calculates SHA1 digest value for all raw data. It
    203 combines Sha1Init(), Sha1Update() and Sha1Final().
    204 
    205 @param[in]  Data          Raw data to be digested.
    206 @param[in]  DataLen       Size of the raw data.
    207 @param[out] Digest        Pointer to a buffer that stores the final digest.
    208 
    209 @retval     EFI_SUCCESS   Always successfully calculate the final digest.
    210 **/
    211 EFI_STATUS
    212 EFIAPI
    213 TpmCommHashAll (
    214   IN  CONST UINT8       *Data,
    215   IN        UINTN       DataLen,
    216   OUT       TPM_DIGEST  *Digest
    217   )
    218 {
    219   VOID   *Sha1Ctx;
    220   UINTN  CtxSize;
    221 
    222   CtxSize = Sha1GetContextSize ();
    223   Sha1Ctx = AllocatePool (CtxSize);
    224   ASSERT (Sha1Ctx != NULL);
    225 
    226   Sha1Init (Sha1Ctx);
    227   Sha1Update (Sha1Ctx, Data, DataLen);
    228   Sha1Final (Sha1Ctx, (UINT8 *)Digest);
    229 
    230   FreePool (Sha1Ctx);
    231 
    232   return EFI_SUCCESS;
    233 }
    234 
    235 /**
    236   Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
    237   and build a GUIDed HOB recording the event which will be passed to the DXE phase and
    238   added into the Event Log.
    239 
    240   @param[in]      PeiServices   Describes the list of possible PEI Services.
    241   @param[in]      HashData      Physical address of the start of the data buffer
    242                                 to be hashed, extended, and logged.
    243   @param[in]      HashDataLen   The length, in bytes, of the buffer referenced by HashData.
    244   @param[in]      NewEventHdr   Pointer to a TCG_PCR_EVENT_HDR data structure.
    245   @param[in]      NewEventData  Pointer to the new event data.
    246 
    247   @retval EFI_SUCCESS           Operation completed successfully.
    248   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
    249   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
    250 
    251 **/
    252 EFI_STATUS
    253 HashLogExtendEvent (
    254   IN      EFI_PEI_SERVICES          **PeiServices,
    255   IN      UINT8                     *HashData,
    256   IN      UINTN                     HashDataLen,
    257   IN      TCG_PCR_EVENT_HDR         *NewEventHdr,
    258   IN      UINT8                     *NewEventData
    259   )
    260 {
    261   EFI_STATUS                        Status;
    262   VOID                              *HobData;
    263 
    264   if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
    265     return EFI_DEVICE_ERROR;
    266   }
    267 
    268   HobData = NULL;
    269   if (HashDataLen != 0) {
    270     Status = TpmCommHashAll (
    271                HashData,
    272                HashDataLen,
    273                &NewEventHdr->Digest
    274                );
    275     if (EFI_ERROR (Status)) {
    276       goto Done;
    277     }
    278   }
    279 
    280   Status = Tpm12Extend (
    281              &NewEventHdr->Digest,
    282              NewEventHdr->PCRIndex,
    283              NULL
    284              );
    285   if (EFI_ERROR (Status)) {
    286     goto Done;
    287   }
    288 
    289   HobData = BuildGuidHob (
    290              &gTcgEventEntryHobGuid,
    291              sizeof (*NewEventHdr) + NewEventHdr->EventSize
    292              );
    293   if (HobData == NULL) {
    294     Status = EFI_OUT_OF_RESOURCES;
    295     goto Done;
    296   }
    297 
    298   CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr));
    299   HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr));
    300   CopyMem (HobData, NewEventData, NewEventHdr->EventSize);
    301 
    302 Done:
    303   if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_TIMEOUT)) {
    304     DEBUG ((EFI_D_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status));
    305     BuildGuidHob (&gTpmErrorHobGuid,0);
    306     REPORT_STATUS_CODE (
    307       EFI_ERROR_CODE | EFI_ERROR_MINOR,
    308       (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
    309       );
    310     Status = EFI_DEVICE_ERROR;
    311   }
    312   return Status;
    313 }
    314 
    315 /**
    316   Measure CRTM version.
    317 
    318   @param[in]      PeiServices   Describes the list of possible PEI Services.
    319 
    320   @retval EFI_SUCCESS           Operation completed successfully.
    321   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
    322   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
    323 
    324 **/
    325 EFI_STATUS
    326 EFIAPI
    327 MeasureCRTMVersion (
    328   IN      EFI_PEI_SERVICES          **PeiServices
    329   )
    330 {
    331   TCG_PCR_EVENT_HDR                 TcgEventHdr;
    332 
    333   //
    334   // Use FirmwareVersion string to represent CRTM version.
    335   // OEMs should get real CRTM version string and measure it.
    336   //
    337 
    338   TcgEventHdr.PCRIndex  = 0;
    339   TcgEventHdr.EventType = EV_S_CRTM_VERSION;
    340   TcgEventHdr.EventSize = (UINT32) StrSize((CHAR16*)PcdGetPtr (PcdFirmwareVersionString));
    341 
    342   return HashLogExtendEvent (
    343            PeiServices,
    344            (UINT8*)PcdGetPtr (PcdFirmwareVersionString),
    345            TcgEventHdr.EventSize,
    346            &TcgEventHdr,
    347            (UINT8*)PcdGetPtr (PcdFirmwareVersionString)
    348            );
    349 }
    350 
    351 /**
    352   Measure FV image.
    353   Add it into the measured FV list after the FV is measured successfully.
    354 
    355   @param[in]  FvBase            Base address of FV image.
    356   @param[in]  FvLength          Length of FV image.
    357 
    358   @retval EFI_SUCCESS           Fv image is measured successfully
    359                                 or it has been already measured.
    360   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
    361   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
    362 
    363 **/
    364 EFI_STATUS
    365 EFIAPI
    366 MeasureFvImage (
    367   IN EFI_PHYSICAL_ADDRESS           FvBase,
    368   IN UINT64                         FvLength
    369   )
    370 {
    371   UINT32                            Index;
    372   EFI_STATUS                        Status;
    373   EFI_PLATFORM_FIRMWARE_BLOB        FvBlob;
    374   TCG_PCR_EVENT_HDR                 TcgEventHdr;
    375 
    376   //
    377   // Check if it is in Excluded FV list
    378   //
    379   if (mMeasurementExcludedFvPpi != NULL) {
    380     for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) {
    381       if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {
    382         DEBUG ((DEBUG_INFO, "The FV which is excluded by TcgPei starts at: 0x%x\n", FvBase));
    383         DEBUG ((DEBUG_INFO, "The FV which is excluded by TcgPei has the size: 0x%x\n", FvLength));
    384         return EFI_SUCCESS;
    385       }
    386     }
    387   }
    388 
    389   //
    390   // Check whether FV is in the measured FV list.
    391   //
    392   for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {
    393     if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) {
    394       return EFI_SUCCESS;
    395     }
    396   }
    397 
    398   //
    399   // Measure and record the FV to the TPM
    400   //
    401   FvBlob.BlobBase   = FvBase;
    402   FvBlob.BlobLength = FvLength;
    403 
    404   DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei starts at: 0x%x\n", FvBlob.BlobBase));
    405   DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei has the size: 0x%x\n", FvBlob.BlobLength));
    406 
    407   TcgEventHdr.PCRIndex = 0;
    408   TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
    409   TcgEventHdr.EventSize = sizeof (FvBlob);
    410 
    411   Status = HashLogExtendEvent (
    412              (EFI_PEI_SERVICES **) GetPeiServicesTablePointer(),
    413              (UINT8*) (UINTN) FvBlob.BlobBase,
    414              (UINTN) FvBlob.BlobLength,
    415              &TcgEventHdr,
    416              (UINT8*) &FvBlob
    417              );
    418 
    419   //
    420   // Add new FV into the measured FV list.
    421   //
    422   ASSERT (mMeasuredBaseFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported));
    423   if (mMeasuredBaseFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)) {
    424     mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase   = FvBase;
    425     mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength;
    426     mMeasuredBaseFvIndex++;
    427   }
    428 
    429   return Status;
    430 }
    431 
    432 /**
    433   Measure main BIOS.
    434 
    435   @param[in]      PeiServices   Describes the list of possible PEI Services.
    436 
    437   @retval EFI_SUCCESS           Operation completed successfully.
    438   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
    439   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
    440 
    441 **/
    442 EFI_STATUS
    443 EFIAPI
    444 MeasureMainBios (
    445   IN      EFI_PEI_SERVICES          **PeiServices
    446   )
    447 {
    448   EFI_STATUS                        Status;
    449   UINT32                            FvInstances;
    450   EFI_PEI_FV_HANDLE                 VolumeHandle;
    451   EFI_FV_INFO                       VolumeInfo;
    452   EFI_PEI_FIRMWARE_VOLUME_PPI       *FvPpi;
    453 
    454   FvInstances    = 0;
    455   while (TRUE) {
    456     //
    457     // Traverse all firmware volume instances of Static Core Root of Trust for Measurement
    458     // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special
    459     // platform for special CRTM TPM measuring.
    460     //
    461     Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);
    462     if (EFI_ERROR (Status)) {
    463       break;
    464     }
    465 
    466     //
    467     // Measure and record the firmware volume that is dispatched by PeiCore
    468     //
    469     Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
    470     ASSERT_EFI_ERROR (Status);
    471     //
    472     // Locate the corresponding FV_PPI according to founded FV's format guid
    473     //
    474     Status = PeiServicesLocatePpi (
    475                &VolumeInfo.FvFormat,
    476                0,
    477                NULL,
    478                (VOID**)&FvPpi
    479                );
    480     if (!EFI_ERROR (Status)) {
    481       MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);
    482     }
    483 
    484     FvInstances++;
    485   }
    486 
    487   return EFI_SUCCESS;
    488 }
    489 
    490 /**
    491   Measure and record the Firmware Volum Information once FvInfoPPI install.
    492 
    493   @param[in] PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
    494   @param[in] NotifyDescriptor  Address of the notification descriptor data structure.
    495   @param[in] Ppi               Address of the PPI that was installed.
    496 
    497   @retval EFI_SUCCESS          The FV Info is measured and recorded to TPM.
    498   @return Others               Fail to measure FV.
    499 
    500 **/
    501 EFI_STATUS
    502 EFIAPI
    503 FirmwareVolmeInfoPpiNotifyCallback (
    504   IN EFI_PEI_SERVICES               **PeiServices,
    505   IN EFI_PEI_NOTIFY_DESCRIPTOR      *NotifyDescriptor,
    506   IN VOID                           *Ppi
    507   )
    508 {
    509   EFI_PEI_FIRMWARE_VOLUME_INFO_PPI  *Fv;
    510   EFI_STATUS                        Status;
    511   EFI_PEI_FIRMWARE_VOLUME_PPI       *FvPpi;
    512   UINTN                             Index;
    513 
    514   Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *) Ppi;
    515 
    516   //
    517   // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.
    518   //
    519   Status = PeiServicesLocatePpi (
    520              &Fv->FvFormat,
    521              0,
    522              NULL,
    523              (VOID**)&FvPpi
    524              );
    525   if (EFI_ERROR (Status)) {
    526     return EFI_SUCCESS;
    527   }
    528 
    529   //
    530   // This is an FV from an FFS file, and the parent FV must have already been measured,
    531   // No need to measure twice, so just record the FV and return
    532   //
    533   if (Fv->ParentFvName != NULL || Fv->ParentFileName != NULL ) {
    534 
    535     ASSERT (mMeasuredChildFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported));
    536     if (mMeasuredChildFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)) {
    537       //
    538       // Check whether FV is in the measured child FV list.
    539       //
    540       for (Index = 0; Index < mMeasuredChildFvIndex; Index++) {
    541         if (mMeasuredChildFvInfo[Index].BlobBase == (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo) {
    542           return EFI_SUCCESS;
    543         }
    544       }
    545       mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase   = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo;
    546       mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize;
    547       mMeasuredChildFvIndex++;
    548     }
    549     return EFI_SUCCESS;
    550   }
    551 
    552   return MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, Fv->FvInfoSize);
    553 }
    554 
    555 /**
    556   Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by corresponding PCDs.
    557   And lock physical presence if needed.
    558 
    559   @param[in] PeiServices        An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
    560   @param[in] NotifyDescriptor   Address of the notification descriptor data structure.
    561   @param[in] Ppi                Address of the PPI that was installed.
    562 
    563   @retval EFI_SUCCESS           Operation completed successfully.
    564   @retval EFI_ABORTED           physicalPresenceCMDEnable is locked.
    565   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
    566 
    567 **/
    568 EFI_STATUS
    569 EFIAPI
    570 PhysicalPresencePpiNotifyCallback (
    571   IN EFI_PEI_SERVICES               **PeiServices,
    572   IN EFI_PEI_NOTIFY_DESCRIPTOR      *NotifyDescriptor,
    573   IN VOID                           *Ppi
    574   )
    575 {
    576   EFI_STATUS                        Status;
    577   TPM_PERMANENT_FLAGS               TpmPermanentFlags;
    578   PEI_LOCK_PHYSICAL_PRESENCE_PPI    *LockPhysicalPresencePpi;
    579   TPM_PHYSICAL_PRESENCE             PhysicalPresenceValue;
    580 
    581   Status = Tpm12GetCapabilityFlagPermanent (&TpmPermanentFlags);
    582   if (EFI_ERROR (Status)) {
    583     return Status;
    584   }
    585 
    586   //
    587   // 1. Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by PCDs.
    588   //
    589   if (PcdGetBool (PcdPhysicalPresenceLifetimeLock) && !TpmPermanentFlags.physicalPresenceLifetimeLock) {
    590     //
    591     // Lock TPM LifetimeLock is required, and LifetimeLock is not locked yet.
    592     //
    593     PhysicalPresenceValue = TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK;
    594 
    595     if (PcdGetBool (PcdPhysicalPresenceCmdEnable)) {
    596       PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_ENABLE;
    597       TpmPermanentFlags.physicalPresenceCMDEnable = TRUE;
    598     } else {
    599       PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_DISABLE;
    600       TpmPermanentFlags.physicalPresenceCMDEnable = FALSE;
    601     }
    602 
    603     if (PcdGetBool (PcdPhysicalPresenceHwEnable)) {
    604       PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_ENABLE;
    605     } else {
    606       PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_DISABLE;
    607     }
    608 
    609     Status = Tpm12PhysicalPresence (
    610                PhysicalPresenceValue
    611                );
    612     if (EFI_ERROR (Status)) {
    613       return Status;
    614     }
    615   }
    616 
    617   //
    618   // 2. Lock physical presence if it is required.
    619   //
    620   LockPhysicalPresencePpi = (PEI_LOCK_PHYSICAL_PRESENCE_PPI *) Ppi;
    621   if (!LockPhysicalPresencePpi->LockPhysicalPresence ((CONST EFI_PEI_SERVICES**) PeiServices)) {
    622     return EFI_SUCCESS;
    623   }
    624 
    625   if (!TpmPermanentFlags.physicalPresenceCMDEnable) {
    626     if (TpmPermanentFlags.physicalPresenceLifetimeLock) {
    627       //
    628       // physicalPresenceCMDEnable is locked, can't change.
    629       //
    630       return EFI_ABORTED;
    631     }
    632 
    633     //
    634     // Enable physical presence command
    635     // It is necessary in order to lock physical presence
    636     //
    637     Status = Tpm12PhysicalPresence (
    638                TPM_PHYSICAL_PRESENCE_CMD_ENABLE
    639                );
    640     if (EFI_ERROR (Status)) {
    641       return Status;
    642     }
    643   }
    644 
    645   //
    646   // Lock physical presence
    647   //
    648   Status = Tpm12PhysicalPresence (
    649               TPM_PHYSICAL_PRESENCE_LOCK
    650               );
    651   return Status;
    652 }
    653 
    654 /**
    655   Check if TPM chip is activeated or not.
    656 
    657   @param[in]      PeiServices   Describes the list of possible PEI Services.
    658 
    659   @retval TRUE    TPM is activated.
    660   @retval FALSE   TPM is deactivated.
    661 
    662 **/
    663 BOOLEAN
    664 IsTpmUsable (
    665   VOID
    666   )
    667 {
    668   EFI_STATUS           Status;
    669   TPM_PERMANENT_FLAGS  TpmPermanentFlags;
    670 
    671   Status = Tpm12GetCapabilityFlagPermanent (&TpmPermanentFlags);
    672   if (EFI_ERROR (Status)) {
    673     return FALSE;
    674   }
    675   return (BOOLEAN)(!TpmPermanentFlags.deactivated);
    676 }
    677 
    678 /**
    679   Do measurement after memory is ready.
    680 
    681   @param[in]      PeiServices   Describes the list of possible PEI Services.
    682 
    683   @retval EFI_SUCCESS           Operation completed successfully.
    684   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
    685   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
    686 
    687 **/
    688 EFI_STATUS
    689 EFIAPI
    690 PeimEntryMP (
    691   IN      EFI_PEI_SERVICES          **PeiServices
    692   )
    693 {
    694   EFI_STATUS                        Status;
    695 
    696   Status = PeiServicesLocatePpi (
    697                &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,
    698                0,
    699                NULL,
    700                (VOID**)&mMeasurementExcludedFvPpi
    701                );
    702   // Do not check status, because it is optional
    703 
    704   mMeasuredBaseFvInfo  = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));
    705   ASSERT (mMeasuredBaseFvInfo != NULL);
    706   mMeasuredChildFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));
    707   ASSERT (mMeasuredChildFvInfo != NULL);
    708 
    709   Status = Tpm12RequestUseTpm ();
    710   if (EFI_ERROR (Status)) {
    711     return Status;
    712   }
    713 
    714   if (IsTpmUsable ()) {
    715     if (PcdGet8 (PcdTpmScrtmPolicy) == 1) {
    716       Status = MeasureCRTMVersion (PeiServices);
    717     }
    718 
    719     Status = MeasureMainBios (PeiServices);
    720   }
    721 
    722   //
    723   // Post callbacks:
    724   // 1). for the FvInfoPpi services to measure and record
    725   // the additional Fvs to TPM
    726   // 2). for the OperatorPresencePpi service to determine whether to
    727   // lock the TPM
    728   //
    729   Status = PeiServicesNotifyPpi (&mNotifyList[0]);
    730   ASSERT_EFI_ERROR (Status);
    731 
    732   return Status;
    733 }
    734 
    735 /**
    736   Entry point of this module.
    737 
    738   @param[in] FileHandle   Handle of the file being invoked.
    739   @param[in] PeiServices  Describes the list of possible PEI Services.
    740 
    741   @return Status.
    742 
    743 **/
    744 EFI_STATUS
    745 EFIAPI
    746 PeimEntryMA (
    747   IN       EFI_PEI_FILE_HANDLE      FileHandle,
    748   IN CONST EFI_PEI_SERVICES         **PeiServices
    749   )
    750 {
    751   EFI_STATUS                        Status;
    752   EFI_STATUS                        Status2;
    753   EFI_BOOT_MODE                     BootMode;
    754 
    755   if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){
    756     DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n"));
    757     return EFI_UNSUPPORTED;
    758   }
    759 
    760   if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
    761     DEBUG ((EFI_D_ERROR, "TPM error!\n"));
    762     return EFI_DEVICE_ERROR;
    763   }
    764 
    765   //
    766   // Initialize TPM device
    767   //
    768   Status = PeiServicesGetBootMode (&BootMode);
    769   ASSERT_EFI_ERROR (Status);
    770 
    771   //
    772   // In S3 path, skip shadow logic. no measurement is required
    773   //
    774   if (BootMode != BOOT_ON_S3_RESUME) {
    775     Status = (**PeiServices).RegisterForShadow(FileHandle);
    776     if (Status == EFI_ALREADY_STARTED) {
    777       mImageInMemory = TRUE;
    778     } else if (Status == EFI_NOT_FOUND) {
    779       ASSERT_EFI_ERROR (Status);
    780     }
    781   }
    782 
    783   if (!mImageInMemory) {
    784     Status = Tpm12RequestUseTpm ();
    785     if (EFI_ERROR (Status)) {
    786       DEBUG ((DEBUG_ERROR, "TPM not detected!\n"));
    787       goto Done;
    788     }
    789 
    790     if (PcdGet8 (PcdTpmInitializationPolicy) == 1) {
    791       if (BootMode == BOOT_ON_S3_RESUME) {
    792         Status = Tpm12Startup (TPM_ST_STATE);
    793       } else {
    794         Status = Tpm12Startup (TPM_ST_CLEAR);
    795       }
    796       if (EFI_ERROR (Status) ) {
    797         goto Done;
    798       }
    799     }
    800 
    801     //
    802     // TpmSelfTest is optional on S3 path, skip it to save S3 time
    803     //
    804     if (BootMode != BOOT_ON_S3_RESUME) {
    805       Status = Tpm12ContinueSelfTest ();
    806       if (EFI_ERROR (Status)) {
    807         goto Done;
    808       }
    809     }
    810 
    811     //
    812     // Only intall TpmInitializedPpi on success
    813     //
    814     Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);
    815     ASSERT_EFI_ERROR (Status);
    816   }
    817 
    818   if (mImageInMemory) {
    819     Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices);
    820     return Status;
    821   }
    822 
    823 Done:
    824   if (EFI_ERROR (Status)) {
    825     DEBUG ((EFI_D_ERROR, "TPM error! Build Hob\n"));
    826     BuildGuidHob (&gTpmErrorHobGuid,0);
    827     REPORT_STATUS_CODE (
    828       EFI_ERROR_CODE | EFI_ERROR_MINOR,
    829       (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
    830       );
    831   }
    832   //
    833   // Always intall TpmInitializationDonePpi no matter success or fail.
    834   // Other driver can know TPM initialization state by TpmInitializedPpi.
    835   //
    836   Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);
    837   ASSERT_EFI_ERROR (Status2);
    838 
    839   return Status;
    840 }
    841