]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
SecurityPkg/Tcg2Pei: drop Tcg2PhysicalPresenceLib dependency
[mirror_edk2.git] / SecurityPkg / Tcg / Tcg2Pei / Tcg2Pei.c
index 0d779f1e3b17a312cd8259de70dff2a7df9f58f5..3758fc6a41fbdbb64416d37cc9428503409cb188 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
   Initialize TPM2 device and measure FVs before handing off control to DXE.\r
 \r
-Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>\r
 This program and the accompanying materials \r
 are licensed and made available under the terms and conditions of the BSD License \r
 which accompanies this distribution.  The full text of the license may be found at \r
@@ -17,11 +18,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <IndustryStandard/UefiTcgPlatform.h>\r
 #include <Ppi/FirmwareVolumeInfo.h>\r
 #include <Ppi/FirmwareVolumeInfo2.h>\r
-#include <Ppi/LockPhysicalPresence.h>\r
 #include <Ppi/TpmInitialized.h>\r
 #include <Ppi/FirmwareVolume.h>\r
 #include <Ppi/EndOfPeiPhase.h>\r
 #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>\r
+#include <Ppi/FirmwareVolumeInfoPrehashedFV.h>\r
 \r
 #include <Guid/TcgEventHob.h>\r
 #include <Guid/MeasuredFvHob.h>\r
@@ -41,7 +42,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/PerformanceLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/ReportStatusCodeLib.h>\r
-#include <Library/Tcg2PhysicalPresenceLib.h>\r
+#include <Library/ResetSystemLib.h>\r
 \r
 #define PERF_ID_TCG2_PEI  0x3080\r
 \r
@@ -132,42 +133,6 @@ EFI_PEI_NOTIFY_DESCRIPTOR           mNotifyList[] = {
   }\r
 };\r
 \r
-EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi;\r
-\r
-/**\r
-  This function get digest from digest list.\r
-\r
-  @param HashAlg    digest algorithm\r
-  @param DigestList digest list\r
-  @param Digest     digest\r
-\r
-  @retval EFI_SUCCESS   Sha1Digest is found and returned.\r
-  @retval EFI_NOT_FOUND Sha1Digest is not found.\r
-**/\r
-EFI_STATUS\r
-Tpm2GetDigestFromDigestList (\r
-  IN TPMI_ALG_HASH      HashAlg,\r
-  IN TPML_DIGEST_VALUES *DigestList,\r
-  IN VOID               *Digest\r
-  )\r
-{\r
-  UINTN  Index;\r
-  UINT16 DigestSize;\r
-\r
-  DigestSize = GetHashSizeFromAlgo (HashAlg);\r
-  for (Index = 0; Index < DigestList->count; Index++) {\r
-    if (DigestList->digests[Index].hashAlg == HashAlg) {\r
-      CopyMem (\r
-        Digest,\r
-        &DigestList->digests[Index].digest,\r
-        DigestSize\r
-        );\r
-      return EFI_SUCCESS;\r
-    }\r
-  }\r
-\r
-  return EFI_NOT_FOUND;\r
-}\r
 \r
 /**\r
   Record all measured Firmware Volum Information into a Guid Hob\r
@@ -225,166 +190,87 @@ EndofPeiSignalNotifyCallBack (
 }\r
 \r
 /**\r
-  Get TPML_DIGEST_VALUES data size.\r
-\r
-  @param[in]     DigestList    TPML_DIGEST_VALUES data.\r
-\r
-  @return TPML_DIGEST_VALUES data size.\r
+  Make sure that the current PCR allocations, the TPM supported PCRs,\r
+  and the PcdTpm2HashMask are all in agreement.\r
 **/\r
-UINT32\r
-GetDigestListSize (\r
-  IN TPML_DIGEST_VALUES             *DigestList\r
+VOID\r
+SyncPcrAllocationsAndPcrMask (\r
+  VOID\r
   )\r
 {\r
-  UINTN  Index;\r
-  UINT16 DigestSize;\r
-  UINT32 TotalSize;\r
-\r
-  TotalSize = sizeof(DigestList->count);\r
-  for (Index = 0; Index < DigestList->count; Index++) {\r
-    DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg);\r
-    TotalSize += sizeof(DigestList->digests[Index].hashAlg) + DigestSize;\r
-  }\r
-\r
-  return TotalSize;\r
-}\r
-\r
-/**\r
-  Return if hash alg is supported in TPM PCR bank.\r
+  EFI_STATUS                        Status;\r
+  EFI_TCG2_EVENT_ALGORITHM_BITMAP   TpmHashAlgorithmBitmap;\r
+  UINT32                            TpmActivePcrBanks;\r
+  UINT32                            NewTpmActivePcrBanks;\r
+  UINT32                            Tpm2PcrMask;\r
+  UINT32                            NewTpm2PcrMask;\r
 \r
-  @param HashAlg  Hash algorithm to be checked.\r
+  DEBUG ((EFI_D_ERROR, "SyncPcrAllocationsAndPcrMask!\n"));\r
 \r
-  @retval TRUE  Hash algorithm is supported.\r
-  @retval FALSE Hash algorithm is not supported.\r
-**/\r
-BOOLEAN\r
-IsHashAlgSupportedInPcrBank (\r
-  IN TPMI_ALG_HASH  HashAlg\r
-  )\r
-{\r
-  UINT32  ActivePcrBanks;\r
+  //\r
+  // Determine the current TPM support and the Platform PCR mask.\r
+  //\r
+  Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &TpmActivePcrBanks);\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
-  ActivePcrBanks = PcdGet32 (PcdTpm2HashMask);\r
-  switch (HashAlg) {\r
-  case TPM_ALG_SHA1:\r
-    if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) {\r
-      return TRUE;\r
-    }\r
-    break;\r
-  case TPM_ALG_SHA256:\r
-    if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) {\r
-      return TRUE;\r
-    }\r
-    break;\r
-  case TPM_ALG_SHA384:\r
-    if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) {\r
-      return TRUE;\r
-    }\r
-    break;\r
-  case TPM_ALG_SHA512:\r
-    if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) {\r
-      return TRUE;\r
-    }\r
-    break;\r
-  case TPM_ALG_SM3_256:\r
-    if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) {\r
-      return TRUE;\r
-    }\r
-    break;\r
+  Tpm2PcrMask = PcdGet32 (PcdTpm2HashMask);\r
+  if (Tpm2PcrMask == 0) {\r
+    //\r
+    // if PcdTPm2HashMask is zero, use ActivePcr setting\r
+    //\r
+    PcdSet32S (PcdTpm2HashMask, TpmActivePcrBanks);\r
+    Tpm2PcrMask = TpmActivePcrBanks;\r
   }\r
 \r
-  return FALSE;\r
-}\r
-\r
-/**\r
-  Copy TPML_DIGEST_VALUES into a buffer\r
-\r
-  @param[in,out] Buffer        Buffer to hold TPML_DIGEST_VALUES.\r
-  @param[in]     DigestList    TPML_DIGEST_VALUES to be copied.\r
+  //\r
+  // Find the intersection of Pcd support and TPM support.\r
+  // If banks are missing from the TPM support that are in the PCD, update the PCD.\r
+  // If banks are missing from the PCD that are active in the TPM, reallocate the banks and reboot.\r
+  //\r
 \r
-  @return The end of buffer to hold TPML_DIGEST_VALUES.\r
-**/\r
-VOID *\r
-CopyDigestListToBuffer (\r
-  IN OUT VOID                       *Buffer,\r
-  IN TPML_DIGEST_VALUES             *DigestList\r
-  )\r
-{\r
-  UINTN  Index;\r
-  UINT16 DigestSize;\r
-\r
-  CopyMem (Buffer, &DigestList->count, sizeof(DigestList->count));\r
-  Buffer = (UINT8 *)Buffer + sizeof(DigestList->count);\r
-  for (Index = 0; Index < DigestList->count; Index++) {\r
-    if (!IsHashAlgSupportedInPcrBank (DigestList->digests[Index].hashAlg)) {\r
-      DEBUG ((EFI_D_ERROR, "WARNING: TPM2 Event log has HashAlg unsupported by PCR bank (0x%x)\n", DigestList->digests[Index].hashAlg));\r
-      continue;\r
+  //\r
+  // If there are active PCR banks that are not supported by the Platform mask,\r
+  // update the TPM allocations and reboot the machine.\r
+  //\r
+  if ((TpmActivePcrBanks & Tpm2PcrMask) != TpmActivePcrBanks) {\r
+    NewTpmActivePcrBanks = TpmActivePcrBanks & Tpm2PcrMask;\r
+\r
+    DEBUG ((EFI_D_INFO, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__, TpmActivePcrBanks, NewTpmActivePcrBanks));\r
+    if (NewTpmActivePcrBanks == 0) {\r
+      DEBUG ((EFI_D_ERROR, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));\r
+      ASSERT (FALSE);\r
+    } else {\r
+      Status = Tpm2PcrAllocateBanks (NULL, (UINT32)TpmHashAlgorithmBitmap, NewTpmActivePcrBanks);\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // We can't do much here, but we hope that this doesn't happen.\r
+        //\r
+        DEBUG ((EFI_D_ERROR, "%a - Failed to reallocate PCRs!\n", __FUNCTION__));\r
+        ASSERT_EFI_ERROR (Status);\r
+      }\r
+      //\r
+      // Need reset system, since we just called Tpm2PcrAllocateBanks().\r
+      //\r
+      ResetCold();\r
     }\r
-    CopyMem (Buffer, &DigestList->digests[Index].hashAlg, sizeof(DigestList->digests[Index].hashAlg));\r
-    Buffer = (UINT8 *)Buffer + sizeof(DigestList->digests[Index].hashAlg);\r
-    DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg);\r
-    CopyMem (Buffer, &DigestList->digests[Index].digest, DigestSize);\r
-    Buffer = (UINT8 *)Buffer + DigestSize;\r
   }\r
 \r
-  return Buffer;\r
-}\r
-\r
-/**\r
-  Set Tpm2HashMask PCD value according to TPM2 PCR bank.\r
-**/\r
-VOID\r
-SetTpm2HashMask (\r
-  VOID\r
-  )\r
-{\r
-  EFI_STATUS           Status;\r
-  UINT32               ActivePcrBanks;\r
-  TPML_PCR_SELECTION   Pcrs;\r
-  UINTN                Index;\r
-\r
-  DEBUG ((EFI_D_ERROR, "SetTpm2HashMask!\n"));\r
+  //\r
+  // If there are any PCRs that claim support in the Platform mask that are\r
+  // not supported by the TPM, update the mask.\r
+  //\r
+  if ((Tpm2PcrMask & TpmHashAlgorithmBitmap) != Tpm2PcrMask) {\r
+    NewTpm2PcrMask = Tpm2PcrMask & TpmHashAlgorithmBitmap;\r
 \r
-  Status = Tpm2GetCapabilityPcrs (&Pcrs);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityPcrs fail!\n"));\r
-    ActivePcrBanks = EFI_TCG2_BOOT_HASH_ALG_SHA1;\r
-  } else {\r
-    DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityPcrs Count - %08x\n", Pcrs.count));\r
-    ActivePcrBanks = 0;\r
-    for (Index = 0; Index < Pcrs.count; Index++) {\r
-      DEBUG ((EFI_D_INFO, "hash - %x\n", Pcrs.pcrSelections[Index].hash));\r
-      switch (Pcrs.pcrSelections[Index].hash) {\r
-      case TPM_ALG_SHA1:\r
-        if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {\r
-          ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA1;\r
-        }        \r
-        break;\r
-      case TPM_ALG_SHA256:\r
-        if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {\r
-          ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA256;\r
-        }\r
-        break;\r
-      case TPM_ALG_SHA384:\r
-        if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {\r
-          ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA384;\r
-        }\r
-        break;\r
-      case TPM_ALG_SHA512:\r
-        if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {\r
-          ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA512;\r
-        }\r
-        break;\r
-      case TPM_ALG_SM3_256:\r
-        if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {\r
-          ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SM3_256;\r
-        }\r
-        break;\r
-      }\r
+    DEBUG ((EFI_D_INFO, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__, Tpm2PcrMask, NewTpm2PcrMask));\r
+    if (NewTpm2PcrMask == 0) {\r
+      DEBUG ((EFI_D_ERROR, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));\r
+      ASSERT (FALSE);\r
     }\r
+\r
+    Status = PcdSet32S (PcdTpm2HashMask, NewTpm2PcrMask);\r
+    ASSERT_EFI_ERROR (Status);\r
   }\r
-  Status = PcdSet32S (PcdTpm2HashMask, ActivePcrBanks);\r
-  ASSERT_EFI_ERROR (Status);\r
 }\r
 \r
 /**\r
@@ -420,7 +306,7 @@ LogHashEvent (
       DEBUG ((EFI_D_INFO, "  LogFormat - 0x%08x\n", mTcg2EventInfo[Index].LogFormat));\r
       switch (mTcg2EventInfo[Index].LogFormat) {\r
       case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2:\r
-        Status = Tpm2GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);\r
+        Status = GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);\r
         if (!EFI_ERROR (Status)) {\r
           HobData = BuildGuidHob (\r
                      &gTcgEventEntryHobGuid,\r
@@ -437,6 +323,10 @@ LogHashEvent (
         }\r
         break;\r
       case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2:\r
+        //\r
+        // Use GetDigestListSize (DigestList) in the GUID HOB DataLength calculation\r
+        // to reserve enough buffer to hold TPML_DIGEST_VALUES compact binary.\r
+        //\r
         HobData = BuildGuidHob (\r
                    &gTcgEvent2EntryHobGuid,\r
                    sizeof(TcgPcrEvent2->PCRIndex) + sizeof(TcgPcrEvent2->EventType) + GetDigestListSize (DigestList) + sizeof(TcgPcrEvent2->EventSize) + NewEventHdr->EventSize\r
@@ -450,7 +340,7 @@ LogHashEvent (
         TcgPcrEvent2->PCRIndex = NewEventHdr->PCRIndex;\r
         TcgPcrEvent2->EventType = NewEventHdr->EventType;\r
         DigestBuffer = (UINT8 *)&TcgPcrEvent2->Digest;\r
-        DigestBuffer = CopyDigestListToBuffer (DigestBuffer, DigestList);\r
+        DigestBuffer = CopyDigestListToBuffer (DigestBuffer, DigestList, PcdGet32 (PcdTpm2HashMask));\r
         CopyMem (DigestBuffer, &NewEventHdr->EventSize, sizeof(TcgPcrEvent2->EventSize));\r
         DigestBuffer = DigestBuffer + sizeof(TcgPcrEvent2->EventSize);\r
         CopyMem (DigestBuffer, NewEventData, NewEventHdr->EventSize);\r
@@ -571,53 +461,152 @@ MeasureFvImage (
   IN UINT64                         FvLength\r
   )\r
 {\r
-  UINT32                            Index;\r
-  EFI_STATUS                        Status;\r
-  EFI_PLATFORM_FIRMWARE_BLOB        FvBlob;\r
-  TCG_PCR_EVENT_HDR                 TcgEventHdr;\r
+  UINT32                                                Index;\r
+  EFI_STATUS                                            Status;\r
+  EFI_PLATFORM_FIRMWARE_BLOB                            FvBlob;\r
+  TCG_PCR_EVENT_HDR                                     TcgEventHdr;\r
+  UINT32                                                Instance;\r
+  UINT32                                                Tpm2HashMask;\r
+  TPML_DIGEST_VALUES                                    DigestList;\r
+  UINT32                                                DigestCount;\r
+  EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *MeasurementExcludedFvPpi;\r
+  EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI       *PrehashedFvPpi;\r
+  HASH_INFO                                             *PreHashInfo;\r
+  UINT32                                                HashAlgoMask;\r
 \r
   //\r
-  // Check if it is in Excluded FV list\r
+  // Check Excluded FV list\r
   //\r
-  if (mMeasurementExcludedFvPpi != NULL) {\r
-    for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) {\r
-      if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {\r
-        DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));\r
-        DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));\r
-        return EFI_SUCCESS;\r
+  Instance = 0;\r
+  do {\r
+    Status = PeiServicesLocatePpi(\r
+                 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,\r
+                 Instance,\r
+                 NULL,\r
+                 (VOID**)&MeasurementExcludedFvPpi\r
+                 );\r
+    if (!EFI_ERROR(Status)) {\r
+      for (Index = 0; Index < MeasurementExcludedFvPpi->Count; Index ++) {\r
+        if (MeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase\r
+         && MeasurementExcludedFvPpi->Fv[Index].FvLength == FvLength) {\r
+          DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei starts at: 0x%x\n", FvBase));\r
+          DEBUG ((DEBUG_INFO, "The FV which is excluded by Tcg2Pei has the size: 0x%x\n", FvLength));\r
+          return EFI_SUCCESS;\r
+        }\r
       }\r
+\r
+      Instance++;\r
     }\r
-  }\r
+  } while (!EFI_ERROR(Status));\r
 \r
   //\r
-  // Check whether FV is in the measured FV list.\r
+  // Check measured FV list\r
   //\r
   for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {\r
-    if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) {\r
+    if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase && mMeasuredBaseFvInfo[Index].BlobLength == FvLength) {\r
+      DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei starts at: 0x%x\n", FvBase));\r
+      DEBUG ((DEBUG_INFO, "The FV which is already measured by Tcg2Pei has the size: 0x%x\n", FvLength));\r
       return EFI_SUCCESS;\r
     }\r
   }\r
-  \r
+\r
   //\r
-  // Measure and record the FV to the TPM\r
+  // Check pre-hashed FV list\r
   //\r
-  FvBlob.BlobBase   = FvBase;\r
-  FvBlob.BlobLength = FvLength;\r
+  Instance     = 0;\r
+  Tpm2HashMask = PcdGet32 (PcdTpm2HashMask);\r
+  do {\r
+    Status = PeiServicesLocatePpi (\r
+               &gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid,\r
+               Instance,\r
+               NULL,\r
+               (VOID**)&PrehashedFvPpi\r
+               );\r
+    if (!EFI_ERROR(Status) && PrehashedFvPpi->FvBase == FvBase && PrehashedFvPpi->FvLength == FvLength) {\r
+      ZeroMem (&DigestList, sizeof(TPML_DIGEST_VALUES));\r
 \r
-  DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));\r
-  DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));\r
+      //\r
+      // The FV is prehashed, check against TPM hash mask\r
+      //\r
+      PreHashInfo = (HASH_INFO *)(PrehashedFvPpi + 1);\r
+      for (Index = 0, DigestCount = 0; Index < PrehashedFvPpi->Count; Index++) {\r
+        DEBUG((DEBUG_INFO, "Hash Algo ID in PrehashedFvPpi=0x%x\n", PreHashInfo->HashAlgoId));\r
+        HashAlgoMask = GetHashMaskFromAlgo(PreHashInfo->HashAlgoId);\r
+        if ((Tpm2HashMask & HashAlgoMask) != 0 ) {\r
+          //\r
+          // Hash is required, copy it to DigestList\r
+          //\r
+          WriteUnaligned16(&(DigestList.digests[DigestCount].hashAlg), PreHashInfo->HashAlgoId);\r
+          CopyMem (\r
+            &DigestList.digests[DigestCount].digest,\r
+            PreHashInfo + 1,\r
+            PreHashInfo->HashSize\r
+            );\r
+          DigestCount++;\r
+          //\r
+          // Clean the corresponding Hash Algo mask bit\r
+          //\r
+          Tpm2HashMask &= ~HashAlgoMask;\r
+        }\r
+        PreHashInfo = (HASH_INFO *)((UINT8 *)(PreHashInfo + 1) + PreHashInfo->HashSize);\r
+      }\r
+\r
+      WriteUnaligned32(&DigestList.count, DigestCount);\r
 \r
-  TcgEventHdr.PCRIndex = 0;\r
+      break;\r
+    }\r
+    Instance++;\r
+  } while (!EFI_ERROR(Status));\r
+\r
+  //\r
+  // Init the log event for FV measurement\r
+  //\r
+  FvBlob.BlobBase       = FvBase;\r
+  FvBlob.BlobLength     = FvLength;\r
+  TcgEventHdr.PCRIndex  = 0;\r
   TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;\r
   TcgEventHdr.EventSize = sizeof (FvBlob);\r
 \r
-  Status = HashLogExtendEvent (\r
-             0,\r
-             (UINT8*) (UINTN) FvBlob.BlobBase,\r
-             (UINTN) FvBlob.BlobLength,\r
-             &TcgEventHdr,\r
-             (UINT8*) &FvBlob\r
-             );\r
+  if (Tpm2HashMask == 0) {\r
+    //\r
+    // FV pre-hash algos comply with current TPM hash requirement\r
+    // Skip hashing step in measure, only extend DigestList to PCR and log event\r
+    //\r
+    Status = Tpm2PcrExtend(\r
+               0,\r
+               &DigestList\r
+               );\r
+\r
+    if (!EFI_ERROR(Status)) {\r
+       Status = LogHashEvent (&DigestList, &TcgEventHdr, (UINT8*) &FvBlob);\r
+       DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));\r
+       DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));\r
+    } else if (Status == EFI_DEVICE_ERROR) {\r
+      BuildGuidHob (&gTpmErrorHobGuid,0);\r
+      REPORT_STATUS_CODE (\r
+        EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+        (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)\r
+        );\r
+    }\r
+  } else {\r
+    //\r
+    // Hash the FV, extend digest to the TPM and log TCG event\r
+    //\r
+    Status = HashLogExtendEvent (\r
+               0,\r
+               (UINT8*) (UINTN) FvBlob.BlobBase,\r
+               (UINTN) FvBlob.BlobLength,\r
+               &TcgEventHdr,\r
+               (UINT8*) &FvBlob\r
+               );\r
+    DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei starts at: 0x%x\n", FvBlob.BlobBase));\r
+    DEBUG ((DEBUG_INFO, "The FV which is measured by Tcg2Pei has the size: 0x%x\n", FvBlob.BlobLength));\r
+  }\r
+\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((DEBUG_ERROR, "The FV which failed to be measured starts at: 0x%x\n", FvBase));\r
+    return Status;\r
+  }\r
 \r
   //\r
   // Add new FV into the measured FV list.\r
@@ -646,47 +635,44 @@ MeasureMainBios (
   )\r
 {\r
   EFI_STATUS                        Status;\r
-  UINT32                            FvInstances;\r
   EFI_PEI_FV_HANDLE                 VolumeHandle;\r
   EFI_FV_INFO                       VolumeInfo;\r
   EFI_PEI_FIRMWARE_VOLUME_PPI       *FvPpi;\r
 \r
   PERF_START_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI);\r
-  FvInstances    = 0;\r
-  while (TRUE) {\r
-    //\r
-    // Traverse all firmware volume instances of Static Core Root of Trust for Measurement\r
-    // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special\r
-    // platform for special CRTM TPM measuring.\r
-    //\r
-    Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);\r
-    if (EFI_ERROR (Status)) {\r
-      break;\r
-    }\r
-  \r
-    //\r
-    // Measure and record the firmware volume that is dispatched by PeiCore\r
-    //\r
-    Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);\r
-    ASSERT_EFI_ERROR (Status);\r
-    //\r
-    // Locate the corresponding FV_PPI according to founded FV's format guid\r
-    //\r
-    Status = PeiServicesLocatePpi (\r
-               &VolumeInfo.FvFormat, \r
-               0, \r
-               NULL,\r
-               (VOID**)&FvPpi\r
-               );\r
-    if (!EFI_ERROR (Status)) {\r
-      MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);\r
-    }\r
 \r
-    FvInstances++;\r
-  }\r
+  //\r
+  // Only measure BFV at the very beginning. Other parts of Static Core Root of\r
+  // Trust for Measurement(S-CRTM) will be measured later on FvInfoNotify.\r
+  // BFV is processed without installing FV Info Ppi. Other FVs either inside BFV or\r
+  // reported by platform will be installed with Fv Info Ppi\r
+  // This firmware volume measure policy can be modified/enhanced by special\r
+  // platform for special CRTM TPM measuring.\r
+  //\r
+  Status = PeiServicesFfsFindNextVolume (0, &VolumeHandle);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Measure and record the firmware volume that is dispatched by PeiCore\r
+  //\r
+  Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);\r
+  ASSERT_EFI_ERROR (Status);\r
+  //\r
+  // Locate the corresponding FV_PPI according to founded FV's format guid\r
+  //\r
+  Status = PeiServicesLocatePpi (\r
+             &VolumeInfo.FvFormat,\r
+             0,\r
+             NULL,\r
+             (VOID**)&FvPpi\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);\r
+\r
   PERF_END_EX (mFileHandle, "EventRec", "Tcg2Pei", 0, PERF_ID_TCG2_PEI + 1);\r
 \r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -771,14 +757,6 @@ PeimEntryMP (
 {\r
   EFI_STATUS                        Status;\r
 \r
-  Status = PeiServicesLocatePpi (\r
-               &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid, \r
-               0, \r
-               NULL,\r
-               (VOID**)&mMeasurementExcludedFvPpi\r
-               );\r
-  // Do not check status, because it is optional\r
-\r
   mMeasuredBaseFvInfo  = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));\r
   ASSERT (mMeasuredBaseFvInfo != NULL);\r
   mMeasuredChildFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));\r
@@ -789,6 +767,9 @@ PeimEntryMP (
   }\r
 \r
   Status = MeasureMainBios ();\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
 \r
   //\r
   // Post callbacks:\r
@@ -852,7 +833,7 @@ PeimEntryMA (
 \r
   if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||\r
       CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){\r
-    DEBUG ((EFI_D_ERROR, "No TPM2 instance required!\n"));\r
+    DEBUG ((DEBUG_INFO, "No TPM2 instance required!\n"));\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
@@ -908,7 +889,7 @@ PeimEntryMA (
     //\r
     // Update Tpm2HashMask according to PCR bank.\r
     //\r
-    SetTpm2HashMask ();\r
+    SyncPcrAllocationsAndPcrMask ();\r
 \r
     if (S3ErrorReport) {\r
       //\r