]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / SecurityPkg / Library / DxeTpmMeasureBootLib / DxeTpmMeasureBootLib.c
index 803c7876a5777889b5afc5326d3bacb98d4f9c4c..220393dd2beb6270da17d29b726ef725be7dd0e4 100644 (file)
@@ -1,24 +1,33 @@
 /** @file\r
-  The library instance provides security service of TPM measure boot.  \r
+  The library instance provides security service of TPM measure boot.\r
 \r
-Copyright (c) 2009 - 2012, Intel 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
-http://opensource.org/licenses/bsd-license.php\r
+  Caution: This file requires additional review when modified.\r
+  This library will have external input - PE/COFF image and GPT partition.\r
+  This external input must be validated carefully to avoid security issue like\r
+  buffer overflow, integer overflow.\r
 \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF image content\r
+  read is within the image buffer.\r
+\r
+  TcgMeasurePeImage() function will accept untrusted PE/COFF image and validate its\r
+  data structure within this image buffer before use.\r
+\r
+  TcgMeasureGptTable() function will receive untrusted GPT partition table, and parse\r
+  partition data carefully.\r
+\r
+Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include <PiDxe.h>\r
 \r
 #include <Protocol/TcgService.h>\r
-#include <Protocol/FirmwareVolume2.h>\r
 #include <Protocol/BlockIo.h>\r
 #include <Protocol/DiskIo.h>\r
-#include <Protocol/DevicePathToText.h>\r
+#include <Protocol/FirmwareVolumeBlock.h>\r
+\r
+#include <Guid/MeasuredFvHob.h>\r
 \r
 #include <Library/BaseLib.h>\r
 #include <Library/DebugLib.h>\r
@@ -29,39 +38,48 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/BaseCryptLib.h>\r
 #include <Library/PeCoffLib.h>\r
 #include <Library/SecurityManagementLib.h>\r
+#include <Library/HobLib.h>\r
 \r
 //\r
 // Flag to check GPT partition. It only need be measured once.\r
 //\r
-BOOLEAN                           mMeasureGptTableFlag = FALSE;\r
-EFI_GUID                          mZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
-UINTN                             mMeasureGptCount = 0;\r
-VOID                              *mFileBuffer;\r
-UINTN                             mImageSize;\r
+BOOLEAN  mMeasureGptTableFlag = FALSE;\r
+UINTN    mMeasureGptCount     = 0;\r
+VOID     *mFileBuffer;\r
+UINTN    mTpmImageSize;\r
+//\r
+// Measured FV handle cache\r
+//\r
+EFI_HANDLE         mCacheMeasuredHandle = NULL;\r
+MEASURED_HOB_DATA  *mMeasuredHobData    = NULL;\r
 \r
 /**\r
   Reads contents of a PE/COFF image in memory buffer.\r
 \r
+  Caution: This function may receive untrusted input.\r
+  PE/COFF image is external input, so this function will make sure the PE/COFF image content\r
+  read is within the image buffer.\r
+\r
   @param  FileHandle      Pointer to the file handle to read the PE/COFF image.\r
   @param  FileOffset      Offset into the PE/COFF image to begin the read operation.\r
-  @param  ReadSize        On input, the size in bytes of the requested read operation.  \r
+  @param  ReadSize        On input, the size in bytes of the requested read operation.\r
                           On output, the number of bytes actually read.\r
   @param  Buffer          Output buffer that contains the data read from the PE/COFF image.\r
-  \r
-  @retval EFI_SUCCESS     The specified portion of the PE/COFF image was read and the size \r
+\r
+  @retval EFI_SUCCESS     The specified portion of the PE/COFF image was read and the size\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 DxeTpmMeasureBootLibImageRead (\r
-  IN     VOID    *FileHandle,\r
-  IN     UINTN   FileOffset,\r
-  IN OUT UINTN   *ReadSize,\r
-  OUT    VOID    *Buffer\r
+  IN     VOID   *FileHandle,\r
+  IN     UINTN  FileOffset,\r
+  IN OUT UINTN  *ReadSize,\r
+  OUT    VOID   *Buffer\r
   )\r
 {\r
-  UINTN               EndPosition;\r
+  UINTN  EndPosition;\r
 \r
-  if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {\r
+  if ((FileHandle == NULL) || (ReadSize == NULL) || (Buffer == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -70,15 +88,15 @@ DxeTpmMeasureBootLibImageRead (
   }\r
 \r
   EndPosition = FileOffset + *ReadSize;\r
-  if (EndPosition > mImageSize) {\r
-    *ReadSize = (UINT32)(mImageSize - FileOffset);\r
+  if (EndPosition > mTpmImageSize) {\r
+    *ReadSize = (UINT32)(mTpmImageSize - FileOffset);\r
   }\r
 \r
-  if (FileOffset >= mImageSize) {\r
+  if (FileOffset >= mTpmImageSize) {\r
     *ReadSize = 0;\r
   }\r
 \r
-  CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize);\r
+  CopyMem (Buffer, (UINT8 *)((UINTN)FileHandle + FileOffset), *ReadSize);\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -86,6 +104,9 @@ DxeTpmMeasureBootLibImageRead (
 /**\r
   Measure GPT table data into TPM log.\r
 \r
+  Caution: This function may receive untrusted input.\r
+  The GPT partition table is external input, so this function should parse partition data carefully.\r
+\r
   @param TcgProtocol             Pointer to the located TCG protocol instance.\r
   @param GptHandle               Handle that GPT partition was installed.\r
 \r
@@ -98,43 +119,46 @@ DxeTpmMeasureBootLibImageRead (
 EFI_STATUS\r
 EFIAPI\r
 TcgMeasureGptTable (\r
-  IN  EFI_TCG_PROTOCOL   *TcgProtocol,\r
-  IN  EFI_HANDLE         GptHandle\r
+  IN  EFI_TCG_PROTOCOL  *TcgProtocol,\r
+  IN  EFI_HANDLE        GptHandle\r
   )\r
 {\r
-  EFI_STATUS                        Status;\r
-  EFI_BLOCK_IO_PROTOCOL             *BlockIo;\r
-  EFI_DISK_IO_PROTOCOL              *DiskIo;\r
-  EFI_PARTITION_TABLE_HEADER        *PrimaryHeader;\r
-  EFI_PARTITION_ENTRY               *PartitionEntry;\r
-  UINT8                             *EntryPtr;\r
-  UINTN                             NumberOfPartition;\r
-  UINT32                            Index;\r
-  TCG_PCR_EVENT                     *TcgEvent;\r
-  EFI_GPT_DATA                      *GptData;\r
-  UINT32                            EventSize;\r
-  UINT32                            EventNumber;\r
-  EFI_PHYSICAL_ADDRESS              EventLogLastEntry;\r
+  EFI_STATUS                  Status;\r
+  EFI_BLOCK_IO_PROTOCOL       *BlockIo;\r
+  EFI_DISK_IO_PROTOCOL        *DiskIo;\r
+  EFI_PARTITION_TABLE_HEADER  *PrimaryHeader;\r
+  EFI_PARTITION_ENTRY         *PartitionEntry;\r
+  UINT8                       *EntryPtr;\r
+  UINTN                       NumberOfPartition;\r
+  UINT32                      Index;\r
+  TCG_PCR_EVENT               *TcgEvent;\r
+  EFI_GPT_DATA                *GptData;\r
+  UINT32                      EventSize;\r
+  UINT32                      EventNumber;\r
+  EFI_PHYSICAL_ADDRESS        EventLogLastEntry;\r
 \r
   if (mMeasureGptCount > 0) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
-  Status = gBS->HandleProtocol (GptHandle, &gEfiBlockIoProtocolGuid, (VOID**)&BlockIo);\r
+  Status = gBS->HandleProtocol (GptHandle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
   if (EFI_ERROR (Status)) {\r
     return EFI_UNSUPPORTED;\r
   }\r
-  Status = gBS->HandleProtocol (GptHandle, &gEfiDiskIoProtocolGuid, (VOID**)&DiskIo);\r
+\r
+  Status = gBS->HandleProtocol (GptHandle, &gEfiDiskIoProtocolGuid, (VOID **)&DiskIo);\r
   if (EFI_ERROR (Status)) {\r
     return EFI_UNSUPPORTED;\r
   }\r
+\r
   //\r
   // Read the EFI Partition Table Header\r
-  //  \r
-  PrimaryHeader = (EFI_PARTITION_TABLE_HEADER *) AllocatePool (BlockIo->Media->BlockSize);\r
+  //\r
+  PrimaryHeader = (EFI_PARTITION_TABLE_HEADER *)AllocatePool (BlockIo->Media->BlockSize);\r
   if (PrimaryHeader == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
-  }  \r
+  }\r
+\r
   Status = DiskIo->ReadDisk (\r
                      DiskIo,\r
                      BlockIo->Media->MediaId,\r
@@ -143,10 +167,11 @@ TcgMeasureGptTable (
                      (UINT8 *)PrimaryHeader\r
                      );\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "Failed to Read Partition Table Header!\n"));\r
+    DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n"));\r
     FreePool (PrimaryHeader);\r
     return EFI_DEVICE_ERROR;\r
-  }  \r
+  }\r
+\r
   //\r
   // Read the partition entry.\r
   //\r
@@ -155,10 +180,11 @@ TcgMeasureGptTable (
     FreePool (PrimaryHeader);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
+\r
   Status = DiskIo->ReadDisk (\r
                      DiskIo,\r
                      BlockIo->Media->MediaId,\r
-                     MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),\r
+                     MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),\r
                      PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry,\r
                      EntryPtr\r
                      );\r
@@ -167,48 +193,49 @@ TcgMeasureGptTable (
     FreePool (EntryPtr);\r
     return EFI_DEVICE_ERROR;\r
   }\r
-  \r
+\r
   //\r
   // Count the valid partition\r
   //\r
   PartitionEntry    = (EFI_PARTITION_ENTRY *)EntryPtr;\r
   NumberOfPartition = 0;\r
   for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {\r
-    if (!CompareGuid (&PartitionEntry->PartitionTypeGUID, &mZeroGuid)) {\r
-      NumberOfPartition++;  \r
+    if (!IsZeroGuid (&PartitionEntry->PartitionTypeGUID)) {\r
+      NumberOfPartition++;\r
     }\r
+\r
     PartitionEntry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);\r
   }\r
 \r
   //\r
   // Prepare Data for Measurement\r
-  // \r
-  EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) \r
-                        + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);\r
-  TcgEvent = (TCG_PCR_EVENT *) AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT_HDR));\r
+  //\r
+  EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions)\r
+                       + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);\r
+  TcgEvent = (TCG_PCR_EVENT *)AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT_HDR));\r
   if (TcgEvent == NULL) {\r
     FreePool (PrimaryHeader);\r
     FreePool (EntryPtr);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  TcgEvent->PCRIndex   = 5;\r
-  TcgEvent->EventType  = EV_EFI_GPT_EVENT;\r
-  TcgEvent->EventSize  = EventSize;\r
-  GptData = (EFI_GPT_DATA *) TcgEvent->Event;  \r
+  TcgEvent->PCRIndex  = 5;\r
+  TcgEvent->EventType = EV_EFI_GPT_EVENT;\r
+  TcgEvent->EventSize = EventSize;\r
+  GptData             = (EFI_GPT_DATA *)TcgEvent->Event;\r
 \r
   //\r
   // Copy the EFI_PARTITION_TABLE_HEADER and NumberOfPartition\r
-  //  \r
-  CopyMem ((UINT8 *)GptData, (UINT8*)PrimaryHeader, sizeof (EFI_PARTITION_TABLE_HEADER));\r
+  //\r
+  CopyMem ((UINT8 *)GptData, (UINT8 *)PrimaryHeader, sizeof (EFI_PARTITION_TABLE_HEADER));\r
   GptData->NumberOfPartitions = NumberOfPartition;\r
   //\r
   // Copy the valid partition entry\r
   //\r
-  PartitionEntry    = (EFI_PARTITION_ENTRY*)EntryPtr;\r
+  PartitionEntry    = (EFI_PARTITION_ENTRY *)EntryPtr;\r
   NumberOfPartition = 0;\r
   for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {\r
-    if (!CompareGuid (&PartitionEntry->PartitionTypeGUID, &mZeroGuid)) {\r
+    if (!IsZeroGuid (&PartitionEntry->PartitionTypeGUID)) {\r
       CopyMem (\r
         (UINT8 *)&GptData->Partitions + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry,\r
         (UINT8 *)PartitionEntry,\r
@@ -216,22 +243,23 @@ TcgMeasureGptTable (
         );\r
       NumberOfPartition++;\r
     }\r
-    PartitionEntry =(EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);\r
+\r
+    PartitionEntry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);\r
   }\r
 \r
   //\r
   // Measure the GPT data\r
   //\r
   EventNumber = 1;\r
-  Status = TcgProtocol->HashLogExtendEvent (\r
-             TcgProtocol,\r
-             (EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) GptData,\r
-             (UINT64) TcgEvent->EventSize,\r
-             TPM_ALG_SHA,\r
-             TcgEvent,\r
-             &EventNumber,\r
-             &EventLogLastEntry\r
-             );\r
+  Status      = TcgProtocol->HashLogExtendEvent (\r
+                               TcgProtocol,\r
+                               (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData,\r
+                               (UINT64)TcgEvent->EventSize,\r
+                               TPM_ALG_SHA,\r
+                               TcgEvent,\r
+                               &EventNumber,\r
+                               &EventLogLastEntry\r
+                               );\r
   if (!EFI_ERROR (Status)) {\r
     mMeasureGptCount++;\r
   }\r
@@ -247,6 +275,13 @@ TcgMeasureGptTable (
   Measure PE image into TPM log based on the authenticode image hashing in\r
   PE/COFF Specification 8.0 Appendix A.\r
 \r
+  Caution: This function may receive untrusted input.\r
+  PE/COFF image is external input, so this function will validate its data structure\r
+  within this image buffer before use.\r
+\r
+  Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in\r
+  its caller function DxeTpmMeasureBootHandler().\r
+\r
   @param[in] TcgProtocol    Pointer to the located TCG protocol instance.\r
   @param[in] ImageAddress   Start address of image buffer.\r
   @param[in] ImageSize      Image size\r
@@ -256,7 +291,7 @@ TcgMeasureGptTable (
 \r
   @retval EFI_SUCCESS            Successfully measure image.\r
   @retval EFI_OUT_OF_RESOURCES   No enough resource to measure image.\r
-  @retval EFI_UNSUPPORTED        ImageType is unsupported or PE image is mal-format.  \r
+  @retval EFI_UNSUPPORTED        ImageType is unsupported or PE image is mal-format.\r
   @retval other error value\r
 \r
 **/\r
@@ -286,7 +321,6 @@ TcgMeasurePeImage (
   EFI_IMAGE_SECTION_HEADER             *SectionHeader;\r
   UINTN                                Index;\r
   UINTN                                Pos;\r
-  UINT16                               Magic;\r
   UINT32                               EventSize;\r
   UINT32                               EventNumber;\r
   EFI_PHYSICAL_ADDRESS                 EventLogLastEntry;\r
@@ -299,19 +333,19 @@ TcgMeasurePeImage (
   ImageLoad     = NULL;\r
   SectionHeader = NULL;\r
   Sha1Ctx       = NULL;\r
-  FilePathSize  = (UINT32) GetDevicePathSize (FilePath);\r
+  FilePathSize  = (UINT32)GetDevicePathSize (FilePath);\r
 \r
   //\r
   // Determine destination PCR by BootPolicy\r
   //\r
   EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;\r
-  TcgEvent = AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT));\r
+  TcgEvent  = AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT));\r
   if (TcgEvent == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
   TcgEvent->EventSize = EventSize;\r
-  ImageLoad           = (EFI_IMAGE_LOAD_EVENT *) TcgEvent->Event;\r
+  ImageLoad           = (EFI_IMAGE_LOAD_EVENT *)TcgEvent->Event;\r
 \r
   switch (ImageType) {\r
     case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:\r
@@ -328,7 +362,7 @@ TcgMeasurePeImage (
       break;\r
     default:\r
       DEBUG ((\r
-        EFI_D_ERROR,\r
+        DEBUG_ERROR,\r
         "TcgMeasurePeImage: Unknown subsystem type %d",\r
         ImageType\r
         ));\r
@@ -339,18 +373,20 @@ TcgMeasurePeImage (
   ImageLoad->ImageLengthInMemory   = ImageSize;\r
   ImageLoad->ImageLinkTimeAddress  = LinkTimeBase;\r
   ImageLoad->LengthOfDevicePath    = FilePathSize;\r
-  CopyMem (ImageLoad->DevicePath, FilePath, FilePathSize);\r
+  if ((FilePath != NULL) && (FilePathSize != 0)) {\r
+    CopyMem (ImageLoad->DevicePath, FilePath, FilePathSize);\r
+  }\r
 \r
   //\r
   // Check PE/COFF image\r
   //\r
-  DosHdr = (EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress;\r
+  DosHdr             = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageAddress;\r
   PeCoffHeaderOffset = 0;\r
   if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
     PeCoffHeaderOffset = DosHdr->e_lfanew;\r
   }\r
 \r
-  Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset);\r
+  Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *)(UINTN)ImageAddress + PeCoffHeaderOffset);\r
   if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
     goto Finish;\r
   }\r
@@ -382,31 +418,30 @@ TcgMeasurePeImage (
   // Measuring PE/COFF Image Header;\r
   // But CheckSum field and SECURITY data directory (certificate) are excluded\r
   //\r
-  Magic = Hdr.Pe32->OptionalHeader.Magic;\r
-  \r
+\r
   //\r
   // 3.  Calculate the distance from the base of the image header to the image checksum address.\r
   // 4.  Hash the image header from its base to beginning of the image checksum.\r
   //\r
-  HashBase = (UINT8 *) (UINTN) ImageAddress;\r
-  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+  HashBase = (UINT8 *)(UINTN)ImageAddress;\r
+  if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
     //\r
     // Use PE32 offset\r
     //\r
     NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
-    HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.CheckSum) - HashBase);\r
+    HashSize            = (UINTN)(&Hdr.Pe32->OptionalHeader.CheckSum) - (UINTN)HashBase;\r
   } else {\r
     //\r
     // Use PE32+ offset\r
     //\r
     NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
-    HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - HashBase);\r
+    HashSize            = (UINTN)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - (UINTN)HashBase;\r
   }\r
 \r
   HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
   if (!HashStatus) {\r
     goto Finish;\r
-  }  \r
+  }\r
 \r
   //\r
   // 5.  Skip over the image checksum (it occupies a single ULONG).\r
@@ -416,46 +451,46 @@ TcgMeasurePeImage (
     // 6.  Since there is no Cert Directory in optional header, hash everything\r
     //     from the end of the checksum to the end of image header.\r
     //\r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
       //\r
       // Use PE32 offset.\r
       //\r
-      HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
-      HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);\r
+      HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
+      HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);\r
     } else {\r
       //\r
       // Use PE32+ offset.\r
       //\r
-      HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
-      HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);\r
+      HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
+      HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);\r
     }\r
 \r
     if (HashSize != 0) {\r
-      HashStatus  = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
+      HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
       if (!HashStatus) {\r
         goto Finish;\r
       }\r
-    }    \r
+    }\r
   } else {\r
     //\r
     // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.\r
     //\r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
       //\r
       // Use PE32 offset\r
       //\r
-      HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
-      HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+      HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
+      HashSize = (UINTN)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;\r
     } else {\r
       //\r
       // Use PE32+ offset\r
-      //    \r
-      HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
-      HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+      //\r
+      HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
+      HashSize = (UINTN)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;\r
     }\r
 \r
     if (HashSize != 0) {\r
-      HashStatus  = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
+      HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
       if (!HashStatus) {\r
         goto Finish;\r
       }\r
@@ -465,22 +500,22 @@ TcgMeasurePeImage (
     // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
     // 9.  Hash everything from the end of the Cert Directory to the end of image header.\r
     //\r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
       //\r
       // Use PE32 offset\r
       //\r
-      HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
-      HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);\r
+      HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
+      HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);\r
     } else {\r
       //\r
       // Use PE32+ offset\r
       //\r
-      HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
-      HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - ImageAddress);\r
+      HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
+      HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);\r
     }\r
-    \r
+\r
     if (HashSize != 0) {\r
-      HashStatus  = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
+      HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
       if (!HashStatus) {\r
         goto Finish;\r
       }\r
@@ -490,7 +525,7 @@ TcgMeasurePeImage (
   //\r
   // 10. Set the SUM_OF_BYTES_HASHED to the size of the header\r
   //\r
-  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+  if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
     //\r
     // Use PE32 offset\r
     //\r
@@ -508,7 +543,7 @@ TcgMeasurePeImage (
   //     header indicates how big the table should be. Do not include any\r
   //     IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.\r
   //\r
-  SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections);\r
+  SectionHeader = (EFI_IMAGE_SECTION_HEADER *)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections);\r
   if (SectionHeader == NULL) {\r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto Finish;\r
@@ -520,20 +555,21 @@ TcgMeasurePeImage (
   //      words, sort the section headers according to the disk-file offset of\r
   //      the section.\r
   //\r
-  Section = (EFI_IMAGE_SECTION_HEADER *) (\r
-               (UINT8 *) (UINTN) ImageAddress +\r
-               PeCoffHeaderOffset +\r
-               sizeof(UINT32) +\r
-               sizeof(EFI_IMAGE_FILE_HEADER) +\r
-               Hdr.Pe32->FileHeader.SizeOfOptionalHeader\r
-               );\r
+  Section = (EFI_IMAGE_SECTION_HEADER *)(\r
+                                         (UINT8 *)(UINTN)ImageAddress +\r
+                                         PeCoffHeaderOffset +\r
+                                         sizeof (UINT32) +\r
+                                         sizeof (EFI_IMAGE_FILE_HEADER) +\r
+                                         Hdr.Pe32->FileHeader.SizeOfOptionalHeader\r
+                                         );\r
   for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {\r
     Pos = Index;\r
     while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {\r
-      CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof(EFI_IMAGE_SECTION_HEADER));\r
+      CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));\r
       Pos--;\r
     }\r
-    CopyMem (&SectionHeader[Pos], Section, sizeof(EFI_IMAGE_SECTION_HEADER));\r
+\r
+    CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));\r
     Section += 1;\r
   }\r
 \r
@@ -545,12 +581,13 @@ TcgMeasurePeImage (
   // 15.  Repeat steps 13 and 14 for all the sections in the sorted table.\r
   //\r
   for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {\r
-    Section  = (EFI_IMAGE_SECTION_HEADER *) &SectionHeader[Index];\r
+    Section = (EFI_IMAGE_SECTION_HEADER *)&SectionHeader[Index];\r
     if (Section->SizeOfRawData == 0) {\r
       continue;\r
     }\r
-    HashBase = (UINT8 *) (UINTN) ImageAddress + Section->PointerToRawData;\r
-    HashSize = (UINTN) Section->SizeOfRawData;\r
+\r
+    HashBase = (UINT8 *)(UINTN)ImageAddress + Section->PointerToRawData;\r
+    HashSize = (UINTN)Section->SizeOfRawData;\r
 \r
     HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
     if (!HashStatus) {\r
@@ -567,12 +604,12 @@ TcgMeasurePeImage (
   //             FileSize  -  (CertDirectory->Size)\r
   //\r
   if (ImageSize > SumOfBytesHashed) {\r
-    HashBase = (UINT8 *) (UINTN) ImageAddress + SumOfBytesHashed;\r
+    HashBase = (UINT8 *)(UINTN)ImageAddress + SumOfBytesHashed;\r
 \r
     if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
       CertSize = 0;\r
     } else {\r
-      if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
         //\r
         // Use PE32 offset.\r
         //\r
@@ -586,7 +623,7 @@ TcgMeasurePeImage (
     }\r
 \r
     if (ImageSize > CertSize + SumOfBytesHashed) {\r
-      HashSize = (UINTN) (ImageSize - CertSize - SumOfBytesHashed);\r
+      HashSize = (UINTN)(ImageSize - CertSize - SumOfBytesHashed);\r
 \r
       HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);\r
       if (!HashStatus) {\r
@@ -600,7 +637,7 @@ TcgMeasurePeImage (
   //\r
   // 17.  Finalize the SHA hash.\r
   //\r
-  HashStatus = Sha1Final (Sha1Ctx, (UINT8 *) &TcgEvent->Digest);\r
+  HashStatus = Sha1Final (Sha1Ctx, (UINT8 *)&TcgEvent->Digest);\r
   if (!HashStatus) {\r
     goto Finish;\r
   }\r
@@ -609,15 +646,23 @@ TcgMeasurePeImage (
   // Log the PE data\r
   //\r
   EventNumber = 1;\r
-  Status = TcgProtocol->HashLogExtendEvent (\r
-             TcgProtocol,\r
-             (EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) NULL,\r
-             0,\r
-             TPM_ALG_SHA,\r
-             TcgEvent,\r
-             &EventNumber,\r
-             &EventLogLastEntry\r
-             );\r
+  Status      = TcgProtocol->HashLogExtendEvent (\r
+                               TcgProtocol,\r
+                               (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)NULL,\r
+                               0,\r
+                               TPM_ALG_SHA,\r
+                               TcgEvent,\r
+                               &EventNumber,\r
+                               &EventLogLastEntry\r
+                               );\r
+  if (Status == EFI_OUT_OF_RESOURCES) {\r
+    //\r
+    // Out of resource here means the image is hashed and its result is extended to PCR.\r
+    // But the event log can't be saved since log area is full.\r
+    // Just return EFI_SUCCESS in order not to block the image load.\r
+    //\r
+    Status = EFI_SUCCESS;\r
+  }\r
 \r
 Finish:\r
   FreePool (TcgEvent);\r
@@ -629,80 +674,75 @@ Finish:
   if (Sha1Ctx != NULL ) {\r
     FreePool (Sha1Ctx);\r
   }\r
+\r
   return Status;\r
 }\r
 \r
 /**\r
-  The security handler is used to abstract platform-specific policy \r
-  from the DXE core response to an attempt to use a file that returns a \r
-  given status for the authentication check from the section extraction protocol.  \r
+  The security handler is used to abstract platform-specific policy\r
+  from the DXE core response to an attempt to use a file that returns a\r
+  given status for the authentication check from the section extraction protocol.\r
 \r
-  The possible responses in a given SAP implementation may include locking \r
-  flash upon failure to authenticate, attestation logging for all signed drivers, \r
-  and other exception operations.  The File parameter allows for possible logging \r
+  The possible responses in a given SAP implementation may include locking\r
+  flash upon failure to authenticate, attestation logging for all signed drivers,\r
+  and other exception operations.  The File parameter allows for possible logging\r
   within the SAP of the driver.\r
 \r
-  If File is NULL, then EFI_INVALID_PARAMETER is returned.\r
-\r
-  If the file specified by File with an authentication status specified by \r
+  If the file specified by File with an authentication status specified by\r
   AuthenticationStatus is safe for the DXE Core to use, then EFI_SUCCESS is returned.\r
 \r
-  If the file specified by File with an authentication status specified by \r
-  AuthenticationStatus is not safe for the DXE Core to use under any circumstances, \r
+  If the file specified by File with an authentication status specified by\r
+  AuthenticationStatus is not safe for the DXE Core to use under any circumstances,\r
   then EFI_ACCESS_DENIED is returned.\r
 \r
-  If the file specified by File with an authentication status specified by \r
-  AuthenticationStatus is not safe for the DXE Core to use right now, but it \r
-  might be possible to use it at a future time, then EFI_SECURITY_VIOLATION is \r
+  If the file specified by File with an authentication status specified by\r
+  AuthenticationStatus is not safe for the DXE Core to use right now, but it\r
+  might be possible to use it at a future time, then EFI_SECURITY_VIOLATION is\r
   returned.\r
 \r
-  @param[in, out] AuthenticationStatus  This is the authentication status returned\r
+  If check image specified by FileBuffer and File is NULL meanwhile, return EFI_ACCESS_DENIED.\r
+\r
+  @param[in]      AuthenticationStatus  This is the authentication status returned\r
                                         from the securitymeasurement services for the\r
                                         input file.\r
   @param[in]      File       This is a pointer to the device path of the file that is\r
                              being dispatched. This will optionally be used for logging.\r
   @param[in]      FileBuffer File buffer matches the input file device path.\r
   @param[in]      FileSize   Size of File buffer matches the input file device path.\r
+  @param[in]      BootPolicy A boot policy that was used to call LoadImage() UEFI service.\r
 \r
-  @retval EFI_SUCCESS            The file specified by File did authenticate, and the\r
-                                 platform policy dictates that the DXE Core may use File.\r
-  @retval EFI_INVALID_PARAMETER  File is NULL.\r
-  @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and\r
-                                 the platform policy dictates that File should be placed\r
-                                 in the untrusted state. A file may be promoted from\r
-                                 the untrusted to the trusted state at a future time\r
-                                 with a call to the Trust() DXE Service.\r
-  @retval EFI_ACCESS_DENIED      The file specified by File did not authenticate, and\r
-                                 the platform policy dictates that File should not be\r
-                                 used for any purpose.\r
-\r
+  @retval EFI_SUCCESS             The file specified by DevicePath and non-NULL\r
+                                  FileBuffer did authenticate, and the platform policy dictates\r
+                                  that the DXE Foundation may use the file.\r
+  @retval other error value\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 DxeTpmMeasureBootHandler (\r
-  IN  OUT   UINT32                     AuthenticationStatus,\r
-  IN  CONST EFI_DEVICE_PATH_PROTOCOL   *File,\r
-  IN  VOID                             *FileBuffer OPTIONAL,\r
-  IN  UINTN                            FileSize OPTIONAL\r
+  IN  UINT32                          AuthenticationStatus,\r
+  IN  CONST EFI_DEVICE_PATH_PROTOCOL  *File  OPTIONAL,\r
+  IN  VOID                            *FileBuffer,\r
+  IN  UINTN                           FileSize,\r
+  IN  BOOLEAN                         BootPolicy\r
   )\r
 {\r
-  EFI_TCG_PROTOCOL                  *TcgProtocol;\r
-  EFI_STATUS                        Status;\r
-  TCG_EFI_BOOT_SERVICE_CAPABILITY   ProtocolCapability;\r
-  UINT32                            TCGFeatureFlags;\r
-  EFI_PHYSICAL_ADDRESS              EventLogLocation;\r
-  EFI_PHYSICAL_ADDRESS              EventLogLastEntry;\r
-  EFI_DEVICE_PATH_PROTOCOL          *DevicePathNode;\r
-  EFI_DEVICE_PATH_PROTOCOL          *OrigDevicePathNode;\r
-  EFI_HANDLE                        Handle;\r
-  BOOLEAN                           ApplicationRequired;\r
-  PE_COFF_LOADER_IMAGE_CONTEXT      ImageContext;\r
-\r
-  if (File == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **) &TcgProtocol);\r
+  EFI_TCG_PROTOCOL                    *TcgProtocol;\r
+  EFI_STATUS                          Status;\r
+  TCG_EFI_BOOT_SERVICE_CAPABILITY     ProtocolCapability;\r
+  UINT32                              TCGFeatureFlags;\r
+  EFI_PHYSICAL_ADDRESS                EventLogLocation;\r
+  EFI_PHYSICAL_ADDRESS                EventLogLastEntry;\r
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePathNode;\r
+  EFI_DEVICE_PATH_PROTOCOL            *OrigDevicePathNode;\r
+  EFI_HANDLE                          Handle;\r
+  EFI_HANDLE                          TempHandle;\r
+  BOOLEAN                             ApplicationRequired;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT        ImageContext;\r
+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *FvbProtocol;\r
+  EFI_PHYSICAL_ADDRESS                FvAddress;\r
+  UINT32                              Index;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol);\r
   if (EFI_ERROR (Status)) {\r
     //\r
     // TCG protocol is not installed. So, TPM is not present.\r
@@ -711,15 +751,15 @@ DxeTpmMeasureBootHandler (
     return EFI_SUCCESS;\r
   }\r
 \r
-  ProtocolCapability.Size = (UINT8) sizeof (ProtocolCapability);\r
-  Status = TcgProtocol->StatusCheck (\r
-             TcgProtocol, \r
-             &ProtocolCapability,\r
-             &TCGFeatureFlags,\r
-             &EventLogLocation,\r
-             &EventLogLastEntry\r
-           );\r
-  if (EFI_ERROR (Status) || ProtocolCapability.TPMDeactivatedFlag) {\r
+  ProtocolCapability.Size = (UINT8)sizeof (ProtocolCapability);\r
+  Status                  = TcgProtocol->StatusCheck (\r
+                                           TcgProtocol,\r
+                                           &ProtocolCapability,\r
+                                           &TCGFeatureFlags,\r
+                                           &EventLogLocation,\r
+                                           &EventLogLastEntry\r
+                                           );\r
+  if (EFI_ERROR (Status) || ProtocolCapability.TPMDeactivatedFlag || (!ProtocolCapability.TPMPresentFlag)) {\r
     //\r
     // TPM device doesn't work or activate.\r
     //\r
@@ -730,42 +770,43 @@ DxeTpmMeasureBootHandler (
   // Copy File Device Path\r
   //\r
   OrigDevicePathNode = DuplicateDevicePath (File);\r
-  ASSERT (OrigDevicePathNode != NULL);\r
-  \r
+\r
   //\r
   // 1. Check whether this device path support BlockIo protocol.\r
   // Is so, this device path may be a GPT device path.\r
   //\r
   DevicePathNode = OrigDevicePathNode;\r
-  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevicePathNode, &Handle);\r
+  Status         = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevicePathNode, &Handle);\r
   if (!EFI_ERROR (Status) && !mMeasureGptTableFlag) {\r
     //\r
-    // Find the gpt partion on the given devicepath\r
+    // Find the gpt partition on the given devicepath\r
     //\r
     DevicePathNode = OrigDevicePathNode;\r
+    ASSERT (DevicePathNode != NULL);\r
     while (!IsDevicePathEnd (DevicePathNode)) {\r
       //\r
       // Find the Gpt partition\r
       //\r
-      if (DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH &&\r
-            DevicePathSubType (DevicePathNode) == MEDIA_HARDDRIVE_DP) {\r
+      if ((DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH) &&\r
+          (DevicePathSubType (DevicePathNode) == MEDIA_HARDDRIVE_DP))\r
+      {\r
         //\r
         // Check whether it is a gpt partition or not\r
-        //                           \r
-        if (((HARDDRIVE_DEVICE_PATH *) DevicePathNode)->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER && \r
-            ((HARDDRIVE_DEVICE_PATH *) DevicePathNode)->SignatureType == SIGNATURE_TYPE_GUID) {\r
-\r
+        //\r
+        if ((((HARDDRIVE_DEVICE_PATH *)DevicePathNode)->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER) &&\r
+            (((HARDDRIVE_DEVICE_PATH *)DevicePathNode)->SignatureType == SIGNATURE_TYPE_GUID))\r
+        {\r
           //\r
           // Change the partition device path to its parent device path (disk) and get the handle.\r
           //\r
           DevicePathNode->Type    = END_DEVICE_PATH_TYPE;\r
           DevicePathNode->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;\r
           DevicePathNode          = OrigDevicePathNode;\r
-          Status = gBS->LocateDevicePath (\r
-                         &gEfiDiskIoProtocolGuid,\r
-                         &DevicePathNode,\r
-                         &Handle\r
-                         );\r
+          Status                  = gBS->LocateDevicePath (\r
+                                           &gEfiDiskIoProtocolGuid,\r
+                                           &DevicePathNode,\r
+                                           &Handle\r
+                                           );\r
           if (!EFI_ERROR (Status)) {\r
             //\r
             // Measure GPT disk.\r
@@ -778,26 +819,28 @@ DxeTpmMeasureBootHandler (
               mMeasureGptTableFlag = TRUE;\r
             }\r
           }\r
+\r
           FreePool (OrigDevicePathNode);\r
           OrigDevicePathNode = DuplicateDevicePath (File);\r
           ASSERT (OrigDevicePathNode != NULL);\r
           break;\r
         }\r
       }\r
-      DevicePathNode    = NextDevicePathNode (DevicePathNode);\r
+\r
+      DevicePathNode = NextDevicePathNode (DevicePathNode);\r
     }\r
   }\r
-  \r
+\r
   //\r
   // 2. Measure PE image.\r
   //\r
   ApplicationRequired = FALSE;\r
 \r
   //\r
-  // Check whether this device path support FV2 protocol.\r
+  // Check whether this device path support FVB protocol.\r
   //\r
   DevicePathNode = OrigDevicePathNode;\r
-  Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &DevicePathNode, &Handle);\r
+  Status         = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &DevicePathNode, &Handle);\r
   if (!EFI_ERROR (Status)) {\r
     //\r
     // Don't check FV image, and directly return EFI_SUCCESS.\r
@@ -806,14 +849,52 @@ DxeTpmMeasureBootHandler (
     if (IsDevicePathEnd (DevicePathNode)) {\r
       return EFI_SUCCESS;\r
     }\r
+\r
     //\r
-    // The image from Firmware image will not be mearsured.\r
-    // Current policy doesn't measure PeImage from Firmware if it is driver\r
-    // If the got PeImage is application, it will be still be measured.\r
+    // The PE image from unmeasured Firmware volume need be measured\r
+    // The PE image from measured Firmware volume will be measured according to policy below.\r
+    //   If it is driver, do not measure\r
+    //   If it is application, still measure.\r
     //\r
     ApplicationRequired = TRUE;\r
+\r
+    if ((mCacheMeasuredHandle != Handle) && (mMeasuredHobData != NULL)) {\r
+      //\r
+      // Search for Root FV of this PE image\r
+      //\r
+      TempHandle = Handle;\r
+      do {\r
+        Status = gBS->HandleProtocol (\r
+                        TempHandle,\r
+                        &gEfiFirmwareVolumeBlockProtocolGuid,\r
+                        (VOID **)&FvbProtocol\r
+                        );\r
+        TempHandle = FvbProtocol->ParentHandle;\r
+      } while (!EFI_ERROR (Status) && FvbProtocol->ParentHandle != NULL);\r
+\r
+      //\r
+      // Search in measured FV Hob\r
+      //\r
+      Status = FvbProtocol->GetPhysicalAddress (FvbProtocol, &FvAddress);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      ApplicationRequired = FALSE;\r
+\r
+      for (Index = 0; Index < mMeasuredHobData->Num; Index++) {\r
+        if (mMeasuredHobData->MeasuredFvBuf[Index].BlobBase == FvAddress) {\r
+          //\r
+          // Cache measured FV for next measurement\r
+          //\r
+          mCacheMeasuredHandle = Handle;\r
+          ApplicationRequired  = TRUE;\r
+          break;\r
+        }\r
+      }\r
+    }\r
   }\r
-  \r
+\r
   //\r
   // File is not found.\r
   //\r
@@ -822,55 +903,57 @@ DxeTpmMeasureBootHandler (
     goto Finish;\r
   }\r
 \r
-  mImageSize  = FileSize;\r
-  mFileBuffer = FileBuffer;\r
+  mTpmImageSize = FileSize;\r
+  mFileBuffer   = FileBuffer;\r
 \r
   //\r
   // Measure PE Image\r
   //\r
   DevicePathNode = OrigDevicePathNode;\r
   ZeroMem (&ImageContext, sizeof (ImageContext));\r
-  ImageContext.Handle    = (VOID *) FileBuffer;\r
-  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) DxeTpmMeasureBootLibImageRead;\r
+  ImageContext.Handle    = (VOID *)FileBuffer;\r
+  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)DxeTpmMeasureBootLibImageRead;\r
 \r
   //\r
   // Get information about the image being loaded\r
   //\r
   Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
   if (EFI_ERROR (Status)) {\r
+    //\r
+    // Check for invalid parameters.\r
+    //\r
+    if (File == NULL) {\r
+      return EFI_ACCESS_DENIED;\r
+    }\r
+\r
     //\r
     // The information can't be got from the invalid PeImage\r
     //\r
     goto Finish;\r
   }\r
-  \r
+\r
   //\r
   // Measure only application if Application flag is set\r
   // Measure drivers and applications if Application flag is not set\r
   //\r
-  if ((!ApplicationRequired) || \r
-        (ApplicationRequired && ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)) {  \r
+  if ((!ApplicationRequired) ||\r
+      (ApplicationRequired && (ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)))\r
+  {\r
     //\r
     // Print the image path to be measured.\r
-    //    \r
+    //\r
     DEBUG_CODE_BEGIN ();\r
-      CHAR16                            *ToText;\r
-      EFI_DEVICE_PATH_TO_TEXT_PROTOCOL  *DevPathToText;\r
-      Status = gBS->LocateProtocol (\r
-                      &gEfiDevicePathToTextProtocolGuid,\r
-                      NULL,\r
-                      (VOID **) &DevPathToText\r
-                      );\r
-      if (!EFI_ERROR (Status)) {\r
-        ToText = DevPathToText->ConvertDevicePathToText (\r
-                                  DevicePathNode,\r
-                                  FALSE,\r
-                                  TRUE\r
-                                  );\r
-        if (ToText != NULL) {\r
-          DEBUG ((DEBUG_INFO, "The measured image path is %s.\n", ToText));\r
-        }\r
-      }\r
+    CHAR16  *ToText;\r
+    ToText = ConvertDevicePathToText (\r
+               DevicePathNode,\r
+               FALSE,\r
+               TRUE\r
+               );\r
+    if (ToText != NULL) {\r
+      DEBUG ((DEBUG_INFO, "The measured image path is %s.\n", ToText));\r
+      FreePool (ToText);\r
+    }\r
+\r
     DEBUG_CODE_END ();\r
 \r
     //\r
@@ -878,10 +961,10 @@ DxeTpmMeasureBootHandler (
     //\r
     Status = TcgMeasurePeImage (\r
                TcgProtocol,\r
-               (EFI_PHYSICAL_ADDRESS) (UINTN) FileBuffer, \r
-               FileSize, \r
-               (UINTN) ImageContext.ImageAddress, \r
-               ImageContext.ImageType, \r
+               (EFI_PHYSICAL_ADDRESS)(UINTN)FileBuffer,\r
+               FileSize,\r
+               (UINTN)ImageContext.ImageAddress,\r
+               ImageContext.ImageType,\r
                DevicePathNode\r
                );\r
   }\r
@@ -890,7 +973,9 @@ DxeTpmMeasureBootHandler (
   // Done, free the allocated resource.\r
   //\r
 Finish:\r
-  FreePool (OrigDevicePathNode);\r
+  if (OrigDevicePathNode != NULL) {\r
+    FreePool (OrigDevicePathNode);\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -911,8 +996,18 @@ DxeTpmMeasureBootLibConstructor (
   IN EFI_SYSTEM_TABLE  *SystemTable\r
   )\r
 {\r
-  return RegisterSecurityHandler (\r
-          DxeTpmMeasureBootHandler,\r
-          EFI_AUTH_OPERATION_MEASURE_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED\r
-          );\r
+  EFI_HOB_GUID_TYPE  *GuidHob;\r
+\r
+  GuidHob = NULL;\r
+\r
+  GuidHob = GetFirstGuidHob (&gMeasuredFvHobGuid);\r
+\r
+  if (GuidHob != NULL) {\r
+    mMeasuredHobData = GET_GUID_HOB_DATA (GuidHob);\r
+  }\r
+\r
+  return RegisterSecurity2Handler (\r
+           DxeTpmMeasureBootHandler,\r
+           EFI_AUTH_OPERATION_MEASURE_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED\r
+           );\r
 }\r