diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc
index 90906796aa..8fb18bd32d 100644
--- a/ArmPkg/ArmPkg.dsc
+++ b/ArmPkg/ArmPkg.dsc
@@ -54,9 +54,9 @@
   UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
   DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
   UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
 
   UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
   HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
@@ -112,7 +112,7 @@
   ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf
   ArmPkg/Library/ArmPsciResetSystemLib/ArmPsciResetSystemLib.inf
   ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.inf
-  ArmPkg/Library/DebugPeCoffExtraActionLib/DebugPeCoffExtraActionLib.inf
+  ArmPkg/Library/DebugUefiImageExtraActionLib/DebugUefiImageExtraActionLib.inf
   ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf
   ArmPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf
   ArmPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf
diff --git a/ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.dsc b/ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.dsc
index f93d31776f..e4488b3b3b 100644
--- a/ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.dsc
+++ b/ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.dsc
@@ -34,7 +34,6 @@
   DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
   MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
   SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
   UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.h b/ArmPkg/Drivers/CpuDxe/CpuDxe.h
index 80d53e3577..a86de6800f 100644
--- a/ArmPkg/Drivers/CpuDxe/CpuDxe.h
+++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.h
@@ -20,7 +20,6 @@
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/DxeServicesTableLib.h>
 #include <Library/CacheMaintenanceLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
 #include <Library/UefiLib.h>
 #include <Library/CpuLib.h>
 #include <Library/DefaultExceptionHandlerLib.h>
diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
index deb4bad8d7..9e6b8805af 100644
--- a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
+++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
@@ -49,7 +49,6 @@
   DxeServicesTableLib
   HobLib
   MemoryAllocationLib
-  PeCoffGetEntryPointLib
   UefiDriverEntryPoint
   UefiLib
 
diff --git a/ArmPkg/Include/Library/ArmStandaloneMmCoreEntryPoint.h b/ArmPkg/Include/Library/ArmStandaloneMmCoreEntryPoint.h
index 1549211613..29bd1a1356 100644
--- a/ArmPkg/Include/Library/ArmStandaloneMmCoreEntryPoint.h
+++ b/ArmPkg/Include/Library/ArmStandaloneMmCoreEntryPoint.h
@@ -25,7 +25,7 @@
 
 #include <Library/ArmSvcLib.h>
 #include <Library/ArmFfaLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/FvLib.h>
 
 #define CPU_INFO_FLAG_PRIMARY_CPU  0x00000001
@@ -157,56 +157,6 @@ typedef RETURN_STATUS (*REGION_PERMISSION_UPDATE_FUNC) (
   IN  UINT64                Length
   );
 
-/**
-  Privileged firmware assigns RO & Executable attributes to all memory occupied
-  by the Boot Firmware Volume. This function sets the correct permissions of
-  sections in the Standalone MM Core module to be able to access RO and RW data
-  and make further progress in the boot process.
-
-  @param  [in] ImageContext           Pointer to PE/COFF image context
-  @param  [in] ImageBase              Base of image in memory
-  @param  [in] SectionHeaderOffset    Offset of PE/COFF image section header
-  @param  [in] NumberOfSections       Number of Sections
-  @param  [in] TextUpdater            Function to change code permissions
-  @param  [in] ReadOnlyUpdater        Function to change RO permissions
-  @param  [in] ReadWriteUpdater       Function to change RW permissions
-
-**/
-EFI_STATUS
-EFIAPI
-UpdateMmFoundationPeCoffPermissions (
-  IN  CONST PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,
-  IN  EFI_PHYSICAL_ADDRESS                ImageBase,
-  IN  UINT32                              SectionHeaderOffset,
-  IN  CONST  UINT16                       NumberOfSections,
-  IN  REGION_PERMISSION_UPDATE_FUNC       TextUpdater,
-  IN  REGION_PERMISSION_UPDATE_FUNC       ReadOnlyUpdater,
-  IN  REGION_PERMISSION_UPDATE_FUNC       ReadWriteUpdater
-  );
-
-/**
-  Privileged firmware assigns RO & Executable attributes to all memory occupied
-  by the Boot Firmware Volume. This function locates the section information of
-  the Standalone MM Core module to be able to change permissions of the
-  individual sections later in the boot process.
-
-  @param  [in]      TeData                Pointer to PE/COFF image data
-  @param  [in, out] ImageContext          Pointer to PE/COFF image context
-  @param  [out]     ImageBase             Pointer to ImageBase variable
-  @param  [in, out] SectionHeaderOffset   Offset of PE/COFF image section header
-  @param  [in, out] NumberOfSections      Number of Sections
-
-**/
-EFI_STATUS
-EFIAPI
-GetStandaloneMmCorePeCoffSections (
-  IN        VOID                          *TeData,
-  IN  OUT   PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,
-  OUT   EFI_PHYSICAL_ADDRESS              *ImageBase,
-  IN  OUT   UINT32                        *SectionHeaderOffset,
-  IN  OUT   UINT16                        *NumberOfSections
-  );
-
 /**
   Privileged firmware assigns RO & Executable attributes to all memory occupied
   by the Boot Firmware Volume. This function locates the Standalone MM Core
@@ -220,10 +170,10 @@ GetStandaloneMmCorePeCoffSections (
 **/
 EFI_STATUS
 EFIAPI
-LocateStandaloneMmCorePeCoffData (
+LocateStandaloneMmCoreUefiImage (
   IN        EFI_FIRMWARE_VOLUME_HEADER  *BfvAddress,
   IN  OUT   VOID                        **TeData,
-  IN  OUT   UINTN                       *TeDataSize
+  IN  OUT   UINT32                      *TeDataSize
   );
 
 /**
diff --git a/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.c b/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.c
index 0d60a491ee..5fd320c3ad 100644
--- a/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.c
+++ b/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.c
@@ -37,6 +37,7 @@
 #include <Library/SerialPortLib.h>
 #include <Library/StandaloneMmMmuLib.h>
 #include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
 
 #include <IndustryStandard/ArmStdSmc.h>
 #include <IndustryStandard/ArmMmSvc.h>
@@ -1010,13 +1011,12 @@ CEntryPoint (
   PE_COFF_LOADER_IMAGE_CONTEXT        ImageContext;
   ARM_SVC_ARGS                        EventCompleteSvcArgs;
   EFI_STATUS                          Status;
-  UINT32                              SectionHeaderOffset;
-  UINT16                              NumberOfSections;
   COMM_PROTOCOL                       CommProtocol;
   VOID                                *HobStart;
   VOID                                *TeData;
-  UINTN                               TeDataSize;
-  EFI_PHYSICAL_ADDRESS                ImageBase;
+  UINT32                              TeDataSize;
+  UINT32                              SectionIndex;
+  UEFI_IMAGE_RECORD                   *ImageRecord;
   EDKII_PI_MM_CPU_DRIVER_EP_PROTOCOL  *PiMmCpuDriverEpProtocol;
   EDKII_PI_MM_CPU_DRIVER_ENTRYPOINT   CpuDriverEntryPoint;
   EFI_HOB_FIRMWARE_VOLUME             *FvHob;
@@ -1051,7 +1051,7 @@ CEntryPoint (
   }
 
   // Locate PE/COFF File information for the Standalone MM core module
-  Status = LocateStandaloneMmCorePeCoffData (
+  Status = LocateStandaloneMmCoreUefiImage (
              (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvHob->BaseAddress,
              &TeData,
              &TeDataSize
@@ -1061,53 +1061,46 @@ CEntryPoint (
     goto finish;
   }
 
+  DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", TeData));
+
   // Obtain the PE/COFF Section information for the Standalone MM core module
-  Status = GetStandaloneMmCorePeCoffSections (
-             TeData,
-             &ImageContext,
-             &ImageBase,
-             &SectionHeaderOffset,
-             &NumberOfSections
-             );
-
+  Status = UefiImageInitializeContext (&ImageContext, TeData, TeDataSize);
   if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Core PE-COFF Section information - %r\n", Status));
     goto finish;
   }
 
-  //
-  // ImageBase may deviate from ImageContext.ImageAddress if we are dealing
-  // with a TE image, in which case the latter points to the actual offset
-  // of the image, whereas ImageBase refers to the address where the image
-  // would start if the stripped PE headers were still in place. In either
-  // case, we need to fix up ImageBase so it refers to the actual current
-  // load address.
-  //
-  ImageBase += (UINTN)TeData - ImageContext.ImageAddress;
+  ImageRecord = UefiImageLoaderGetImageRecord (&ImageContext);
 
-  // Update the memory access permissions of individual sections in the
-  // Standalone MM core module
-  Status = UpdateMmFoundationPeCoffPermissions (
-             &ImageContext,
-             ImageBase,
-             SectionHeaderOffset,
-             NumberOfSections,
-             ArmSetMemoryRegionNoExec,
-             ArmSetMemoryRegionReadOnly,
-             ArmClearMemoryRegionReadOnly
-             );
-  if (EFI_ERROR (Status)) {
+  if (ImageRecord == NULL) {
     goto finish;
   }
 
-  if (ImageContext.ImageAddress != (UINTN)TeData) {
-    ImageContext.ImageAddress = (UINTN)TeData;
-    ArmSetMemoryRegionNoExec (ImageBase, SIZE_4KB);
-    ArmClearMemoryRegionReadOnly (ImageBase, SIZE_4KB);
+  UINT32 Address = 0;
+  for (SectionIndex = 0; SectionIndex < ImageRecord->NumSegments; ++ SectionIndex) {
+    if ((ImageRecord->Segments[SectionIndex].Attributes & EFI_MEMORY_XP) != 0) {
+      ArmSetMemoryRegionNoExec (
+        Address,
+        ImageRecord->Segments[SectionIndex].Size
+        );
+    }
 
-    Status = PeCoffLoaderRelocateImage (&ImageContext);
-    ASSERT_EFI_ERROR (Status);
+    if ((ImageRecord->Segments[SectionIndex].Attributes & EFI_MEMORY_RO) == 0) {
+      ArmClearMemoryRegionReadOnly (
+        Address,
+        ImageRecord->Segments[SectionIndex].Size
+        );
+    }
+
+    Address += ImageRecord->Segments[SectionIndex].Size;
   }
 
+  FreePool (ImageRecord);
+
+  // FIXME: Should relocation not be performed with all of the Image writable?
+  Status = UefiImageRelocateImageInplaceForExecution (&ImageContext);
+  ASSERT_EFI_ERROR (Status);
+
   // Set the gHobList to point to the HOB list passed by TF-A.
   // This will be used by StandaloneMmCoreHobLib in early stage.
   gHobList = HobStart;
diff --git a/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.inf b/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.inf
index e5bfb810f1..df86752525 100644
--- a/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.inf
+++ b/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/ArmStandaloneMmCoreEntryPoint.inf
@@ -63,11 +63,9 @@
   gArmTokenSpaceGuid.PcdStMmStackSize
 
 #
-# This configuration fails for CLANGPDB, which does not support PIE in the GCC
-# sense. Such however is required for ARM family StandaloneMmCore
-# self-relocation, and thus the CLANGPDB toolchain is unsupported for ARM and
-# AARCH64 for this module.
+# This configuration fails for CLANGDPB, which does not support PIE in the GCC
+# sense. Such however is required for AArch64 StandaloneMmCore self-relocation,
+# and thus the CLANGPDB toolchain is unsupported for AArch64 for this module.
 #
 [BuildOptions]
-  GCC:*_*_ARM_CC_FLAGS = -fpie
   GCC:*_*_AARCH64_CC_FLAGS = -fpie
diff --git a/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/SetPermissions.c b/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/SetPermissions.c
index fd3fdae4f0..728e26c814 100644
--- a/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/SetPermissions.c
+++ b/ArmPkg/Library/ArmStandaloneMmCoreEntryPoint/SetPermissions.c
@@ -24,162 +24,23 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 
 #include <IndustryStandard/ArmStdSmc.h>
 
-/**
-  Privileged firmware assigns RO & Executable attributes to all memory occupied
-  by the Boot Firmware Volume. This function sets the correct permissions of
-  sections in the Standalone MM Core module to be able to access RO and RW data
-  and make further progress in the boot process.
-
-  @param  [in] ImageContext           Pointer to PE/COFF image context
-  @param  [in] ImageBase              Base of image in memory
-  @param  [in] SectionHeaderOffset    Offset of PE/COFF image section header
-  @param  [in] NumberOfSections       Number of Sections
-  @param  [in] TextUpdater            Function to change code permissions
-  @param  [in] ReadOnlyUpdater        Function to change RO permissions
-  @param  [in] ReadWriteUpdater       Function to change RW permissions
-
-**/
-EFI_STATUS
-EFIAPI
-UpdateMmFoundationPeCoffPermissions (
-  IN  CONST PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,
-  IN  EFI_PHYSICAL_ADDRESS                ImageBase,
-  IN  UINT32                              SectionHeaderOffset,
-  IN  CONST  UINT16                       NumberOfSections,
-  IN  REGION_PERMISSION_UPDATE_FUNC       TextUpdater,
-  IN  REGION_PERMISSION_UPDATE_FUNC       ReadOnlyUpdater,
-  IN  REGION_PERMISSION_UPDATE_FUNC       ReadWriteUpdater
-  )
-{
-  EFI_IMAGE_SECTION_HEADER  SectionHeader;
-  RETURN_STATUS             Status;
-  EFI_PHYSICAL_ADDRESS      Base;
-  UINTN                     Size;
-  UINTN                     ReadSize;
-  UINTN                     Index;
-
-  ASSERT (ImageContext != NULL);
-
-  //
-  // Iterate over the sections
-  //
-  for (Index = 0; Index < NumberOfSections; Index++) {
-    //
-    // Read section header from file
-    //
-    Size     = sizeof (EFI_IMAGE_SECTION_HEADER);
-    ReadSize = Size;
-    Status   = ImageContext->ImageRead (
-                               ImageContext->Handle,
-                               SectionHeaderOffset,
-                               &Size,
-                               &SectionHeader
-                               );
-
-    if (RETURN_ERROR (Status) || (Size != ReadSize)) {
-      DEBUG ((
-        DEBUG_ERROR,
-        "%a: ImageContext->ImageRead () failed (Status = %r)\n",
-        __func__,
-        Status
-        ));
-      return Status;
-    }
-
-    DEBUG ((
-      DEBUG_INFO,
-      "%a: Section %d of image at 0x%lx has 0x%x permissions\n",
-      __func__,
-      Index,
-      ImageContext->ImageAddress,
-      SectionHeader.Characteristics
-      ));
-    DEBUG ((
-      DEBUG_INFO,
-      "%a: Section %d of image at 0x%lx has %a name\n",
-      __func__,
-      Index,
-      ImageContext->ImageAddress,
-      SectionHeader.Name
-      ));
-    DEBUG ((
-      DEBUG_INFO,
-      "%a: Section %d of image at 0x%lx has 0x%x address\n",
-      __func__,
-      Index,
-      ImageContext->ImageAddress,
-      ImageContext->ImageAddress + SectionHeader.VirtualAddress
-      ));
-    DEBUG ((
-      DEBUG_INFO,
-      "%a: Section %d of image at 0x%lx has 0x%x data\n",
-      __func__,
-      Index,
-      ImageContext->ImageAddress,
-      SectionHeader.PointerToRawData
-      ));
-
-    //
-    // If the section is marked as XN then remove the X attribute. Furthermore,
-    // if it is a writeable section then mark it appropriately as well.
-    //
-    if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) {
-      Base = ImageBase + SectionHeader.VirtualAddress;
-
-      TextUpdater (Base, SectionHeader.Misc.VirtualSize);
-
-      if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_WRITE) != 0) {
-        ReadWriteUpdater (Base, SectionHeader.Misc.VirtualSize);
-        DEBUG ((
-          DEBUG_INFO,
-          "%a: Mapping section %d of image at 0x%lx with RW-XN permissions\n",
-          __func__,
-          Index,
-          ImageContext->ImageAddress
-          ));
-      } else {
-        DEBUG ((
-          DEBUG_INFO,
-          "%a: Mapping section %d of image at 0x%lx with RO-XN permissions\n",
-          __func__,
-          Index,
-          ImageContext->ImageAddress
-          ));
-      }
-    } else {
-      DEBUG ((
-        DEBUG_INFO,
-        "%a: Ignoring section %d of image at 0x%lx with 0x%x permissions\n",
-        __func__,
-        Index,
-        ImageContext->ImageAddress,
-        SectionHeader.Characteristics
-        ));
-    }
-
-    SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
-  }
-
-  return RETURN_SUCCESS;
-}
-
 /**
   Privileged firmware assigns RO & Executable attributes to all memory occupied
   by the Boot Firmware Volume. This function locates the Standalone MM Core
   module PE/COFF image in the BFV and returns this information.
 
-  @param  [in]      BfvAddress         Base Address of Boot Firmware Volume
-  @param  [in, out] TeData             Pointer to address for allocating memory
-                                       for PE/COFF image data
-  @param  [in, out] TeDataSize         Pointer to size of PE/COFF image data
+  @param  [in]      BfvAddress        Base Address of Boot Firmware Volume
+  @param  [in, out] UefiImage         Pointer to address for allocating memory
+                                      for PE/COFF image data
+  @param  [in, out] UefiImageSize     Pointer to size of PE/COFF image data
 
 **/
 EFI_STATUS
 EFIAPI
-LocateStandaloneMmCorePeCoffData (
+LocateStandaloneMmCoreUefiImage (
   IN        EFI_FIRMWARE_VOLUME_HEADER  *BfvAddress,
-  IN  OUT   VOID                        **TeData,
-  IN  OUT   UINTN                       *TeDataSize
+  IN  OUT   VOID                            **UefiImage,
+  IN  OUT   UINT32                          *UefiImageSize
   )
 {
   EFI_FFS_FILE_HEADER  *FileHeader;
@@ -201,9 +62,9 @@ LocateStandaloneMmCorePeCoffData (
     return Status;
   }
 
-  Status = FfsFindSectionData (EFI_SECTION_PE32, FileHeader, TeData, TeDataSize);
+  Status = FfsFindSectionData (EFI_SECTION_PE32, FileHeader, UefiImage, UefiImageSize);
   if (EFI_ERROR (Status)) {
-    Status = FfsFindSectionData (EFI_SECTION_TE, FileHeader, TeData, TeDataSize);
+    Status = FfsFindSectionData (EFI_SECTION_TE, FileHeader, UefiImage, UefiImageSize);
     if (EFI_ERROR (Status)) {
       DEBUG ((
         DEBUG_ERROR,
@@ -214,170 +75,6 @@ LocateStandaloneMmCorePeCoffData (
     }
   }
 
-  DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", *TeData));
-  return Status;
-}
-
-/**
-  Returns the PC COFF section information.
-
-  @param  [in, out] ImageContext         Pointer to PE/COFF image context
-  @param  [out]     ImageBase            Base of image in memory
-  @param  [out]     SectionHeaderOffset  Offset of PE/COFF image section header
-  @param  [out]     NumberOfSections     Number of Sections
-
-**/
-STATIC
-EFI_STATUS
-GetPeCoffSectionInformation (
-  IN  OUT   PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,
-  OUT   EFI_PHYSICAL_ADDRESS              *ImageBase,
-  OUT   UINT32                            *SectionHeaderOffset,
-  OUT   UINT16                            *NumberOfSections
-  )
-{
-  RETURN_STATUS                        Status;
-  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;
-  EFI_IMAGE_OPTIONAL_HEADER_UNION      HdrData;
-  UINTN                                Size;
-  UINTN                                ReadSize;
-
-  ASSERT (ImageContext != NULL);
-  ASSERT (SectionHeaderOffset != NULL);
-  ASSERT (NumberOfSections != NULL);
-
-  Status = PeCoffLoaderGetImageInfo (ImageContext);
-  if (RETURN_ERROR (Status)) {
-    DEBUG ((
-      DEBUG_ERROR,
-      "%a: PeCoffLoaderGetImageInfo () failed (Status == %r)\n",
-      __func__,
-      Status
-      ));
-    return Status;
-  }
-
-  if (ImageContext->SectionAlignment < EFI_PAGE_SIZE) {
-    //
-    // The sections need to be at least 4 KB aligned, since that is the
-    // granularity at which we can tighten permissions.
-    //
-    if (!ImageContext->IsTeImage) {
-      DEBUG ((
-        DEBUG_WARN,
-        "%a: non-TE Image at 0x%lx has SectionAlignment < 4 KB (%lu)\n",
-        __func__,
-        ImageContext->ImageAddress,
-        ImageContext->SectionAlignment
-        ));
-      return RETURN_UNSUPPORTED;
-    }
-
-    ImageContext->SectionAlignment = EFI_PAGE_SIZE;
-  }
-
-  //
-  // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much
-  // data, but that should not hurt anything. Hdr.Pe32->OptionalHeader.Magic
-  // determines if this is a PE32 or PE32+ image. The magic is in the same
-  // location in both images.
-  //
-  Hdr.Union = &HdrData;
-  Size      = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
-  ReadSize  = Size;
-  Status    = ImageContext->ImageRead (
-                              ImageContext->Handle,
-                              ImageContext->PeCoffHeaderOffset,
-                              &Size,
-                              Hdr.Pe32
-                              );
-
-  if (RETURN_ERROR (Status) || (Size != ReadSize)) {
-    DEBUG ((
-      DEBUG_ERROR,
-      "%a: TmpContext->ImageRead () failed (Status = %r)\n",
-      __func__,
-      Status
-      ));
-    return Status;
-  }
-
-  *ImageBase = ImageContext->ImageAddress;
-  if (!ImageContext->IsTeImage) {
-    ASSERT (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE);
-
-    *SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) +
-                           sizeof (EFI_IMAGE_FILE_HEADER);
-    *NumberOfSections = Hdr.Pe32->FileHeader.NumberOfSections;
-
-    switch (Hdr.Pe32->OptionalHeader.Magic) {
-      case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC:
-        *SectionHeaderOffset += Hdr.Pe32->FileHeader.SizeOfOptionalHeader;
-        break;
-      case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC:
-        *SectionHeaderOffset += Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader;
-        break;
-      default:
-        ASSERT (FALSE);
-    }
-  } else {
-    *SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER));
-    *NumberOfSections    = Hdr.Te->NumberOfSections;
-    *ImageBase          -= (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
-  }
-
-  return RETURN_SUCCESS;
-}
-
-/**
-  Privileged firmware assigns RO & Executable attributes to all memory occupied
-  by the Boot Firmware Volume. This function locates the section information of
-  the Standalone MM Core module to be able to change permissions of the
-  individual sections later in the boot process.
-
-  @param  [in]      TeData                Pointer to PE/COFF image data
-  @param  [in, out] ImageContext          Pointer to PE/COFF image context
-  @param  [out]     ImageBase             Pointer to ImageBase variable
-  @param  [in, out] SectionHeaderOffset   Offset of PE/COFF image section header
-  @param  [in, out] NumberOfSections      Number of Sections
-
-**/
-EFI_STATUS
-EFIAPI
-GetStandaloneMmCorePeCoffSections (
-  IN        VOID                          *TeData,
-  IN  OUT   PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,
-  OUT   EFI_PHYSICAL_ADDRESS              *ImageBase,
-  IN  OUT   UINT32                        *SectionHeaderOffset,
-  IN  OUT   UINT16                        *NumberOfSections
-  )
-{
-  EFI_STATUS  Status;
-
-  // Initialize the Image Context
-  ZeroMem (ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
-  ImageContext->Handle    = TeData;
-  ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory;
-
-  DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", TeData));
-
-  Status = GetPeCoffSectionInformation (
-             ImageContext,
-             ImageBase,
-             SectionHeaderOffset,
-             NumberOfSections
-             );
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Core PE-COFF Section information - %r\n", Status));
-    return Status;
-  }
-
-  DEBUG ((
-    DEBUG_INFO,
-    "Standalone MM Core PE-COFF SectionHeaderOffset - 0x%x, NumberOfSections - %d\n",
-    *SectionHeaderOffset,
-    *NumberOfSections
-    ));
-
+  DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", *UefiImage));
   return Status;
 }
diff --git a/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.c b/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.c
index 77c92f9ecc..a985f525d3 100644
--- a/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.c
+++ b/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.c
@@ -13,8 +13,8 @@
 #include <Library/DebugLib.h>
 #include <Library/DebugAgentLib.h>
 #include <Library/PcdLib.h>
-#include <Library/PeCoffExtraActionLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageExtraActionLib.h>
+#include <Library/UefiImageLib.h>
 
 #include <Pi/PiFirmwareFile.h>
 #include <Pi/PiFirmwareVolume.h>
@@ -165,34 +165,39 @@ GetFfsFile (
 
 EFI_STATUS
 GetImageContext (
-  IN  EFI_FFS_FILE_HEADER           *FfsHeader,
-  OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+  IN  EFI_FFS_FILE_HEADER              *FfsHeader,
+  OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
   )
 {
-  EFI_STATUS                       Status;
-  UINTN                            ParsedLength;
-  UINTN                            SectionSize;
-  UINTN                            SectionLength;
-  EFI_COMMON_SECTION_HEADER        *Section;
-  VOID                             *EfiImage;
-  UINTN                            ImageAddress;
-  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY  *DebugEntry;
-  VOID                             *CodeViewEntryPointer;
+  EFI_STATUS                              Status;
+  UINTN                                   ParsedLength;
+  UINT32                                  SectionSize;
+  UINT32                                  SectionLength;
+  EFI_COMMON_SECTION_HEADER               *Section;
+  VOID                                    *EfiImage;
 
-  Section      = (EFI_COMMON_SECTION_HEADER *)(FfsHeader + 1);
-  SectionSize  = *(UINT32 *)(FfsHeader->Size) & 0x00FFFFFF;
-  SectionSize -= sizeof (EFI_FFS_FILE_HEADER);
-  ParsedLength = 0;
-  EfiImage     = NULL;
+  Section       = (EFI_COMMON_SECTION_HEADER *)(FfsHeader + 1);
+  SectionLength = 0;
+  SectionSize   = *(UINT32 *)(FfsHeader->Size) & 0x00FFFFFF;
+  SectionSize  -= sizeof (EFI_FFS_FILE_HEADER);
+  ParsedLength  = 0;
+  EfiImage      = NULL;
 
   while (ParsedLength < SectionSize) {
+    //
+    // Size is 24 bits wide so mask upper 8 bits.
+    //
+    SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;
+    if (SectionLength < sizeof (*Section)) {
+      return EFI_VOLUME_CORRUPTED;
+    }
+
     if ((Section->Type == EFI_SECTION_PE32) || (Section->Type == EFI_SECTION_TE)) {
-      EfiImage = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(Section + 1);
+      EfiImage = (Section + 1);
       break;
     }
 
     //
-    // Size is 24 bits wide so mask upper 8 bits.
     // SectionLength is adjusted it is 4 byte aligned.
     // Go to the next section
     //
@@ -208,34 +213,10 @@ GetImageContext (
   }
 
   // Initialize the Image Context
-  ZeroMem (ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
-  ImageContext->Handle    = EfiImage;
-  ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory;
-
-  Status =  PeCoffLoaderGetImageInfo (ImageContext);
-  if (!EFI_ERROR (Status) && ((VOID *)(UINTN)ImageContext->DebugDirectoryEntryRva != NULL)) {
-    ImageAddress = ImageContext->ImageAddress;
-    if (ImageContext->IsTeImage) {
-      ImageAddress += sizeof (EFI_TE_IMAGE_HEADER) - ((EFI_TE_IMAGE_HEADER *)EfiImage)->StrippedSize;
-    }
-
-    DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(ImageAddress + ImageContext->DebugDirectoryEntryRva);
-    if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
-      CodeViewEntryPointer = (VOID *)(ImageAddress + (UINTN)DebugEntry->RVA);
-      switch (*(UINT32 *)CodeViewEntryPointer) {
-        case CODEVIEW_SIGNATURE_NB10:
-          ImageContext->PdbPointer = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
-          break;
-        case CODEVIEW_SIGNATURE_RSDS:
-          ImageContext->PdbPointer = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
-          break;
-        case CODEVIEW_SIGNATURE_MTOC:
-          ImageContext->PdbPointer = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY);
-          break;
-        default:
-          break;
-      }
-    }
+  // FIXME: Common FFS API with size checks
+  Status = UefiImageInitializeContext (ImageContext, EfiImage, SectionLength - sizeof (*Section));
+  if (!EFI_ERROR(Status)) {
+    Status = UefiImageLoadImageInplace( ImageContext);
   }
 
   return Status;
@@ -271,9 +252,9 @@ InitializeDebugAgent (
   IN DEBUG_AGENT_CONTINUE  Function  OPTIONAL
   )
 {
-  EFI_STATUS                    Status;
-  EFI_FFS_FILE_HEADER           *FfsHeader;
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
+  EFI_STATUS                      Status;
+  EFI_FFS_FILE_HEADER             *FfsHeader;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext;
 
   // We use InitFlag to know if DebugAgent has been initialized from
   // Sec (DEBUG_AGENT_INIT_PREMEM_SEC) or PrePi (DEBUG_AGENT_INIT_POSTMEM_SEC)
@@ -286,7 +267,7 @@ InitializeDebugAgent (
     if (!EFI_ERROR (Status)) {
       Status = GetImageContext (FfsHeader, &ImageContext);
       if (!EFI_ERROR (Status)) {
-        PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+        UefiImageLoaderRelocateImageExtraAction (&ImageContext);
       }
     }
   } else if (InitFlag == DEBUG_AGENT_INIT_POSTMEM_SEC) {
@@ -297,7 +278,7 @@ InitializeDebugAgent (
     if (!EFI_ERROR (Status)) {
       Status = GetImageContext (FfsHeader, &ImageContext);
       if (!EFI_ERROR (Status)) {
-        PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+        UefiImageLoaderRelocateImageExtraAction (&ImageContext);
       }
     }
 
@@ -308,7 +289,7 @@ InitializeDebugAgent (
     if (!EFI_ERROR (Status)) {
       Status = GetImageContext (FfsHeader, &ImageContext);
       if (!EFI_ERROR (Status)) {
-        PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+        UefiImageLoaderRelocateImageExtraAction (&ImageContext);
       }
     }
   }
diff --git a/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.inf b/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.inf
index 2ceeebbdee..03a637346e 100644
--- a/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.inf
+++ b/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.inf
@@ -24,8 +24,8 @@
 [LibraryClasses]
   DebugLib
   PcdLib
-  PeCoffExtraActionLib
-  PeCoffLib
+  UefiImageExtraActionLib
+  UefiImageLib
 
 [Pcd]
   gArmTokenSpaceGuid.PcdSecureFvBaseAddress
diff --git a/ArmPkg/Library/DebugUefiImageExtraActionLib/DebugUefiImageExtraActionLib.c b/ArmPkg/Library/DebugUefiImageExtraActionLib/DebugUefiImageExtraActionLib.c
new file mode 100644
index 0000000000..db74ff779b
--- /dev/null
+++ b/ArmPkg/Library/DebugUefiImageExtraActionLib/DebugUefiImageExtraActionLib.c
@@ -0,0 +1,141 @@
+/**@file
+
+Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+Portions copyright (c) 2011 - 2012, ARM Ltd. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/UefiImageLib.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiImageExtraActionLib.h>
+#include <Library/PrintLib.h>
+
+/**
+  If the build is done on cygwin the paths are cygpaths.
+  /cygdrive/c/tmp.txt vs c:\tmp.txt so we need to convert
+  them to work with RVD commands
+
+  @param  Name  Path to convert if needed
+
+**/
+CONST CHAR8 *
+DeCygwinPathIfNeeded (
+  IN  CONST CHAR8   *Name,
+  IN  CHAR8         *Temp,
+  IN  UINTN         Size
+  )
+{
+  CHAR8  *Ptr;
+  UINTN  Index;
+  UINTN  Index2;
+
+  Ptr = AsciiStrStr (Name, "/cygdrive/");
+  if (Ptr == NULL) {
+    return Name;
+  }
+
+  for (Index = 9, Index2 = 0; (Index < (Size + 9)) && (Ptr[Index] != '\0'); Index++, Index2++) {
+    Temp[Index2] = Ptr[Index];
+    if (Temp[Index2] == '/') {
+      Temp[Index2] = '\\';
+    }
+
+    if (Index2 == 1) {
+      Temp[Index2 - 1] = Ptr[Index];
+      Temp[Index2]     = ':';
+    }
+  }
+
+  return Temp;
+}
+
+/**
+  Performs additional actions after a PE/COFF image has been loaded and relocated.
+
+  If ImageContext is NULL, then ASSERT().
+
+  @param  ImageContext  Pointer to the image context structure that describes the
+                        PE/COFF image that has already been loaded and relocated.
+
+**/
+VOID
+EFIAPI
+UefiImageLoaderRelocateImageExtraAction (
+  IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
+  )
+{
+  RETURN_STATUS Status;
+  CONST CHAR8   *PdbPath;
+  UINT32        PdbPathSize;
+#if defined (__CC_ARM) || defined (__GNUC__)
+  CHAR8         Temp[512];
+#endif
+
+  Status = UefiImageGetSymbolsPath (ImageContext, &PdbPath, &PdbPathSize);
+
+  if (!RETURN_ERROR (Status)) {
+ #ifdef __CC_ARM
+ #if (__ARMCC_VERSION < 500000)
+    // Print out the command for the RVD debugger to load symbols for this image
+    DEBUG ((DEBUG_LOAD | DEBUG_INFO, "load /a /ni /np %a &0x%p\n", DeCygwinPathIfNeeded (PdbPath, Temp, sizeof (Temp)), UefiImageLoaderGetImageAddress (ImageContext)));
+ #else
+    // Print out the command for the DS-5 to load symbols for this image
+    DEBUG ((DEBUG_LOAD | DEBUG_INFO, "add-symbol-file %a -o 0x%p\n", DeCygwinPathIfNeeded (PdbPath, Temp, sizeof (Temp)), UefiImageLoaderGetImageAddress (ImageContext)));
+ #endif
+ #elif __GNUC__
+    // This may not work correctly if you generate PE/COFF directly as then the Offset would not be required
+    DEBUG ((DEBUG_LOAD | DEBUG_INFO, "add-symbol-file %a -o 0x%p\n", DeCygwinPathIfNeeded (PdbPath, Temp, sizeof (Temp)), UefiImageLoaderGetImageAddress (ImageContext)));
+ #else
+    DEBUG ((DEBUG_LOAD | DEBUG_INFO, "Loading driver at 0x%11p EntryPoint=0x%11p\n", (VOID *)(UINTN)UefiImageLoaderGetImageAddress (ImageContext), FUNCTION_ENTRY_POINT (UefiImageLoaderGetImageEntryPoint (ImageContext))));
+ #endif
+  } else {
+    DEBUG ((DEBUG_LOAD | DEBUG_INFO, "Loading driver at 0x%11p EntryPoint=0x%11p\n", (VOID *)(UINTN)UefiImageLoaderGetImageAddress (ImageContext), FUNCTION_ENTRY_POINT (UefiImageLoaderGetImageEntryPoint (ImageContext))));
+  }
+}
+
+/**
+  Performs additional actions just before a PE/COFF image is unloaded.  Any resources
+  that were allocated by UefiImageLoaderRelocateImageExtraAction() must be freed.
+
+  If ImageContext is NULL, then ASSERT().
+
+  @param  ImageContext  Pointer to the image context structure that describes the
+                        PE/COFF image that is being unloaded.
+
+**/
+VOID
+EFIAPI
+UefiImageLoaderUnloadImageExtraAction (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
+  )
+{
+  RETURN_STATUS Status;
+  CONST CHAR8   *PdbPath;
+  UINT32        PdbPathSize;
+#if defined (__CC_ARM) || defined (__GNUC__)
+  CHAR8         Temp[512];
+#endif
+
+  Status = UefiImageGetSymbolsPath (ImageContext, &PdbPath, &PdbPathSize);
+
+  if (!RETURN_ERROR (Status)) {
+ #ifdef __CC_ARM
+    // Print out the command for the RVD debugger to load symbols for this image
+    DEBUG ((DEBUG_LOAD | DEBUG_INFO, "unload symbols_only %a\n", DeCygwinPathIfNeeded (PdbPath, Temp, sizeof (Temp))));
+ #elif __GNUC__
+    // This may not work correctly if you generate PE/COFF directly as then the Offset would not be required
+    DEBUG ((DEBUG_LOAD | DEBUG_INFO, "remove-symbol-file %a 0x%08x\n", DeCygwinPathIfNeeded (PdbPath, Temp, sizeof (Temp)), (UINTN)UefiImageLoaderGetImageAddress (ImageContext)));
+ #else
+    DEBUG ((DEBUG_LOAD | DEBUG_INFO, "Unloading %a\n", PdbPath));
+ #endif
+  } else {
+    DEBUG ((DEBUG_LOAD | DEBUG_INFO, "Unloading driver at 0x%11p\n", (VOID *)(UINTN)UefiImageLoaderGetImageAddress (ImageContext)));
+  }
+}
diff --git a/ArmPkg/Library/DebugUefiImageExtraActionLib/DebugUefiImageExtraActionLib.inf b/ArmPkg/Library/DebugUefiImageExtraActionLib/DebugUefiImageExtraActionLib.inf
new file mode 100644
index 0000000000..31728d04d1
--- /dev/null
+++ b/ArmPkg/Library/DebugUefiImageExtraActionLib/DebugUefiImageExtraActionLib.inf
@@ -0,0 +1,33 @@
+#/** @file
+# UEFI Image extra action library for DXE phase that run Unix emulator.
+#
+# Lib to provide memory journal status code reporting Routines
+# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+# Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DebugUnixUefiImageExtraActionLib
+  FILE_GUID                      = C3E9448E-1726-42fb-9368-41F75B038C0C
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = UefiImageExtraActionLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = ARM
+#
+
+[Sources.common]
+  DebugUefiImageExtraActionLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  DebugLib
diff --git a/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c b/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c
index 5f9bcf7966..93814bb266 100644
--- a/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c
+++ b/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c
@@ -12,7 +12,6 @@
 #include <Library/UefiLib.h>
 #include <Library/BaseLib.h>
 #include <Library/DebugLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
 #include <Library/PrintLib.h>
 #include <Library/SerialPortLib.h>
 #include <Library/UefiBootServicesTableLib.h>
@@ -36,11 +35,10 @@ STATIC CHAR8  *gExceptionTypeString[] = {
 
 STATIC BOOLEAN  mRecursiveException;
 
-CHAR8 *
+CONST CHAR8 *
 GetImageName (
   IN  UINTN  FaultAddress,
-  OUT UINTN  *ImageBase,
-  OUT UINTN  *PeCoffSizeOfHeaders
+  OUT UINTN  *ImageBase
   );
 
 STATIC
@@ -211,14 +209,13 @@ DefaultExceptionHandler (
   UnicodeSPrintAsciiFormat (UnicodeBuffer, MAX_PRINT_CHARS, Buffer);
 
   DEBUG_CODE_BEGIN ();
-  CHAR8   *Pdb, *PrevPdb;
-  UINTN   ImageBase;
-  UINTN   PeCoffSizeOfHeader;
-  UINT64  *Fp;
-  UINT64  RootFp[2];
-  UINTN   Idx;
+  CONST CHAR8  *Pdb, *PrevPdb;
+  UINTN        ImageBase;
+  UINT64       *Fp;
+  UINT64       RootFp[2];
+  UINTN        Idx;
 
-  PrevPdb = Pdb = GetImageName (SystemContext.SystemContextAArch64->ELR, &ImageBase, &PeCoffSizeOfHeader);
+  PrevPdb = Pdb = GetImageName (SystemContext.SystemContextAArch64->ELR, &ImageBase);
   if (Pdb != NULL) {
     DEBUG ((
       DEBUG_ERROR,
@@ -243,7 +240,7 @@ DefaultExceptionHandler (
     }
 
     for (Fp = RootFp; Fp[0] != 0; Fp = (UINT64 *)Fp[0]) {
-      Pdb = GetImageName (Fp[1], &ImageBase, &PeCoffSizeOfHeader);
+      Pdb = GetImageName (Fp[1], &ImageBase);
       if (Pdb != NULL) {
         if (Pdb != PrevPdb) {
           Idx++;
@@ -264,14 +261,14 @@ DefaultExceptionHandler (
       }
     }
 
-    PrevPdb = Pdb = GetImageName (SystemContext.SystemContextAArch64->ELR, &ImageBase, &PeCoffSizeOfHeader);
+    PrevPdb = Pdb = GetImageName (SystemContext.SystemContextAArch64->ELR, &ImageBase);
     if (Pdb != NULL) {
       DEBUG ((DEBUG_ERROR, "\n[ 0] %a\n", Pdb));
     }
 
     Idx = 0;
     for (Fp = RootFp; Fp[0] != 0; Fp = (UINT64 *)Fp[0]) {
-      Pdb = GetImageName (Fp[1], &ImageBase, &PeCoffSizeOfHeader);
+      Pdb = GetImageName (Fp[1], &ImageBase);
       if ((Pdb != NULL) && (Pdb != PrevPdb)) {
         DEBUG ((DEBUG_ERROR, "[% 2d] %a\n", ++Idx, Pdb));
         PrevPdb = Pdb;
diff --git a/ArmPkg/Library/DefaultExceptionHandlerLib/Arm/DefaultExceptionHandler.c b/ArmPkg/Library/DefaultExceptionHandlerLib/Arm/DefaultExceptionHandler.c
index 50e4205c23..d05b2f7d80 100644
--- a/ArmPkg/Library/DefaultExceptionHandlerLib/Arm/DefaultExceptionHandler.c
+++ b/ArmPkg/Library/DefaultExceptionHandlerLib/Arm/DefaultExceptionHandler.c
@@ -11,7 +11,6 @@
 #include <Uefi.h>
 #include <Library/BaseLib.h>
 #include <Library/DebugLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
 #include <Library/PrintLib.h>
 #include <Library/SerialPortLib.h>
 #include <Library/UefiBootServicesTableLib.h>
@@ -53,11 +52,10 @@ STATIC CONST CPSR_CHAR  mCpsrChar[] = {
   { 0,  '?' }
 };
 
-CHAR8 *
+CONST CHAR8 *
 GetImageName (
   IN  UINTN  FaultAddress,
-  OUT UINTN  *ImageBase,
-  OUT UINTN  *PeCoffSizeOfHeaders
+  OUT UINTN  *ImageBase
   );
 
 /**
@@ -225,16 +223,16 @@ DefaultExceptionHandler (
   UnicodeSPrintAsciiFormat (UnicodeBuffer, MAX_PRINT_CHARS, Buffer);
 
   DEBUG_CODE_BEGIN ();
-  CHAR8   *Pdb;
-  UINT32  ImageBase;
-  UINT32  PeCoffSizeOfHeader;
-  UINT32  Offset;
-  CHAR8   CpsrStr[CPSR_STRING_SIZE];
+  CONST CHAR8   *Pdb;
+  UINT32        ImageBase;
+  UINT32        Offset;
+  CHAR8         CpsrStr[CPSR_STRING_SIZE];  // char per bit. Lower 5-bits are mode
+                                            // that is a 3 char string
 
   CpsrString (SystemContext.SystemContextArm->CPSR, CpsrStr);
   DEBUG ((DEBUG_ERROR, "%a\n", CpsrStr));
 
-  Pdb    = GetImageName (SystemContext.SystemContextArm->PC, &ImageBase, &PeCoffSizeOfHeader);
+  Pdb    = GetImageName (SystemContext.SystemContextArm->PC, &ImageBase);
   Offset = SystemContext.SystemContextArm->PC - ImageBase;
   if (Pdb != NULL) {
     DEBUG ((DEBUG_ERROR, "%a\n", Pdb));
@@ -247,7 +245,9 @@ DefaultExceptionHandler (
     // you need to subtract out the size of the PE/COFF header to get
     // get the offset that matches the link map.
     //
-    DEBUG ((DEBUG_ERROR, "loaded at 0x%08x (PE/COFF offset) 0x%x (ELF or Mach-O offset) 0x%x", ImageBase, Offset, Offset - PeCoffSizeOfHeader));
+    // FIXME: Used to have  (ELF or Mach-O offset) 0x%x
+    //        Substitute with .text address (better + may be needed for GDB symbols?)
+    DEBUG ((EFI_D_ERROR, "loaded at 0x%08x (PE/COFF offset) 0x%x", ImageBase, Offset));
   }
 
   DEBUG_CODE_END ();
diff --git a/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf b/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf
index 30291a4663..40fa5d552e 100644
--- a/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf
+++ b/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf
@@ -34,7 +34,6 @@
   BaseLib
   PrintLib
   DebugLib
-  PeCoffGetEntryPointLib
   SerialPortLib
   UefiBootServicesTableLib
 
diff --git a/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c b/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c
index 752a763f04..290827a99b 100644
--- a/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c
+++ b/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c
@@ -7,7 +7,6 @@
 **/
 
 #include <Uefi.h>
-#include <Library/PeCoffGetEntryPointLib.h>
 #include <Library/UefiLib.h>
 
 #include <Guid/DebugImageInfoTable.h>
@@ -20,17 +19,15 @@
 
   @param  FaultAddress         Address to find PE/COFF image for.
   @param  ImageBase            Return load address of found image
-  @param  PeCoffSizeOfHeaders  Return the size of the PE/COFF header for the image that was found
 
   @retval NULL                 FaultAddress not in a loaded PE/COFF image.
   @retval                      Path and file name of PE/COFF image.
 
 **/
-CHAR8 *
+CONST CHAR8 *
 GetImageName (
   IN  UINTN  FaultAddress,
-  OUT UINTN  *ImageBase,
-  OUT UINTN  *PeCoffSizeOfHeaders
+  OUT UINTN  *ImageBase
   )
 {
   EFI_STATUS                         Status;
@@ -59,8 +56,7 @@ GetImageName (
             (Address <= ((CHAR8 *)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase + DebugTable->NormalImage->LoadedImageProtocolInstance->ImageSize)))
         {
           *ImageBase           = (UINTN)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase;
-          *PeCoffSizeOfHeaders = PeCoffGetSizeOfHeaders ((VOID *)(UINTN)*ImageBase);
-          return PeCoffLoaderGetPdbPointer (DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase);
+          return DebugTable->NormalImage->PdbPath;
         }
       }
     }
diff --git a/ArmPlatformPkg/ArmPlatformPkg.dsc b/ArmPlatformPkg/ArmPlatformPkg.dsc
index d805778cee..f6655a4911 100644
--- a/ArmPlatformPkg/ArmPlatformPkg.dsc
+++ b/ArmPlatformPkg/ArmPlatformPkg.dsc
@@ -52,8 +52,9 @@
   MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
   MemoryInitPeiLib|ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
   PL011UartClockLib|ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf
   PL011UartLib|ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf
diff --git a/ArmVirtPkg/ArmVirt.dsc.inc b/ArmVirtPkg/ArmVirt.dsc.inc
index f053f5088e..bac77af65d 100644
--- a/ArmVirtPkg/ArmVirt.dsc.inc
+++ b/ArmVirtPkg/ArmVirt.dsc.inc
@@ -61,8 +61,8 @@
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
   PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf
   UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
   CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
@@ -125,8 +125,8 @@
   SerialPortLib|ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf
   FdtSerialPortAddressLib|OvmfPkg/Library/FdtSerialPortAddressLib/FdtSerialPortAddressLib.inf
 
-  PeCoffExtraActionLib|ArmPkg/Library/DebugPeCoffExtraActionLib/DebugPeCoffExtraActionLib.inf
-  #PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  UefiImageExtraActionLib|ArmPkg/Library/DebugUefiImageExtraActionLib/DebugUefiImageExtraActionLib.inf
+  #UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
 
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
   DebugAgentTimerLib|EmbeddedPkg/Library/DebugAgentTimerLibNull/DebugAgentTimerLibNull.inf
@@ -205,7 +205,6 @@
   PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
   PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
 
   PeiServicesTablePointerLib|ArmPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
@@ -223,7 +222,6 @@
   PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
   PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
 
   PeiServicesTablePointerLib|ArmPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
diff --git a/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S b/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S
index 06a0020f25..0f8ec68035 100644
--- a/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S
+++ b/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S
@@ -149,9 +149,8 @@ ASM_PFX(DiscoverDramFromDt):
   // window at the beginning of the FD image as a temp stack.
   //
   mov   x0, x7
-  adr   x1, PeCoffLoaderImageReadFromMemory
   mov   sp, x7
-  bl    RelocatePeCoffImage
+  bl    RelocateUefiImage
 
   //
   // Discover the memory size and offset from the DTB, and record in the
diff --git a/ArmVirtPkg/PrePi/Arm/ModuleEntryPoint.S b/ArmVirtPkg/PrePi/Arm/ModuleEntryPoint.S
index cfb5de864f..7fefd4cd06 100644
--- a/ArmVirtPkg/PrePi/Arm/ModuleEntryPoint.S
+++ b/ArmVirtPkg/PrePi/Arm/ModuleEntryPoint.S
@@ -146,9 +146,8 @@ ASM_PFX(ArmPlatformPeiBootAction):
   // window at the beginning of the FD image as a temp stack.
   //
   mov   r0, r5
-  ADRL  (r1, PeCoffLoaderImageReadFromMemory)
   mov   sp, r5
-  bl    RelocatePeCoffImage
+  bl    RelocateUefiImage
 
   //
   // Discover the memory size and offset from the DTB, and record in the
diff --git a/ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf b/ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
index 1f6538a4e5..9db6dd4dbe 100755
--- a/ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
+++ b/ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
@@ -46,7 +46,7 @@
   TimerLib
   SerialPortLib
   ExtractGuidedSectionLib
-  PeCoffLib
+  UefiImageLib
   PrePiLib
   MemoryAllocationLib
   HobLib
diff --git a/ArmVirtPkg/PrePi/PrePi.c b/ArmVirtPkg/PrePi/PrePi.c
old mode 100755
new mode 100644
index 9dbb5af942..0ed4db2903
--- a/ArmVirtPkg/PrePi/PrePi.c
+++ b/ArmVirtPkg/PrePi/PrePi.c
@@ -9,7 +9,7 @@
 #include <PiPei.h>
 #include <Pi/PiBootMode.h>
 
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/PrePiLib.h>
 #include <Library/PrintLib.h>
 #include <Library/PrePiHobListPointerLib.h>
@@ -129,15 +129,15 @@ CEntryPoint (
 }
 
 VOID
-RelocatePeCoffImage (
-  IN  EFI_PEI_FV_HANDLE         FwVolHeader,
-  IN  PE_COFF_LOADER_READ_FILE  ImageRead
+RelocateUefiImage (
+  IN  EFI_PEI_FV_HANDLE             FwVolHeader
   )
 {
-  EFI_PEI_FILE_HANDLE           FileHandle;
-  VOID                          *SectionData;
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
-  EFI_STATUS                    Status;
+  EFI_PEI_FILE_HANDLE             FileHandle;
+  VOID                            *SectionData;
+  UINT32                          SectionSize;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext;
+  EFI_STATUS                      Status;
 
   FileHandle = NULL;
   Status     = FfsFindNextFile (
@@ -147,21 +147,16 @@ RelocatePeCoffImage (
                  );
   ASSERT_EFI_ERROR (Status);
 
-  Status = FfsFindSectionData (EFI_SECTION_PE32, FileHandle, &SectionData);
+  Status = FfsFindSectionData (EFI_SECTION_PE32, FileHandle, &SectionData, &SectionSize);
   if (EFI_ERROR (Status)) {
-    Status = FfsFindSectionData (EFI_SECTION_TE, FileHandle, &SectionData);
+    Status = FfsFindSectionData (EFI_SECTION_TE, FileHandle, &SectionData, &SectionSize);
   }
 
   ASSERT_EFI_ERROR (Status);
 
-  ZeroMem (&ImageContext, sizeof ImageContext);
+  Status = UefiImageInitializeContext (&ImageContext, SectionData, SectionSize);
+  ASSERT_RETURN_ERROR (Status);
 
-  ImageContext.Handle    = (EFI_HANDLE)SectionData;
-  ImageContext.ImageRead = ImageRead;
-  PeCoffLoaderGetImageInfo (&ImageContext);
-
-  if (ImageContext.ImageAddress != (UINTN)SectionData) {
-    ImageContext.ImageAddress = (UINTN)SectionData;
-    PeCoffLoaderRelocateImage (&ImageContext);
-  }
+  Status = UefiImageRelocateImageInplaceForExecution (&ImageContext);
+  ASSERT_RETURN_ERROR (Status);
 }
diff --git a/BaseTools/Source/C/GenFv/GenFvInternalLib.c b/BaseTools/Source/C/GenFv/GenFvInternalLib.c
index 3f982c529b..4fc2abf0a8 100644
--- a/BaseTools/Source/C/GenFv/GenFvInternalLib.c
+++ b/BaseTools/Source/C/GenFv/GenFvInternalLib.c
@@ -54,6 +54,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
                                     (((Imm32) >> 2) & 0x7fffff))
 #define ARM_JUMP_TO_THUMB(Offset)  _ARM_JUMP_TO_THUMB((Offset) - 8)
 
+#define ALIGN_VALUE_ADDEND(Value, Alignment)  (((Alignment) - (Value)) & ((Alignment) - 1U))
+#define ALIGN_VALUE(Value, Alignment) ((Value) + ALIGN_VALUE_ADDEND (Value, Alignment))
+#define IS_ALIGNED(Value, Alignment)  (((Value) & ((Alignment) - 1U)) == 0U)
+
 /*
  * Arm instruction to return from exception (MOVS PC, LR)
  */
@@ -1308,11 +1312,17 @@ Returns:
       // Rebase the PE or TE image in FileBuffer of FFS file for XIP
       // Rebase for the debug genfvmap tool
       //
-      Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage, FvMapFile);
+      Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER **)&FileBuffer, &FileSize, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage, FvMapFile);
       if (EFI_ERROR (Status)) {
         Error (NULL, 0, 3000, "Invalid", "Could not rebase %s.", FvInfo->FvFiles[Index]);
         return Status;
       }
+
+      if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {
+        free (FileBuffer);
+        Error (NULL, 0, 4002, "Resource", "FV space is full, not enough room to add file %s after ImageBase aligning.", FvInfo->FvFiles[Index]);
+        return EFI_OUT_OF_RESOURCES;
+      }
       //
       // copy VTF File
       //
@@ -1354,11 +1364,17 @@ Returns:
     // Rebase the PE or TE image in FileBuffer of FFS file for XIP.
     // Rebase Bs and Rt drivers for the debug genfvmap tool.
     //
-    Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage, FvMapFile);
-  if (EFI_ERROR (Status)) {
-    Error (NULL, 0, 3000, "Invalid", "Could not rebase %s.", FvInfo->FvFiles[Index]);
-    return Status;
-  }
+    Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER **)&FileBuffer, &FileSize, (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage, FvMapFile);
+    if (EFI_ERROR (Status)) {
+      Error (NULL, 0, 3000, "Invalid", "Could not rebase %s.", FvInfo->FvFiles[Index]);
+      return Status;
+    }
+
+    if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {
+      free (FileBuffer);
+      Error (NULL, 0, 4002, "Resource", "FV space is full, not enough room to add file %s after ImageBase aligning.", FvInfo->FvFiles[Index]);
+      return EFI_OUT_OF_RESOURCES;
+    }
     //
     // Copy the file
     //
@@ -3456,11 +3472,109 @@ Returns:
   return EFI_SUCCESS;
 }
 
+EFI_PHYSICAL_ADDRESS
+AddPadSection (
+  IN OUT EFI_PHYSICAL_ADDRESS     *BaseAddress,
+  IN     UINT32                   Alignment,
+  IN OUT EFI_FFS_FILE_HEADER      **FfsFile,
+  IN OUT UINTN                    *FileSize,
+  IN OUT EFI_FILE_SECTION_POINTER *Section
+  )
+{
+  EFI_COMMON_SECTION_HEADER *NewSection;
+  UINT32                    FfsHeaderLength;
+  UINT32                    FfsFileLength;
+  UINT32                    PadSize;
+  UINTN                     PadAddress;
+  UINT8                     *FfsPart;
+  UINT32                    PartSize;
+  UINT32                    Offset;
+  EFI_FFS_INTEGRITY_CHECK   *IntegrityCheck;
+
+  PadAddress = ALIGN_VALUE (*BaseAddress + sizeof (EFI_COMMON_SECTION_HEADER), Alignment);
+  PadSize    = PadAddress - *BaseAddress;
+
+  Offset = (UINT32)((UINTN)((*Section).Pe32Section) - (UINTN)(*FfsFile));
+  PartSize = GetFfsFileLength (*FfsFile) - Offset;
+  FfsPart = calloc (1, PartSize);
+  if (FfsPart == NULL) {
+    fprintf (stderr, "GenFv: Could not allocate memory for FfsPart\n");
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  CopyMem (FfsPart, (UINT8 *)(UINTN)((*Section).Pe32Section), PartSize);
+
+  FfsFileLength = GetFfsFileLength (*FfsFile) + PadSize;
+  *FfsFile = realloc (*FfsFile, FfsFileLength);
+  if (*FfsFile == NULL) {
+    fprintf (stderr, "GenFv: Could not reallocate memory for FfsFile\n");
+    free (FfsPart);
+    return EFI_OUT_OF_RESOURCES;
+  }
+  *FileSize += PadSize;
+
+  NewSection = (EFI_COMMON_SECTION_HEADER *)((UINTN)(*FfsFile) + Offset);
+
+  NewSection->Size[0] = (UINT8)(PadSize & 0xff);
+  NewSection->Size[1] = (UINT8)((PadSize & 0xff00) >> 8);
+  NewSection->Size[2] = (UINT8)((PadSize & 0xff0000) >> 16);
+  NewSection->Type    = EFI_SECTION_RAW;
+  ++NewSection;
+  ZeroMem ((VOID *)NewSection, PadSize - sizeof (EFI_COMMON_SECTION_HEADER));
+
+  *Section = (EFI_FILE_SECTION_POINTER)(EFI_PE32_SECTION *)((UINT8 *)NewSection + PadSize - sizeof (EFI_COMMON_SECTION_HEADER));
+
+  CopyMem (
+    (UINT8 *)((*Section).Pe32Section),
+    FfsPart,
+    PartSize
+    );
+
+  FfsHeaderLength = GetFfsHeaderLength(*FfsFile);
+  if (FfsHeaderLength > sizeof(EFI_FFS_FILE_HEADER)) {
+    ((EFI_FFS_FILE_HEADER2 *)(*FfsFile))->ExtendedSize = FfsFileLength;
+  } else {
+    (*FfsFile)->Size[0] = (UINT8)(FfsFileLength & 0x000000FF);
+    (*FfsFile)->Size[1] = (UINT8)((FfsFileLength & 0x0000FF00) >> 8);
+    (*FfsFile)->Size[2] = (UINT8)((FfsFileLength & 0x00FF0000) >> 16);
+  }
+
+  //
+  // Recalculate the FFS header checksum. Instead of setting Header and State
+  // both to zero, set Header to (UINT8)(-State) so State preserves its original
+  // value
+  //
+  IntegrityCheck = &(*FfsFile)->IntegrityCheck;
+  IntegrityCheck->Checksum.Header = (UINT8) (0x100 - (*FfsFile)->State);
+  IntegrityCheck->Checksum.File = 0;
+
+  IntegrityCheck->Checksum.Header = CalculateChecksum8 (
+                                      (UINT8 *)(*FfsFile), FfsHeaderLength);
+
+  if ((*FfsFile)->Attributes & FFS_ATTRIB_CHECKSUM) {
+    //
+    // Ffs header checksum = zero, so only need to calculate ffs body.
+    //
+    IntegrityCheck->Checksum.File = CalculateChecksum8 (
+                                      (UINT8 *)(*FfsFile) + FfsHeaderLength,
+                                      FfsFileLength - FfsHeaderLength);
+  } else {
+    IntegrityCheck->Checksum.File = FFS_FIXED_CHECKSUM;
+  }
+
+  *BaseAddress = PadAddress;
+
+  free (FfsPart);
+
+  return EFI_SUCCESS;
+}
+
 EFI_STATUS
 FfsRebase (
   IN OUT  FV_INFO               *FvInfo,
   IN      CHAR8                 *FileName,
-  IN OUT  EFI_FFS_FILE_HEADER   *FfsFile,
+  IN OUT  EFI_FFS_FILE_HEADER   **FfsFile,
+  IN OUT  UINTN                 *FileSize,
   IN      UINTN                 XipOffset,
   IN      FILE                  *FvMapFile
   )
@@ -3533,13 +3647,12 @@ Returns:
     return EFI_SUCCESS;
   }
 
-
   XipBase = FvInfo->BaseAddress + XipOffset;
 
   //
   // We only process files potentially containing PE32 sections.
   //
-  switch (FfsFile->Type) {
+  switch ((*FfsFile)->Type) {
     case EFI_FV_FILETYPE_SECURITY_CORE:
     case EFI_FV_FILETYPE_PEI_CORE:
     case EFI_FV_FILETYPE_PEIM:
@@ -3551,7 +3664,7 @@ Returns:
       //
       // Rebase the inside FvImage.
       //
-      GetChildFvFromFfs (FvInfo, FfsFile, XipOffset);
+      GetChildFvFromFfs (FvInfo, *FfsFile, XipOffset);
 
       //
       // Search PE/TE section in FV sectin.
@@ -3561,7 +3674,7 @@ Returns:
       return EFI_SUCCESS;
   }
 
-  FfsHeaderSize = GetFfsHeaderLength(FfsFile);
+  FfsHeaderSize = GetFfsHeaderLength(*FfsFile);
   //
   // Rebase each PE32 section
   //
@@ -3575,7 +3688,7 @@ Returns:
     //
     // Find Pe Image
     //
-    Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);
+    Status = GetSectionByType (*FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);
     if (EFI_ERROR (Status)) {
       break;
     }
@@ -3624,7 +3737,7 @@ Returns:
     //
     // Calculate the PE32 base address, based on file type
     //
-    switch (FfsFile->Type) {
+    switch ((*FfsFile)->Type) {
       case EFI_FV_FILETYPE_SECURITY_CORE:
       case EFI_FV_FILETYPE_PEI_CORE:
       case EFI_FV_FILETYPE_PEIM:
@@ -3702,7 +3815,7 @@ Returns:
           ImageContext.RelocationsStripped = FALSE;
         }
 
-        NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize - (UINTN)FfsFile;
+        NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize - (UINTN)(*FfsFile);
         break;
 
       case EFI_FV_FILETYPE_DRIVER:
@@ -3717,7 +3830,7 @@ Returns:
           Error (NULL, 0, 3000, "Invalid", "PE image Section-Alignment and File-Alignment do not match : %s.", FileName);
           return EFI_ABORTED;
         }
-        NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize - (UINTN)FfsFile;
+        NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize - (UINTN)(*FfsFile);
         break;
 
       default:
@@ -3741,15 +3854,28 @@ Returns:
     //
     // Load and Relocate Image Data
     //
-    MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
+    MemoryImagePointer = (UINT8 *) calloc (1, (UINTN)ImageContext.ImageSize + ImageContext.SectionAlignment);
     if (MemoryImagePointer == NULL) {
       Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
       return EFI_OUT_OF_RESOURCES;
     }
-    memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
-    ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((UINTN) ImageContext.SectionAlignment - 1));
+    ImageContext.ImageAddress = ALIGN_VALUE ((UINTN)MemoryImagePointer, ImageContext.SectionAlignment);
 
-    Status =  PeCoffLoaderLoadImage (&ImageContext);
+    if (!(IS_ALIGNED (NewPe32BaseAddress, ImageContext.SectionAlignment))) {
+      Status = AddPadSection (&NewPe32BaseAddress, ImageContext.SectionAlignment, FfsFile, FileSize, &CurrentPe32Section);
+      if (EFI_ERROR (Status)) {
+        free ((VOID *) MemoryImagePointer);
+        return Status;
+      }
+
+      CurSecHdrSize       = GetSectionHeaderLength (CurrentPe32Section.CommonHeader);
+      ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize);
+      PdbPointer          = PeCoffLoaderGetPdbPointer (ImageContext.Handle);
+
+      ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize + ImageContext.PeCoffHeaderOffset);
+    }
+
+    Status = PeCoffLoaderLoadImage (&ImageContext);
     if (EFI_ERROR (Status)) {
       Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);
       free ((VOID *) MemoryImagePointer);
@@ -3757,7 +3883,8 @@ Returns:
     }
 
     ImageContext.DestinationAddress = NewPe32BaseAddress;
-    Status                          = PeCoffLoaderRelocateImage (&ImageContext);
+
+    Status = PeCoffLoaderRelocateImage (&ImageContext);
     if (EFI_ERROR (Status)) {
       Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s Status=%d", FileName, Status);
       free ((VOID *) MemoryImagePointer);
@@ -3807,15 +3934,15 @@ Returns:
     //
     // Now update file checksum
     //
-    if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
-      SavedState  = FfsFile->State;
-      FfsFile->IntegrityCheck.Checksum.File = 0;
-      FfsFile->State                        = 0;
-      FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
-                                                (UINT8 *) ((UINT8 *)FfsFile + FfsHeaderSize),
-                                                GetFfsFileLength (FfsFile) - FfsHeaderSize
+    if ((*FfsFile)->Attributes & FFS_ATTRIB_CHECKSUM) {
+      SavedState  = (*FfsFile)->State;
+      (*FfsFile)->IntegrityCheck.Checksum.File = 0;
+      (*FfsFile)->State                        = 0;
+      (*FfsFile)->IntegrityCheck.Checksum.File = CalculateChecksum8 (
+                                                (UINT8 *) ((UINT8 *)(*FfsFile) + FfsHeaderSize),
+                                                GetFfsFileLength (*FfsFile) - FfsHeaderSize
                                                 );
-      FfsFile->State = SavedState;
+      (*FfsFile)->State = SavedState;
     }
 
     //
@@ -3829,14 +3956,14 @@ Returns:
       PdbPointer = FileName;
     }
 
-    WriteMapFile (FvMapFile, PdbPointer, FfsFile, NewPe32BaseAddress, &OrigImageContext);
+    WriteMapFile (FvMapFile, PdbPointer, *FfsFile, NewPe32BaseAddress, &OrigImageContext);
   }
 
-  if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
-      FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&
-      FfsFile->Type != EFI_FV_FILETYPE_PEIM &&
-      FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER &&
-      FfsFile->Type != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
+  if ((*FfsFile)->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
+      (*FfsFile)->Type != EFI_FV_FILETYPE_PEI_CORE &&
+      (*FfsFile)->Type != EFI_FV_FILETYPE_PEIM &&
+      (*FfsFile)->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER &&
+      (*FfsFile)->Type != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
       ) {
     //
     // Only Peim code may have a TE section
@@ -3853,7 +3980,7 @@ Returns:
     //
     // Find Te Image
     //
-    Status = GetSectionByType (FfsFile, EFI_SECTION_TE, Index, &CurrentPe32Section);
+    Status = GetSectionByType (*FfsFile, EFI_SECTION_TE, Index, &CurrentPe32Section);
     if (EFI_ERROR (Status)) {
       break;
     }
@@ -3901,7 +4028,7 @@ Returns:
     // Set new rebased address.
     //
     NewPe32BaseAddress = XipBase + (UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) \
-                         - TEImageHeader->StrippedSize - (UINTN) FfsFile;
+                         - TEImageHeader->StrippedSize - (UINTN) (*FfsFile);
 
     //
     // if reloc is stripped, try to get the original efi image to get reloc info.
@@ -4044,15 +4171,15 @@ Returns:
     //
     // Now update file checksum
     //
-    if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
-      SavedState  = FfsFile->State;
-      FfsFile->IntegrityCheck.Checksum.File = 0;
-      FfsFile->State                        = 0;
-      FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
-                                                (UINT8 *)((UINT8 *)FfsFile + FfsHeaderSize),
-                                                GetFfsFileLength (FfsFile) - FfsHeaderSize
+    if ((*FfsFile)->Attributes & FFS_ATTRIB_CHECKSUM) {
+      SavedState  = (*FfsFile)->State;
+      (*FfsFile)->IntegrityCheck.Checksum.File = 0;
+      (*FfsFile)->State                        = 0;
+      (*FfsFile)->IntegrityCheck.Checksum.File = CalculateChecksum8 (
+                                                (UINT8 *)((UINT8 *)(*FfsFile) + FfsHeaderSize),
+                                                GetFfsFileLength (*FfsFile) - FfsHeaderSize
                                                 );
-      FfsFile->State = SavedState;
+      (*FfsFile)->State = SavedState;
     }
     //
     // Get this module function address from ModulePeMapFile and add them into FvMap file
@@ -4068,7 +4195,7 @@ Returns:
     WriteMapFile (
       FvMapFile,
       PdbPointer,
-      FfsFile,
+      *FfsFile,
       NewPe32BaseAddress,
       &OrigImageContext
       );
diff --git a/BaseTools/Source/C/GenFv/GenFvInternalLib.h b/BaseTools/Source/C/GenFv/GenFvInternalLib.h
index 58dadc3fa9..bf476f2c08 100644
--- a/BaseTools/Source/C/GenFv/GenFvInternalLib.h
+++ b/BaseTools/Source/C/GenFv/GenFvInternalLib.h
@@ -331,7 +331,8 @@ EFI_STATUS
 FfsRebase (
   IN OUT  FV_INFO               *FvInfo,
   IN      CHAR8                 *FileName,
-  IN OUT  EFI_FFS_FILE_HEADER   *FfsFile,
+  IN OUT  EFI_FFS_FILE_HEADER   **FfsFile,
+  IN OUT  UINTN                 *FileSize,
   IN      UINTN                 XipOffset,
   IN      FILE                  *FvMapFile
   );
diff --git a/BaseTools/Source/Python/build/build.py b/BaseTools/Source/Python/build/build.py
index 74b4242a16..9fb5ae758e 100755
--- a/BaseTools/Source/Python/build/build.py
+++ b/BaseTools/Source/Python/build/build.py
@@ -72,6 +72,24 @@ gSupportedTarget = ['all', 'genc', 'genmake', 'modules', 'libraries', 'fds', 'cl
 TemporaryTablePattern = re.compile(r'^_\d+_\d+_[a-fA-F0-9]+$')
 TmpTableDict = {}
 
+## Return the biggest multiple of alignment that is smaller than or equal to
+#  value.
+#
+#   @param value      The value to align down.
+#   @param alignment  The boundary to align down to.
+#
+def AlignDown(value, alignment):
+    return value - (value % alignment)
+
+## Return the smallest multiple of alignment that is bigger than or equal to
+#  value.
+#
+#   @param value      The value to align up.
+#   @param alignment  The boundary to align up to.
+#
+def AlignUp(value, alignment):
+    return AlignDown(value + alignment - 1, alignment)
+
 ## Check environment PATH variable to make sure the specified tool is found
 #
 #   If the tool is found in the PATH, then True is returned
@@ -706,7 +724,7 @@ class PeImageInfo():
         self.OutputDir        = OutputDir
         self.DebugDir         = DebugDir
         self.Image            = ImageClass
-        self.Image.Size       = (self.Image.Size // 0x1000 + 1) * 0x1000
+        self.Image.Size       = AlignUp(self.Image.Size, 0x1000)
 
 ## The class implementing the EDK2 build process
 #
@@ -1520,12 +1538,15 @@ class Build():
             ## for SMM module in SMRAM, the SMRAM will be allocated from base to top.
             if not ModeIsSmm:
                 BaseAddress = BaseAddress - ModuleInfo.Image.Size
+                BaseAddress = AlignDown(BaseAddress, ModuleInfo.Image.SectionAlignment)
                 #
                 # Update Image to new BaseAddress by GenFw tool
                 #
                 LaunchCommand(["GenFw", "--rebase", str(BaseAddress), "-r", ModuleOutputImage], ModuleInfo.OutputDir)
                 LaunchCommand(["GenFw", "--rebase", str(BaseAddress), "-r", ModuleDebugImage], ModuleInfo.DebugDir)
+            ## for SMM module in SMRAM, the SMRAM will be allocated from base to top.
             else:
+                BaseAddress = AlignUp(BaseAddress, ModuleInfo.Image.SectionAlignment)
                 #
                 # Set new address to the section header only for SMM driver.
                 #
diff --git a/EmbeddedPkg/EmbeddedPkg.dec b/EmbeddedPkg/EmbeddedPkg.dec
index bb0b677bdc..7536e8d4ab 100644
--- a/EmbeddedPkg/EmbeddedPkg.dec
+++ b/EmbeddedPkg/EmbeddedPkg.dec
@@ -81,7 +81,6 @@
   gEmbeddedDeviceGuid =   { 0xbf4b9d10, 0x13ec, 0x43dd, { 0x88, 0x80, 0xe9, 0xb, 0x71, 0x8f, 0x27, 0xde } }
   gEmbeddedExternalDeviceProtocolGuid = { 0x735F8C64, 0xD696, 0x44D0, { 0xBD, 0xF2, 0x44, 0x7F, 0xD0, 0x5A, 0x54, 0x06 }}
   gEmbeddedGpioProtocolGuid           = { 0x17a0a3d7, 0xc0a5, 0x4635, { 0xbb, 0xd5, 0x07, 0x21, 0x87, 0xdf, 0xe2, 0xee }}
-  gPeCoffLoaderProtocolGuid =  { 0xB323179B, 0x97FB, 0x477E, { 0xB0, 0xFE, 0xD8, 0x85, 0x91, 0xFA, 0x11, 0xAB } }
   gEmbeddedMmcHostProtocolGuid         = { 0x3e591c00, 0x9e4a, 0x11df, {0x92, 0x44, 0x00, 0x02, 0xA5, 0xD5, 0xC5, 0x1B }}
   gAndroidFastbootTransportProtocolGuid = { 0x74bd9fe0, 0x8902, 0x11e3, {0xb9, 0xd3, 0xf7, 0x22, 0x38, 0xfc, 0x9a, 0x31}}
   gAndroidFastbootPlatformProtocolGuid =  { 0x524685a0, 0x89a0, 0x11e3, {0x9d, 0x4d, 0xbf, 0xa9, 0xf6, 0xa4, 0x03, 0x08}}
diff --git a/EmbeddedPkg/EmbeddedPkg.dsc b/EmbeddedPkg/EmbeddedPkg.dsc
index 5cc0bb7ad6..44f220eb7e 100644
--- a/EmbeddedPkg/EmbeddedPkg.dsc
+++ b/EmbeddedPkg/EmbeddedPkg.dsc
@@ -58,9 +58,9 @@
 
   ReportStatusCodeLib|MdeModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf
 
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
   CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
   PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf
 
diff --git a/EmbeddedPkg/GdbStub/GdbStub.c b/EmbeddedPkg/GdbStub/GdbStub.c
index e6e07b87b6..3d317cb05a 100644
--- a/EmbeddedPkg/GdbStub/GdbStub.c
+++ b/EmbeddedPkg/GdbStub/GdbStub.c
@@ -807,166 +807,6 @@ gXferObjectReadResponse (
   return Count;
 }
 
-/**
-  Note: This should be a library function.  In the Apple case you have to add
-  the size of the PE/COFF header into the starting address to make things work
-  right as there is no way to pad the Mach-O for the size of the PE/COFF header.
-
-
-  Returns a pointer to the PDB file name for a PE/COFF image that has been
-  loaded into system memory with the PE/COFF Loader Library functions.
-
-  Returns the PDB file name for the PE/COFF image specified by Pe32Data.  If
-  the PE/COFF image specified by Pe32Data is not a valid, then NULL is
-  returned.  If the PE/COFF image specified by Pe32Data does not contain a
-  debug directory entry, then NULL is returned.  If the debug directory entry
-  in the PE/COFF image specified by Pe32Data does not contain a PDB file name,
-  then NULL is returned.
-  If Pe32Data is NULL, then ASSERT().
-
-  @param  Pe32Data   Pointer to the PE/COFF image that is loaded in system
-                     memory.
-  @param  DebugBase  Address that the debugger would use as the base of the image
-
-  @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL
-          if it cannot be retrieved. DebugBase is only valid if PDB file name is
-          valid.
-
-**/
-VOID *
-EFIAPI
-PeCoffLoaderGetDebuggerInfo (
-  IN VOID   *Pe32Data,
-  OUT VOID  **DebugBase
-  )
-{
-  EFI_IMAGE_DOS_HEADER                 *DosHdr;
-  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;
-  EFI_IMAGE_DATA_DIRECTORY             *DirectoryEntry;
-  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY      *DebugEntry;
-  UINTN                                DirCount;
-  VOID                                 *CodeViewEntryPointer;
-  INTN                                 TEImageAdjust;
-  UINT32                               NumberOfRvaAndSizes;
-  UINT16                               Magic;
-  UINTN                                SizeOfHeaders;
-
-  ASSERT (Pe32Data   != NULL);
-
-  TEImageAdjust       = 0;
-  DirectoryEntry      = NULL;
-  DebugEntry          = NULL;
-  NumberOfRvaAndSizes = 0;
-  SizeOfHeaders       = 0;
-
-  DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
-  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
-    //
-    // DOS image header is present, so read the PE header after the DOS image header.
-    //
-    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));
-  } else {
-    //
-    // DOS image header is not present, so PE header is at the image base.
-    //
-    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
-  }
-
-  if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
-    if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {
-      DirectoryEntry = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];
-      TEImageAdjust  = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;
-      DebugEntry     = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN)Hdr.Te +
-                                                           Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +
-                                                           TEImageAdjust);
-    }
-
-    SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize;
-
-    // __APPLE__ check this math...
-    *DebugBase = ((CHAR8 *)Pe32Data) -  TEImageAdjust;
-  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
-    *DebugBase = Pe32Data;
-
-    //
-    // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.
-    //       It is due to backward-compatibility, for some system might
-    //       generate PE32+ image with PE32 Magic.
-    //
-    switch (Hdr.Pe32->FileHeader.Machine) {
-      case EFI_IMAGE_MACHINE_IA32:
-        //
-        // Assume PE32 image with IA32 Machine field.
-        //
-        Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
-        break;
-      case EFI_IMAGE_MACHINE_X64:
-      case EFI_IMAGE_MACHINE_IA64:
-        //
-        // Assume PE32+ image with X64 or IPF Machine field
-        //
-        Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
-        break;
-      default:
-        //
-        // For unknown Machine field, use Magic in optional Header
-        //
-        Magic = Hdr.Pe32->OptionalHeader.Magic;
-    }
-
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-      //
-      // Use PE32 offset get Debug Directory Entry
-      //
-      SizeOfHeaders       = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
-      NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
-      DirectoryEntry      = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
-      DebugEntry          = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN)Pe32Data + DirectoryEntry->VirtualAddress);
-    } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
-      //
-      // Use PE32+ offset get Debug Directory Entry
-      //
-      SizeOfHeaders       = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders;
-      NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
-      DirectoryEntry      = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
-      DebugEntry          = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN)Pe32Data + DirectoryEntry->VirtualAddress);
-    }
-
-    if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
-      DirectoryEntry = NULL;
-      DebugEntry     = NULL;
-    }
-  } else {
-    return NULL;
-  }
-
-  if ((DebugEntry == NULL) || (DirectoryEntry == NULL)) {
-    return NULL;
-  }
-
-  for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) {
-    if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
-      if (DebugEntry->SizeOfData > 0) {
-        CodeViewEntryPointer = (VOID *)((UINTN)DebugEntry->RVA + ((UINTN)Pe32Data) + (UINTN)TEImageAdjust);
-        switch (*(UINT32 *)CodeViewEntryPointer) {
-          case CODEVIEW_SIGNATURE_NB10:
-            return (VOID *)((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY));
-          case CODEVIEW_SIGNATURE_RSDS:
-            return (VOID *)((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY));
-          case CODEVIEW_SIGNATURE_MTOC:
-            *DebugBase = (VOID *)(UINTN)((UINTN)DebugBase - SizeOfHeaders);
-            return (VOID *)((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY));
-          default:
-            break;
-        }
-      }
-    }
-  }
-
-  (void)SizeOfHeaders;
-  return NULL;
-}
-
 /**
   Process "qXfer:object:read:annex:offset,length" request.
 
@@ -1007,7 +847,7 @@ QxferLibrary (
   )
 {
   VOID   *LoadAddress;
-  CHAR8  *Pdb;
+  CONST CHAR8                       *Pdb;
   UINTN  Size;
 
   if (Offset != gPacketqXferLibraryOffset) {
@@ -1035,12 +875,8 @@ QxferLibrary (
     for ( ; gEfiDebugImageTableEntry < gDebugImageTableHeader->TableSize; gEfiDebugImageTableEntry++, gDebugTable++) {
       if (gDebugTable->NormalImage != NULL) {
         if ((gDebugTable->NormalImage->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) &&
-            (gDebugTable->NormalImage->LoadedImageProtocolInstance != NULL))
-        {
-          Pdb = PeCoffLoaderGetDebuggerInfo (
-                  gDebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase,
-                  &LoadAddress
-                  );
+            (gDebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) {
+          Pdb = gDebugTable->NormalImage->PdbPath;
           if (Pdb != NULL) {
             Size = AsciiSPrint (
                      gXferLibraryBuffer,
diff --git a/EmbeddedPkg/GdbStub/GdbStubInternal.h b/EmbeddedPkg/GdbStub/GdbStubInternal.h
index 9c3929c812..cc954c0666 100644
--- a/EmbeddedPkg/GdbStub/GdbStubInternal.h
+++ b/EmbeddedPkg/GdbStub/GdbStubInternal.h
@@ -26,7 +26,7 @@
 #include <Protocol/LoadedImage.h>
 #include <Protocol/LoadedImage.h>
 #include <Guid/DebugImageInfoTable.h>
-#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/PeImage2.h>
 
 extern CONST CHAR8  mHexToStr[];
 
diff --git a/EmbeddedPkg/Include/Library/PrePiLib.h b/EmbeddedPkg/Include/Library/PrePiLib.h
index 93a9115eac..a76d4c5686 100644
--- a/EmbeddedPkg/Include/Library/PrePiLib.h
+++ b/EmbeddedPkg/Include/Library/PrePiLib.h
@@ -71,6 +71,7 @@ EFI_STATUS
   @param  FileHeader            A pointer to the file header that contains the set of sections to
                                 be searched.
   @param  SectionData           A pointer to the discovered section, if successful.
+  @param  SectionSize           A pointer to the size of the discovered section, if successful.
 
   @retval EFI_SUCCESS           The section was found.
   @retval EFI_NOT_FOUND         The section was not found.
@@ -82,7 +83,8 @@ FfsFindSectionDataWithHook (
   IN EFI_SECTION_TYPE        SectionType,
   IN FFS_CHECK_SECTION_HOOK  SectionCheckHook,
   IN EFI_PEI_FILE_HANDLE     FileHandle,
-  OUT VOID                   **SectionData
+  OUT VOID                   **SectionData,
+  OUT UINT32                 *SectionSize
   );
 
 /**
@@ -92,6 +94,7 @@ FfsFindSectionDataWithHook (
   @param  FileHandle            A pointer to the file header that contains the set of sections to
                                 be searched.
   @param  SectionData           A pointer to the discovered section, if successful.
+  @param  SectionSize           A pointer to the size of the discovered section, if successful.
 
   @retval EFI_SUCCESS           The section was found.
   @retval EFI_NOT_FOUND         The section was not found.
@@ -102,7 +105,8 @@ EFIAPI
 FfsFindSectionData (
   IN EFI_SECTION_TYPE     SectionType,
   IN EFI_PEI_FILE_HANDLE  FileHandle,
-  OUT VOID                **SectionData
+  OUT VOID                **SectionData,
+  OUT UINT32              *SectionSize
   );
 
 /**
@@ -675,7 +679,7 @@ BuildExtractSectionHob (
 
 VOID
 EFIAPI
-BuildPeCoffLoaderHob (
+BuildUefiLoaderHob (
   VOID
   );
 
@@ -760,10 +764,11 @@ AllocateAlignedPages (
 
 EFI_STATUS
 EFIAPI
-LoadPeCoffImage (
-  IN  VOID                  *PeCoffImage,
+LoadUefiImage (
+  IN  VOID                                      *UefiImage,
+  IN  UINT32                                    UefiImageSize,
   OUT EFI_PHYSICAL_ADDRESS  *ImageAddress,
-  OUT UINT64                *ImageSize,
+  OUT UINT32                *ImageSize,
   OUT EFI_PHYSICAL_ADDRESS  *EntryPoint
   );
 
diff --git a/EmbeddedPkg/Library/PrePiHobLib/Hob.c b/EmbeddedPkg/Library/PrePiHobLib/Hob.c
index a394ca00b4..3cdcfbaf8d 100644
--- a/EmbeddedPkg/Library/PrePiHobLib/Hob.c
+++ b/EmbeddedPkg/Library/PrePiHobLib/Hob.c
@@ -12,12 +12,11 @@
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/HobLib.h>
 #include <Library/PcdLib.h>
 #include <Library/PrePiHobListPointerLib.h>
 
-#include <Protocol/PeCoffLoader.h>
 #include <Guid/ExtractSection.h>
 #include <Guid/MemoryTypeInformation.h>
 #include <Guid/MemoryAllocationHob.h>
@@ -821,27 +820,6 @@ BuildExtractSectionHob (
   BuildGuidDataHob (Guid, &Data, sizeof (Data));
 }
 
-PE_COFF_LOADER_PROTOCOL  gPeCoffProtocol = {
-  PeCoffLoaderGetImageInfo,
-  PeCoffLoaderLoadImage,
-  PeCoffLoaderRelocateImage,
-  PeCoffLoaderImageReadFromMemory,
-  PeCoffLoaderRelocateImageForRuntime,
-  PeCoffLoaderUnloadImage
-};
-
-VOID
-EFIAPI
-BuildPeCoffLoaderHob (
-  VOID
-  )
-{
-  VOID  *Ptr;
-
-  Ptr = &gPeCoffProtocol;
-  BuildGuidDataHob (&gPeCoffLoaderProtocolGuid, &Ptr, sizeof (VOID *));
-}
-
 // May want to put this into a library so you only need the PCD settings if you are using the feature?
 VOID
 BuildMemoryTypeInformationHob (
diff --git a/EmbeddedPkg/Library/PrePiLib/FwVol.c b/EmbeddedPkg/Library/PrePiLib/FwVol.c
index cfb1ff46b7..8ce5cab236 100644
--- a/EmbeddedPkg/Library/PrePiLib/FwVol.c
+++ b/EmbeddedPkg/Library/PrePiLib/FwVol.c
@@ -278,7 +278,8 @@ FfsProcessSection (
   IN FFS_CHECK_SECTION_HOOK     SectionCheckHook,
   IN EFI_COMMON_SECTION_HEADER  *Section,
   IN UINTN                      SectionSize,
-  OUT VOID                      **OutputBuffer
+  OUT VOID                      **OutputBuffer,
+  OUT UINT32                    *OutputSize
   )
 {
   EFI_STATUS                Status;
@@ -298,6 +299,7 @@ FfsProcessSection (
 
   Found         = FALSE;
   *OutputBuffer = NULL;
+  *OutputSize   = 0;
   ParsedLength  = 0;
   Status        = EFI_NOT_FOUND;
   while (ParsedLength < SectionSize) {
@@ -313,10 +315,13 @@ FfsProcessSection (
       }
 
       if (Found) {
+        // FIXME: Use common API with size checks
         if (IS_SECTION2 (Section)) {
           *OutputBuffer = (VOID *)((UINT8 *)Section + sizeof (EFI_COMMON_SECTION_HEADER2));
+          *OutputSize   = SECTION2_SIZE (Section) - sizeof (EFI_COMMON_SECTION_HEADER2);
         } else {
           *OutputBuffer = (VOID *)((UINT8 *)Section + sizeof (EFI_COMMON_SECTION_HEADER));
+          *OutputSize   = SECTION_SIZE (Section) - sizeof (EFI_COMMON_SECTION_HEADER);
         }
 
         return EFI_SUCCESS;
@@ -432,7 +437,8 @@ FfsProcessSection (
                  SectionCheckHook,
                  DstBuffer,
                  DstBufferSize,
-                 OutputBuffer
+                 OutputBuffer,
+                 OutputSize
                  );
       }
     }
@@ -466,6 +472,7 @@ CheckNextSection:
   @param  FileHandle            A pointer to the file header that contains the set of sections to
                                 be searched.
   @param  SectionData           A pointer to the discovered section, if successful.
+  @param  SectionSize           A pointer to the size of the discovered section, if successful.
 
   @retval EFI_SUCCESS           The section was found.
   @retval EFI_NOT_FOUND         The section was not found.
@@ -477,7 +484,8 @@ FfsFindSectionDataWithHook (
   IN EFI_SECTION_TYPE        SectionType,
   IN FFS_CHECK_SECTION_HOOK  SectionCheckHook,
   IN EFI_PEI_FILE_HANDLE     FileHandle,
-  OUT VOID                   **SectionData
+  OUT VOID                   **SectionData,
+  OUT UINT32                 *SectionSize
   )
 {
   EFI_FFS_FILE_HEADER        *FfsFileHeader;
@@ -500,7 +508,8 @@ FfsFindSectionDataWithHook (
            SectionCheckHook,
            Section,
            FileSize,
-           SectionData
+           SectionData,
+           SectionSize
            );
 }
 
@@ -511,6 +520,7 @@ FfsFindSectionDataWithHook (
   @param  FileHandle            A pointer to the file header that contains the set of sections to
                                 be searched.
   @param  SectionData           A pointer to the discovered section, if successful.
+  @param  SectionSize           A pointer to the size of the discovered section, if successful.
 
   @retval EFI_SUCCESS           The section was found.
   @retval EFI_NOT_FOUND         The section was not found.
@@ -521,10 +531,11 @@ EFIAPI
 FfsFindSectionData (
   IN EFI_SECTION_TYPE     SectionType,
   IN EFI_PEI_FILE_HANDLE  FileHandle,
-  OUT VOID                **SectionData
+  OUT VOID                **SectionData,
+  OUT UINT32              *SectionSize
   )
 {
-  return FfsFindSectionDataWithHook (SectionType, NULL, FileHandle, SectionData);
+  return FfsFindSectionDataWithHook (SectionType, NULL, FileHandle, SectionData, SectionSize);
 }
 
 /**
@@ -816,6 +827,7 @@ FfsProcessFvFile (
 {
   EFI_STATUS            Status;
   EFI_PEI_FV_HANDLE     FvImageHandle;
+  UINT32                FvImageHandleSize;
   EFI_FV_INFO           FvImageInfo;
   UINT32                FvAlignment;
   VOID                  *FvBuffer;
@@ -842,7 +854,13 @@ FfsProcessFvFile (
   //
   // Find FvImage in FvFile
   //
-  Status = FfsFindSectionDataWithHook (EFI_SECTION_FIRMWARE_VOLUME_IMAGE, NULL, FvFileHandle, (VOID **)&FvImageHandle);
+  Status = FfsFindSectionDataWithHook (
+    EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
+    NULL,
+    FvFileHandle,
+    (VOID **)&FvImageHandle,
+    &FvImageHandleSize
+    );
   if (EFI_ERROR (Status)) {
     return Status;
   }
diff --git a/EmbeddedPkg/Library/PrePiLib/PrePi.h b/EmbeddedPkg/Library/PrePiLib/PrePi.h
index a00c946512..c327081dc1 100644
--- a/EmbeddedPkg/Library/PrePiLib/PrePi.h
+++ b/EmbeddedPkg/Library/PrePiLib/PrePi.h
@@ -18,7 +18,7 @@
 #include <Library/DebugLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/UefiDecompressLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/CacheMaintenanceLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/TimerLib.h>
diff --git a/EmbeddedPkg/Library/PrePiLib/PrePiLib.c b/EmbeddedPkg/Library/PrePiLib/PrePiLib.c
index 3cf866dab2..650d864264 100644
--- a/EmbeddedPkg/Library/PrePiLib/PrePiLib.c
+++ b/EmbeddedPkg/Library/PrePiLib/PrePiLib.c
@@ -6,6 +6,7 @@
 
 **/
 
+#include "ProcessorBind.h"
 #include <PrePi.h>
 
 //
@@ -56,54 +57,45 @@ AllocateCodePages (
 
 EFI_STATUS
 EFIAPI
-LoadPeCoffImage (
-  IN  VOID                  *PeCoffImage,
+LoadUefiImage (
+  IN  VOID                  *UefiImage,
+  IN  UINT32                UefiImageSize,
   OUT EFI_PHYSICAL_ADDRESS  *ImageAddress,
-  OUT UINT64                *ImageSize,
+  OUT UINT32                *DestinationSize,
   OUT EFI_PHYSICAL_ADDRESS  *EntryPoint
   )
 {
-  RETURN_STATUS                 Status;
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
-  VOID                          *Buffer;
+  RETURN_STATUS                   Status;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext;
+  UINT32                          ImageSize;
+  VOID                            *Buffer;
+  UINT32                          BufferSize;
+  UINT32                          BufferPages;
+  UINT32                          BufferAlignment;
 
-  ZeroMem (&ImageContext, sizeof (ImageContext));
-
-  ImageContext.Handle    = PeCoffImage;
-  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
-
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);
+  Status = UefiImageInitializeContext (&ImageContext, UefiImage, UefiImageSize);
   ASSERT_EFI_ERROR (Status);
 
+  ImageSize       = UefiImageGetImageSize (&ImageContext);
+  BufferPages     = EFI_SIZE_TO_PAGES (ImageSize);
+  BufferSize      = EFI_PAGES_TO_SIZE (BufferPages);
+  BufferAlignment = UefiImageGetSegmentAlignment (&ImageContext);
+
   //
   // Allocate Memory for the image
   //
-  Buffer = AllocateCodePages (EFI_SIZE_TO_PAGES ((UINT32)ImageContext.ImageSize));
+  Buffer = AllocateAlignedCodePages (BufferPages, BufferAlignment);
   ASSERT (Buffer != 0);
 
-  ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
-
   //
-  // Load the image to our new buffer
+  // Load and relocate the image to our new buffer
   //
-  Status = PeCoffLoaderLoadImage (&ImageContext);
+  Status = UefiImageLoadImageForExecution (&ImageContext, Buffer, BufferSize, NULL, 0);
   ASSERT_EFI_ERROR (Status);
 
-  //
-  // Relocate the image in our new buffer
-  //
-  Status = PeCoffLoaderRelocateImage (&ImageContext);
-  ASSERT_EFI_ERROR (Status);
-
-  *ImageAddress = ImageContext.ImageAddress;
-  *ImageSize    = ImageContext.ImageSize;
-  *EntryPoint   = ImageContext.EntryPoint;
-
-  //
-  // Flush not needed for all architectures. We could have a processor specific
-  // function in this library that does the no-op if needed.
-  //
-  InvalidateInstructionCacheRange ((VOID *)(UINTN)*ImageAddress, (UINTN)*ImageSize);
+  *ImageAddress    = (UINTN) Buffer;
+  *DestinationSize = BufferSize;
+  *EntryPoint      = (UINTN) UefiImageLoaderGetImageEntryPoint (&ImageContext);
 
   return Status;
 }
@@ -122,22 +114,23 @@ LoadDxeCoreFromFfsFile (
   )
 {
   EFI_STATUS            Status;
-  VOID                  *PeCoffImage;
+  VOID                  *UefiImage;
+  UINT32                UefiImageSize;
   EFI_PHYSICAL_ADDRESS  ImageAddress;
-  UINT64                ImageSize;
+  UINT32                DestinationSize;
   EFI_PHYSICAL_ADDRESS  EntryPoint;
   VOID                  *BaseOfStack;
   VOID                  *TopOfStack;
   VOID                  *Hob;
   EFI_FV_FILE_INFO      FvFileInfo;
 
-  Status = FfsFindSectionDataWithHook (EFI_SECTION_PE32, NULL, FileHandle, &PeCoffImage);
+  Status = FfsFindSectionDataWithHook (EFI_SECTION_PE32, NULL, FileHandle, &UefiImage, &UefiImageSize);
   if (EFI_ERROR (Status)) {
     return Status;
   }
 
-  Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint);
-  // For NT32 Debug  Status = SecWinNtPeiLoadFile (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint);
+  Status = LoadUefiImage (UefiImage, UefiImageSize, &ImageAddress, &DestinationSize, &EntryPoint);
+  // For NT32 Debug  Status = SecWinNtPeiLoadFile (UefiImage, &ImageAddress, &ImageSize, &EntryPoint);
   ASSERT_EFI_ERROR (Status);
 
   //
@@ -146,7 +139,7 @@ LoadDxeCoreFromFfsFile (
   Status = FfsGetFileInfo (FileHandle, &FvFileInfo);
   ASSERT_EFI_ERROR (Status);
 
-  BuildModuleHob (&FvFileInfo.FileName, (EFI_PHYSICAL_ADDRESS)(UINTN)ImageAddress, EFI_SIZE_TO_PAGES ((UINT32)ImageSize) * EFI_PAGE_SIZE, EntryPoint);
+  BuildModuleHob (&FvFileInfo.FileName, (EFI_PHYSICAL_ADDRESS)(UINTN)ImageAddress, DestinationSize, EntryPoint);
 
   DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DxeCore at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)EntryPoint));
 
diff --git a/EmbeddedPkg/Library/PrePiLib/PrePiLib.inf b/EmbeddedPkg/Library/PrePiLib/PrePiLib.inf
index 090bfe888f..9b8e6f4c07 100644
--- a/EmbeddedPkg/Library/PrePiLib/PrePiLib.inf
+++ b/EmbeddedPkg/Library/PrePiLib/PrePiLib.inf
@@ -41,7 +41,7 @@
   DebugLib
   BaseMemoryLib
   UefiDecompressLib
-  PeCoffLib
+  UefiImageLib
   CacheMaintenanceLib
   PrintLib
   SerialPortLib
@@ -53,9 +53,6 @@
 [Guids]
   gEfiMemoryTypeInformationGuid
 
-[Protocols]
-  gPeCoffLoaderProtocolGuid
-
 
 [FixedPcd.common]
   gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory
diff --git a/EmulatorPkg/EmulatorPkg.dsc b/EmulatorPkg/EmulatorPkg.dsc
index 5bba746a02..1a9b985c03 100644
--- a/EmulatorPkg/EmulatorPkg.dsc
+++ b/EmulatorPkg/EmulatorPkg.dsc
@@ -62,8 +62,8 @@
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
   CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
   FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
 
@@ -145,8 +145,7 @@
 [LibraryClasses.common.SEC]
   PeiServicesLib|EmulatorPkg/Library/SecPeiServicesLib/SecPeiServicesLib.inf
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
-  PeCoffGetEntryPointLib|EmulatorPkg/Library/PeiEmuPeCoffGetEntryPointLib/PeiEmuPeCoffGetEntryPointLib.inf
-  PeCoffExtraActionLib|EmulatorPkg/Library/PeiEmuPeCoffExtraActionLib/PeiEmuPeCoffExtraActionLib.inf
+  UefiImageExtraActionLib|EmulatorPkg/Library/PeiEmuUefiImageExtraActionLib/PeiEmuUefiImageExtraActionLib.inf
   SerialPortLib|EmulatorPkg/Library/PeiEmuSerialPortLib/PeiEmuSerialPortLib.inf
   PpiListLib|EmulatorPkg/Library/SecPpiListLib/SecPpiListLib.inf
   DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
@@ -154,13 +153,13 @@
 
 [LibraryClasses.common.USER_DEFINED, LibraryClasses.common.BASE]
   DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
+  HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
   MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
   PpiListLib|EmulatorPkg/Library/SecPpiListLib/SecPpiListLib.inf
   ThunkPpiList|EmulatorPkg/Library/ThunkPpiList/ThunkPpiList.inf
   ThunkProtocolList|EmulatorPkg/Library/ThunkProtocolList/ThunkProtocolList.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   PpiListLib|EmulatorPkg/Library/SecPpiListLib/SecPpiListLib.inf
   PeiServicesLib|EmulatorPkg/Library/SecPeiServicesLib/SecPeiServicesLib.inf
 
@@ -169,8 +168,7 @@
   HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
   MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
   ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
-  PeCoffGetEntryPointLib|EmulatorPkg/Library/PeiEmuPeCoffGetEntryPointLib/PeiEmuPeCoffGetEntryPointLib.inf
-  PeCoffExtraActionLib|EmulatorPkg/Library/PeiEmuPeCoffExtraActionLib/PeiEmuPeCoffExtraActionLib.inf
+  UefiImageExtraActionLib|EmulatorPkg/Library/PeiEmuUefiImageExtraActionLib/PeiEmuUefiImageExtraActionLib.inf
   ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
   SerialPortLib|EmulatorPkg/Library/PeiEmuSerialPortLib/PeiEmuSerialPortLib.inf
   ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
@@ -186,7 +184,7 @@
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
   MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
   ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
-  PeCoffExtraActionLib|EmulatorPkg/Library/DxeEmuPeCoffExtraActionLib/DxeEmuPeCoffExtraActionLib.inf
+  UefiImageExtraActionLib|EmulatorPkg/Library/DxeEmuUefiImageExtraActionLib/DxeEmuUefiImageExtraActionLib.inf
   ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
   TimerLib|EmulatorPkg/Library/DxeCoreTimerLib/DxeCoreTimerLib.inf
@@ -208,7 +206,7 @@
   MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
   ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
   EmuThunkLib|EmulatorPkg/Library/DxeEmuLib/DxeEmuLib.inf
-  PeCoffExtraActionLib|EmulatorPkg/Library/DxeEmuPeCoffExtraActionLib/DxeEmuPeCoffExtraActionLib.inf
+  UefiImageExtraActionLib|EmulatorPkg/Library/DxeEmuUefiImageExtraActionLib/DxeEmuUefiImageExtraActionLib.inf
   ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
   TimerLib|EmulatorPkg/Library/DxeTimerLib/DxeTimerLib.inf
 
diff --git a/EmulatorPkg/Include/Library/EmuMagicPageLib.h b/EmulatorPkg/Include/Library/EmuMagicPageLib.h
index d102f1666a..9652a1186e 100644
--- a/EmulatorPkg/Include/Library/EmuMagicPageLib.h
+++ b/EmulatorPkg/Include/Library/EmuMagicPageLib.h
@@ -23,7 +23,7 @@ typedef struct {
   // Used by SecPeiServicesLib
   EFI_PEI_PPI_DESCRIPTOR    *PpiList;
 
-  // Needed by PEI PEI PeCoffLoaderExtraActionLib
+  // Needed by PEI PEI UefiImageLoaderExtraActionLib
   EMU_THUNK_PROTOCOL        *Thunk;
 } EMU_MAGIC_PAGE_LAYOUT;
 
diff --git a/EmulatorPkg/Include/Protocol/EmuThunk.h b/EmulatorPkg/Include/Protocol/EmuThunk.h
index bdd57f410b..ae0dbc95c9 100644
--- a/EmulatorPkg/Include/Protocol/EmuThunk.h
+++ b/EmulatorPkg/Include/Protocol/EmuThunk.h
@@ -17,7 +17,7 @@
 // neded for things like EFI_TIME_CAPABILITIES
 #include <Uefi.h>
 
-#include <Library/PeCoffExtraActionLib.h>
+#include <Library/UefiImageExtraActionLib.h>
 
 #include <Protocol/EmuIoThunk.h>
 #include <Protocol/DevicePath.h>
@@ -88,20 +88,21 @@ BOOLEAN
 typedef
 EFI_STATUS
 (EFIAPI *EMU_PE_COFF_GET_ENTRY_POINT)(
-  IN     VOID  *Pe32Data,
-  IN OUT VOID  **EntryPoint
+  IN     VOID   *Pe32Data,
+  IN     UINT32 Pe32Size,
+  IN OUT VOID   **EntryPoint
   );
 
 typedef
 VOID
 (EFIAPI *EMU_PE_COFF_RELOCATE_EXTRA_ACTION)(
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
   );
 
 typedef
 VOID
 (EFIAPI *EMU_PE_COFF_UNLOAD_EXTRA_ACTION)(
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
   );
 
 typedef
@@ -217,9 +218,9 @@ struct _EMU_THUNK_PROTOCOL {
   ///
   /// PE/COFF loader hooks to get symbols loaded
   ///
-  EMU_PE_COFF_GET_ENTRY_POINT          PeCoffGetEntryPoint;
-  EMU_PE_COFF_RELOCATE_EXTRA_ACTION    PeCoffRelocateImageExtraAction;
-  EMU_PE_COFF_UNLOAD_EXTRA_ACTION      PeCoffUnloadImageExtraAction;
+  EMU_PE_COFF_GET_ENTRY_POINT       UefiImageGetEntryPoint;
+  EMU_PE_COFF_RELOCATE_EXTRA_ACTION UefiImageRelocateImageExtraAction;
+  EMU_PE_COFF_UNLOAD_EXTRA_ACTION   UefiImageUnloadImageExtraAction;
 
   ///
   /// DXE Architecture Protocol Services
diff --git a/EmulatorPkg/Library/DxeEmuPeCoffExtraActionLib/DxeEmuPeCoffExtraActionLib.c b/EmulatorPkg/Library/DxeEmuPeCoffExtraActionLib/DxeEmuPeCoffExtraActionLib.c
index c3c5ae4246..eba37b8755 100644
--- a/EmulatorPkg/Library/DxeEmuPeCoffExtraActionLib/DxeEmuPeCoffExtraActionLib.c
+++ b/EmulatorPkg/Library/DxeEmuPeCoffExtraActionLib/DxeEmuPeCoffExtraActionLib.c
@@ -1,3 +1,5 @@
+#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
+
 /** @file
   Provides services to perform additional actions to relocate and unload
   PE/Coff image for Emu environment specific purpose such as souce level debug.
@@ -23,7 +25,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 //
 // Cache of UnixThunk protocol
 //
-EMU_THUNK_PROTOCOL  *mThunk = NULL;
+EMU_THUNK_PROTOCOL   *mThunk = NULL;
+
 
 /**
   The constructor function gets  the pointer of the WinNT thunk functions
@@ -39,7 +42,7 @@ DxeEmuPeCoffLibExtraActionConstructor (
   IN EFI_SYSTEM_TABLE  *SystemTable
   )
 {
-  EFI_HOB_GUID_TYPE  *GuidHob;
+   EFI_HOB_GUID_TYPE        *GuidHob;
 
   //
   // Retrieve EmuThunkProtocol from GUID'ed HOB
@@ -72,6 +75,8 @@ PeCoffLoaderRelocateImageExtraAction (
   }
 }
 
+
+
 /**
   Performs additional actions just before a PE/COFF image is unloaded.  Any resources
   that were allocated by PeCoffLoaderRelocateImageExtraAction() must be freed.
@@ -92,3 +97,5 @@ PeCoffLoaderUnloadImageExtraAction (
     mThunk->PeCoffUnloadImageExtraAction (ImageContext);
   }
 }
+
+#endif // DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/EmulatorPkg/Library/DxeEmuUefiImageExtraActionLib/DxeEmuUefiImageExtraActionLib.c b/EmulatorPkg/Library/DxeEmuUefiImageExtraActionLib/DxeEmuUefiImageExtraActionLib.c
new file mode 100644
index 0000000000..246c4d0068
--- /dev/null
+++ b/EmulatorPkg/Library/DxeEmuUefiImageExtraActionLib/DxeEmuUefiImageExtraActionLib.c
@@ -0,0 +1,94 @@
+/** @file
+  Provides services to perform additional actions to relocate and unload
+  PE/Coff image for Emu environment specific purpose such as souce level debug.
+  This version only works for DXE phase
+
+Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Protocol/EmuThunk.h>
+
+#include <Library/UefiImageLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiImageExtraActionLib.h>
+
+//
+// Cache of UnixThunk protocol
+//
+EMU_THUNK_PROTOCOL  *mThunk = NULL;
+
+/**
+  The constructor function gets  the pointer of the WinNT thunk functions
+  It will ASSERT() if Unix thunk protocol is not installed.
+
+  @retval EFI_SUCCESS   Unix thunk protocol is found and cached.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeEmuUefiImageLibExtraActionConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_HOB_GUID_TYPE  *GuidHob;
+
+  //
+  // Retrieve EmuThunkProtocol from GUID'ed HOB
+  //
+  GuidHob = GetFirstGuidHob (&gEmuThunkProtocolGuid);
+  ASSERT (GuidHob != NULL);
+  mThunk = (EMU_THUNK_PROTOCOL *)(*(UINTN *)(GET_GUID_HOB_DATA (GuidHob)));
+  ASSERT (mThunk != NULL);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Performs additional actions after a PE/COFF image has been loaded and relocated.
+
+  If ImageContext is NULL, then ASSERT().
+
+  @param  ImageContext  Pointer to the image context structure that describes the
+                        PE/COFF image that has already been loaded and relocated.
+
+**/
+VOID
+EFIAPI
+UefiImageLoaderRelocateImageExtraAction (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
+  )
+{
+  if (mThunk != NULL) {
+    mThunk->UefiImageRelocateImageExtraAction (ImageContext);
+  }
+}
+
+/**
+  Performs additional actions just before a PE/COFF image is unloaded.  Any resources
+  that were allocated by UefiImageLoaderRelocateImageExtraAction() must be freed.
+
+  If ImageContext is NULL, then ASSERT().
+
+  @param  ImageContext  Pointer to the image context structure that describes the
+                        PE/COFF image that is being unloaded.
+
+**/
+VOID
+EFIAPI
+UefiImageLoaderUnloadImageExtraAction (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
+  )
+{
+  if (mThunk != NULL) {
+    mThunk->UefiImageUnloadImageExtraAction (ImageContext);
+  }
+}
diff --git a/EmulatorPkg/Library/DxeEmuUefiImageExtraActionLib/DxeEmuUefiImageExtraActionLib.inf b/EmulatorPkg/Library/DxeEmuUefiImageExtraActionLib/DxeEmuUefiImageExtraActionLib.inf
new file mode 100644
index 0000000000..8c7161b573
--- /dev/null
+++ b/EmulatorPkg/Library/DxeEmuUefiImageExtraActionLib/DxeEmuUefiImageExtraActionLib.inf
@@ -0,0 +1,42 @@
+## @file
+# PeCoff extra action libary for DXE phase that run Emu emulator.
+#
+# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+# Portions copyright (c) 2011, Apple Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DxeEmuUefiImageExtraActionLib
+  FILE_GUID                      = 68FCD487-D230-6846-95B1-5E1F2EF942C4
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = UefiImageExtraActionLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER UEFI_APPLICATION
+
+  CONSTRUCTOR                    = DxeEmuUefiImageLibExtraActionConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32
+#
+
+[Sources]
+  DxeEmuUefiImageExtraActionLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  EmulatorPkg/EmulatorPkg.dec
+
+[LibraryClasses]
+  DebugLib
+  HobLib
+  BaseMemoryLib
+
+[Protocols]
+  gEmuThunkProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
+
diff --git a/EmulatorPkg/Library/PeiEmuPeCoffExtraActionLib/PeiEmuPeCoffExtraActionLib.c b/EmulatorPkg/Library/PeiEmuPeCoffExtraActionLib/PeiEmuPeCoffExtraActionLib.c
index 9e1a8be607..f941158b88 100644
--- a/EmulatorPkg/Library/PeiEmuPeCoffExtraActionLib/PeiEmuPeCoffExtraActionLib.c
+++ b/EmulatorPkg/Library/PeiEmuPeCoffExtraActionLib/PeiEmuPeCoffExtraActionLib.c
@@ -1,3 +1,5 @@
+#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
+
 /** @file
   Provides services to perform additional actions to relocate and unload
   PE/Coff image for Emu environment specific purpose such as souce level debug.
@@ -22,7 +24,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 //
 // Cache of UnixThunk protocol
 //
-EMU_THUNK_PROTOCOL  *mThunk = NULL;
+EMU_THUNK_PROTOCOL   *mThunk = NULL;
 
 /**
   The function caches the pointer of the Unix thunk functions
@@ -36,21 +38,22 @@ EFIAPI
 EmuPeCoffGetThunkStucture (
   )
 {
-  EMU_THUNK_PPI  *ThunkPpi;
-  EFI_STATUS     Status;
+  EMU_THUNK_PPI     *ThunkPpi;
+  EFI_STATUS        Status;
+
 
   //
   // Locate Unix ThunkPpi for retrieving standard output handle
   //
   Status = PeiServicesLocatePpi (
-             &gEmuThunkPpiGuid,
-             0,
-             NULL,
-             (VOID **)&ThunkPpi
-             );
+              &gEmuThunkPpiGuid,
+              0,
+              NULL,
+              (VOID **) &ThunkPpi
+              );
   ASSERT_EFI_ERROR (Status);
 
-  EMU_MAGIC_PAGE ()->Thunk = (EMU_THUNK_PROTOCOL *)ThunkPpi->Thunk ();
+  EMU_MAGIC_PAGE()->Thunk = (EMU_THUNK_PROTOCOL *) ThunkPpi->Thunk ();
 
   return EFI_SUCCESS;
 }
@@ -70,12 +73,12 @@ PeCoffLoaderRelocateImageExtraAction (
   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
   )
 {
-  if (EMU_MAGIC_PAGE ()->Thunk == NULL) {
+  if (EMU_MAGIC_PAGE()->Thunk == NULL) {
     EmuPeCoffGetThunkStucture ();
   }
+    EMU_MAGIC_PAGE()->Thunk->PeCoffRelocateImageExtraAction (ImageContext);
+  }
 
-  EMU_MAGIC_PAGE ()->Thunk->PeCoffRelocateImageExtraAction (ImageContext);
-}
 
 /**
   Performs additional actions just before a PE/COFF image is unloaded.  Any resources
@@ -93,9 +96,10 @@ PeCoffLoaderUnloadImageExtraAction (
   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
   )
 {
-  if (EMU_MAGIC_PAGE ()->Thunk == NULL) {
+  if (EMU_MAGIC_PAGE()->Thunk == NULL) {
     EmuPeCoffGetThunkStucture ();
   }
-
-  EMU_MAGIC_PAGE ()->Thunk->PeCoffUnloadImageExtraAction (ImageContext);
+  EMU_MAGIC_PAGE()->Thunk->PeCoffUnloadImageExtraAction (ImageContext);
 }
+
+#endif // DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/EmulatorPkg/Library/PeiEmuPeCoffGetEntryPointLib/PeiEmuPeCoffGetEntryPointLib.c b/EmulatorPkg/Library/PeiEmuPeCoffGetEntryPointLib/PeiEmuPeCoffGetEntryPointLib.c
index a9d28f48cf..e0a6b0f00f 100644
--- a/EmulatorPkg/Library/PeiEmuPeCoffGetEntryPointLib/PeiEmuPeCoffGetEntryPointLib.c
+++ b/EmulatorPkg/Library/PeiEmuPeCoffGetEntryPointLib/PeiEmuPeCoffGetEntryPointLib.c
@@ -7,7 +7,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 **/
 
 #include "PiPei.h"
-#include <Library/PeCoffGetEntryPointLib.h>
+//#include <Library/PeCoffGetEntryPointLib.h>
 #include <Library/PeiServicesLib.h>
 #include <IndustryStandard/PeImage.h>
 #include <Library/DebugLib.h>
@@ -35,8 +35,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 RETURN_STATUS
 EFIAPI
 PeCoffLoaderGetEntryPoint (
-  IN     VOID  *Pe32Data,
-  IN OUT VOID  **EntryPoint
+  IN     VOID   *Pe32Data,
+  IN     UINT32 Pe32Size,
+  IN OUT VOID   **EntryPoint
   )
 {
   EMU_THUNK_PPI       *ThunkPpi;
@@ -56,7 +57,7 @@ PeCoffLoaderGetEntryPoint (
 
   Thunk = (EMU_THUNK_PROTOCOL *)ThunkPpi->Thunk ();
 
-  return Thunk->PeCoffGetEntryPoint (Pe32Data, EntryPoint);
+  return Thunk->PeCoffGetEntryPoint (Pe32Data, Pe32Size, EntryPoint);
 }
 
 /**
diff --git a/EmulatorPkg/Library/PeiEmuUefiImageExtraActionLib/PeiEmuUefiImageExtraActionLib.c b/EmulatorPkg/Library/PeiEmuUefiImageExtraActionLib/PeiEmuUefiImageExtraActionLib.c
new file mode 100644
index 0000000000..ce19922aec
--- /dev/null
+++ b/EmulatorPkg/Library/PeiEmuUefiImageExtraActionLib/PeiEmuUefiImageExtraActionLib.c
@@ -0,0 +1,101 @@
+/** @file
+  Provides services to perform additional actions to relocate and unload
+  PE/Coff image for Emu environment specific purpose such as souce level debug.
+  This version only works for PEI phase
+
+Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <PiPei.h>
+#include <Ppi/EmuThunk.h>
+#include <Protocol/EmuThunk.h>
+
+#include <Library/UefiImageLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiImageExtraActionLib.h>
+#include <Library/EmuMagicPageLib.h>
+
+//
+// Cache of UnixThunk protocol
+//
+EMU_THUNK_PROTOCOL  *mThunk = NULL;
+
+/**
+  The function caches the pointer of the Unix thunk functions
+  It will ASSERT() if Unix thunk ppi is not installed.
+
+  @retval EFI_SUCCESS   WinNT thunk protocol is found and cached.
+
+**/
+EFI_STATUS
+EFIAPI
+EmuUefiImageGetThunkStucture (
+  )
+{
+  EMU_THUNK_PPI  *ThunkPpi;
+  EFI_STATUS     Status;
+
+  //
+  // Locate Unix ThunkPpi for retrieving standard output handle
+  //
+  Status = PeiServicesLocatePpi (
+             &gEmuThunkPpiGuid,
+             0,
+             NULL,
+             (VOID **)&ThunkPpi
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  EMU_MAGIC_PAGE ()->Thunk = (EMU_THUNK_PROTOCOL *)ThunkPpi->Thunk ();
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Performs additional actions after a PE/COFF image has been loaded and relocated.
+
+  If ImageContext is NULL, then ASSERT().
+
+  @param  ImageContext  Pointer to the image context structure that describes the
+                        PE/COFF image that has already been loaded and relocated.
+
+**/
+VOID
+EFIAPI
+UefiImageLoaderRelocateImageExtraAction (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
+  )
+{
+  if (EMU_MAGIC_PAGE ()->Thunk == NULL) {
+    EmuUefiImageGetThunkStucture ();
+  }
+
+  EMU_MAGIC_PAGE ()->Thunk->UefiImageRelocateImageExtraAction (ImageContext);
+}
+
+/**
+  Performs additional actions just before a PE/COFF image is unloaded.  Any resources
+  that were allocated by UefiImageLoaderRelocateImageExtraAction() must be freed.
+
+  If ImageContext is NULL, then ASSERT().
+
+  @param  ImageContext  Pointer to the image context structure that describes the
+                        PE/COFF image that is being unloaded.
+
+**/
+VOID
+EFIAPI
+UefiImageLoaderUnloadImageExtraAction (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
+  )
+{
+  if (EMU_MAGIC_PAGE ()->Thunk == NULL) {
+    EmuUefiImageGetThunkStucture ();
+  }
+
+  EMU_MAGIC_PAGE ()->Thunk->UefiImageUnloadImageExtraAction (ImageContext);
+}
diff --git a/EmulatorPkg/Library/PeiEmuUefiImageExtraActionLib/PeiEmuUefiImageExtraActionLib.inf b/EmulatorPkg/Library/PeiEmuUefiImageExtraActionLib/PeiEmuUefiImageExtraActionLib.inf
new file mode 100644
index 0000000000..d2b109da86
--- /dev/null
+++ b/EmulatorPkg/Library/PeiEmuUefiImageExtraActionLib/PeiEmuUefiImageExtraActionLib.inf
@@ -0,0 +1,43 @@
+## @file
+# PeCoff extra action libary for Pei phase that run Emu emulator.
+#
+# Lib to provide memory journal status code reporting Routines
+# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+# Portions copyright (c) 2011, Apple Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiEmuUefiImageExtraActionLib
+  FILE_GUID                      = 79C4E72A-730B-F040-8129-95877B3A97A8
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = UefiImageExtraActionLib|PEI_CORE PEIM
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32
+#
+
+[Sources]
+  PeiEmuUefiImageExtraActionLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  EmulatorPkg/EmulatorPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PeiServicesLib
+  DebugLib
+
+[Ppis]
+  gEmuThunkPpiGuid                          # PPI ALWAYS_CONSUMED
+
+[Pcd]
+  gEmulatorPkgTokenSpaceGuid.PcdPeiServicesTablePage
diff --git a/EmulatorPkg/Library/SecPeiServicesLib/FwVol.c b/EmulatorPkg/Library/SecPeiServicesLib/FwVol.c
index e1cc6c6a51..7bb6cd0fe9 100644
--- a/EmulatorPkg/Library/SecPeiServicesLib/FwVol.c
+++ b/EmulatorPkg/Library/SecPeiServicesLib/FwVol.c
@@ -276,3 +276,52 @@ Returns:
 
   return EFI_NOT_FOUND;
 }
+
+// FIXME: Docs
+EFI_STATUS
+SecFfsFindSectionData2 (
+  IN EFI_SECTION_TYPE      SectionType,
+  IN EFI_FFS_FILE_HEADER   *FfsFileHeader,
+  IN OUT VOID              **SectionData,
+  OUT UINT32               *SectionDataSize
+  )
+{
+  UINT32                    FileSize;
+  EFI_COMMON_SECTION_HEADER *Section;
+  UINT32                    SectionLength;
+  UINT32                    ParsedLength;
+
+  //
+  // Size is 24 bits wide so mask upper 8 bits.
+  //    Does not include FfsFileHeader header size
+  // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
+  //
+  Section   = (EFI_COMMON_SECTION_HEADER *) (FfsFileHeader + 1);
+  FileSize  = *(UINT32 *) (FfsFileHeader->Size) & 0x00FFFFFF;
+  FileSize -= sizeof (EFI_FFS_FILE_HEADER);
+
+  *SectionData  = NULL;
+  ParsedLength  = 0;
+  while (ParsedLength < FileSize) {
+    // FIXME: Common API with size checks
+    //
+    // Size is 24 bits wide so mask upper 8 bits.
+    //
+    SectionLength = *(UINT32 *) Section->Size & 0x00FFFFFF;
+    if (Section->Type == SectionType) {
+      *SectionData = (VOID *) (Section + 1);
+      *SectionDataSize = SectionLength - sizeof (*Section);
+      return EFI_SUCCESS;
+    }
+    //
+    // SectionLength is adjusted it is 4 byte aligned.
+    // Go to the next section
+    //
+    SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
+
+    ParsedLength += SectionLength;
+    Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + SectionLength);
+  }
+
+  return EFI_NOT_FOUND;
+}
diff --git a/EmulatorPkg/Library/SecPeiServicesLib/PeiServicesLib.c b/EmulatorPkg/Library/SecPeiServicesLib/PeiServicesLib.c
index 9409cbdb66..51bd3f9e1a 100644
--- a/EmulatorPkg/Library/SecPeiServicesLib/PeiServicesLib.c
+++ b/EmulatorPkg/Library/SecPeiServicesLib/PeiServicesLib.c
@@ -26,6 +26,14 @@ SecFfsFindSectionData (
   OUT VOID                **SectionData
   );
 
+EFI_STATUS
+SecFfsFindSectionData2 (
+  IN EFI_SECTION_TYPE      SectionType,
+  IN EFI_FFS_FILE_HEADER   *FfsFileHeader,
+  IN OUT VOID              **SectionData,
+  OUT UINT32               *SectionDataSize
+  );
+
 /**
   This service enables a given PEIM to register an interface into the PEI Foundation.
 
@@ -304,6 +312,38 @@ PeiServicesFfsFindSectionData (
   return SecFfsFindSectionData (SectionType, FileHandle, SectionData);
 }
 
+/**
+  This service enables PEIMs to discover sections of a given instance and type within a valid FFS file.
+
+  @param  SectionType           The value of the section type to find.
+  @param  SectionInstance       Section instance to find.
+  @param  FileHandle            A pointer to the file header that contains the set
+                                of sections to be searched.
+  @param  SectionData           A pointer to the discovered section, if successful.
+  @param  SectionDataSize       The size of the discovered section, if successful.
+  @param  AuthenticationStatus  A pointer to the authentication status for this section.
+
+  @retval EFI_SUCCESS           The section was found.
+  @retval EFI_NOT_FOUND         The section was not found.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiServicesFfsFindSectionData4 (
+  IN EFI_SECTION_TYPE           SectionType,
+  IN UINTN                      SectionInstance,
+  IN EFI_PEI_FILE_HANDLE        FileHandle,
+  OUT VOID                      **SectionData,
+  OUT UINT32                    *SectionDataSize,
+  OUT UINT32                    *AuthenticationStatus
+  )
+{
+  ASSERT (SectionInstance == 0);
+
+  *AuthenticationStatus = 0;
+  return SecFfsFindSectionData2 (SectionType, FileHandle, SectionData, SectionDataSize);
+}
+
 /**
   This service enables PEIMs to register the permanent memory configuration
   that has been initialized with the PEI Foundation.
diff --git a/EmulatorPkg/Sec/Sec.c b/EmulatorPkg/Sec/Sec.c
index 3d792adc94..e1d9373b90 100644
--- a/EmulatorPkg/Sec/Sec.c
+++ b/EmulatorPkg/Sec/Sec.c
@@ -9,6 +9,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 **/
 
 #include "Sec.h"
+#include <Ppi/EmuThunk.h>
 
 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI  mSecTemporaryRamSupportPpi = {
   SecTemporaryRamSupport
@@ -22,6 +23,53 @@ EFI_PEI_PPI_DESCRIPTOR  gPrivateDispatchTable[] = {
   }
 };
 
+//FIXME:
+/**
+  Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
+  into system memory with the PE/COFF Loader Library functions.
+
+  Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
+  point in EntryPoint.  If the entry point could not be retrieved from the PE/COFF image, then
+  return RETURN_INVALID_PARAMETER.  Otherwise return RETURN_SUCCESS.
+  If Pe32Data is NULL, then ASSERT().
+  If EntryPoint is NULL, then ASSERT().
+
+  @param  Pe32Data                  The pointer to the PE/COFF image that is loaded in system memory.
+  @param  EntryPoint                The pointer to entry point to the PE/COFF image to return.
+
+  @retval RETURN_SUCCESS            EntryPoint was returned.
+  @retval RETURN_INVALID_PARAMETER  The entry point could not be found in the PE/COFF image.
+
+**/
+RETURN_STATUS
+EFIAPI
+UefiImageLoaderGetEntryPoint (
+  IN     VOID   *Pe32Data,
+  IN     UINT32 Pe32Size,
+  IN OUT VOID   **EntryPoint
+  )
+{
+  EMU_THUNK_PPI           *ThunkPpi;
+  EFI_STATUS              Status;
+  EMU_THUNK_PROTOCOL      *Thunk;
+
+  //
+  // Locate EmuThunkPpi for retrieving standard output handle
+  //
+  Status = PeiServicesLocatePpi (
+              &gEmuThunkPpiGuid,
+              0,
+              NULL,
+              (VOID **) &ThunkPpi
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  Thunk  = (EMU_THUNK_PROTOCOL *)ThunkPpi->Thunk ();
+
+  return Thunk->UefiImageGetEntryPoint (Pe32Data, Pe32Size, EntryPoint);
+}
+
+
 /**
   The entry point of PE/COFF Image for the PEI Core, that has been hijacked by this
   SEC that sits on top of an OS application. So the entry and exit of this module
@@ -64,13 +112,15 @@ _ModuleEntryPoint (
   EFI_STATUS                Status;
   EFI_PEI_FV_HANDLE         VolumeHandle;
   EFI_PEI_FILE_HANDLE       FileHandle;
-  VOID                      *PeCoffImage;
+  VOID                      *UefiImage;
+  UINT32                    UefiImageSize;
   EFI_PEI_CORE_ENTRY_POINT  EntryPoint;
   EFI_PEI_PPI_DESCRIPTOR    *Ppi;
   EFI_PEI_PPI_DESCRIPTOR    *SecPpiList;
   UINTN                     SecReseveredMemorySize;
   UINTN                     Index;
   EFI_PEI_PPI_DESCRIPTOR    PpiArray[10];
+  UINT32                    AuthenticationStatus;
 
   EMU_MAGIC_PAGE ()->PpiList = PpiList;
   ProcessLibraryConstructorList ();
@@ -118,10 +168,10 @@ _ModuleEntryPoint (
   Status       = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_PEI_CORE, VolumeHandle, &FileHandle);
   ASSERT_EFI_ERROR (Status);
 
-  Status = PeiServicesFfsFindSectionData (EFI_SECTION_PE32, FileHandle, &PeCoffImage);
+  Status = PeiServicesFfsFindSectionData4 (EFI_SECTION_PE32, 0, FileHandle, &UefiImage, &UefiImageSize, &AuthenticationStatus);
   ASSERT_EFI_ERROR (Status);
 
-  Status = PeCoffLoaderGetEntryPoint (PeCoffImage, (VOID **)&EntryPoint);
+  Status = UefiImageLoaderGetEntryPoint (UefiImage, UefiImageSize, (VOID **)&EntryPoint);
   ASSERT_EFI_ERROR (Status);
 
   // Transfer control to PEI Core
diff --git a/EmulatorPkg/Sec/Sec.h b/EmulatorPkg/Sec/Sec.h
index 94689eb41d..e357add14c 100644
--- a/EmulatorPkg/Sec/Sec.h
+++ b/EmulatorPkg/Sec/Sec.h
@@ -15,7 +15,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/EmuMagicPageLib.h>
 #include <Library/DebugLib.h>
 #include <Library/PeiServicesLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
 #include <Library/BaseMemoryLib.h>
 
 #include <Ppi/TemporaryRamSupport.h>
diff --git a/EmulatorPkg/Sec/Sec.inf b/EmulatorPkg/Sec/Sec.inf
index 5d47eed7ae..0de84f565a 100644
--- a/EmulatorPkg/Sec/Sec.inf
+++ b/EmulatorPkg/Sec/Sec.inf
@@ -36,7 +36,6 @@
 
 [LibraryClasses]
   DebugLib
-  PeCoffGetEntryPointLib
   PeiServicesLib
   PpiListLib
   BaseMemoryLib
diff --git a/EmulatorPkg/Unix/GdbRun.sh b/EmulatorPkg/Unix/GdbRun.sh
index b050ad5e2c..6fea1c9d5b 100644
--- a/EmulatorPkg/Unix/GdbRun.sh
+++ b/EmulatorPkg/Unix/GdbRun.sh
@@ -41,7 +41,7 @@ set $SymbolFileChangesCount = 0
 #
 define AddFirmwareSymbolFile
   if $SymbolFileChangesCount < $arg0
-    add-symbol-file $arg1 $arg2
+    add-symbol-file $arg1 -o $arg2
     set $SymbolFileChangesCount = $arg0
   end
 end
diff --git a/EmulatorPkg/Unix/Host/EmuThunk.c b/EmulatorPkg/Unix/Host/EmuThunk.c
index c57c105a53..bdc6d62035 100644
--- a/EmulatorPkg/Unix/Host/EmuThunk.c
+++ b/EmulatorPkg/Unix/Host/EmuThunk.c
@@ -415,9 +415,9 @@ EMU_THUNK_PROTOCOL  gEmuThunkProtocol = {
   GasketSecMalloc,
   GasketSecValloc,
   GasketSecFree,
-  GasketSecPeCoffGetEntryPoint,
-  GasketSecPeCoffRelocateImageExtraAction,
-  GasketSecPeCoffUnloadImageExtraAction,
+  GasketSecUefiImageGetEntryPoint,
+  GasketSecUefiImageRelocateImageExtraAction,
+  GasketSecUefiImageUnloadImageExtraAction,
   GasketSecEnableInterrupt,
   GasketSecDisableInterrupt,
   GasketQueryPerformanceFrequency,
diff --git a/EmulatorPkg/Unix/Host/Gasket.h b/EmulatorPkg/Unix/Host/Gasket.h
index 71b459ddd8..6fe28b202b 100644
--- a/EmulatorPkg/Unix/Host/Gasket.h
+++ b/EmulatorPkg/Unix/Host/Gasket.h
@@ -67,21 +67,22 @@ GasketSecFree (
 
 RETURN_STATUS
 EFIAPI
-GasketSecPeCoffGetEntryPoint (
+GasketSecUefiImageGetEntryPoint (
   IN     VOID  *Pe32Data,
+  IN     UINT32 Pe32Size,
   IN OUT VOID  **EntryPoint
   );
 
 VOID
 EFIAPI
-GasketSecPeCoffRelocateImageExtraAction (
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+GasketSecUefiImageRelocateImageExtraAction (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
   );
 
 VOID
 EFIAPI
-GasketSecPeCoffUnloadImageExtraAction (
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+GasketSecUefiImageUnloadImageExtraAction (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
   );
 
 VOID
diff --git a/EmulatorPkg/Unix/Host/Host.c b/EmulatorPkg/Unix/Host/Host.c
index 1f29dd00a3..134481b617 100644
--- a/EmulatorPkg/Unix/Host/Host.c
+++ b/EmulatorPkg/Unix/Host/Host.c
@@ -44,9 +44,6 @@ EMU_FD_INFO  *gFdInfo;
 UINTN              gSystemMemoryCount = 0;
 EMU_SYSTEM_MEMORY  *gSystemMemory;
 
-UINTN                        mImageContextModHandleArraySize = 0;
-IMAGE_CONTEXT_TO_MOD_HANDLE  *mImageContextModHandleArray    = NULL;
-
 EFI_PEI_PPI_DESCRIPTOR  *gPpiList;
 
 int  gInXcode = 0;
@@ -98,11 +95,13 @@ main (
   BOOLEAN               Done;
   EFI_PEI_FILE_HANDLE   FileHandle;
   VOID                  *SecFile;
+  UINT32                SecFileSize;
   CHAR16                *MemorySizeStr;
   CHAR16                *FirmwareVolumesStr;
   UINTN                 *StackPointer;
   FILE                  *GdbTempFile;
   EMU_THUNK_PPI         *SecEmuThunkPpi;
+  UINT32                AuthenticationStatus;
 
   //
   // Xcode does not support sourcing gdb scripts directly, so the Xcode XML
@@ -111,8 +110,7 @@ main (
   SecGdbConfigBreak ();
 
   //
-  // If dlopen doesn't work, then we build a gdb script to allow the
-  // symbols to be loaded.
+  // We build a gdb script to allow the symbols to be loaded.
   //
   Index               = strlen (*Argv);
   gGdbWorkingFileName = AllocatePool (Index + strlen (".gdb") + 1);
@@ -284,7 +282,14 @@ main (
                      &FileHandle
                      );
       if (!EFI_ERROR (Status)) {
-        Status = PeiServicesFfsFindSectionData (EFI_SECTION_PE32, FileHandle, &SecFile);
+        Status = PeiServicesFfsFindSectionData4 (
+                   EFI_SECTION_PE32,
+                   0,
+                   FileHandle,
+                   &SecFile,
+                   &SecFileSize,
+                   &AuthenticationStatus
+                   );
         if (!EFI_ERROR (Status)) {
           PeiIndex = Index;
           printf (" contains SEC Core");
@@ -330,7 +335,7 @@ main (
   //
   // Hand off to SEC
   //
-  SecLoadFromCore ((UINTN)InitialStackMemory, (UINTN)InitialStackMemorySize, (UINTN)gFdInfo[0].Address, SecFile);
+  SecLoadFromCore ((UINTN)InitialStackMemory, (UINTN)InitialStackMemorySize, (UINTN)gFdInfo[0].Address, SecFile, SecFileSize);
 
   //
   // If we get here, then the SEC Core returned. This is an error as SEC should
@@ -546,7 +551,8 @@ SecLoadFromCore (
   IN  UINTN  LargestRegion,
   IN  UINTN  LargestRegionSize,
   IN  UINTN  BootFirmwareVolumeBase,
-  IN  VOID   *PeiCorePe32File
+  IN  VOID    *PeiCorePe32File,
+  IN  UINT32  PeiCorePe32Size
   )
 {
   EFI_STATUS            Status;
@@ -597,7 +603,7 @@ SecLoadFromCore (
   //
   // Find the SEC Core Entry Point
   //
-  Status = SecPeCoffGetEntryPoint (PeiCorePe32File, (VOID **)&PeiCoreEntryPoint);
+  Status = SecUefiImageGetEntryPoint (PeiCorePe32File, PeiCorePe32Size, (VOID **)&PeiCoreEntryPoint);
   if (EFI_ERROR (Status)) {
     return;
   }
@@ -731,53 +737,28 @@ SecEmuThunkAddress (
 
 RETURN_STATUS
 EFIAPI
-SecPeCoffGetEntryPoint (
-  IN     VOID  *Pe32Data,
-  IN OUT VOID  **EntryPoint
+SecUefiImageGetEntryPoint (
+  IN     VOID   *Pe32Data,
+  IN     UINT32 Pe32Size,
+  IN OUT VOID   **EntryPoint
   )
 {
-  EFI_STATUS                    Status;
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
+  EFI_STATUS                      Status;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext;
 
-  ZeroMem (&ImageContext, sizeof (ImageContext));
-  ImageContext.Handle    = Pe32Data;
-  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)SecImageRead;
-
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);
+  Status                  = UefiImageInitializeContext (&ImageContext, Pe32Data, Pe32Size);
   if (EFI_ERROR (Status)) {
     return Status;
   }
 
-  if (ImageContext.ImageAddress != (UINTN)Pe32Data) {
-    //
-    // Relocate image to match the address where it resides
-    //
-    ImageContext.ImageAddress = (UINTN)Pe32Data;
-    Status                    = PeCoffLoaderLoadImage (&ImageContext);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    Status = PeCoffLoaderRelocateImage (&ImageContext);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-  } else {
-    //
-    // Or just return image entry point
-    //
-    ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer (Pe32Data);
-    Status                  = PeCoffLoaderGetEntryPoint (Pe32Data, EntryPoint);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    ImageContext.EntryPoint = (UINTN)*EntryPoint;
+  // FIXME: Why cannot the Image be in-place already?
+  Status = UefiImageRelocateImageInplaceForExecution (&ImageContext);
+  if (EFI_ERROR (Status)) {
+    return Status;
   }
 
-  // On Unix a dlopen is done that will change the entry point
-  SecPeCoffRelocateImageExtraAction (&ImageContext);
-  *EntryPoint = (VOID *)(UINTN)ImageContext.EntryPoint;
+  SecUefiImageRelocateImageExtraAction (&ImageContext);
+  *EntryPoint = (VOID *) (UefiImageLoaderGetImageEntryPoint (&ImageContext));
 
   return Status;
 }
@@ -900,114 +881,9 @@ Returns:
   return EFI_SUCCESS;
 }
 
-/*++
-
-Routine Description:
-  Store the ModHandle in an array indexed by the Pdb File name.
-  The ModHandle is needed to unload the image.
-
-Arguments:
-  ImageContext - Input data returned from PE Loader Library. Used to find the
-                 .PDB file name of the PE Image.
-  ModHandle    - Returned from LoadLibraryEx() and stored for call to
-                 FreeLibrary().
-
-Returns:
-  EFI_SUCCESS - ModHandle was stored.
-
-**/
-EFI_STATUS
-AddHandle (
-  IN  PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,
-  IN  VOID                          *ModHandle
-  )
-{
-  UINTN                        Index;
-  IMAGE_CONTEXT_TO_MOD_HANDLE  *Array;
-  UINTN                        PreviousSize;
-
-  Array = mImageContextModHandleArray;
-  for (Index = 0; Index < mImageContextModHandleArraySize; Index++, Array++) {
-    if (Array->ImageContext == NULL) {
-      //
-      // Make a copy of the string and store the ModHandle
-      //
-      Array->ImageContext = ImageContext;
-      Array->ModHandle    = ModHandle;
-      return EFI_SUCCESS;
-    }
-  }
-
-  //
-  // No free space in mImageContextModHandleArray so grow it by
-  // IMAGE_CONTEXT_TO_MOD_HANDLE entires. realloc will
-  // copy the old values to the new location. But it does
-  // not zero the new memory area.
-  //
-  PreviousSize                     = mImageContextModHandleArraySize * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE);
-  mImageContextModHandleArraySize += MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE;
-
-  mImageContextModHandleArray = ReallocatePool (
-                                  (mImageContextModHandleArraySize - 1) * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE),
-                                  mImageContextModHandleArraySize * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE),
-                                  mImageContextModHandleArray
-                                  );
-  if (mImageContextModHandleArray == NULL) {
-    ASSERT (FALSE);
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  memset (mImageContextModHandleArray + PreviousSize, 0, MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE));
-
-  return AddHandle (ImageContext, ModHandle);
-}
-
-/*++
-
-Routine Description:
-  Return the ModHandle and delete the entry in the array.
-
-Arguments:
-  ImageContext - Input data returned from PE Loader Library. Used to find the
-                 .PDB file name of the PE Image.
-
-Returns:
-  ModHandle - ModHandle associated with ImageContext is returned
-  NULL      - No ModHandle associated with ImageContext
-
-**/
-VOID *
-RemoveHandle (
-  IN  PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
-  )
-{
-  UINTN                        Index;
-  IMAGE_CONTEXT_TO_MOD_HANDLE  *Array;
-
-  if (ImageContext->PdbPointer == NULL) {
-    //
-    // If no PDB pointer there is no ModHandle so return NULL
-    //
-    return NULL;
-  }
-
-  Array = mImageContextModHandleArray;
-  for (Index = 0; Index < mImageContextModHandleArraySize; Index++, Array++) {
-    if (Array->ImageContext == ImageContext) {
-      //
-      // If you find a match return it and delete the entry
-      //
-      Array->ImageContext = NULL;
-      return Array->ModHandle;
-    }
-  }
-
-  return NULL;
-}
-
 BOOLEAN
 IsPdbFile (
-  IN  CHAR8  *PdbFileName
+  IN  CONST CHAR8   *PdbFileName
   )
 {
   UINTN  Len;
@@ -1035,23 +911,29 @@ IsPdbFile (
 
 void
 PrintLoadAddress (
-  IN PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT       *ImageContext
   )
 {
-  if (ImageContext->PdbPointer == NULL) {
+  EFI_STATUS                   Status;
+  CONST CHAR8                  *PdbPath;
+  UINT32                       PdbPathSize;
+
+  Status = UefiImageGetSymbolsPath (ImageContext, &PdbPath, &PdbPathSize);
+
+  if (EFI_ERROR (Status)) {
     fprintf (
       stderr,
       "0x%08lx Loading NO DEBUG with entry point 0x%08lx\n",
-      (unsigned long)(ImageContext->ImageAddress),
-      (unsigned long)ImageContext->EntryPoint
+      (unsigned long) UefiImageLoaderGetImageAddress (ImageContext),
+      (unsigned long) UefiImageLoaderGetImageEntryPoint (ImageContext)
       );
   } else {
     fprintf (
       stderr,
       "0x%08lx Loading %s with entry point 0x%08lx\n",
-      (unsigned long)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders),
-      ImageContext->PdbPointer,
-      (unsigned long)ImageContext->EntryPoint
+      (unsigned long) UefiImageLoaderGetImageAddress (ImageContext),
+      PdbPath,
+      (unsigned long) UefiImageLoaderGetImageEntryPoint (ImageContext)
       );
   }
 
@@ -1059,71 +941,12 @@ PrintLoadAddress (
   fflush (stderr);
 }
 
-/**
-  Loads the image using dlopen so symbols will be automatically
-  loaded by gdb.
-
-  @param  ImageContext  The PE/COFF image context
-
-  @retval TRUE - The image was successfully loaded
-  @retval FALSE - The image was successfully loaded
-
-**/
-BOOLEAN
-DlLoadImage (
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
-  )
-{
- #ifdef __APPLE__
-
-  return FALSE;
-
- #else
-
-  void  *Handle = NULL;
-  void  *Entry  = NULL;
-
-  if (ImageContext->PdbPointer == NULL) {
-    return FALSE;
-  }
-
-  if (!IsPdbFile (ImageContext->PdbPointer)) {
-    return FALSE;
-  }
-
-  fprintf (
-    stderr,
-    "Loading %s 0x%08lx - entry point 0x%08lx\n",
-    ImageContext->PdbPointer,
-    (unsigned long)ImageContext->ImageAddress,
-    (unsigned long)ImageContext->EntryPoint
-    );
-
-  Handle = dlopen (ImageContext->PdbPointer, RTLD_NOW);
-  if (Handle != NULL) {
-    Entry = dlsym (Handle, "_ModuleEntryPoint");
-    AddHandle (ImageContext, Handle);
-  } else {
-    printf ("%s\n", dlerror ());
-  }
-
-  if (Entry != NULL) {
-    ImageContext->EntryPoint = (UINTN)Entry;
-    printf ("Change %s Entrypoint to :0x%08lx\n", ImageContext->PdbPointer, (unsigned long)Entry);
-    return TRUE;
-  } else {
-    return FALSE;
-  }
-
- #endif
-}
-
 #ifdef __APPLE__
 __attribute__ ((noinline))
 #endif
 VOID
 SecGdbScriptBreak (
-  char               *FileName,
+  const char          *FileName,
   int                FileNameLength,
   long unsigned int  LoadAddress,
   int                AddSymbolFlag
@@ -1141,28 +964,37 @@ SecGdbScriptBreak (
 **/
 VOID
 GdbScriptAddImage (
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT      *ImageContext
   )
 {
+  EFI_STATUS  Status;
+  CONST CHAR8 *PdbPath;
+  UINT32      PdbPathSize;
+
   PrintLoadAddress (ImageContext);
 
-  if ((ImageContext->PdbPointer != NULL) && !IsPdbFile (ImageContext->PdbPointer)) {
+  Status = UefiImageGetSymbolsPath ((ImageContext, &PdbPath,) &PdbPathSize);
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  if (!IsPdbFile (PdbPath)) {
     FILE  *GdbTempFile;
     if (FeaturePcdGet (PcdEmulatorLazyLoadSymbols)) {
       GdbTempFile = fopen (gGdbWorkingFileName, "a");
       if (GdbTempFile != NULL) {
-        long unsigned int  SymbolsAddr = (long unsigned int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders);
+        long unsigned int SymbolsAddr = (long unsigned int)UefiImageLoaderGetImageAddress (ImageContext);
         mScriptSymbolChangesCount++;
         fprintf (
           GdbTempFile,
           "AddFirmwareSymbolFile 0x%x %s 0x%08lx\n",
           mScriptSymbolChangesCount,
-          ImageContext->PdbPointer,
+          PdbPath,
           SymbolsAddr
           );
         fclose (GdbTempFile);
         // This is for the lldb breakpoint only
-        SecGdbScriptBreak (ImageContext->PdbPointer, strlen (ImageContext->PdbPointer) + 1, (long unsigned int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders), 1);
+        SecGdbScriptBreak (PdbPath, PdbPathSize, (long unsigned int)UefiImageLoaderGetImageAddress (ImageContext), 1);
       } else {
         ASSERT (FALSE);
       }
@@ -1171,9 +1003,9 @@ GdbScriptAddImage (
       if (GdbTempFile != NULL) {
         fprintf (
           GdbTempFile,
-          "add-symbol-file %s 0x%08lx\n",
-          ImageContext->PdbPointer,
-          (long unsigned int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders)
+          "add-symbol-file %s -o 0x%08lx\n",
+          PdbPath,
+          (long unsigned int)UefiImageLoaderGetImageAddress (ImageContext)
           );
         fclose (GdbTempFile);
 
@@ -1183,7 +1015,7 @@ GdbScriptAddImage (
         // Also used for the lldb breakpoint script. The lldb breakpoint script does
         // not use the file, it uses the arguments.
         //
-        SecGdbScriptBreak (ImageContext->PdbPointer, strlen (ImageContext->PdbPointer) + 1, (long unsigned int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders), 1);
+        SecGdbScriptBreak (PdbPath, PdbPathSize, (long unsigned int)UefiImageLoaderGetImageAddress (ImageContext), 1);
       } else {
         ASSERT (FALSE);
       }
@@ -1193,13 +1025,11 @@ GdbScriptAddImage (
 
 VOID
 EFIAPI
-SecPeCoffRelocateImageExtraAction (
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+SecUefiImageRelocateImageExtraAction (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT      *ImageContext
   )
 {
-  if (!DlLoadImage (ImageContext)) {
-    GdbScriptAddImage (ImageContext);
-  }
+  GdbScriptAddImage (ImageContext);
 }
 
 /**
@@ -1211,15 +1041,23 @@ SecPeCoffRelocateImageExtraAction (
 **/
 VOID
 GdbScriptRemoveImage (
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT      *ImageContext
   )
 {
-  FILE  *GdbTempFile;
+  FILE        *GdbTempFile;
+  EFI_STATUS  Status;
+  CONST CHAR8 *PdbPath;
+  UINT32      PdbPathSize;
+
+  Status = UefiImageGetSymbolsPath (ImageContext, &PdbPath, &PdbPathSize);
+  if (EFI_ERROR (Status)) {
+    return;
+  }
 
   //
   // Need to skip .PDB files created from VC++
   //
-  if (IsPdbFile (ImageContext->PdbPointer)) {
+  if (IsPdbFile (PdbPath)) {
     return;
   }
 
@@ -1234,24 +1072,24 @@ GdbScriptRemoveImage (
         GdbTempFile,
         "RemoveFirmwareSymbolFile 0x%x %s\n",
         mScriptSymbolChangesCount,
-        ImageContext->PdbPointer
+        PdbPath
         );
       fclose (GdbTempFile);
-      SecGdbScriptBreak (ImageContext->PdbPointer, strlen (ImageContext->PdbPointer) + 1, 0, 0);
+      SecGdbScriptBreak (PdbPath, PdbPathSize, 0, 0);
     } else {
       ASSERT (FALSE);
     }
   } else {
     GdbTempFile = fopen (gGdbWorkingFileName, "w");
     if (GdbTempFile != NULL) {
-      fprintf (GdbTempFile, "remove-symbol-file %s\n", ImageContext->PdbPointer);
+      fprintf (GdbTempFile, "remove-symbol-file %s\n", PdbPath);
       fclose (GdbTempFile);
 
       //
       // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint.
       // Hey what can you say scripting in gdb is not that great....
       //
-      SecGdbScriptBreak (ImageContext->PdbPointer, strlen (ImageContext->PdbPointer) + 1, 0, 0);
+      SecGdbScriptBreak (PdbPath, PdbPathSize, 0, 0);
     } else {
       ASSERT (FALSE);
     }
@@ -1260,22 +1098,9 @@ GdbScriptRemoveImage (
 
 VOID
 EFIAPI
-SecPeCoffUnloadImageExtraAction (
-  IN PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+SecUefiImageUnloadImageExtraAction (
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT      *ImageContext
   )
 {
-  VOID  *Handle;
-
-  //
-  // Check to see if the image symbols were loaded with gdb script, or dlopen
-  //
-  Handle = RemoveHandle (ImageContext);
-  if (Handle != NULL) {
- #ifndef __APPLE__
-    dlclose (Handle);
- #endif
-    return;
-  }
-
   GdbScriptRemoveImage (ImageContext);
 }
diff --git a/EmulatorPkg/Unix/Host/Host.h b/EmulatorPkg/Unix/Host/Host.h
index 0c81cdfc01..c3b4214f84 100644
--- a/EmulatorPkg/Unix/Host/Host.h
+++ b/EmulatorPkg/Unix/Host/Host.h
@@ -85,7 +85,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <PiPei.h>
 #include <Uefi.h>
 
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/MemoryAllocationLib.h>
@@ -97,7 +97,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/ThunkPpiList.h>
 #include <Library/ThunkProtocolList.h>
 #include <Library/PeiServicesLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
 #include <Library/EmuMagicPageLib.h>
 
 #include <Ppi/EmuThunk.h>
@@ -137,7 +136,7 @@ typedef struct {
 #define MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE  0x100
 
 typedef struct {
-  PE_COFF_LOADER_IMAGE_CONTEXT    *ImageContext;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT   *ImageContext;
   VOID                            *ModHandle;
 } IMAGE_CONTEXT_TO_MOD_HANDLE;
 
@@ -162,7 +161,8 @@ SecLoadFromCore (
   IN  UINTN  LargestRegion,
   IN  UINTN  LargestRegionSize,
   IN  UINTN  BootFirmwareVolumeBase,
-  IN  VOID   *PeiCoreFile
+  IN  VOID    *PeiCoreFile,
+  IN  UINT32  PeiCorePe32Size
   );
 
 EFI_STATUS
@@ -194,17 +194,11 @@ SecFfsFindSectionData (
   );
 
 EFI_STATUS
-EFIAPI
-SecUnixPeCoffLoaderLoadAsDll (
-  IN CHAR8  *PdbFileName,
-  IN VOID   **ImageEntryPoint,
-  OUT VOID  **ModHandle
-  );
-
-EFI_STATUS
-EFIAPI
-SecUnixPeCoffLoaderFreeLibrary (
-  OUT VOID  *ModHandle
+SecFfsFindSectionData2 (
+  IN EFI_SECTION_TYPE      SectionType,
+  IN EFI_FFS_FILE_HEADER   *FfsFileHeader,
+  IN OUT VOID              **SectionData,
+  OUT UINT32               *SectionDataSize
   );
 
 EFI_STATUS
@@ -228,7 +222,7 @@ GasketSecUnixFdAddress (
 
 EFI_STATUS
 GetImageReadFunction (
-  IN PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT          *ImageContext,
   IN EFI_PHYSICAL_ADDRESS          *TopOfMemory
   );
 
@@ -273,21 +267,22 @@ GasketSecTemporaryRamSupport (
 
 RETURN_STATUS
 EFIAPI
-SecPeCoffGetEntryPoint (
+SecUefiImageGetEntryPoint (
   IN     VOID  *Pe32Data,
+  IN     UINT32 Pe32Size,
   IN OUT VOID  **EntryPoint
   );
 
 VOID
 EFIAPI
-SecPeCoffRelocateImageExtraAction (
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+SecUefiImageRelocateImageExtraAction (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
   );
 
 VOID
 EFIAPI
-SecPeCoffLoaderUnloadImageExtraAction (
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+SecUefiImageLoaderUnloadImageExtraAction (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
   );
 
 VOID
diff --git a/EmulatorPkg/Unix/Host/Host.inf b/EmulatorPkg/Unix/Host/Host.inf
index 550cb9f6e8..cae6ea0979 100644
--- a/EmulatorPkg/Unix/Host/Host.inf
+++ b/EmulatorPkg/Unix/Host/Host.inf
@@ -55,12 +55,11 @@
   PrintLib
   BaseMemoryLib
   BaseLib
-  PeCoffLib
+  UefiImageLib
   ThunkPpiList
   ThunkProtocolList
   PpiListLib
   PeiServicesLib
-  PeCoffGetEntryPointLib
   StackCheckLib
 
 [Ppis]
diff --git a/EmulatorPkg/Unix/Host/Ia32/Gasket.S b/EmulatorPkg/Unix/Host/Ia32/Gasket.S
index 36197ff260..81c9fd2cc1 100644
--- a/EmulatorPkg/Unix/Host/Ia32/Gasket.S
+++ b/EmulatorPkg/Unix/Host/Ia32/Gasket.S
@@ -313,24 +313,26 @@ ASM_PFX(GasketSecGetNextProtocol):
 
 // PPIs produced by SEC
 
-ASM_GLOBAL ASM_PFX(GasketSecPeCoffGetEntryPoint)
-ASM_PFX(GasketSecPeCoffGetEntryPoint):
+ASM_GLOBAL ASM_PFX(GasketSecUefiImageGetEntryPoint)
+ASM_PFX(GasketSecUefiImageGetEntryPoint):
   pushl %ebp
   movl  %esp, %ebp
-  subl  $24, %esp      // sub extra 16 from the stack for alignment
+  subl  $40, %esp      // sub extra 16 from the stack for alignment
   and   $-16, %esp    // stack needs to end in 0xFFFFFFF0 before call
+  movl  16(%ebp), %eax
+  movl  %eax, 8(%esp)
   movl  12(%ebp), %eax
   movl  %eax, 4(%esp)
   movl  8(%ebp), %eax
   movl  %eax, (%esp)
 
-  call    ASM_PFX(SecPeCoffGetEntryPoint)
+  call    ASM_PFX(SecUefiImageGetEntryPoint)
 
   leave
   ret
 
-ASM_GLOBAL ASM_PFX(GasketSecPeCoffRelocateImageExtraAction)
-ASM_PFX(GasketSecPeCoffRelocateImageExtraAction):
+ASM_GLOBAL ASM_PFX(GasketSecUefiImageRelocateImageExtraAction)
+ASM_PFX(GasketSecUefiImageRelocateImageExtraAction):
   pushl %ebp
   movl  %esp, %ebp
   subl  $24, %esp      // sub extra 16 from the stack for alignment
@@ -338,13 +340,13 @@ ASM_PFX(GasketSecPeCoffRelocateImageExtraAction):
   movl  8(%ebp), %eax
   movl  %eax, (%esp)
 
-  call    ASM_PFX(SecPeCoffRelocateImageExtraAction)
+  call    ASM_PFX(SecUefiImageRelocateImageExtraAction)
 
   leave
   ret
 
-ASM_GLOBAL ASM_PFX(GasketSecPeCoffUnloadImageExtraAction)
-ASM_PFX(GasketSecPeCoffUnloadImageExtraAction):
+ASM_GLOBAL ASM_PFX(GasketSecUefiImageUnloadImageExtraAction)
+ASM_PFX(GasketSecUefiImageUnloadImageExtraAction):
   pushl %ebp
   movl  %esp, %ebp
   subl  $24, %esp      // sub extra 16 from the stack for alignment
@@ -352,7 +354,7 @@ ASM_PFX(GasketSecPeCoffUnloadImageExtraAction):
   movl  8(%ebp), %eax
   movl  %eax, (%esp)
 
-  call    ASM_PFX(SecPeCoffUnloadImageExtraAction)
+  call    ASM_PFX(SecUefiImageUnloadImageExtraAction)
 
   leave
   ret
diff --git a/EmulatorPkg/Unix/Host/X64/Gasket.S b/EmulatorPkg/Unix/Host/X64/Gasket.S
index 030faa8e4c..006faa95d0 100644
--- a/EmulatorPkg/Unix/Host/X64/Gasket.S
+++ b/EmulatorPkg/Unix/Host/X64/Gasket.S
@@ -358,8 +358,8 @@ ASM_PFX(GasketSecGetNextProtocol):
 
 // PPIs produced by SEC
 
-ASM_GLOBAL ASM_PFX(GasketSecPeCoffGetEntryPoint)
-ASM_PFX(GasketSecPeCoffGetEntryPoint):
+ASM_GLOBAL ASM_PFX(GasketSecUefiImageGetEntryPoint)
+ASM_PFX(GasketSecUefiImageGetEntryPoint):
   pushq   %rbp            // stack frame is for the debugger
   movq    %rsp, %rbp
 
@@ -368,16 +368,17 @@ ASM_PFX(GasketSecPeCoffGetEntryPoint):
 
   movq    %rcx, %rdi    // Swizzle args
   movq    %rdx, %rsi
+  movq    %r8,  %rdx
 
-  call    ASM_PFX(SecPeCoffGetEntryPoint)
+  call    ASM_PFX(SecUefiImageGetEntryPoint)
 
   popq    %rdi          // restore state
   popq    %rsi
   popq    %rbp
   ret
 
-ASM_GLOBAL ASM_PFX(GasketSecPeCoffRelocateImageExtraAction)
-ASM_PFX(GasketSecPeCoffRelocateImageExtraAction):
+ASM_GLOBAL ASM_PFX(GasketSecUefiImageRelocateImageExtraAction)
+ASM_PFX(GasketSecUefiImageRelocateImageExtraAction):
   pushq   %rbp            // stack frame is for the debugger
   movq    %rsp, %rbp
 
@@ -386,15 +387,15 @@ ASM_PFX(GasketSecPeCoffRelocateImageExtraAction):
 
   movq    %rcx, %rdi    // Swizzle args
 
-  call    ASM_PFX(SecPeCoffRelocateImageExtraAction)
+  call    ASM_PFX(SecUefiImageRelocateImageExtraAction)
 
   popq    %rdi          // restore state
   popq    %rsi
   popq    %rbp
   ret
 
-ASM_GLOBAL ASM_PFX(GasketSecPeCoffUnloadImageExtraAction)
-ASM_PFX(GasketSecPeCoffUnloadImageExtraAction):
+ASM_GLOBAL ASM_PFX(GasketSecUefiImageUnloadImageExtraAction)
+ASM_PFX(GasketSecUefiImageUnloadImageExtraAction):
   pushq   %rbp            // stack frame is for the debugger
   movq    %rsp, %rbp
 
@@ -403,7 +404,7 @@ ASM_PFX(GasketSecPeCoffUnloadImageExtraAction):
 
   movq    %rcx, %rdi    // Swizzle args
 
-  call    ASM_PFX(SecPeCoffUnloadImageExtraAction)
+  call    ASM_PFX(SecUefiImageUnloadImageExtraAction)
 
   popq    %rdi          // restore state
   popq    %rsi
diff --git a/EmulatorPkg/Unix/lldbefi.py b/EmulatorPkg/Unix/lldbefi.py
old mode 100755
new mode 100644
index 952f8bf982..85be276d10
--- a/EmulatorPkg/Unix/lldbefi.py
+++ b/EmulatorPkg/Unix/lldbefi.py
@@ -361,7 +361,7 @@ def LoadEmulatorEfiSymbols(frame, bp_loc , internal_dict):
     #
     # VOID
     # SecGdbScriptBreak (
-    #   char                *FileName,
+    #   const char          *FileName,
     #   int                 FileNameLength,
     #   long unsigned int   LoadAddress,
     #   int                 AddSymbolFlag
@@ -394,7 +394,7 @@ def LoadEmulatorEfiSymbols(frame, bp_loc , internal_dict):
 
     debugger = frame.thread.process.target.debugger
     if frame.FindVariable ("AddSymbolFlag").GetValueAsUnsigned() == 1:
-        LoadAddress = frame.FindVariable ("LoadAddress").GetValueAsUnsigned() - 0x240
+        LoadAddress = frame.FindVariable ("LoadAddress").GetValueAsUnsigned()
 
         debugger.HandleCommand ("target modules add  %s" % FileName)
         print("target modules load --slid 0x%x %s" % (LoadAddress, FileName))
diff --git a/EmulatorPkg/Win/Host/WinHost.c b/EmulatorPkg/Win/Host/WinHost.c
index 9a5201f4d1..9cfeeef693 100644
--- a/EmulatorPkg/Win/Host/WinHost.c
+++ b/EmulatorPkg/Win/Host/WinHost.c
@@ -444,6 +444,7 @@ Returns:
   BOOLEAN              Done;
   EFI_PEI_FILE_HANDLE  FileHandle;
   VOID                 *SecFile;
+  UINT32                SecFileSize;
   CHAR16               *MemorySizeStr;
   CHAR16               *FirmwareVolumesStr;
   UINTN                ProcessAffinityMask;
@@ -451,6 +452,7 @@ Returns:
   INT32                LowBit;
   UINTN                ResetJumpCode;
   EMU_THUNK_PPI        *SecEmuThunkPpi;
+  UINT32               AuthenticationStatus;
 
   //
   // If enabled use the magic page to communicate between modules
@@ -648,7 +650,14 @@ Returns:
                      &FileHandle
                      );
       if (!EFI_ERROR (Status)) {
-        Status = PeiServicesFfsFindSectionData (EFI_SECTION_PE32, FileHandle, &SecFile);
+        Status = PeiServicesFfsFindSectionData4 (
+                   EFI_SECTION_PE32,
+                   0,
+                   FileHandle,
+                   &SecFile,
+                   &SecFileSize,
+                   &AuthenticationStatus
+                   );
         if (!EFI_ERROR (Status)) {
           SecPrint (" contains SEC Core");
         }
@@ -679,7 +688,7 @@ Returns:
   //
   // Hand off to SEC Core
   //
-  SecLoadSecCore ((UINTN)TemporaryRam, TemporaryRamSize, gFdInfo[0].Address, gFdInfo[0].Size, SecFile);
+  SecLoadSecCore ((UINTN)TemporaryRam, TemporaryRamSize, gFdInfo[0].Address, gFdInfo[0].Size, SecFile, SecFileSize);
 
   //
   // If we get here, then the SEC Core returned. This is an error as SEC should
@@ -695,7 +704,8 @@ SecLoadSecCore (
   IN  UINTN  TemporaryRamSize,
   IN  VOID   *BootFirmwareVolumeBase,
   IN  UINTN  BootFirmwareVolumeSize,
-  IN  VOID   *SecCorePe32File
+  IN  VOID   *SecCorePe32File,
+  IN  UINT32  SecCorePe32Size
   )
 
 /*++
@@ -759,8 +769,9 @@ Returns:
   //
   // Load the PEI Core from a Firmware Volume
   //
-  Status = SecPeCoffGetEntryPoint (
+  Status = SecUefiImageGetEntryPoint (
              SecCorePe32File,
+            SecCorePe32Size,
              &SecCoreEntryPoint
              );
   if (EFI_ERROR (Status)) {
@@ -784,40 +795,47 @@ Returns:
 
 RETURN_STATUS
 EFIAPI
-SecPeCoffGetEntryPoint (
-  IN     VOID  *Pe32Data,
-  IN OUT VOID  **EntryPoint
+SecUefiImageGetEntryPoint (
+  IN     VOID   *Pe32Data,
+  IN     UINT32 Pe32Size,
+  IN OUT VOID   **EntryPoint
   )
 {
-  EFI_STATUS                    Status;
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
+  EFI_STATUS                       Status;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT  ImageContext;
+  VOID                             *Dest;
+  UINT32                           DestSize;
 
-  ZeroMem (&ImageContext, sizeof (ImageContext));
-  ImageContext.Handle = Pe32Data;
-
-  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)SecImageRead;
-
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);
+  Status                  = UefiImageInitializeContext (&ImageContext, Pe32Data, Pe32Size);
   if (EFI_ERROR (Status)) {
     return Status;
   }
 
   //
-  // XIP for SEC and PEI_CORE
+  // Allocate space in NT (not emulator) memory with ReadWrite and Execute attribute.
+  // Extra space is for alignment
   //
-  ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data;
-
-  Status = PeCoffLoaderLoadImage (&ImageContext);
+  Status = UefiImageLoaderGetDestinationSize(&ImageContext, &DestSize);
   if (EFI_ERROR (Status)) {
     return Status;
   }
 
-  Status = PeCoffLoaderRelocateImage (&ImageContext);
+  Dest = VirtualAlloc (NULL, (SIZE_T) DestSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+  if (Dest == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = UefiImageLoadImage (&ImageContext, Dest, DestSize);
   if (EFI_ERROR (Status)) {
     return Status;
   }
 
-  *EntryPoint = (VOID *)(UINTN)ImageContext.EntryPoint;
+  Status = UefiImageRelocateImage (&ImageContext, (UINTN) Dest, NULL, 0);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *EntryPoint   = (VOID *) (UefiImageLoaderGetImageEntryPoint (&ImageContext));
 
   return EFI_SUCCESS;
 }
@@ -951,7 +969,7 @@ Returns:
 --*/
 EFI_STATUS
 AddModHandle (
-  IN  PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,
+  IN  UEFI_IMAGE_LOADER_IMAGE_CONTEXT      *ImageContext,
   IN  VOID                          *ModHandle
   )
 
@@ -1028,7 +1046,7 @@ AddModHandle (
 **/
 VOID *
 RemoveModHandle (
-  IN  PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+  IN  UEFI_IMAGE_LOADER_IMAGE_CONTEXT      *ImageContext
   )
 {
   UINTN                   Index;
@@ -1064,8 +1082,8 @@ typedef struct {
 
 VOID
 EFIAPI
-PeCoffLoaderRelocateImageExtraAction (
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+UefiImageLoaderRelocateImageExtraAction (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT      *ImageContext
   )
 {
   EFI_STATUS                           Status;
@@ -1103,7 +1121,7 @@ PeCoffLoaderRelocateImageExtraAction (
   // Load the DLL if it's not an EBC image.
   //
   if ((ImageContext->PdbPointer != NULL) &&
-      (ImageContext->Machine != EFI_IMAGE_MACHINE_EBC))
+      (UefiImageGetMachine (ImageContext) != EFI_IMAGE_MACHINE_EBC))
   {
     //
     // Convert filename from ASCII to Unicode
@@ -1117,7 +1135,7 @@ PeCoffLoaderRelocateImageExtraAction (
       free (DllFileName);
 
       //
-      // Never return an error if PeCoffLoaderRelocateImage() succeeded.
+      // Never return an error if UefiImageRelocateImage() succeeded.
       // The image will run, but we just can't source level debug. If we
       // return an error the image will not run.
       //
@@ -1316,8 +1334,8 @@ PeCoffLoaderRelocateImageExtraAction (
 
 VOID
 EFIAPI
-PeCoffLoaderUnloadImageExtraAction (
-  IN PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+UefiImageLoaderUnloadImageExtraAction (
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
   )
 {
   VOID  *ModHandle;
diff --git a/EmulatorPkg/Win/Host/WinHost.h b/EmulatorPkg/Win/Host/WinHost.h
index a9a21007e3..bad2fca5ce 100644
--- a/EmulatorPkg/Win/Host/WinHost.h
+++ b/EmulatorPkg/Win/Host/WinHost.h
@@ -21,7 +21,7 @@ Abstract:
 #include "WinInclude.h"
 
 #include <PiPei.h>
-#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/PeImage2.h>
 #include <Guid/FileInfo.h>
 #include <Guid/FileSystemInfo.h>
 #include <Guid/FileSystemVolumeLabelInfo.h>
@@ -35,7 +35,7 @@ Abstract:
 #include <Protocol/EmuSnp.h>
 
 #include <Library/BaseLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/DebugLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/ThunkPpiList.h>
@@ -44,7 +44,7 @@ Abstract:
 #include <Library/PrintLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/PeiServicesLib.h>
-#include <Library/PeCoffExtraActionLib.h>
+#include <Library/UefiImageExtraActionLib.h>
 #include <Library/NetLib.h>
 
 #define TEMPORARY_RAM_SIZE  0x20000
@@ -61,8 +61,9 @@ typedef struct {
 
 RETURN_STATUS
 EFIAPI
-SecPeCoffGetEntryPoint (
+SecUefiImageGetEntryPoint (
   IN     VOID  *Pe32Data,
+  IN     UINT32 Pe32Size,
   IN OUT VOID  **EntryPoint
   );
 
@@ -72,7 +73,8 @@ SecLoadSecCore (
   IN  UINTN  TemporaryRamSize,
   IN  VOID   *BootFirmwareVolumeBase,
   IN  UINTN  BootFirmwareVolumeSize,
-  IN  VOID   *SecCorePe32File
+  IN  VOID   *SecCorePe32File,
+  IN  UINT32  SecCorePe32Size
   )
 
 /*++
diff --git a/EmulatorPkg/Win/Host/WinHost.inf b/EmulatorPkg/Win/Host/WinHost.inf
index b123ea9dcf..3a4adcb711 100644
--- a/EmulatorPkg/Win/Host/WinHost.inf
+++ b/EmulatorPkg/Win/Host/WinHost.inf
@@ -49,7 +49,7 @@
   PrintLib
   BaseMemoryLib
   BaseLib
-  PeCoffLib
+  UefiImageLib
   ThunkPpiList
   ThunkProtocolList
   PpiListLib
diff --git a/EmulatorPkg/Win/Host/WinThunk.c b/EmulatorPkg/Win/Host/WinThunk.c
index e1b158c2da..257046d0aa 100644
--- a/EmulatorPkg/Win/Host/WinThunk.c
+++ b/EmulatorPkg/Win/Host/WinThunk.c
@@ -592,9 +592,9 @@ EMU_THUNK_PROTOCOL  gEmuThunkProtocol = {
   SecAlloc,
   NULL,
   SecFree,
-  SecPeCoffGetEntryPoint,
-  PeCoffLoaderRelocateImageExtraAction,
-  PeCoffLoaderUnloadImageExtraAction,
+  SecUefiImageGetEntryPoint,
+  UefiImageLoaderRelocateImageExtraAction,
+  UefiImageLoaderUnloadImageExtraAction,
   SecEnableInterrupt,
   SecDisableInterrupt,
   SecQueryPerformanceFrequency,
diff --git a/IntelFsp2Pkg/Tools/Tests/QemuFspPkg.dsc b/IntelFsp2Pkg/Tools/Tests/QemuFspPkg.dsc
index 3155812118..4fbaf8efd0 100644
--- a/IntelFsp2Pkg/Tools/Tests/QemuFspPkg.dsc
+++ b/IntelFsp2Pkg/Tools/Tests/QemuFspPkg.dsc
@@ -90,11 +90,11 @@
   PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
   PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
   MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
   CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
   UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
diff --git a/IntelFsp2WrapperPkg/FspWrapperNotifyDxe/FspWrapperNotifyDxe.inf b/IntelFsp2WrapperPkg/FspWrapperNotifyDxe/FspWrapperNotifyDxe.inf
index 4e8b618513..37db0a5a21 100644
--- a/IntelFsp2WrapperPkg/FspWrapperNotifyDxe/FspWrapperNotifyDxe.inf
+++ b/IntelFsp2WrapperPkg/FspWrapperNotifyDxe/FspWrapperNotifyDxe.inf
@@ -39,12 +39,13 @@
   BaseMemoryLib
   UefiLib
   FspWrapperApiLib
-  PeCoffLib
+  UefiImageLib
   CacheMaintenanceLib
   DxeServicesLib
   PerformanceLib
   HobLib
   FspWrapperPlatformLib
+  MemoryAllocationLib
 
 [Protocols]
   gEfiPciEnumerationCompleteProtocolGuid            ## CONSUMES
diff --git a/IntelFsp2WrapperPkg/FspWrapperNotifyDxe/LoadBelow4G.c b/IntelFsp2WrapperPkg/FspWrapperNotifyDxe/LoadBelow4G.c
index 97723aad65..1a1d052b4d 100644
--- a/IntelFsp2WrapperPkg/FspWrapperNotifyDxe/LoadBelow4G.c
+++ b/IntelFsp2WrapperPkg/FspWrapperNotifyDxe/LoadBelow4G.c
@@ -11,11 +11,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/UefiDriverEntryPoint.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/DxeServicesLib.h>
 #include <Library/CacheMaintenanceLib.h>
 #include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/MemoryAllocationLibEx.h>
 
 /**
   Relocate this image under 4G memory.
@@ -37,9 +39,11 @@ RelocateImageUnder4GIfNeeded (
   UINT8                         *Buffer;
   UINTN                         BufferSize;
   EFI_HANDLE                    NewImageHandle;
+  UINT32                        ImageSize;
+  UINT32                        ImageAlignment;
   UINTN                         Pages;
   EFI_PHYSICAL_ADDRESS          FfsBuffer;
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext;
   VOID                          *Interface;
 
   //
@@ -83,43 +87,34 @@ RelocateImageUnder4GIfNeeded (
              &BufferSize
              );
   ASSERT_EFI_ERROR (Status);
-  ImageContext.Handle    = Buffer;
-  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
   //
   // Get information about the image being loaded
   //
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);
+  Status = UefiImageInitializeContext (&ImageContext, Buffer, (UINT32) BufferSize);
   ASSERT_EFI_ERROR (Status);
-  if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
-    Pages = EFI_SIZE_TO_PAGES ((UINTN)(ImageContext.ImageSize + ImageContext.SectionAlignment));
-  } else {
-    Pages = EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize);
-  }
+  ImageSize      = UefiImageGetImageSize (&ImageContext);
+  ImageAlignment = UefiImageGetSegmentAlignment (&ImageContext);
+  Pages = EFI_SIZE_TO_PAGES (ImageSize);
 
   FfsBuffer = 0xFFFFFFFF;
-  Status    = gBS->AllocatePages (
-                     AllocateMaxAddress,
-                     EfiBootServicesCode,
-                     Pages,
-                     &FfsBuffer
-                     );
+  Status    = AllocateAlignedPagesEx (
+                AllocateMaxAddress,
+                EfiBootServicesCode,
+                Pages,
+                ImageAlignment,
+                &FfsBuffer
+                );
   ASSERT_EFI_ERROR (Status);
-  ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;
   //
-  // Align buffer on section boundary
+  // Load and relocate the image to our new buffer
   //
-  ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
-  ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);
-  //
-  // Load the image to our new buffer
-  //
-  Status = PeCoffLoaderLoadImage (&ImageContext);
-  ASSERT_EFI_ERROR (Status);
-
-  //
-  // Relocate the image in our new buffer
-  //
-  Status = PeCoffLoaderRelocateImage (&ImageContext);
+  Status = UefiImageLoadImageForExecution (
+             &ImageContext,
+             (VOID *) (UINTN) FfsBuffer,
+             ImageSize,
+             NULL,
+             0
+             );
   ASSERT_EFI_ERROR (Status);
 
   //
@@ -127,16 +122,11 @@ RelocateImageUnder4GIfNeeded (
   //
   gBS->FreePool (Buffer);
 
-  //
-  // Flush the instruction cache so the image data is written before we execute it
-  //
-  InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
-
-  DEBUG ((DEBUG_INFO, "Loading driver at 0x%08x EntryPoint=0x%08x\n", (UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.EntryPoint));
-  Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint))(NewImageHandle, gST);
+  DEBUG ((DEBUG_INFO, "Loading driver at 0x%08llx EntryPoint=0x%08x\n", FfsBuffer, UefiImageLoaderGetImageEntryPoint (&ImageContext)));
+  Status = ((EFI_IMAGE_ENTRY_POINT)(UefiImageLoaderGetImageEntryPoint (&ImageContext)))(NewImageHandle, gST);
   if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "Error: Image at 0x%08x start failed: %r\n", ImageContext.ImageAddress, Status));
-    gBS->FreePages (FfsBuffer, Pages);
+    DEBUG ((DEBUG_ERROR, "Error: Image at 0x%08llx start failed: %r\n", FfsBuffer, Status));
+    FreeAlignedPages ((VOID *)(UINTN)FfsBuffer, Pages);
   }
 
   //
diff --git a/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf b/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
index a0f384f992..6b0b422773 100644
--- a/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
+++ b/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
@@ -38,8 +38,8 @@
   FspWrapperPlatformLib
   FspWrapperHobProcessLib
   CpuLib
-  PeCoffGetEntryPointLib
-  PeCoffExtraActionLib
+  UefiCpuLib
+  UefiImageExtraActionLib
   PerformanceLib
   TimerLib
   FspWrapperApiLib
diff --git a/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf b/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
index a7b28e56b5..bc5be2f4cc 100644
--- a/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
+++ b/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
@@ -39,8 +39,8 @@
   FspWrapperPlatformLib
   FspWrapperHobProcessLib
   CpuLib
-  PeCoffGetEntryPointLib
-  PeCoffExtraActionLib
+  UefiCpuLib
+  UefiImageExtraActionLib
   PerformanceLib
   FspWrapperApiLib
   FspWrapperApiTestLib
diff --git a/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dsc b/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dsc
index f51e1c89f6..4276859e72 100644
--- a/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dsc
+++ b/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dsc
@@ -27,9 +27,9 @@
   DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
   PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
   IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
 
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
diff --git a/LoaderFlow.png b/LoaderFlow.png
new file mode 100644
index 0000000000..323e1b9aa3
Binary files /dev/null and b/LoaderFlow.png differ
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index ca5c06204d..e37d34c16d 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -40,7 +40,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/PcdLib.h>
 
 #include <IndustryStandard/Pci.h>
-#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/PeImage2.h>
 #include <IndustryStandard/Acpi.h>
 
 typedef struct _PCI_IO_DEVICE  PCI_IO_DEVICE;
diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h
index cd3940d34b..9ebbd2b853 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain.h
+++ b/MdeModulePkg/Core/Dxe/DxeMain.h
@@ -73,11 +73,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/ExtractGuidedSectionLib.h>
 #include <Library/CacheMaintenanceLib.h>
 #include <Library/BaseMemoryLib.h>
-#include <Library/PeCoffLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
-#include <Library/PeCoffExtraActionLib.h>
+#include <Library/UefiImageLib.h>
+#include <Library/UefiImageExtraActionLib.h>
 #include <Library/PcdLib.h>
 #include <Library/MemoryAllocationLib.h>
+#include <Library/MemoryAllocationLibEx.h>
 #include <Library/DevicePathLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/ReportStatusCodeLib.h>
@@ -220,10 +220,10 @@ typedef struct {
   EFI_RUNTIME_IMAGE_ENTRY                 *RuntimeData;
   /// Pointer to Loaded Image Device Path Protocol
   EFI_DEVICE_PATH_PROTOCOL                *LoadedImageDevicePath;
-  /// PeCoffLoader ImageContext
-  PE_COFF_LOADER_IMAGE_CONTEXT            ImageContext;
   /// Status returned by LoadImage() service.
   EFI_STATUS                              LoadImageStatus;
+
+  VOID *HiiData;
 } LOADED_IMAGE_PRIVATE_DATA;
 
 #define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \
@@ -390,7 +390,8 @@ CoreInitializeEventServices (
 **/
 EFI_STATUS
 CoreInitializeImageServices (
-  IN  VOID  *HobStart
+  IN  VOID                         *HobStart,
+  OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *ImageContext
   );
 
 /**
@@ -2385,7 +2386,8 @@ VOID
 CoreNewDebugImageInfoEntry (
   IN  UINT32                     ImageInfoType,
   IN  EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage,
-  IN  EFI_HANDLE                 ImageHandle
+  IN  EFI_HANDLE                 ImageHandle,
+  IN  UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
   );
 
 /**
@@ -2574,7 +2576,8 @@ VerifyFvHeaderChecksum (
 **/
 VOID
 MemoryProfileInit (
-  IN VOID  *HobStart
+  IN VOID                         *HobStart,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *ImageContext
   );
 
 /**
@@ -2600,8 +2603,9 @@ MemoryProfileInstallProtocol (
 **/
 EFI_STATUS
 RegisterMemoryProfileImage (
-  IN LOADED_IMAGE_PRIVATE_DATA  *DriverEntry,
-  IN EFI_FV_FILETYPE            FileType
+  IN EFI_DEVICE_PATH_PROTOCOL   *FilePath,
+  IN EFI_FV_FILETYPE            FileType,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT      *ImageContext
   );
 
 /**
@@ -2617,7 +2621,8 @@ RegisterMemoryProfileImage (
 **/
 EFI_STATUS
 UnregisterMemoryProfileImage (
-  IN LOADED_IMAGE_PRIVATE_DATA  *DriverEntry
+  EFI_DEVICE_PATH_PROTOCOL  *FilePath,
+  IN EFI_PHYSICAL_ADDRESS  ImageAddress
   );
 
 /**
@@ -2704,7 +2709,8 @@ InstallMemoryAttributesTableOnMemoryAllocation (
 **/
 VOID
 InsertImageRecord (
-  IN EFI_RUNTIME_IMAGE_ENTRY  *RuntimeImage
+  IN LOADED_IMAGE_PRIVATE_DATA   *Image,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *ImageContext
   );
 
 /**
@@ -2725,8 +2731,8 @@ RemoveImageRecord (
 **/
 VOID
 ProtectUefiImage (
-  IN EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage,
-  IN EFI_DEVICE_PATH_PROTOCOL   *LoadedImageDevicePath
+  IN LOADED_IMAGE_PRIVATE_DATA  *Image,
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT *ImageContext
   );
 
 /**
diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf
index cc315ac92a..4f20d6420f 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain.inf
+++ b/MdeModulePkg/Core/Dxe/DxeMain.inf
@@ -82,9 +82,8 @@
   UefiLib
   DebugLib
   DxeCoreEntryPoint
-  PeCoffLib
-  PeCoffGetEntryPointLib
-  PeCoffExtraActionLib
+  UefiImageLib
+  UefiImageExtraActionLib
   ExtractGuidedSectionLib
   MemoryAllocationLib
   UefiBootServicesTableLib
diff --git a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
index 50ab5fb844..da8d411d9b 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
+++ b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
@@ -236,15 +236,14 @@ DxeMain (
   IN  VOID  *HobStart
   )
 {
-  EFI_STATUS                    Status;
-  EFI_PHYSICAL_ADDRESS          MemoryBaseAddress;
-  UINT64                        MemoryLength;
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
-  UINTN                         Index;
-  EFI_HOB_GUID_TYPE             *GuidHob;
-  EFI_VECTOR_HANDOFF_INFO       *VectorInfoList;
-  EFI_VECTOR_HANDOFF_INFO       *VectorInfo;
-  VOID                          *EntryPoint;
+  EFI_STATUS                      Status;
+  EFI_PHYSICAL_ADDRESS            MemoryBaseAddress;
+  UINT64                          MemoryLength;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext;
+  UINTN                           Index;
+  EFI_HOB_GUID_TYPE               *GuidHob;
+  EFI_VECTOR_HANDOFF_INFO         *VectorInfoList;
+  EFI_VECTOR_HANDOFF_INFO         *VectorInfo;
 
   //
   // Setup the default exception handlers
@@ -276,8 +275,6 @@ DxeMain (
   //
   CoreInitializeMemoryServices (&HobStart, &MemoryBaseAddress, &MemoryLength);
 
-  MemoryProfileInit (HobStart);
-
   //
   // Start the Handle Services.
   //
@@ -287,9 +284,11 @@ DxeMain (
   //
   // Start the Image Services.
   //
-  Status = CoreInitializeImageServices (HobStart);
+  Status = CoreInitializeImageServices (HobStart, &ImageContext);
   ASSERT_EFI_ERROR (Status);
 
+  MemoryProfileInit (HobStart, &ImageContext);
+
   //
   // Initialize the Global Coherency Domain Services
   //
@@ -335,19 +334,9 @@ DxeMain (
 
   //
   // Report DXE Core image information to the PE/COFF Extra Action Library
+  // FIXME: This is done by DxeIpl, why is this needed here? Difference PEI/DXE?
   //
-  ZeroMem (&ImageContext, sizeof (ImageContext));
-  ImageContext.ImageAddress  = (EFI_PHYSICAL_ADDRESS)(UINTN)gDxeCoreLoadedImage->ImageBase;
-  ImageContext.PdbPointer    = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress);
-  ImageContext.SizeOfHeaders = PeCoffGetSizeOfHeaders ((VOID *)(UINTN)ImageContext.ImageAddress);
-  Status                     = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)ImageContext.ImageAddress, &EntryPoint);
-  if (Status == EFI_SUCCESS) {
-    ImageContext.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)EntryPoint;
-  }
-
-  ImageContext.Handle    = (VOID *)(UINTN)gDxeCoreLoadedImage->ImageBase;
-  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
-  PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+  UefiImageLoaderRelocateImageExtraAction (&ImageContext);
 
   //
   // Install the DXE Services Table into the EFI System Tables's Configuration Table
@@ -394,7 +383,8 @@ DxeMain (
   CoreNewDebugImageInfoEntry (
     EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL,
     gDxeCoreLoadedImage,
-    gDxeCoreImageHandle
+    gDxeCoreImageHandle,
+    &ImageContext
     );
 
   DEBUG ((DEBUG_INFO | DEBUG_LOAD, "HOBLIST address in DXE = 0x%p\n", HobStart));
diff --git a/MdeModulePkg/Core/Dxe/Image/Image.c b/MdeModulePkg/Core/Dxe/Image/Image.c
index 8d12f93d7f..818b7fb513 100644
--- a/MdeModulePkg/Core/Dxe/Image/Image.c
+++ b/MdeModulePkg/Core/Dxe/Image/Image.c
@@ -86,7 +86,20 @@ GLOBAL_REMOVE_IF_UNREFERENCED MACHINE_TYPE_INFO  mMachineTypeInfo[] = {
   { EFI_IMAGE_MACHINE_LOONGARCH64,    L"LOONGARCH64" },
 };
 
-UINT16  mDxeCoreImageMachineType = 0;
+//  FIXME: RISC-V, IA64
+#if defined (MDE_CPU_IA32)
+  CONST CHAR16 *mDxeCoreImageMachineTypeName = L"IA32";
+#elif defined (MDE_CPU_IPF)
+  CONST CHAR16 *mDxeCoreImageMachineTypeName = L"IA64";
+#elif defined (MDE_CPU_X64)
+  CONST CHAR16 *mDxeCoreImageMachineTypeName = L"X64";
+#elif defined (MDE_CPU_ARM)
+  CONST CHAR16 *mDxeCoreImageMachineTypeName = L"ARM";
+#elif defined (MDE_CPU_AARCH64)
+  CONST CHAR16 *mDxeCoreImageMachineTypeName = L"AARCH64";
+#else
+  #error Unkown CPU architecture
+#endif
 
 /**
  Return machine type name.
@@ -102,7 +115,7 @@ GetMachineTypeName (
 {
   UINTN  Index;
 
-  for (Index = 0; Index < sizeof (mMachineTypeInfo)/sizeof (mMachineTypeInfo[0]); Index++) {
+  for (Index = 0; Index < sizeof (mMachineTypeInfo)/sizeof (mMachineTypeInfo[0]); ++Index) {
     if (mMachineTypeInfo[Index].MachineType == MachineType) {
       return mMachineTypeInfo[Index].MachineTypeName;
     }
@@ -182,7 +195,8 @@ PeCoffEmuProtocolNotify (
 **/
 EFI_STATUS
 CoreInitializeImageServices (
-  IN  VOID  *HobStart
+  IN  VOID                            *HobStart,
+  OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *ImageContext
   )
 {
   EFI_STATUS                 Status;
@@ -219,6 +233,18 @@ CoreInitializeImageServices (
   //
   Image = &mCorePrivateImage;
 
+  Status = UefiImageInitializeContext (
+             ImageContext,
+             (VOID *) (UINTN) DxeCoreImageBaseAddress,
+             (UINT32) DxeCoreImageLength
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  // FIXME: DxeCore is dynamically loaded by DxeIpl, can't it pass the context?
+  ImageContext->ImageBuffer = (VOID *) ImageContext->FileBuffer;
+
+  ASSERT ((UINTN) DxeCoreEntryPoint == UefiImageLoaderGetImageEntryPoint (ImageContext));
+
   Image->EntryPoint     = (EFI_IMAGE_ENTRY_POINT)(UINTN)DxeCoreEntryPoint;
   Image->ImageBasePage  = DxeCoreImageBaseAddress;
   Image->NumberOfPages  = (UINTN)(EFI_SIZE_TO_PAGES ((UINTN)(DxeCoreImageLength)));
@@ -242,9 +268,8 @@ CoreInitializeImageServices (
   //
   // Fill in DXE globals
   //
-  mDxeCoreImageMachineType = PeCoffLoaderGetMachineType (Image->Info.ImageBase);
-  gDxeCoreImageHandle      = Image->Handle;
-  gDxeCoreLoadedImage      = &Image->Info;
+  gDxeCoreImageHandle = Image->Handle;
+  gDxeCoreLoadedImage = &Image->Info;
 
   //
   // Create the PE/COFF emulator protocol registration event
@@ -270,64 +295,11 @@ CoreInitializeImageServices (
 
   InitializeListHead (&mAvailableEmulators);
 
-  ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath);
+  ProtectUefiImage (Image, ImageContext);
 
   return Status;
 }
 
-/**
-  Read image file (specified by UserHandle) into user specified buffer with specified offset
-  and length.
-
-  @param  UserHandle             Image file handle
-  @param  Offset                 Offset to the source file
-  @param  ReadSize               For input, pointer of size to read; For output,
-                                 pointer of size actually read.
-  @param  Buffer                 Buffer to write into
-
-  @retval EFI_SUCCESS            Successfully read the specified part of file
-                                 into buffer.
-
-**/
-EFI_STATUS
-EFIAPI
-CoreReadImageFile (
-  IN     VOID   *UserHandle,
-  IN     UINTN  Offset,
-  IN OUT UINTN  *ReadSize,
-  OUT    VOID   *Buffer
-  )
-{
-  UINTN              EndPosition;
-  IMAGE_FILE_HANDLE  *FHand;
-
-  if ((UserHandle == NULL) || (ReadSize == NULL) || (Buffer == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (MAX_ADDRESS - Offset < *ReadSize) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  FHand = (IMAGE_FILE_HANDLE  *)UserHandle;
-  ASSERT (FHand->Signature == IMAGE_FILE_HANDLE_SIGNATURE);
-
-  //
-  // Move data from our local copy of the file
-  //
-  EndPosition = Offset + *ReadSize;
-  if (EndPosition > FHand->SourceSize) {
-    *ReadSize = (UINT32)(FHand->SourceSize - Offset);
-  }
-
-  if (Offset >= FHand->SourceSize) {
-    *ReadSize = 0;
-  }
-
-  CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);
-  return EFI_SUCCESS;
-}
-
 /**
   To check memory usage bit map array to figure out if the memory range the image will be loaded in is available or not. If
   memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.
@@ -378,8 +350,8 @@ CheckAndMarkFixLoadingMemoryUsageBitMap (
   //
   // Test the memory range for loading the image in the DXE code range.
   //
-  if ((gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress <  ImageBase + ImageSize) ||
-      (DxeCodeBase >  ImageBase))
+  if ((gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress < ImageBase + ImageSize) ||
+      (DxeCodeBase > ImageBase))
   {
     return EFI_NOT_FOUND;
   }
@@ -389,7 +361,7 @@ CheckAndMarkFixLoadingMemoryUsageBitMap (
   //
   BaseOffsetPageNumber = EFI_SIZE_TO_PAGES ((UINT32)(ImageBase - DxeCodeBase));
   TopOffsetPageNumber  = EFI_SIZE_TO_PAGES ((UINT32)(ImageBase + ImageSize - DxeCodeBase));
-  for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index++) {
+  for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; ++Index) {
     if ((mDxeCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64 (1, (Index % 64))) != 0) {
       //
       // This page is already used.
@@ -401,7 +373,7 @@ CheckAndMarkFixLoadingMemoryUsageBitMap (
   //
   // Being here means the memory range is available.  So mark the bits for the memory range
   //
-  for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index++) {
+  for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; ++Index) {
     mDxeCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64 (1, (Index % 64));
   }
 
@@ -420,88 +392,35 @@ CheckAndMarkFixLoadingMemoryUsageBitMap (
 
 **/
 EFI_STATUS
-GetPeCoffImageFixLoadingAssignedAddress (
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+GetUefiImageFixLoadingAssignedAddress (
+  OUT    EFI_PHYSICAL_ADDRESS  *LoadAddress,
+  IN     UINT64                ValueInSectionHeader,
+  IN     UINT32                ImageDestSize
   )
 {
-  UINTN                            SectionHeaderOffset;
-  EFI_STATUS                       Status;
-  EFI_IMAGE_SECTION_HEADER         SectionHeader;
-  EFI_IMAGE_OPTIONAL_HEADER_UNION  *ImgHdr;
-  UINT16                           Index;
-  UINTN                            Size;
-  UINT16                           NumberOfSections;
-  IMAGE_FILE_HANDLE                *Handle;
-  UINT64                           ValueInSectionHeader;
+  EFI_STATUS           Status;
+  EFI_PHYSICAL_ADDRESS FixLoadingAddress;
 
-  Status = EFI_NOT_FOUND;
-
-  //
-  // Get PeHeader pointer
-  //
-  Handle              = (IMAGE_FILE_HANDLE *)ImageContext->Handle;
-  ImgHdr              = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8 *)Handle->Source + ImageContext->PeCoffHeaderOffset);
-  SectionHeaderOffset = ImageContext->PeCoffHeaderOffset +
-                        sizeof (UINT32) +
-                        sizeof (EFI_IMAGE_FILE_HEADER) +
-                        ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;
-  NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;
-
-  //
-  // Get base address from the first section header that doesn't point to code section.
-  //
-  for (Index = 0; Index < NumberOfSections; Index++) {
+  if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) > 0) {
     //
-    // Read section header from file
+    // When LMFA feature is configured as Load Module at Fixed Absolute Address mode, PointerToRelocations & PointerToLineNumbers field
+    // hold the absolute address of image base running in memory
     //
-    Size   = sizeof (EFI_IMAGE_SECTION_HEADER);
-    Status = ImageContext->ImageRead (
-                             ImageContext->Handle,
-                             SectionHeaderOffset,
-                             &Size,
-                             &SectionHeader
-                             );
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    if (Size != sizeof (EFI_IMAGE_SECTION_HEADER)) {
-      return EFI_NOT_FOUND;
-    }
-
-    Status = EFI_NOT_FOUND;
-
-    if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
-      //
-      // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
-      // that doesn't point to code section in image header, as well as ImageBase field of image header. And there is an
-      // assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations
-      // & PointerToLineNumbers fields should NOT be Zero, or else, these 2 fields should be set to Zero
-      //
-      ValueInSectionHeader = ReadUnaligned64 ((UINT64 *)&SectionHeader.PointerToRelocations);
-      if (ValueInSectionHeader != 0) {
-        //
-        // When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext
-        // hold the specified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset
-        // relative to top address
-        //
-        if ((INT64)PcdGet64 (PcdLoadModuleAtFixAddressEnable) < 0) {
-          ImageContext->ImageAddress = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress + (INT64)(INTN)ImageContext->ImageAddress;
-        }
-
-        //
-        // Check if the memory range is available.
-        //
-        Status = CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext->ImageAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));
-      }
-
-      break;
-    }
-
-    SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
+    FixLoadingAddress = ValueInSectionHeader;
+  } else {
+    //
+    // When LMFA feature is configured as Load Module at Fixed offset mode, PointerToRelocations & PointerToLineNumbers field
+    // hold the offset relative to a platform-specific top address.
+    //
+    FixLoadingAddress = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress + ValueInSectionHeader;
   }
+  //
+  // Check if the memory range is available.
+  //
+  Status       = CheckAndMarkFixLoadingMemoryUsageBitMap (FixLoadingAddress, ImageDestSize);
+  *LoadAddress = FixLoadingAddress;
 
-  DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status = %r \n", (VOID *)(UINTN)(ImageContext->ImageAddress), Status));
+   DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status = %r \n", (VOID *)(UINTN)FixLoadingAddress, Status));
   return Status;
 }
 
@@ -520,7 +439,8 @@ GetPeCoffImageFixLoadingAssignedAddress (
 STATIC
 BOOLEAN
 CoreIsImageTypeSupported (
-  IN OUT LOADED_IMAGE_PRIVATE_DATA  *Image
+  IN OUT LOADED_IMAGE_PRIVATE_DATA       *Image,
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *ImageContext
   )
 {
   LIST_ENTRY      *Link;
@@ -531,13 +451,13 @@ CoreIsImageTypeSupported (
        Link = GetNextNode (&mAvailableEmulators, Link))
   {
     Entry = BASE_CR (Link, EMULATOR_ENTRY, Link);
-    if (Entry->MachineType != Image->ImageContext.Machine) {
+    if (Entry->MachineType != UefiImageGetMachine (ImageContext)) {
       continue;
     }
 
     if (Entry->Emulator->IsImageSupported (
                            Entry->Emulator,
-                           Image->ImageContext.ImageType,
+                           UefiImageGetSubsystem (ImageContext),
                            Image->Info.FilePath
                            ))
     {
@@ -546,8 +466,8 @@ CoreIsImageTypeSupported (
     }
   }
 
-  return EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine) ||
-         EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image->ImageContext.Machine);
+  return EFI_IMAGE_MACHINE_TYPE_SUPPORTED (UefiImageGetMachine (ImageContext)) ||
+         EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (UefiImageGetMachine (ImageContext));
 }
 
 /**
@@ -557,7 +477,6 @@ CoreIsImageTypeSupported (
                                   from the boot manager, and that the boot
                                   manager is attempting to load FilePath as a
                                   boot selection.
-  @param  Pe32Handle              The handle of PE32 image
   @param  Image                   PE image to be loaded
   @param  DstBuffer               The buffer to store the image
   @param  EntryPoint              A pointer to the entry point
@@ -573,32 +492,30 @@ CoreIsImageTypeSupported (
 **/
 EFI_STATUS
 CoreLoadPeImage (
-  IN BOOLEAN                    BootPolicy,
-  IN VOID                       *Pe32Handle,
-  IN LOADED_IMAGE_PRIVATE_DATA  *Image,
-  IN EFI_PHYSICAL_ADDRESS       DstBuffer    OPTIONAL,
-  OUT EFI_PHYSICAL_ADDRESS      *EntryPoint  OPTIONAL,
-  IN  UINT32                    Attribute
+  IN     BOOLEAN                          BootPolicy,
+  IN     LOADED_IMAGE_PRIVATE_DATA        *Image,
+  IN     EFI_PHYSICAL_ADDRESS             *DstBuffer   OPTIONAL,
+  OUT    EFI_PHYSICAL_ADDRESS             *EntryPoint  OPTIONAL,
+  IN     UINT32                           Attribute,
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
   )
 {
-  EFI_STATUS  Status;
-  BOOLEAN     DstBufAlocated;
-  UINTN       Size;
+  EFI_STATUS                        Status;
+  BOOLEAN                           DstBufAlocated;
+  UINT32                            ImageSize;
+  UINT32                            ImageAlignment;
+  UINT64                            ValueInSectionHeader;
+  UINT32                            DstBufPages;
+  UINT32                            DstBufSize;
+  EFI_MEMORY_TYPE                   ImageCodeMemoryType;
+  EFI_MEMORY_TYPE                   ImageDataMemoryType;
+  UEFI_IMAGE_LOADER_RUNTIME_CONTEXT *RelocationData;
+  EFI_PHYSICAL_ADDRESS              BufferAddress;
+  UINT32                            RelocDataSize;
 
-  ZeroMem (&Image->ImageContext, sizeof (Image->ImageContext));
+  RelocationData = NULL;
 
-  Image->ImageContext.Handle    = Pe32Handle;
-  Image->ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)CoreReadImageFile;
-
-  //
-  // Get information about the image being loaded
-  //
-  Status = PeCoffLoaderGetImageInfo (&Image->ImageContext);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  if (!CoreIsImageTypeSupported (Image)) {
+  if (!CoreIsImageTypeSupported (Image, ImageContext)) {
     //
     // The PE/COFF loader can support loading image types that can be executed.
     // If we loaded an image type that we can not execute return EFI_UNSUPPORTED.
@@ -606,50 +523,50 @@ CoreLoadPeImage (
     DEBUG ((
       DEBUG_ERROR,
       "Image type %s can't be loaded on %s UEFI system.\n",
-      GetMachineTypeName (Image->ImageContext.Machine),
-      GetMachineTypeName (mDxeCoreImageMachineType)
+      GetMachineTypeName (UefiImageGetMachine (ImageContext)),
+      mDxeCoreImageMachineTypeName
       ));
+
     return EFI_UNSUPPORTED;
   }
 
   //
   // Set EFI memory type based on ImageType
   //
-  switch (Image->ImageContext.ImageType) {
+  switch (UefiImageGetSubsystem (ImageContext)) {
     case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:
-      Image->ImageContext.ImageCodeMemoryType = EfiLoaderCode;
-      Image->ImageContext.ImageDataMemoryType = EfiLoaderData;
+      ImageCodeMemoryType = EfiLoaderCode;
+      ImageDataMemoryType = EfiLoaderData;
       break;
     case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
-      Image->ImageContext.ImageCodeMemoryType = EfiBootServicesCode;
-      Image->ImageContext.ImageDataMemoryType = EfiBootServicesData;
+      ImageCodeMemoryType = EfiBootServicesCode;
+      ImageDataMemoryType = EfiBootServicesData;
       break;
     case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
     case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:
-      Image->ImageContext.ImageCodeMemoryType = EfiRuntimeServicesCode;
-      Image->ImageContext.ImageDataMemoryType = EfiRuntimeServicesData;
+      ImageCodeMemoryType = EfiRuntimeServicesCode;
+      ImageDataMemoryType = EfiRuntimeServicesData;
       break;
-    default:
-      Image->ImageContext.ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;
-      return EFI_UNSUPPORTED;
+  default:
+    DEBUG ((DEBUG_INFO, "Unsupported type %d\n", UefiImageGetSubsystem (ImageContext)));
+    return EFI_UNSUPPORTED;
   }
 
+  ImageSize      = UefiImageGetImageSize (ImageContext);
+  DstBufPages    = EFI_SIZE_TO_PAGES (ImageSize);
+  DstBufSize     = EFI_PAGES_TO_SIZE (DstBufPages);
+  ImageAlignment = UefiImageGetSegmentAlignment (ImageContext);
+
+  BufferAddress = 0;
   //
   // Allocate memory of the correct memory type aligned on the required image boundary
   //
   DstBufAlocated = FALSE;
-  if (DstBuffer == 0) {
+  if (*DstBuffer == 0) {
     //
     // Allocate Destination Buffer as caller did not pass it in
     //
-
-    if (Image->ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
-      Size = (UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment;
-    } else {
-      Size = (UINTN)Image->ImageContext.ImageSize;
-    }
-
-    Image->NumberOfPages = EFI_SIZE_TO_PAGES (Size);
+    Image->NumberOfPages = DstBufPages;
 
     //
     // If the image relocations have not been stripped, then load at any address.
@@ -664,98 +581,105 @@ CoreLoadPeImage (
     // a specified address.
     //
     if (PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0 ) {
-      Status = GetPeCoffImageFixLoadingAssignedAddress (&(Image->ImageContext));
+      Status = UefiImageGetFixedAddress (ImageContext, &ValueInSectionHeader);
+      if (RETURN_ERROR (Status)) {
+        return Status;
+      }
 
-      if (EFI_ERROR (Status)) {
+      Status = GetUefiImageFixLoadingAssignedAddress (&BufferAddress, ValueInSectionHeader, DstBufSize);
+
+      if (!EFI_ERROR (Status))  {
+        if (BufferAddress != UefiImageGetPreferredAddress (ImageContext) && UefiImageGetRelocsStripped (ImageContext)) {
+          Status = EFI_UNSUPPORTED;
+          DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Loading module at fixed address failed since relocs have been stripped.\n"));
+        }
+      } else {
         //
         // If the code memory is not ready, invoke CoreAllocatePage with AllocateAnyPages to load the driver.
         //
         DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED ERROR: Loading module at fixed address failed since specified memory is not available.\n"));
-
-        Status = CoreAllocatePages (
-                   AllocateAnyPages,
-                   (EFI_MEMORY_TYPE)(Image->ImageContext.ImageCodeMemoryType),
-                   Image->NumberOfPages,
-                   &Image->ImageContext.ImageAddress
-                   );
       }
-    } else {
-      if ((PcdGetBool (PcdImageLargeAddressLoad) && ((Image->ImageContext.ImageAddress) >= 0x100000)) ||
-          Image->ImageContext.RelocationsStripped)
-      {
-        Status = CoreAllocatePages (
+    }
+    if (EFI_ERROR (Status)) {
+      BufferAddress = UefiImageGetPreferredAddress (ImageContext);
+      if ((BufferAddress >= 0x100000) || UefiImageGetRelocsStripped (ImageContext)) {
+        Status = AllocatePagesEx (
                    AllocateAddress,
-                   (EFI_MEMORY_TYPE)(Image->ImageContext.ImageCodeMemoryType),
-                   Image->NumberOfPages,
-                   &Image->ImageContext.ImageAddress
+                   ImageCodeMemoryType,
+                   DstBufPages,
+                   &BufferAddress
                    );
       }
 
-      if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {
-        Status = CoreAllocatePages (
+      if (EFI_ERROR (Status) && !UefiImageGetRelocsStripped (ImageContext)) {
+        Status = AllocateAlignedPagesEx (
                    AllocateAnyPages,
-                   (EFI_MEMORY_TYPE)(Image->ImageContext.ImageCodeMemoryType),
-                   Image->NumberOfPages,
-                   &Image->ImageContext.ImageAddress
+                   ImageCodeMemoryType,
+                   DstBufPages,
+                   ImageAlignment,
+                   &BufferAddress
                    );
       }
     }
 
     if (EFI_ERROR (Status)) {
+      ASSERT (FALSE);
       return Status;
     }
 
     DstBufAlocated = TRUE;
+    *DstBuffer     = BufferAddress;
   } else {
     //
     // Caller provided the destination buffer
     //
 
-    if (Image->ImageContext.RelocationsStripped && (Image->ImageContext.ImageAddress != DstBuffer)) {
+    if (UefiImageGetRelocsStripped (ImageContext) && (BufferAddress != *DstBuffer)) {
       //
       // If the image relocations were stripped, and the caller provided a
       // destination buffer address that does not match the address that the
       // image is linked at, then the image cannot be loaded.
       //
+      ASSERT (FALSE);
       return EFI_INVALID_PARAMETER;
     }
 
     if ((Image->NumberOfPages != 0) &&
         (Image->NumberOfPages <
-         (EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment))))
+         DstBufPages))
     {
-      Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
+      Image->NumberOfPages = DstBufPages;
+      ASSERT (FALSE);
       return EFI_BUFFER_TOO_SMALL;
     }
 
-    Image->NumberOfPages             = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);
-    Image->ImageContext.ImageAddress = DstBuffer;
+    Image->NumberOfPages = DstBufPages;
+    BufferAddress        = *DstBuffer;
   }
 
-  Image->ImageBasePage = Image->ImageContext.ImageAddress;
-  if (!Image->ImageContext.IsTeImage) {
-    Image->ImageContext.ImageAddress =
-      (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &
-      ~((UINTN)Image->ImageContext.SectionAlignment - 1);
-  }
-
-  //
-  // Load the image from the file into the allocated memory
-  //
-  Status = PeCoffLoaderLoadImage (&Image->ImageContext);
-  if (EFI_ERROR (Status)) {
-    goto Done;
-  }
+  Image->ImageBasePage = BufferAddress;
 
   //
   // If this is a Runtime Driver, then allocate memory for the FixupData that
   // is used to relocate the image when SetVirtualAddressMap() is called. The
   // relocation is done by the Runtime AP.
   //
+  RelocDataSize = 0;
   if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {
-    if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
-      Image->ImageContext.FixupData = AllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));
-      if (Image->ImageContext.FixupData == NULL) {
+    if (UefiImageGetSubsystem (ImageContext) == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
+      if (UefiImageGetRelocsStripped (ImageContext)) {
+        ASSERT (FALSE);
+        Status = RETURN_UNSUPPORTED;
+        goto Done;
+      }
+      Status = UefiImageLoaderGetRuntimeContextSize (ImageContext, &RelocDataSize);
+      if (EFI_ERROR (Status)) {
+        ASSERT (FALSE);
+        goto Done;
+      }
+      RelocationData = AllocateRuntimeZeroPool (RelocDataSize);
+      if (RelocationData == NULL) {
+        ASSERT (FALSE);
         Status = EFI_OUT_OF_RESOURCES;
         goto Done;
       }
@@ -763,38 +687,40 @@ CoreLoadPeImage (
   }
 
   //
-  // Relocate the image in memory
+  // Load the image from the file into the allocated memory
   //
-  Status = PeCoffLoaderRelocateImage (&Image->ImageContext);
+  Status = UefiImageLoadImageForExecution (
+             ImageContext,
+             (VOID *)(UINTN)BufferAddress,
+             DstBufSize,
+             RelocationData,
+             RelocDataSize
+             );
   if (EFI_ERROR (Status)) {
+    ASSERT (FALSE);
     goto Done;
   }
 
-  //
-  // Flush the Instruction Cache
-  //
-  InvalidateInstructionCacheRange ((VOID *)(UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.ImageSize);
-
   //
   // Copy the machine type from the context to the image private data.
   //
-  Image->Machine = Image->ImageContext.Machine;
+  Image->Machine = UefiImageGetMachine (ImageContext);
 
   //
   // Get the image entry point.
   //
-  Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)Image->ImageContext.EntryPoint;
+  Image->EntryPoint   = (EFI_IMAGE_ENTRY_POINT)(UefiImageLoaderGetImageEntryPoint (ImageContext));
 
   //
   // Fill in the image information for the Loaded Image Protocol
   //
-  Image->Type               = Image->ImageContext.ImageType;
-  Image->Info.ImageBase     = (VOID *)(UINTN)Image->ImageContext.ImageAddress;
-  Image->Info.ImageSize     = Image->ImageContext.ImageSize;
-  Image->Info.ImageCodeType = (EFI_MEMORY_TYPE)(Image->ImageContext.ImageCodeMemoryType);
-  Image->Info.ImageDataType = (EFI_MEMORY_TYPE)(Image->ImageContext.ImageDataMemoryType);
+  Image->Type               = UefiImageGetSubsystem (ImageContext);
+  Image->Info.ImageBase     = (VOID *)(UINTN)BufferAddress;
+  Image->Info.ImageSize     = ImageSize;
+  Image->Info.ImageCodeType = ImageCodeMemoryType;
+  Image->Info.ImageDataType = ImageDataMemoryType;
   if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {
-    if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
+    if (UefiImageGetSubsystem (ImageContext) == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
       //
       // Make a list off all the RT images so we can let the RT AP know about them.
       //
@@ -805,10 +731,10 @@ CoreLoadPeImage (
 
       Image->RuntimeData->ImageBase      = Image->Info.ImageBase;
       Image->RuntimeData->ImageSize      = (UINT64)(Image->Info.ImageSize);
-      Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;
+      Image->RuntimeData->RelocationData = RelocationData;
       Image->RuntimeData->Handle         = Image->Handle;
       InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);
-      InsertImageRecord (Image->RuntimeData);
+      InsertImageRecord (Image, ImageContext);
     }
   }
 
@@ -816,7 +742,17 @@ CoreLoadPeImage (
   // Fill in the entry point of the image if it is available
   //
   if (EntryPoint != NULL) {
-    *EntryPoint = Image->ImageContext.EntryPoint;
+    *EntryPoint = UefiImageLoaderGetImageEntryPoint (ImageContext);
+  }
+
+  UINT32 Hiioff;
+  UINT32 Hiisize;
+  Status = UefiImageGetHiiDataRva (ImageContext, &Hiioff, &Hiisize);
+  if (Status != RETURN_NOT_FOUND) {
+    ASSERT_EFI_ERROR (Status);
+  }
+  if (!EFI_ERROR (Status)) {
+    Image->HiiData = (VOID *)((UINTN)BufferAddress + Hiioff);
   }
 
   //
@@ -825,56 +761,25 @@ CoreLoadPeImage (
 
   DEBUG_CODE_BEGIN ();
 
-  UINTN  Index;
-  UINTN  StartIndex;
-  CHAR8  EfiFileName[256];
+  CHAR8 EfiFileName[256];
 
-  DEBUG ((
-    DEBUG_INFO | DEBUG_LOAD,
-    "Loading driver at 0x%11p EntryPoint=0x%11p ",
-    (VOID *)(UINTN)Image->ImageContext.ImageAddress,
-    FUNCTION_ENTRY_POINT (Image->ImageContext.EntryPoint)
-    ));
+  DEBUG ((DEBUG_INFO | DEBUG_LOAD,
+         "Loading driver at 0x%11p EntryPoint=0x%11p \n",
+         (VOID *)(UINTN)BufferAddress,
+           FUNCTION_ENTRY_POINT (UefiImageLoaderGetImageEntryPoint (ImageContext))));
+
+    Status = UefiImageGetModuleNameFromSymbolsPath (
+             ImageContext,
+             EfiFileName,
+             sizeof (EfiFileName)
+             );
 
   //
   // Print Module Name by Pdb file path.
-  // Windows and Unix style file path are all trimmed correctly.
   //
-  if (Image->ImageContext.PdbPointer != NULL) {
-    StartIndex = 0;
-    for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {
-      if ((Image->ImageContext.PdbPointer[Index] == '\\') || (Image->ImageContext.PdbPointer[Index] == '/')) {
-        StartIndex = Index + 1;
-      }
-    }
-
-    //
-    // Copy the PDB file name to our temporary string, and replace .pdb with .efi
-    // The PDB file name is limited in the range of 0~255.
-    // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.
-    //
-    for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {
-      EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];
-      if (EfiFileName[Index] == 0) {
-        EfiFileName[Index] = '.';
-      }
-
-      if (EfiFileName[Index] == '.') {
-        EfiFileName[Index + 1] = 'e';
-        EfiFileName[Index + 2] = 'f';
-        EfiFileName[Index + 3] = 'i';
-        EfiFileName[Index + 4] = 0;
-        break;
-      }
-    }
-
-    if (Index == sizeof (EfiFileName) - 4) {
-      EfiFileName[Index] = 0;
-    }
-
-    DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName));   // &Image->ImageContext.PdbPointer[StartIndex]));
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName));
   }
-
   DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n"));
 
   DEBUG_CODE_END ();
@@ -888,13 +793,13 @@ Done:
   //
 
   if (DstBufAlocated) {
-    CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);
-    Image->ImageContext.ImageAddress = 0;
+    ZeroMem ((VOID *)(UINTN)BufferAddress, EFI_PAGES_TO_SIZE (Image->NumberOfPages));
+    FreeAlignedPages ((VOID *)(UINTN)BufferAddress, Image->NumberOfPages);
     Image->ImageBasePage             = 0;
   }
 
-  if (Image->ImageContext.FixupData != NULL) {
-    CoreFreePool (Image->ImageContext.FixupData);
+  if (RelocationData != NULL) {
+    CoreFreePool (RelocationData);
   }
 
   return Status;
@@ -959,23 +864,20 @@ CoreUnloadAndCloseImage (
   HandleBuffer      = NULL;
   ProtocolGuidArray = NULL;
 
-  if (Image->Started) {
-    UnregisterMemoryProfileImage (Image);
-  }
-
-  UnprotectUefiImage (&Image->Info, Image->LoadedImageDevicePath);
+  UnregisterMemoryProfileImage (Image->Info.FilePath, Image->ImageBasePage);
 
   if (Image->PeCoffEmu != NULL) {
     //
     // If the PE/COFF Emulator protocol exists we must unregister the image.
     //
-    Image->PeCoffEmu->UnregisterImage (Image->PeCoffEmu, Image->ImageBasePage);
+    Image->PeCoffEmu->UnregisterImage (Image->PeCoffEmu, (UINTN) Image->Info.ImageBase);
   }
 
   //
   // Unload image, free Image->ImageContext->ModHandle
   //
-  PeCoffLoaderUnloadImage (&Image->ImageContext);
+  // FIXME:
+  //PeCoffUnloadImage (&Image->ImageContext);
 
   //
   // Free our references to the image handle
@@ -989,14 +891,14 @@ CoreUnloadAndCloseImage (
                &HandleBuffer
                );
     if (!EFI_ERROR (Status)) {
-      for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
+      for (HandleIndex = 0; HandleIndex < HandleCount; ++HandleIndex) {
         Status = CoreProtocolsPerHandle (
                    HandleBuffer[HandleIndex],
                    &ProtocolGuidArray,
                    &ArrayCount
                    );
         if (!EFI_ERROR (Status)) {
-          for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
+          for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ++ProtocolIndex) {
             Status = CoreOpenProtocolInformation (
                        HandleBuffer[HandleIndex],
                        ProtocolGuidArray[ProtocolIndex],
@@ -1004,7 +906,7 @@ CoreUnloadAndCloseImage (
                        &OpenInfoCount
                        );
             if (!EFI_ERROR (Status)) {
-              for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
+              for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; ++OpenInfoIndex) {
                 if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {
                   Status = CoreCloseProtocol (
                              HandleBuffer[HandleIndex],
@@ -1046,11 +948,11 @@ CoreUnloadAndCloseImage (
                &Image->Info
                );
 
-    if (Image->ImageContext.HiiResourceData != 0) {
+    if (Image->HiiData != NULL) {
       Status = CoreUninstallProtocolInterface (
                  Image->Handle,
                  &gEfiHiiPackageListProtocolGuid,
-                 (VOID *)(UINTN)Image->ImageContext.HiiResourceData
+                 Image->HiiData
                  );
     }
   }
@@ -1068,15 +970,22 @@ CoreUnloadAndCloseImage (
   }
 
   //
-  // Free the Image from memory
+  // Done with the Image structure
   //
-  if ((Image->ImageBasePage != 0) && FreePage) {
-    CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);
+  if (Image->FixupData != NULL) {
+    CoreFreePool (Image->FixupData);
   }
 
   //
-  // Done with the Image structure
+  // Free the Image from memory
   //
+  if ((Image->ImageBasePage != 0) && FreePage) {
+    UnprotectUefiImage (&Image->Info, Image->LoadedImageDevicePath);
+    // FIXME: SecureZeroMem; instruction pattern to trap?
+    ZeroMem ((VOID *)(UINTN)Image->ImageBasePage, EFI_PAGES_TO_SIZE (Image->NumberOfPages));
+    CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);
+  }
+
   if (Image->Info.FilePath != NULL) {
     CoreFreePool (Image->Info.FilePath);
   }
@@ -1085,10 +994,6 @@ CoreUnloadAndCloseImage (
     CoreFreePool (Image->LoadedImageDevicePath);
   }
 
-  if (Image->FixupData != NULL) {
-    CoreFreePool (Image->FixupData);
-  }
-
   CoreFreePool (Image);
 }
 
@@ -1150,20 +1055,21 @@ CoreLoadImageCommon (
   IN  UINT32                    Attribute
   )
 {
-  LOADED_IMAGE_PRIVATE_DATA  *Image;
-  LOADED_IMAGE_PRIVATE_DATA  *ParentImage;
-  IMAGE_FILE_HANDLE          FHand;
-  EFI_STATUS                 Status;
-  EFI_STATUS                 SecurityStatus;
-  EFI_HANDLE                 DeviceHandle;
-  UINT32                     AuthenticationStatus;
-  EFI_DEVICE_PATH_PROTOCOL   *OriginalFilePath;
-  EFI_DEVICE_PATH_PROTOCOL   *HandleFilePath;
-  EFI_DEVICE_PATH_PROTOCOL   *InputFilePath;
-  EFI_DEVICE_PATH_PROTOCOL   *Node;
-  UINTN                      FilePathSize;
-  BOOLEAN                    ImageIsFromFv;
-  BOOLEAN                    ImageIsFromLoadFile;
+  LOADED_IMAGE_PRIVATE_DATA       *Image;
+  LOADED_IMAGE_PRIVATE_DATA       *ParentImage;
+  IMAGE_FILE_HANDLE               FHand;
+  EFI_STATUS                      Status;
+  EFI_STATUS                      SecurityStatus;
+  EFI_HANDLE                      DeviceHandle;
+  UINT32                          AuthenticationStatus;
+  EFI_DEVICE_PATH_PROTOCOL        *OriginalFilePath;
+  EFI_DEVICE_PATH_PROTOCOL        *HandleFilePath;
+  EFI_DEVICE_PATH_PROTOCOL        *InputFilePath;
+  EFI_DEVICE_PATH_PROTOCOL        *Node;
+  UINTN                           FilePathSize;
+  BOOLEAN                         ImageIsFromFv;
+  BOOLEAN                         ImageIsFromLoadFile;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext;
 
   SecurityStatus = EFI_SUCCESS;
 
@@ -1206,6 +1112,18 @@ CoreLoadImageCommon (
     }
 
     if (SourceSize > 0) {
+      if (DeviceHandle != NULL) {
+        Status = CoreOpenProtocol (
+                   DeviceHandle,
+                   &gEfiFirmwareVolume2ProtocolGuid,
+                   NULL,
+                   NULL,
+                   NULL,
+                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+                   );
+        ImageIsFromFv = !EFI_ERROR (Status);
+      }
+
       Status = EFI_SUCCESS;
     } else {
       Status = EFI_LOAD_ERROR;
@@ -1269,6 +1187,16 @@ CoreLoadImageCommon (
     goto Done;
   }
 
+  //
+  // Get information about the image being loaded
+  //
+  Status = UefiImageInitializeContextPreHash (&ImageContext, FHand.Source, (UINT32) FHand.SourceSize);
+  if (EFI_ERROR (Status)) {
+    ASSERT (FALSE);
+    return Status;
+  }
+
+  // FIXME: Context
   if (gSecurity2 != NULL) {
     //
     // Verify File Authentication through the Security2 Architectural Protocol
@@ -1276,8 +1204,8 @@ CoreLoadImageCommon (
     SecurityStatus = gSecurity2->FileAuthentication (
                                    gSecurity2,
                                    OriginalFilePath,
-                                   FHand.Source,
-                                   FHand.SourceSize,
+                                  &ImageContext,
+                                  sizeof (ImageContext),
                                    BootPolicy
                                    );
     if (!EFI_ERROR (SecurityStatus) && ImageIsFromFv) {
@@ -1324,6 +1252,11 @@ CoreLoadImageCommon (
     goto Done;
   }
 
+  Status = UefiImageInitializeContextPostHash (&ImageContext);
+  if (RETURN_ERROR (Status)) {
+    goto Done;
+  }
+
   //
   // Allocate a new image structure
   //
@@ -1379,7 +1312,8 @@ CoreLoadImageCommon (
   //
   // Load the image.  If EntryPoint is Null, it will not be set.
   //
-  Status = CoreLoadPeImage (BootPolicy, &FHand, Image, DstBuffer, EntryPoint, Attribute);
+  EFI_PHYSICAL_ADDRESS LoadAddress = DstBuffer;
+  Status = CoreLoadPeImage (BootPolicy, Image, &LoadAddress, EntryPoint, Attribute, &ImageContext);
   if (EFI_ERROR (Status)) {
     if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {
       if (NumberOfPages != NULL) {
@@ -1398,7 +1332,7 @@ CoreLoadImageCommon (
   // Register the image in the Debug Image Info Table if the attribute is set
   //
   if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) != 0) {
-    CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);
+    CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle, &ImageContext);
   }
 
   //
@@ -1445,22 +1379,26 @@ CoreLoadImageCommon (
     goto Done;
   }
 
-  //
-  // Install HII Package List Protocol onto the image handle
-  //
-  if (Image->ImageContext.HiiResourceData != 0) {
+  if (Image->HiiData != NULL) {
     Status = CoreInstallProtocolInterface (
                &Image->Handle,
                &gEfiHiiPackageListProtocolGuid,
                EFI_NATIVE_INTERFACE,
-               (VOID *)(UINTN)Image->ImageContext.HiiResourceData
+               Image->HiiData
                );
     if (EFI_ERROR (Status)) {
       goto Done;
     }
   }
 
-  ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath);
+  Status = EFI_SUCCESS;
+  ProtectUefiImage (Image, &ImageContext);
+
+  RegisterMemoryProfileImage (
+    Image->LoadedImageDevicePath,
+    (UefiImageGetSubsystem (&ImageContext) == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ? EFI_FV_FILETYPE_APPLICATION : EFI_FV_FILETYPE_DRIVER),
+    &ImageContext
+    );
 
   //
   // Success.  Return the image handle
@@ -1623,6 +1561,8 @@ CoreStartImage (
     return Image->LoadImageStatus;
   }
 
+  DEBUG ((DEBUG_WARN, "Starting driver at %lu\n", Image->Info.ImageBase));
+
   //
   // The image to be started must have the machine type supported by DxeCore.
   //
@@ -1633,16 +1573,16 @@ CoreStartImage (
     // Do not ASSERT here, because image might be loaded via EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED
     // But it can not be started.
     //
-    DEBUG ((DEBUG_ERROR, "Image type %s can't be started ", GetMachineTypeName (Image->Machine)));
-    DEBUG ((DEBUG_ERROR, "on %s UEFI system.\n", GetMachineTypeName (mDxeCoreImageMachineType)));
+    DEBUG ((EFI_D_ERROR, "Image type %s can't be started ", GetMachineTypeName(Image->Machine)));
+    DEBUG ((EFI_D_ERROR, "on %s UEFI system.\n", mDxeCoreImageMachineTypeName));
     return EFI_UNSUPPORTED;
   }
 
   if (Image->PeCoffEmu != NULL) {
     Status = Image->PeCoffEmu->RegisterImage (
                                  Image->PeCoffEmu,
-                                 Image->ImageBasePage,
-                                 EFI_PAGES_TO_SIZE (Image->NumberOfPages),
+                                 (UINTN) Image->Info.ImageBase,
+                                 Image->Info.ImageSize,
                                  &Image->EntryPoint
                                  );
     if (EFI_ERROR (Status)) {
@@ -1696,7 +1636,6 @@ CoreStartImage (
   // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
   //
   if (SetJumpFlag == 0) {
-    RegisterMemoryProfileImage (Image, (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ? EFI_FV_FILETYPE_APPLICATION : EFI_FV_FILETYPE_DRIVER));
     //
     // Call the image's entry point
     //
diff --git a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c
index 4071053036..3baeef0dfc 100644
--- a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c
+++ b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c
@@ -1533,7 +1533,7 @@ PromoteGuardedFreePages (
   OUT EFI_PHYSICAL_ADDRESS  *EndAddress
   )
 {
-  EFI_STATUS            Status;
+  EFI_STATUS              Status;
   UINTN                 AvailablePages;
   UINT64                Bitmap;
   EFI_PHYSICAL_ADDRESS  Start;
diff --git a/MdeModulePkg/Core/Dxe/Mem/MemoryProfileRecord.c b/MdeModulePkg/Core/Dxe/Mem/MemoryProfileRecord.c
index 00e33b707d..b67596f48e 100644
--- a/MdeModulePkg/Core/Dxe/Mem/MemoryProfileRecord.c
+++ b/MdeModulePkg/Core/Dxe/Mem/MemoryProfileRecord.c
@@ -8,6 +8,10 @@
 
 #include "DxeMain.h"
 #include "Imem.h"
+#include "Library/UefiImageLib.h"
+#include "ProcessorBind.h"
+#include "Protocol/LoadedImage.h"
+#include "Uefi/UefiBaseType.h"
 
 #define IS_UEFI_MEMORY_PROFILE_ENABLED  ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0)
 
@@ -104,8 +108,7 @@ EFIAPI
 ProfileProtocolRegisterImage (
   IN EDKII_MEMORY_PROFILE_PROTOCOL  *This,
   IN EFI_DEVICE_PATH_PROTOCOL       *FilePath,
-  IN PHYSICAL_ADDRESS               ImageBase,
-  IN UINT64                         ImageSize,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT    *ImageContext,
   IN EFI_FV_FILETYPE                FileType
   );
 
@@ -247,110 +250,6 @@ GetMemoryProfileContext (
   return mMemoryProfileContextPtr;
 }
 
-/**
-  Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.
-  If Pe32Data is NULL, then ASSERT().
-
-  @param Pe32Data   The pointer to the PE/COFF image that is loaded in system memory.
-
-  @return The Subsystem of the PE/COFF image.
-
-**/
-UINT16
-InternalPeCoffGetSubsystem (
-  IN VOID  *Pe32Data
-  )
-{
-  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;
-  EFI_IMAGE_DOS_HEADER                 *DosHdr;
-  UINT16                               Magic;
-
-  ASSERT (Pe32Data != NULL);
-
-  DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
-  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
-    //
-    // DOS image header is present, so read the PE header after the DOS image header.
-    //
-    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));
-  } else {
-    //
-    // DOS image header is not present, so PE header is at the image base.
-    //
-    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
-  }
-
-  if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
-    return Hdr.Te->Subsystem;
-  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
-    Magic = Hdr.Pe32->OptionalHeader.Magic;
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-      return Hdr.Pe32->OptionalHeader.Subsystem;
-    } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
-      return Hdr.Pe32Plus->OptionalHeader.Subsystem;
-    }
-  }
-
-  return 0x0000;
-}
-
-/**
-  Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
-  into system memory with the PE/COFF Loader Library functions.
-
-  Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
-  point in EntryPoint.  If the entry point could not be retrieved from the PE/COFF image, then
-  return RETURN_INVALID_PARAMETER.  Otherwise return RETURN_SUCCESS.
-  If Pe32Data is NULL, then ASSERT().
-  If EntryPoint is NULL, then ASSERT().
-
-  @param  Pe32Data                  The pointer to the PE/COFF image that is loaded in system memory.
-  @param  EntryPoint                The pointer to entry point to the PE/COFF image to return.
-
-  @retval RETURN_SUCCESS            EntryPoint was returned.
-  @retval RETURN_INVALID_PARAMETER  The entry point could not be found in the PE/COFF image.
-
-**/
-RETURN_STATUS
-InternalPeCoffGetEntryPoint (
-  IN  VOID  *Pe32Data,
-  OUT VOID  **EntryPoint
-  )
-{
-  EFI_IMAGE_DOS_HEADER                 *DosHdr;
-  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;
-
-  ASSERT (Pe32Data   != NULL);
-  ASSERT (EntryPoint != NULL);
-
-  DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
-  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
-    //
-    // DOS image header is present, so read the PE header after the DOS image header.
-    //
-    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));
-  } else {
-    //
-    // DOS image header is not present, so PE header is at the image base.
-    //
-    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
-  }
-
-  //
-  // Calculate the entry point relative to the start of the image.
-  // AddressOfEntryPoint is common for PE32 & PE32+
-  //
-  if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
-    *EntryPoint = (VOID *)((UINTN)Pe32Data + (UINTN)(Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);
-    return RETURN_SUCCESS;
-  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
-    *EntryPoint = (VOID *)((UINTN)Pe32Data + (UINTN)(Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));
-    return RETURN_SUCCESS;
-  }
-
-  return RETURN_UNSUPPORTED;
-}
-
 /**
   Build driver info.
 
@@ -367,32 +266,27 @@ InternalPeCoffGetEntryPoint (
 **/
 MEMORY_PROFILE_DRIVER_INFO_DATA *
 BuildDriverInfo (
-  IN MEMORY_PROFILE_CONTEXT_DATA  *ContextData,
-  IN EFI_GUID                     *FileName,
-  IN PHYSICAL_ADDRESS             ImageBase,
-  IN UINT64                       ImageSize,
-  IN PHYSICAL_ADDRESS             EntryPoint,
-  IN UINT16                       ImageSubsystem,
-  IN EFI_FV_FILETYPE              FileType
+  IN MEMORY_PROFILE_CONTEXT_DATA      *ContextData,
+  IN EFI_GUID                         *FileName,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext,
+  IN EFI_FV_FILETYPE                  FileType
   )
 {
+  RETURN_STATUS                     PdbStatus;
   EFI_STATUS                       Status;
   MEMORY_PROFILE_DRIVER_INFO       *DriverInfo;
   MEMORY_PROFILE_DRIVER_INFO_DATA  *DriverInfoData;
-  VOID                             *EntryPointInImage;
-  CHAR8                            *PdbString;
-  UINTN                            PdbSize;
+  CONST CHAR8                       *PdbString;
+  UINT32                            PdbSize;
   UINTN                            PdbOccupiedSize;
 
-  PdbSize         = 0;
   PdbOccupiedSize = 0;
-  PdbString       = NULL;
-  if (ImageBase != 0) {
-    PdbString = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageBase);
-    if (PdbString != NULL) {
-      PdbSize         = AsciiStrSize (PdbString);
-      PdbOccupiedSize = GET_OCCUPIED_SIZE (PdbSize, sizeof (UINT64));
-    }
+
+  ASSERT (UefiImageLoaderGetImageAddress (ImageContext) != 0);
+
+  PdbStatus = UefiImageGetSymbolsPath (ImageContext, &PdbString, &PdbSize);
+  if (!EFI_ERROR (PdbStatus)) {
+    PdbOccupiedSize = GET_OCCUPIED_SIZE (PdbSize, sizeof (UINT64));
   }
 
   //
@@ -420,19 +314,10 @@ BuildDriverInfo (
     CopyMem (&DriverInfo->FileName, FileName, sizeof (EFI_GUID));
   }
 
-  DriverInfo->ImageBase      = ImageBase;
-  DriverInfo->ImageSize      = ImageSize;
-  DriverInfo->EntryPoint     = EntryPoint;
-  DriverInfo->ImageSubsystem = ImageSubsystem;
-  if ((EntryPoint != 0) && ((EntryPoint < ImageBase) || (EntryPoint >= (ImageBase + ImageSize)))) {
-    //
-    // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
-    // So patch ImageBuffer here to align the EntryPoint.
-    //
-    Status = InternalPeCoffGetEntryPoint ((VOID *)(UINTN)ImageBase, &EntryPointInImage);
-    ASSERT_EFI_ERROR (Status);
-    DriverInfo->ImageBase = ImageBase + EntryPoint - (PHYSICAL_ADDRESS)(UINTN)EntryPointInImage;
-  }
+  DriverInfo->ImageBase      = UefiImageLoaderGetImageAddress (ImageContext);
+  DriverInfo->ImageSize      = UefiImageGetImageSize (ImageContext);
+  DriverInfo->EntryPoint     = UefiImageLoaderGetImageEntryPoint (ImageContext);
+  DriverInfo->ImageSubsystem = UefiImageGetSubsystem (ImageContext);
 
   DriverInfo->FileType          = FileType;
   DriverInfoData->AllocInfoList = (LIST_ENTRY *)(DriverInfoData + 1);
@@ -440,7 +325,7 @@ BuildDriverInfo (
   DriverInfo->CurrentUsage     = 0;
   DriverInfo->PeakUsage        = 0;
   DriverInfo->AllocRecordCount = 0;
-  if (PdbSize != 0) {
+  if (!RETURN_ERROR (PdbStatus)) {
     DriverInfo->PdbStringOffset = (UINT16)sizeof (MEMORY_PROFILE_DRIVER_INFO);
     DriverInfoData->PdbString   = (CHAR8 *)(DriverInfoData->AllocInfoList + 1);
     CopyMem (DriverInfoData->PdbString, PdbString, PdbSize);
@@ -528,13 +413,13 @@ NeedRecordThisDriver (
 **/
 BOOLEAN
 RegisterDxeCore (
-  IN VOID                         *HobStart,
-  IN MEMORY_PROFILE_CONTEXT_DATA  *ContextData
+  IN VOID                             *HobStart,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext,
+  IN MEMORY_PROFILE_CONTEXT_DATA      *ContextData
   )
 {
   EFI_PEI_HOB_POINTERS               DxeCoreHob;
   MEMORY_PROFILE_DRIVER_INFO_DATA    *DriverInfoData;
-  PHYSICAL_ADDRESS                   ImageBase;
   UINT8                              TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  *FilePath;
 
@@ -565,14 +450,10 @@ RegisterDxeCore (
     return FALSE;
   }
 
-  ImageBase      = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;
   DriverInfoData = BuildDriverInfo (
                      ContextData,
                      &DxeCoreHob.MemoryAllocationModule->ModuleName,
-                     ImageBase,
-                     DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength,
-                     DxeCoreHob.MemoryAllocationModule->EntryPoint,
-                     InternalPeCoffGetSubsystem ((VOID *)(UINTN)ImageBase),
+                     ImageContext,
                      EFI_FV_FILETYPE_DXE_CORE
                      );
   if (DriverInfoData == NULL) {
@@ -590,7 +471,8 @@ RegisterDxeCore (
 **/
 VOID
 MemoryProfileInit (
-  IN VOID  *HobStart
+  IN VOID                            *HobStart,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *ImageContext
   )
 {
   MEMORY_PROFILE_CONTEXT_DATA  *ContextData;
@@ -615,7 +497,7 @@ MemoryProfileInit (
   mMemoryProfileDriverPath     = AllocateCopyPool (mMemoryProfileDriverPathSize, PcdGetPtr (PcdMemoryProfileDriverPath));
   mMemoryProfileContextPtr     = &mMemoryProfileContext;
 
-  RegisterDxeCore (HobStart, &mMemoryProfileContext);
+  RegisterDxeCore (HobStart, ImageContext, &mMemoryProfileContext);
 
   DEBUG ((DEBUG_INFO, "MemoryProfileInit MemoryProfileContext - 0x%x\n", &mMemoryProfileContext));
 }
@@ -692,8 +574,9 @@ GetFileNameFromFilePath (
 **/
 EFI_STATUS
 RegisterMemoryProfileImage (
-  IN LOADED_IMAGE_PRIVATE_DATA  *DriverEntry,
-  IN EFI_FV_FILETYPE            FileType
+  IN EFI_DEVICE_PATH_PROTOCOL         *FilePath,
+  IN EFI_FV_FILETYPE                  FileType,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
   )
 {
   MEMORY_PROFILE_CONTEXT_DATA      *ContextData;
@@ -703,7 +586,7 @@ RegisterMemoryProfileImage (
     return EFI_UNSUPPORTED;
   }
 
-  if (!NeedRecordThisDriver (DriverEntry->Info.FilePath)) {
+  if (!NeedRecordThisDriver (FilePath)) {
     return EFI_UNSUPPORTED;
   }
 
@@ -714,11 +597,8 @@ RegisterMemoryProfileImage (
 
   DriverInfoData = BuildDriverInfo (
                      ContextData,
-                     GetFileNameFromFilePath (DriverEntry->Info.FilePath),
-                     DriverEntry->ImageContext.ImageAddress,
-                     DriverEntry->ImageContext.ImageSize,
-                     DriverEntry->ImageContext.EntryPoint,
-                     DriverEntry->ImageContext.ImageType,
+                     GetFileNameFromFilePath (FilePath),
+                     ImageContext,
                      FileType
                      );
   if (DriverInfoData == NULL) {
@@ -831,21 +711,21 @@ GetMemoryProfileDriverInfoFromAddress (
 **/
 EFI_STATUS
 UnregisterMemoryProfileImage (
-  IN LOADED_IMAGE_PRIVATE_DATA  *DriverEntry
+  EFI_DEVICE_PATH_PROTOCOL  *FilePath,
+  IN EFI_PHYSICAL_ADDRESS  ImageAddress
   )
 {
-  EFI_STATUS                       Status;
+  //EFI_STATUS                        Status;
   MEMORY_PROFILE_CONTEXT_DATA      *ContextData;
   MEMORY_PROFILE_DRIVER_INFO_DATA  *DriverInfoData;
   EFI_GUID                         *FileName;
-  PHYSICAL_ADDRESS                 ImageAddress;
-  VOID                             *EntryPointInImage;
+  //VOID                              *EntryPointInImage;
 
   if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
     return EFI_UNSUPPORTED;
   }
 
-  if (!NeedRecordThisDriver (DriverEntry->Info.FilePath)) {
+  if (!NeedRecordThisDriver (FilePath)) {
     return EFI_UNSUPPORTED;
   }
 
@@ -855,17 +735,7 @@ UnregisterMemoryProfileImage (
   }
 
   DriverInfoData = NULL;
-  FileName       = GetFileNameFromFilePath (DriverEntry->Info.FilePath);
-  ImageAddress   = DriverEntry->ImageContext.ImageAddress;
-  if ((DriverEntry->ImageContext.EntryPoint < ImageAddress) || (DriverEntry->ImageContext.EntryPoint >= (ImageAddress + DriverEntry->ImageContext.ImageSize))) {
-    //
-    // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
-    // So patch ImageAddress here to align the EntryPoint.
-    //
-    Status = InternalPeCoffGetEntryPoint ((VOID *)(UINTN)ImageAddress, &EntryPointInImage);
-    ASSERT_EFI_ERROR (Status);
-    ImageAddress = ImageAddress + (UINTN)DriverEntry->ImageContext.EntryPoint - (UINTN)EntryPointInImage;
-  }
+  FileName = GetFileNameFromFilePath (FilePath);
 
   if (FileName != NULL) {
     DriverInfoData = GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData, FileName, ImageAddress);
@@ -1629,27 +1499,13 @@ ProfileProtocolGetData (
 EFI_STATUS
 EFIAPI
 ProfileProtocolRegisterImage (
-  IN EDKII_MEMORY_PROFILE_PROTOCOL  *This,
-  IN EFI_DEVICE_PATH_PROTOCOL       *FilePath,
-  IN PHYSICAL_ADDRESS               ImageBase,
-  IN UINT64                         ImageSize,
-  IN EFI_FV_FILETYPE                FileType
+  IN EDKII_MEMORY_PROFILE_PROTOCOL      *This,
+  IN EFI_DEVICE_PATH_PROTOCOL           *FilePath,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT    *ImageContext,
+  IN EFI_FV_FILETYPE                    FileType
   )
 {
-  EFI_STATUS                 Status;
-  LOADED_IMAGE_PRIVATE_DATA  DriverEntry;
-  VOID                       *EntryPointInImage;
-
-  ZeroMem (&DriverEntry, sizeof (DriverEntry));
-  DriverEntry.Info.FilePath             = FilePath;
-  DriverEntry.ImageContext.ImageAddress = ImageBase;
-  DriverEntry.ImageContext.ImageSize    = ImageSize;
-  Status                                = InternalPeCoffGetEntryPoint ((VOID *)(UINTN)ImageBase, &EntryPointInImage);
-  ASSERT_EFI_ERROR (Status);
-  DriverEntry.ImageContext.EntryPoint = (PHYSICAL_ADDRESS)(UINTN)EntryPointInImage;
-  DriverEntry.ImageContext.ImageType  = InternalPeCoffGetSubsystem ((VOID *)(UINTN)ImageBase);
-
-  return RegisterMemoryProfileImage (&DriverEntry, FileType);
+  return RegisterMemoryProfileImage (FilePath, FileType, ImageContext);
 }
 
 /**
@@ -1675,19 +1531,7 @@ ProfileProtocolUnregisterImage (
   IN UINT64                         ImageSize
   )
 {
-  EFI_STATUS                 Status;
-  LOADED_IMAGE_PRIVATE_DATA  DriverEntry;
-  VOID                       *EntryPointInImage;
-
-  ZeroMem (&DriverEntry, sizeof (DriverEntry));
-  DriverEntry.Info.FilePath             = FilePath;
-  DriverEntry.ImageContext.ImageAddress = ImageBase;
-  DriverEntry.ImageContext.ImageSize    = ImageSize;
-  Status                                = InternalPeCoffGetEntryPoint ((VOID *)(UINTN)ImageBase, &EntryPointInImage);
-  ASSERT_EFI_ERROR (Status);
-  DriverEntry.ImageContext.EntryPoint = (PHYSICAL_ADDRESS)(UINTN)EntryPointInImage;
-
-  return UnregisterMemoryProfileImage (&DriverEntry);
+  return UnregisterMemoryProfileImage (FilePath, ImageBase);
 }
 
 /**
diff --git a/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c b/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c
index eeb18f6e47..d6e732e021 100644
--- a/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c
+++ b/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c
@@ -160,15 +160,20 @@ CoreUpdateDebugTableCrc32 (
 **/
 VOID
 CoreNewDebugImageInfoEntry (
-  IN  UINT32                     ImageInfoType,
-  IN  EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage,
-  IN  EFI_HANDLE                 ImageHandle
+  IN     UINT32                           ImageInfoType,
+  IN     EFI_LOADED_IMAGE_PROTOCOL        *LoadedImage,
+  IN     EFI_HANDLE                       ImageHandle,
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
   )
 {
-  EFI_DEBUG_IMAGE_INFO  *Table;
-  EFI_DEBUG_IMAGE_INFO  *NewTable;
-  UINTN                 Index;
-  UINTN                 TableSize;
+  EFI_DEBUG_IMAGE_INFO        *Table;
+  EFI_DEBUG_IMAGE_INFO        *NewTable;
+  UINTN                       Index;
+  UINTN                       TableSize;
+  EFI_DEBUG_IMAGE_INFO_NORMAL *NormalImage;
+  RETURN_STATUS               Status;
+  CONST CHAR8                 *PdbPath;
+  UINT32                      PdbPathSize;
 
   //
   // Set the flag indicating that we're in the process of updating the table.
@@ -205,6 +210,15 @@ CoreNewDebugImageInfoEntry (
     // Copy the old table into the new one
     //
     CopyMem (NewTable, Table, TableSize);
+    mDebugInfoTableHeader.EfiDebugImageInfoTable = NewTable;
+    //
+    // Set the first empty entry index to be the original max table entries.
+    //
+    Index = mMaxTableEntries;
+    //
+    // Enlarge the max table entries.
+    //
+    mMaxTableEntries += EFI_PAGE_SIZE / EFI_DEBUG_TABLE_ENTRY_SIZE;
     //
     // Free the old table
     //
@@ -212,32 +226,31 @@ CoreNewDebugImageInfoEntry (
     //
     // Update the table header
     //
-    Table                                        = NewTable;
-    mDebugInfoTableHeader.EfiDebugImageInfoTable = NewTable;
-    //
-    // Enlarge the max table entries and set the first empty entry index to
-    // be the original max table entries.
-    //
-    Index             = mMaxTableEntries;
-    mMaxTableEntries += EFI_PAGE_SIZE / EFI_DEBUG_TABLE_ENTRY_SIZE;
+    Table = NewTable;
   }
 
   //
   // Allocate data for new entry
   //
-  Table[Index].NormalImage = AllocateZeroPool (sizeof (EFI_DEBUG_IMAGE_INFO_NORMAL));
-  if (Table[Index].NormalImage != NULL) {
+  NormalImage = AllocateZeroPool (sizeof (EFI_DEBUG_IMAGE_INFO_NORMAL));
+  if (NormalImage != NULL) {
     //
     // Update the entry
     //
-    Table[Index].NormalImage->ImageInfoType               = (UINT32)ImageInfoType;
-    Table[Index].NormalImage->LoadedImageProtocolInstance = LoadedImage;
-    Table[Index].NormalImage->ImageHandle                 = ImageHandle;
+    NormalImage->ImageInfoType               = (UINT32)ImageInfoType;
+    NormalImage->LoadedImageProtocolInstance = LoadedImage;
+    NormalImage->ImageHandle                 = ImageHandle;
+
+    Status = UefiImageGetSymbolsPath (ImageContext, &PdbPath, &PdbPathSize);
+    if (!RETURN_ERROR (Status)) {
+      NormalImage->PdbPath = AllocateCopyPool (PdbPathSize, PdbPath);
+    }
     //
     // Increase the number of EFI_DEBUG_IMAGE_INFO elements and set the mDebugInfoTable in modified status.
     //
-    mDebugInfoTableHeader.TableSize++;
     mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED;
+    Table[Index].NormalImage = NormalImage;
+    mDebugInfoTableHeader.TableSize++;
   }
 
   mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
@@ -254,8 +267,9 @@ CoreRemoveDebugImageInfoEntry (
   EFI_HANDLE  ImageHandle
   )
 {
-  EFI_DEBUG_IMAGE_INFO  *Table;
-  UINTN                 Index;
+  EFI_DEBUG_IMAGE_INFO        *Table;
+  UINTN                       Index;
+  EFI_DEBUG_IMAGE_INFO_NORMAL *NormalImage;
 
   mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
 
@@ -267,13 +281,19 @@ CoreRemoveDebugImageInfoEntry (
       // Found a match. Free up the record, then NULL the pointer to indicate the slot
       // is free.
       //
-      CoreFreePool (Table[Index].NormalImage);
-      Table[Index].NormalImage = NULL;
+      NormalImage = Table[Index].NormalImage;
       //
       // Decrease the number of EFI_DEBUG_IMAGE_INFO elements and set the mDebugInfoTable in modified status.
       //
-      mDebugInfoTableHeader.TableSize--;
       mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED;
+      mDebugInfoTableHeader.TableSize--;
+      Table[Index].NormalImage = NULL;
+
+      if (NormalImage->PdbPath != NULL) {
+        FreePool (NormalImage->PdbPath);
+      }
+
+      CoreFreePool (NormalImage);
       break;
     }
   }
diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
index a11c455ab5..670297a339 100644
--- a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
+++ b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
@@ -22,6 +22,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 
 #include "DxeMain.h"
 #include "HeapGuard.h"
+#include "IndustryStandard/PeImage2.h"
+#include "ProcessorBind.h"
 
 /**
   This function for GetMemoryMap() with properties table capability.
@@ -73,7 +75,7 @@ CoreGetMemoryMapWithSeparatedImageSection (
 typedef struct {
   UINT32        Signature;
   UINTN         ImageRecordCount;
-  UINTN         CodeSegmentCountMax;
+  UINTN         SectionCountMax;
   LIST_ENTRY    ImageRecordList;
 } IMAGE_PROPERTIES_PRIVATE_DATA;
 
@@ -201,7 +203,7 @@ InstallMemoryAttributesTable (
       case EfiRuntimeServicesCode:
       case EfiRuntimeServicesData:
         CopyMem (MemoryAttributesEntry, MemoryMap, DescriptorSize);
-        MemoryAttributesEntry->Attribute &= (EFI_MEMORY_RO|EFI_MEMORY_XP|EFI_MEMORY_RUNTIME);
+        MemoryAttributesEntry->Attribute &= EFI_MEMORY_ACCESS_MASK | EFI_MEMORY_RUNTIME;
         DEBUG ((DEBUG_VERBOSE, "Entry (0x%x)\n", MemoryAttributesEntry));
         DEBUG ((DEBUG_VERBOSE, "  Type              - 0x%x\n", MemoryAttributesEntry->Type));
         DEBUG ((DEBUG_VERBOSE, "  PhysicalStart     - 0x%016lx\n", MemoryAttributesEntry->PhysicalStart));
@@ -284,15 +286,6 @@ InstallMemoryAttributesTableOnEndOfDxe (
 {
   mMemoryAttributesTableEndOfDxe = TRUE;
   InstallMemoryAttributesTable ();
-
-  DEBUG_CODE_BEGIN ();
-  if ( mImagePropertiesPrivateData.ImageRecordCount > 0) {
-    DEBUG ((DEBUG_INFO, "DXE - Total Runtime Image Count: 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
-    DEBUG ((DEBUG_INFO, "DXE - Dump Runtime Image Records:\n"));
-    DumpImageRecords (&mImagePropertiesPrivateData.ImageRecordList);
-  }
-
-  DEBUG_CODE_END ();
 }
 
 /**
@@ -534,7 +527,11 @@ CoreGetMemoryMapWithSeparatedImageSection (
 
   CoreAcquiremMemoryAttributesTableLock ();
 
-  AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 3) * mImagePropertiesPrivateData.ImageRecordCount;
+  //
+  // Per image, there may be one additional trailer. There may be prefixed data
+  // (counted as the original entry).
+  //
+  AdditionalRecordCount = (mImagePropertiesPrivateData.SectionCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount;
 
   OldMemoryMapSize = *MemoryMapSize;
   Status           = CoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
@@ -574,6 +571,68 @@ CoreGetMemoryMapWithSeparatedImageSection (
 // Below functions are for ImageRecord
 //
 
+/**
+  Set MemoryAttributesTable according to PE/COFF image section alignment.
+
+  @param  SectionAlignment    PE/COFF section alignment
+**/
+STATIC
+VOID
+SetMemoryAttributesTableSectionAlignment (
+  IN UINT32  SectionAlignment
+  )
+{
+  if (((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) &&
+      mMemoryAttributesTableEnable)
+  {
+    DEBUG ((DEBUG_VERBOSE, "SetMemoryAttributesTableSectionAlignment - Clear\n"));
+    mMemoryAttributesTableEnable = FALSE;
+  }
+}
+
+/**
+  Sort image record based upon the ImageBase from low to high.
+**/
+STATIC
+VOID
+InsertSortImageRecord (
+  IN UEFI_IMAGE_RECORD  *NewImageRecord
+  )
+{
+  UEFI_IMAGE_RECORD  *ImageRecord;
+  LIST_ENTRY         *PrevImageRecordLink;
+  LIST_ENTRY         *ImageRecordLink;
+  LIST_ENTRY         *ImageRecordList;
+
+  ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
+
+  PrevImageRecordLink = ImageRecordList;
+  for (
+    ImageRecordLink = GetFirstNode (ImageRecordList);
+    !IsNull (ImageRecordLink, ImageRecordList);
+    ImageRecordLink = GetNextNode (ImageRecordList, PrevImageRecordLink)
+    ) {
+    ImageRecord = CR (
+                    ImageRecordLink,
+                    UEFI_IMAGE_RECORD,
+                    Link,
+                    UEFI_IMAGE_RECORD_SIGNATURE
+                    );
+    if (NewImageRecord->StartAddress < ImageRecord->StartAddress) {
+      break;
+    }
+
+    PrevImageRecordLink = ImageRecordLink;
+  }
+
+  InsertHeadList (PrevImageRecordLink, &NewImageRecord->Link);
+  mImagePropertiesPrivateData.ImageRecordCount++;
+
+  if (mImagePropertiesPrivateData.SectionCountMax < NewImageRecord->NumSegments) {
+    mImagePropertiesPrivateData.SectionCountMax = NewImageRecord->NumSegments;
+  }
+}
+
 /**
   Insert image record.
 
@@ -581,13 +640,18 @@ CoreGetMemoryMapWithSeparatedImageSection (
 **/
 VOID
 InsertImageRecord (
-  IN EFI_RUNTIME_IMAGE_ENTRY  *RuntimeImage
+  IN     LOADED_IMAGE_PRIVATE_DATA        *Image,
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
   )
 {
-  EFI_STATUS               Status;
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  CHAR8                    *PdbPointer;
-  UINT32                   RequiredAlignment;
+  RETURN_STATUS            PdbStatus;
+  EFI_RUNTIME_IMAGE_ENTRY  *RuntimeImage;
+  UINT32                   SectionAlignment;
+  UEFI_IMAGE_RECORD        *ImageRecord;
+  CONST CHAR8              *PdbPointer;
+  UINT32                   PdbSize;
+
+  RuntimeImage = Image->RuntimeData;
 
   DEBUG ((DEBUG_VERBOSE, "InsertImageRecord - 0x%x\n", RuntimeImage));
 
@@ -596,71 +660,85 @@ InsertImageRecord (
     return;
   }
 
-  ImageRecord = AllocatePool (sizeof (*ImageRecord));
-  if (ImageRecord == NULL) {
-    return;
-  }
+  DEBUG ((DEBUG_VERBOSE, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
 
-  InitializeListHead (&ImageRecord->Link);
-  InitializeListHead (&ImageRecord->CodeSegmentList);
-
-  PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)RuntimeImage->ImageBase);
-  if (PdbPointer != NULL) {
+  PdbStatus = UefiImageGetSymbolsPath (ImageContext, &PdbPointer, &PdbSize);
+  if (!EFI_ERROR (PdbStatus)) {
     DEBUG ((DEBUG_VERBOSE, "  Image - %a\n", PdbPointer));
   }
 
-  RequiredAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
-  Status            = CreateImagePropertiesRecord (
-                        RuntimeImage->ImageBase,
-                        RuntimeImage->ImageSize,
-                        &RequiredAlignment,
-                        ImageRecord
-                        );
+  //
+  // Get SectionAlignment
+  //
+  SectionAlignment  = UefiImageGetSegmentAlignment (ImageContext);
 
-  if (EFI_ERROR (Status)) {
-    if (Status == EFI_ABORTED) {
-      mMemoryAttributesTableEnable = FALSE;
+  SetMemoryAttributesTableSectionAlignment (SectionAlignment);
+  if ((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {
+    DEBUG ((
+      DEBUG_WARN,
+      "!!!!!!!!  InsertImageRecord - Section Alignment(0x%x) is not %dK  !!!!!!!!\n",
+      SectionAlignment, RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10));
+    if (!EFI_ERROR (PdbStatus)) {
+      DEBUG ((DEBUG_WARN, "!!!!!!!!  Image - %a  !!!!!!!!\n", PdbPointer));
     }
 
-    Status = EFI_ABORTED;
-    goto Finish;
+    return;
   }
 
-  if (ImageRecord->CodeSegmentCount == 0) {
-    mMemoryAttributesTableEnable = FALSE;
-    DEBUG ((DEBUG_ERROR, "!!!!!!!!  InsertImageRecord - CodeSegmentCount is 0  !!!!!!!!\n"));
-    if (PdbPointer != NULL) {
-      DEBUG ((DEBUG_ERROR, "!!!!!!!!  Image - %a  !!!!!!!!\n", PdbPointer));
+  ImageRecord = UefiImageLoaderGetImageRecord (ImageContext);
+  if (ImageRecord == NULL) {
+    return ;
+  }
+
+  UefiImageDebugPrintSegments (ImageContext);
+  UefiImageDebugPrintImageRecord (ImageRecord);
+
+  //
+  // Section order is guaranteed by the PE specification.
+  // Section validity (e.g. no overlap) is guaranteed by the PE specification.
+  //
+
+  InsertSortImageRecord (ImageRecord);
+}
+
+/**
+  Find image record according to image base and size.
+
+  @param  ImageBase    Base of PE image
+  @param  ImageSize    Size of PE image
+
+  @return image record
+**/
+STATIC
+UEFI_IMAGE_RECORD *
+FindImageRecord (
+  IN EFI_PHYSICAL_ADDRESS  ImageBase
+  )
+{
+  UEFI_IMAGE_RECORD  *ImageRecord;
+  LIST_ENTRY         *ImageRecordLink;
+  LIST_ENTRY         *ImageRecordList;
+
+  ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
+
+  for (ImageRecordLink = ImageRecordList->ForwardLink;
+       ImageRecordLink != ImageRecordList;
+       ImageRecordLink = ImageRecordLink->ForwardLink)
+  {
+    ImageRecord = CR (
+                    ImageRecordLink,
+                    UEFI_IMAGE_RECORD,
+                    Link,
+                    UEFI_IMAGE_RECORD_SIGNATURE
+                    );
+
+    if (ImageBase == ImageRecord->StartAddress)
+    {
+      return ImageRecord;
     }
-
-    Status = EFI_ABORTED;
-    goto Finish;
   }
 
-  //
-  // Check overlap all section in ImageBase/Size
-  //
-  if (!IsImageRecordCodeSectionValid (ImageRecord)) {
-    DEBUG ((DEBUG_ERROR, "IsImageRecordCodeSectionValid - FAIL\n"));
-    Status = EFI_ABORTED;
-    goto Finish;
-  }
-
-  InsertTailList (&mImagePropertiesPrivateData.ImageRecordList, &ImageRecord->Link);
-  mImagePropertiesPrivateData.ImageRecordCount++;
-
-  if (mImagePropertiesPrivateData.CodeSegmentCountMax < ImageRecord->CodeSegmentCount) {
-    mImagePropertiesPrivateData.CodeSegmentCountMax = ImageRecord->CodeSegmentCount;
-  }
-
-  SortImageRecord (&mImagePropertiesPrivateData.ImageRecordList);
-
-Finish:
-  if (EFI_ERROR (Status) && (ImageRecord != NULL)) {
-    DeleteImagePropertiesRecord (ImageRecord);
-  }
-
-  return;
+  return NULL;
 }
 
 /**
@@ -673,7 +751,7 @@ RemoveImageRecord (
   IN EFI_RUNTIME_IMAGE_ENTRY  *RuntimeImage
   )
 {
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
+  UEFI_IMAGE_RECORD  *ImageRecord;
 
   DEBUG ((DEBUG_VERBOSE, "RemoveImageRecord - 0x%x\n", RuntimeImage));
   DEBUG ((DEBUG_VERBOSE, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize));
@@ -683,7 +761,7 @@ RemoveImageRecord (
     return;
   }
 
-  ImageRecord = FindImageRecord ((EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize, &mImagePropertiesPrivateData.ImageRecordList);
+  ImageRecord = FindImageRecord ((EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase);
   if (ImageRecord == NULL) {
     DEBUG ((DEBUG_ERROR, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));
     return;
diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
index 2c069cc12c..2d568b2463 100644
--- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
+++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
@@ -40,8 +40,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Protocol/FirmwareVolume2.h>
 #include <Protocol/SimpleFileSystem.h>
 
+#include "Base.h"
 #include "DxeMain.h"
+#include "Library/UefiImageLib.h"
 #include "Mem/HeapGuard.h"
+#include "ProcessorBind.h"
+#include "Uefi/UefiMultiPhase.h"
 
 //
 // Image type definitions
@@ -213,113 +217,73 @@ SetUefiImageMemoryAttributes (
 **/
 VOID
 SetUefiImageProtectionAttributes (
-  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
+  IN UEFI_IMAGE_RECORD  *ImageRecord
   )
 {
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
-  LIST_ENTRY                            *ImageRecordCodeSectionLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionList;
-  UINT64                                CurrentBase;
-  UINT64                                ImageEnd;
+  UEFI_IMAGE_RECORD_SEGMENT  *ImageRecordSegment;
+  UINTN                      SectionAddress;
+  UINT32                     Index;
 
-  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
-
-  CurrentBase = ImageRecord->ImageBase;
-  ImageEnd    = ImageRecord->ImageBase + ImageRecord->ImageSize;
-
-  ImageRecordCodeSectionLink    = ImageRecordCodeSectionList->ForwardLink;
-  ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
-  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
-    ImageRecordCodeSection = CR (
-                               ImageRecordCodeSectionLink,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
-                               Link,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
-                               );
-    ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
-
-    ASSERT (CurrentBase <= ImageRecordCodeSection->CodeSegmentBase);
-    if (CurrentBase < ImageRecordCodeSection->CodeSegmentBase) {
-      //
-      // DATA
-      //
-      SetUefiImageMemoryAttributes (
-        CurrentBase,
-        ImageRecordCodeSection->CodeSegmentBase - CurrentBase,
-        EFI_MEMORY_XP
-        );
-    }
-
-    //
-    // CODE
-    //
+  SectionAddress = ImageRecord->StartAddress;
+  for (Index = 0; Index < ImageRecord->NumSegments; Index++) {
+    ImageRecordSegment = &ImageRecord->Segments[Index];
     SetUefiImageMemoryAttributes (
-      ImageRecordCodeSection->CodeSegmentBase,
-      ImageRecordCodeSection->CodeSegmentSize,
-      EFI_MEMORY_RO
+      SectionAddress,
+      ImageRecordSegment->Size,
+      ImageRecordSegment->Attributes
       );
-    CurrentBase = ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize;
-  }
 
-  //
-  // Last DATA
-  //
-  ASSERT (CurrentBase <= ImageEnd);
-  if (CurrentBase < ImageEnd) {
-    //
-    // DATA
-    //
-    SetUefiImageMemoryAttributes (
-      CurrentBase,
-      ImageEnd - CurrentBase,
-      EFI_MEMORY_XP
-      );
+    SectionAddress += ImageRecordSegment->Size;
   }
-
-  return;
 }
 
 /**
-  Return the section alignment requirement for the PE image section type.
+  Return if the PE image section is aligned.
 
-  @param[in]  MemoryType  PE/COFF image memory type
-
-  @retval     The required section alignment for this memory type
+  @param[in]  SectionAlignment    PE/COFF section alignment
+  @param[in]  MemoryType          PE/COFF image memory type
 
+  @retval TRUE  The PE image section is aligned.
+  @retval FALSE The PE image section is not aligned.
 **/
 STATIC
-UINT32
-GetMemoryProtectionSectionAlignment (
+BOOLEAN
+IsMemoryProtectionSectionAligned (
+  IN UINT32           SectionAlignment,
   IN EFI_MEMORY_TYPE  MemoryType
   )
 {
-  UINT32  SectionAlignment;
+  UINT32  PageAlignment;
 
   switch (MemoryType) {
     case EfiRuntimeServicesCode:
     case EfiACPIMemoryNVS:
     case EfiReservedMemoryType:
-      SectionAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
+      PageAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
       break;
     case EfiRuntimeServicesData:
       ASSERT (FALSE);
-      SectionAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
+      PageAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
       break;
     case EfiBootServicesCode:
     case EfiLoaderCode:
-      SectionAlignment = EFI_PAGE_SIZE;
+      PageAlignment = EFI_PAGE_SIZE;
       break;
     case EfiACPIReclaimMemory:
     default:
       ASSERT (FALSE);
-      SectionAlignment = EFI_PAGE_SIZE;
+      PageAlignment = EFI_PAGE_SIZE;
       break;
   }
 
-  return SectionAlignment;
+  if ((SectionAlignment & (PageAlignment - 1)) != 0) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
 }
 
+// FIXME: Deduplicate
 /**
   Protect UEFI PE/COFF image.
 
@@ -328,22 +292,26 @@ GetMemoryProtectionSectionAlignment (
 **/
 VOID
 ProtectUefiImage (
-  IN EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage,
-  IN EFI_DEVICE_PATH_PROTOCOL   *LoadedImageDevicePath
+  IN LOADED_IMAGE_PRIVATE_DATA     *Image,
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
   )
 {
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  UINT32                   ProtectionPolicy;
-  EFI_STATUS               Status;
-  UINT32                   RequiredAlignment;
+  RETURN_STATUS              PdbStatus;
+  EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage;
+  EFI_DEVICE_PATH_PROTOCOL   *LoadedImageDevicePath;
+  UINT32                     SectionAlignment;
+  UEFI_IMAGE_RECORD          *ImageRecord;
+  CONST CHAR8                *PdbPointer;
+  UINT32                     PdbSize;
+  BOOLEAN                    IsAligned;
+  UINT32                     ProtectionPolicy;
+
+  LoadedImage = &Image->Info;
+  LoadedImageDevicePath = Image->LoadedImageDevicePath;
 
   DEBUG ((DEBUG_INFO, "ProtectUefiImageCommon - 0x%x\n", LoadedImage));
   DEBUG ((DEBUG_INFO, "  - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImage->ImageBase, LoadedImage->ImageSize));
 
-  if (gCpu == NULL) {
-    return;
-  }
-
   ProtectionPolicy = GetUefiImageProtectionPolicy (LoadedImage, LoadedImageDevicePath);
   switch (ProtectionPolicy) {
     case DO_NOT_PROTECT:
@@ -355,36 +323,49 @@ ProtectUefiImage (
       return;
   }
 
-  ImageRecord = AllocateZeroPool (sizeof (*ImageRecord));
-  if (ImageRecord == NULL) {
-    return;
+  PdbStatus = UefiImageGetSymbolsPath (ImageContext, &PdbPointer, &PdbSize);
+  if (!RETURN_ERROR (PdbStatus)) {
+    DEBUG ((DEBUG_VERBOSE, "  Image - %a\n", PdbPointer));
   }
 
-  RequiredAlignment = GetMemoryProtectionSectionAlignment (LoadedImage->ImageCodeType);
+  //
+  // Get SectionAlignment
+  //
+  SectionAlignment = UefiImageGetSegmentAlignment (ImageContext);
 
-  Status = CreateImagePropertiesRecord (
-             LoadedImage->ImageBase,
-             LoadedImage->ImageSize,
-             &RequiredAlignment,
-             ImageRecord
-             );
+  IsAligned = IsMemoryProtectionSectionAligned (SectionAlignment, LoadedImage->ImageCodeType);
+  if (!IsAligned) {
+    DEBUG ((
+      DEBUG_VERBOSE,
+      "!!!!!!!!  ProtectUefiImageCommon - Section Alignment(0x%x) is incorrect  !!!!!!!!\n",
+      SectionAlignment));
+    if (!RETURN_ERROR (PdbStatus)) {
+      DEBUG ((DEBUG_VERBOSE, "!!!!!!!!  Image - %a  !!!!!!!!\n", PdbPointer));
+    }
 
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a failed to create image properties record\n", __func__));
-    FreePool (ImageRecord);
     goto Finish;
   }
 
-  //
-  // CPU ARCH present. Update memory attribute directly.
-  //
-  SetUefiImageProtectionAttributes (ImageRecord);
+  ImageRecord = UefiImageLoaderGetImageRecord (ImageContext);
+  if (ImageRecord == NULL) {
+    return ;
+  }
+
+  UefiImageDebugPrintSegments (ImageContext);
+  UefiImageDebugPrintImageRecord (ImageRecord);
 
   //
   // Record the image record in the list so we can undo the protections later
   //
   InsertTailList (&mProtectedImageRecordList, &ImageRecord->Link);
 
+  if (gCpu != NULL) {
+    //
+    // CPU ARCH present. Update memory attribute directly.
+    //
+    SetUefiImageProtectionAttributes (ImageRecord);
+  }
+
 Finish:
   return;
 }
@@ -401,30 +382,31 @@ UnprotectUefiImage (
   IN EFI_DEVICE_PATH_PROTOCOL   *LoadedImageDevicePath
   )
 {
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  LIST_ENTRY               *ImageRecordLink;
+  UEFI_IMAGE_RECORD  *ImageRecord;
+  LIST_ENTRY         *ImageRecordLink;
 
-  if (PcdGet32 (PcdImageProtectionPolicy) != 0) {
-    for (ImageRecordLink = mProtectedImageRecordList.ForwardLink;
-         ImageRecordLink != &mProtectedImageRecordList;
-         ImageRecordLink = ImageRecordLink->ForwardLink)
-    {
-      ImageRecord = CR (
-                      ImageRecordLink,
-                      IMAGE_PROPERTIES_RECORD,
-                      Link,
-                      IMAGE_PROPERTIES_RECORD_SIGNATURE
-                      );
+  for (ImageRecordLink = mProtectedImageRecordList.ForwardLink;
+        ImageRecordLink != &mProtectedImageRecordList;
+        ImageRecordLink = ImageRecordLink->ForwardLink) {
+    ImageRecord = CR (
+                    ImageRecordLink,
+                    UEFI_IMAGE_RECORD,
+                    Link,
+                    UEFI_IMAGE_RECORD_SIGNATURE
+                    );
 
-      if (ImageRecord->ImageBase == (EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImage->ImageBase) {
+    if (ImageRecord->StartAddress == (EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImage->ImageBase) {
+      // TODO: Revise for removal (e.g. CpuDxe integration)
+      if (gCpu != NULL) {
         SetUefiImageMemoryAttributes (
-          ImageRecord->ImageBase,
-          ImageRecord->ImageSize,
+          ImageRecord->StartAddress,
+          ImageRecord->EndAddress - ImageRecord->StartAddress,
           0
           );
-        DeleteImagePropertiesRecord (ImageRecord);
-        return;
       }
+      RemoveEntryList (&ImageRecord->Link);
+      FreePool (ImageRecord);
+      return;
     }
   }
 }
@@ -567,7 +549,6 @@ MergeMemoryMapForProtectionPolicy (
   Remove exec permissions from all regions whose type is identified by
   PcdDxeNxMemoryProtectionPolicy.
 **/
-STATIC
 VOID
 InitializeDxeNxMemoryProtectionPolicy (
   VOID
@@ -775,12 +756,9 @@ MemoryProtectionCpuArchProtocolNotify (
   IN VOID       *Context
   )
 {
-  EFI_STATUS                 Status;
-  EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage;
-  EFI_DEVICE_PATH_PROTOCOL   *LoadedImageDevicePath;
-  UINTN                      NoHandles;
-  EFI_HANDLE                 *HandleBuffer;
-  UINTN                      Index;
+  EFI_STATUS         Status;
+  LIST_ENTRY         *ImageRecordLink;
+  UEFI_IMAGE_RECORD  *ImageRecord;
 
   DEBUG ((DEBUG_INFO, "MemoryProtectionCpuArchProtocolNotify:\n"));
   Status = CoreLocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu);
@@ -804,41 +782,22 @@ MemoryProtectionCpuArchProtocolNotify (
     goto Done;
   }
 
-  Status = gBS->LocateHandleBuffer (
-                  ByProtocol,
-                  &gEfiLoadedImageProtocolGuid,
-                  NULL,
-                  &NoHandles,
-                  &HandleBuffer
-                  );
-  if (EFI_ERROR (Status) && (NoHandles == 0)) {
-    goto Done;
-  }
-
-  for (Index = 0; Index < NoHandles; Index++) {
-    Status = gBS->HandleProtocol (
-                    HandleBuffer[Index],
-                    &gEfiLoadedImageProtocolGuid,
-                    (VOID **)&LoadedImage
+  for (ImageRecordLink = mProtectedImageRecordList.ForwardLink;
+        ImageRecordLink != &mProtectedImageRecordList;
+        ImageRecordLink = ImageRecordLink->ForwardLink) {
+    ImageRecord = CR (
+                    ImageRecordLink,
+                    UEFI_IMAGE_RECORD,
+                    Link,
+                    UEFI_IMAGE_RECORD_SIGNATURE
                     );
-    if (EFI_ERROR (Status)) {
-      continue;
-    }
 
-    Status = gBS->HandleProtocol (
-                    HandleBuffer[Index],
-                    &gEfiLoadedImageDevicePathProtocolGuid,
-                    (VOID **)&LoadedImageDevicePath
-                    );
-    if (EFI_ERROR (Status)) {
-      LoadedImageDevicePath = NULL;
-    }
-
-    ProtectUefiImage (LoadedImage, LoadedImageDevicePath);
+    //
+    // CPU ARCH present. Update memory attribute directly.
+    //
+    SetUefiImageProtectionAttributes (ImageRecord);
   }
 
-  FreePool (HandleBuffer);
-
 Done:
   CoreCloseEvent (Event);
 }
diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
index 4073bad82c..da2dcd796f 100644
--- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
+++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
@@ -9,6 +9,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 **/
 
 #include "PeiMain.h"
+#include "ProcessorBind.h"
 
 //
 // Utility global variables
@@ -1377,8 +1378,7 @@ MigratePeim (
   EFI_FFS_FILE_HEADER  *FileHeader;
   VOID                 *Pe32Data;
   VOID                 *ImageAddress;
-  CHAR8                *AsciiString;
-  UINTN                Index;
+  UINT32                    ImageSize;
 
   Status = EFI_SUCCESS;
 
@@ -1386,24 +1386,10 @@ MigratePeim (
   ASSERT (!IS_FFS_FILE2 (FileHeader));
 
   ImageAddress = NULL;
-  PeiGetPe32Data (MigratedFileHandle, &ImageAddress);
+  PeiGetPe32Data (MigratedFileHandle, &ImageAddress, &ImageSize);
   if (ImageAddress != NULL) {
-    DEBUG_CODE_BEGIN ();
-    AsciiString = PeCoffLoaderGetPdbPointer (ImageAddress);
-    for (Index = 0; AsciiString[Index] != 0; Index++) {
-      if ((AsciiString[Index] == '\\') || (AsciiString[Index] == '/')) {
-        AsciiString = AsciiString + Index + 1;
-        Index       = 0;
-      } else if (AsciiString[Index] == '.') {
-        AsciiString[Index] = 0;
-      }
-    }
-
-    DEBUG ((DEBUG_VERBOSE, "%a", AsciiString));
-    DEBUG_CODE_END ();
-
     Pe32Data = (VOID *)((UINTN)ImageAddress - (UINTN)MigratedFileHandle + (UINTN)FileHandle);
-    Status   = LoadAndRelocatePeCoffImageInPlace (Pe32Data, ImageAddress);
+    Status   = LoadAndRelocateUefiImageInPlace (Pe32Data, ImageAddress, ImageSize);
     ASSERT_EFI_ERROR (Status);
   }
 
@@ -1465,6 +1451,104 @@ ConvertStatusCodeCallbacks (
   }
 }
 
+/**
+  Migrates SEC modules in the given firmware volume.
+
+  Migrating SECURITY_CORE files requires special treatment since they are not tracked for PEI dispatch.
+
+  This functioun should be called after the FV has been copied to its post-memory location and the PEI Core FV list has
+  been updated.
+
+  @param Private          Pointer to the PeiCore's private data structure.
+  @param FvIndex          The firmware volume index to migrate.
+  @param OrgFvHandle      The handle to the firmware volume in temporary memory.
+
+  @retval   EFI_SUCCESS           SEC modules were migrated successfully
+  @retval   EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid.
+  @retval   EFI_NOT_FOUND         Can't find valid FFS header.
+
+**/
+EFI_STATUS
+EFIAPI
+MigrateSecModulesInFv (
+  IN PEI_CORE_INSTANCE    *Private,
+  IN  UINTN               FvIndex,
+  IN  UINTN               OrgFvHandle
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_STATUS                  FindFileStatus;
+  EFI_PEI_FILE_HANDLE         MigratedFileHandle;
+  EFI_PEI_FILE_HANDLE         FileHandle;
+  UINT32                      SectionAuthenticationStatus;
+  UINT32                      FileSize;
+  VOID                        *OrgPe32SectionData;
+  VOID                        *Pe32SectionData;
+  UINT32                      Pe32SectionDataSize;
+  EFI_FFS_FILE_HEADER         *FfsFileHeader;
+  EFI_COMMON_SECTION_HEADER   *Section;
+  BOOLEAN                     IsFfs3Fv;
+  UINTN                       SectionInstance;
+
+  if (Private == NULL || FvIndex >= Private->FvCount) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  do {
+    FindFileStatus =  PeiFfsFindNextFile (
+                        GetPeiServicesTablePointer (),
+                        EFI_FV_FILETYPE_SECURITY_CORE,
+                        Private->Fv[FvIndex].FvHandle,
+                        &MigratedFileHandle
+                        );
+    if (!EFI_ERROR (FindFileStatus ) && MigratedFileHandle != NULL) {
+      FileHandle = (EFI_PEI_FILE_HANDLE) ((UINTN) MigratedFileHandle - (UINTN) Private->Fv[FvIndex].FvHandle + OrgFvHandle);
+      FfsFileHeader = (EFI_FFS_FILE_HEADER *) MigratedFileHandle;
+
+      DEBUG ((DEBUG_VERBOSE, "    Migrating SEC_CORE MigratedFileHandle at 0x%x.\n", (UINTN) MigratedFileHandle));
+      DEBUG ((DEBUG_VERBOSE, "                       FileHandle at 0x%x.\n", (UINTN) FileHandle));
+
+      IsFfs3Fv = CompareGuid (&Private->Fv[FvIndex].FvHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);
+      if (IS_FFS_FILE2 (FfsFileHeader)) {
+        ASSERT (FFS_FILE2_SIZE (FfsFileHeader) > 0x00FFFFFF);
+        if (!IsFfs3Fv) {
+          DEBUG ((DEBUG_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name));
+          return EFI_NOT_FOUND;
+        }
+        Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
+        FileSize = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
+      } else {
+        Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER));
+        FileSize = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
+      }
+
+      SectionInstance = 1;
+      SectionAuthenticationStatus = 0;
+      Status = ProcessSection (
+                GetPeiServicesTablePointer (),
+                EFI_SECTION_PE32,
+                &SectionInstance,
+                Section,
+                FileSize,
+                &Pe32SectionData,
+                &Pe32SectionDataSize,
+                &SectionAuthenticationStatus,
+                IsFfs3Fv
+                );
+
+      if (!EFI_ERROR (Status)) {
+        OrgPe32SectionData = (VOID *) ((UINTN) Pe32SectionData - (UINTN) MigratedFileHandle + (UINTN) FileHandle);
+        DEBUG ((DEBUG_VERBOSE, "      PE32 section in migrated file at 0x%x.\n", (UINTN) Pe32SectionData));
+        DEBUG ((DEBUG_VERBOSE, "      PE32 section in original file at 0x%x.\n", (UINTN) OrgPe32SectionData));
+        Status = LoadAndRelocateUefiImageInPlace (OrgPe32SectionData, Pe32SectionData, Pe32SectionDataSize);
+        ASSERT_EFI_ERROR (Status);
+      }
+    }
+  } while (!EFI_ERROR (FindFileStatus));
+
+  return EFI_SUCCESS;
+}
+
 /**
   Migrates PEIMs in the given firmware volume.
 
diff --git a/MdeModulePkg/Core/Pei/FwVol/FwVol.c b/MdeModulePkg/Core/Pei/FwVol/FwVol.c
index 04bec986e4..f63565ff13 100644
--- a/MdeModulePkg/Core/Pei/FwVol/FwVol.c
+++ b/MdeModulePkg/Core/Pei/FwVol/FwVol.c
@@ -35,7 +35,8 @@ PEI_FW_VOL_INSTANCE  mPeiFfs2FwVol = {
     PeiFfsFvPpiGetFileInfo2,
     PeiFfsFvPpiFindSectionByType2,
     EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE,
-    EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION
+    EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION,
+    PeiFfsFvPpiFindSectionByType3
   }
 };
 
@@ -52,7 +53,8 @@ PEI_FW_VOL_INSTANCE  mPeiFfs3FwVol = {
     PeiFfsFvPpiGetFileInfo2,
     PeiFfsFvPpiFindSectionByType2,
     EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE,
-    EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION
+    EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION,
+    PeiFfsFvPpiFindSectionByType3
   }
 };
 
@@ -771,6 +773,8 @@ VerifyGuidedSectionGuid (
   @param SectionSize       The file size to search.
   @param OutputBuffer      A pointer to the discovered section, if successful.
                            NULL if section not found
+  @param OutputSize        The size of the discovered section, if successful.
+                           0 if section not found
   @param AuthenticationStatus Updated upon return to point to the authentication status for this section.
   @param IsFfs3Fv          Indicates the FV format.
 
@@ -786,6 +790,7 @@ ProcessSection (
   IN EFI_COMMON_SECTION_HEADER  *Section,
   IN UINTN                      SectionSize,
   OUT VOID                      **OutputBuffer,
+  OUT UINT32                    *OutputSize,
   OUT UINT32                    *AuthenticationStatus,
   IN BOOLEAN                    IsFfs3Fv
   )
@@ -803,11 +808,13 @@ ProcessSection (
   EFI_GUID                               *SectionDefinitionGuid;
   BOOLEAN                                SectionCached;
   VOID                                   *TempOutputBuffer;
+  UINT32                                  TempOutputSize;
   UINT32                                 TempAuthenticationStatus;
   UINT16                                 GuidedSectionAttributes;
 
   PrivateData   = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
   *OutputBuffer = NULL;
+  *OutputSize   = 0;
   ParsedLength  = 0;
   Index         = 0;
   Status        = EFI_NOT_FOUND;
@@ -844,10 +851,13 @@ ProcessSection (
         //
         // Got it!
         //
+        // FIXME: Size checks
         if (IS_SECTION2 (Section)) {
           *OutputBuffer = (VOID *)((UINT8 *)Section + sizeof (EFI_COMMON_SECTION_HEADER2));
+          *OutputSize   = SECTION2_SIZE (Section) - sizeof (EFI_COMMON_SECTION_HEADER2);
         } else {
           *OutputBuffer = (VOID *)((UINT8 *)Section + sizeof (EFI_COMMON_SECTION_HEADER));
+          *OutputSize   = SECTION_SIZE (Section) - sizeof (EFI_COMMON_SECTION_HEADER);
         }
 
         return EFI_SUCCESS;
@@ -894,11 +904,13 @@ ProcessSection (
                                        PpiOutput,
                                        PpiOutputSize,
                                        &TempOutputBuffer,
+                     &TempOutputSize,
                                        &TempAuthenticationStatus,
                                        IsFfs3Fv
                                        );
           if (!EFI_ERROR (Status)) {
             *OutputBuffer         = TempOutputBuffer;
+            *OutputSize   = TempOutputSize;
             *AuthenticationStatus = TempAuthenticationStatus | Authentication;
             return EFI_SUCCESS;
           }
@@ -981,11 +993,13 @@ ProcessSection (
                                        PpiOutput,
                                        PpiOutputSize,
                                        &TempOutputBuffer,
+                     &TempOutputSize,
                                        &TempAuthenticationStatus,
                                        IsFfs3Fv
                                        );
           if (!EFI_ERROR (Status)) {
             *OutputBuffer         = TempOutputBuffer;
+            *OutputSize   = TempOutputSize;
             *AuthenticationStatus = TempAuthenticationStatus | Authentication;
             return EFI_SUCCESS;
           }
@@ -1072,6 +1086,38 @@ PeiFfsFindSectionData3 (
   OUT VOID                    **SectionData,
   OUT UINT32                  *AuthenticationStatus
   )
+{
+  UINT32 SectionDataSize;
+
+  return PeiFfsFindSectionData4 (PeiServices, SectionType, SectionInstance, FileHandle, SectionData, &SectionDataSize, AuthenticationStatus);
+}
+
+/**
+  Searches for the next matching section within the specified file.
+
+  @param  PeiServices           An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
+  @param  SectionType           The value of the section type to find.
+  @param  SectionInstance       Section instance to find.
+  @param  FileHandle            Handle of the firmware file to search.
+  @param  SectionData           A pointer to the discovered section, if successful.
+  @param  SectionDataSize       The size of the discovered section, if successful.
+  @param  AuthenticationStatus  A pointer to the authentication status for this section.
+
+  @retval EFI_SUCCESS      The section was found.
+  @retval EFI_NOT_FOUND    The section was not found.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiFfsFindSectionData4 (
+  IN CONST EFI_PEI_SERVICES    **PeiServices,
+  IN     EFI_SECTION_TYPE      SectionType,
+  IN     UINTN                 SectionInstance,
+  IN     EFI_PEI_FILE_HANDLE   FileHandle,
+  OUT VOID                     **SectionData,
+  OUT UINT32                   *SectionDataSize,
+  OUT UINT32                   *AuthenticationStatus
+  )
 {
   PEI_CORE_FV_HANDLE  *CoreFvHandle;
 
@@ -1083,7 +1129,7 @@ PeiFfsFindSectionData3 (
   if ((CoreFvHandle->FvPpi->Signature == EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE) &&
       (CoreFvHandle->FvPpi->Revision == EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION))
   {
-    return CoreFvHandle->FvPpi->FindSectionByType2 (CoreFvHandle->FvPpi, SectionType, SectionInstance, FileHandle, SectionData, AuthenticationStatus);
+    return CoreFvHandle->FvPpi->FindSectionByType3 (CoreFvHandle->FvPpi, SectionType, SectionInstance, FileHandle, SectionData, SectionDataSize, AuthenticationStatus);
   }
 
   //
@@ -2040,6 +2086,57 @@ PeiFfsFvPpiFindSectionByType2 (
   OUT VOID                               **SectionData,
   OUT UINT32                             *AuthenticationStatus
   )
+{
+  UINT32 SectionDataSize;
+
+  // FIXME: Deprecate
+  return PeiFfsFvPpiFindSectionByType3 (
+           This,
+           SearchType,
+           SearchInstance,
+           FileHandle,
+           SectionData,
+           &SectionDataSize,
+           AuthenticationStatus
+           );
+}
+
+/**
+  Find the next matching section in the firmware file.
+
+  This service enables PEI modules to discover sections
+  of a given instance and type within a valid file.
+
+  @param This                   Points to this instance of the
+                                EFI_PEI_FIRMWARE_VOLUME_PPI.
+  @param SearchType             A filter to find only sections of this
+                                type.
+  @param SearchInstance         A filter to find the specific instance
+                                of sections.
+  @param FileHandle             Handle of firmware file in which to
+                                search.
+  @param SectionData            Updated upon return to point to the
+                                section found.
+  @param SectionDataSize        Updated upon return to point to the
+                                section size found.
+  @param AuthenticationStatus   Updated upon return to point to the
+                                authentication status for this section.
+
+  @retval EFI_SUCCESS     Section was found.
+  @retval EFI_NOT_FOUND   Section of the specified type was not
+                          found. SectionData contains NULL.
+**/
+EFI_STATUS
+EFIAPI
+PeiFfsFvPpiFindSectionByType3 (
+  IN  CONST EFI_PEI_FIRMWARE_VOLUME_PPI    *This,
+  IN        EFI_SECTION_TYPE               SearchType,
+  IN        UINTN                          SearchInstance,
+  IN        EFI_PEI_FILE_HANDLE            FileHandle,
+  OUT VOID                                 **SectionData,
+  OUT UINT32                               *SectionDataSize,
+  OUT UINT32                               *AuthenticationStatus
+  )
 {
   EFI_STATUS                 Status;
   EFI_FFS_FILE_HEADER        *FfsFileHeader;
@@ -2089,6 +2186,7 @@ PeiFfsFvPpiFindSectionByType2 (
                                     Section,
                                     FileSize,
                                     SectionData,
+             SectionDataSize,
                                     &ExtractedAuthenticationStatus,
                                     FwVolInstance->IsFfs3Fv
                                     );
diff --git a/MdeModulePkg/Core/Pei/FwVol/FwVol.h b/MdeModulePkg/Core/Pei/FwVol/FwVol.h
index 7d1dc9cba1..02a732845e 100644
--- a/MdeModulePkg/Core/Pei/FwVol/FwVol.h
+++ b/MdeModulePkg/Core/Pei/FwVol/FwVol.h
@@ -185,6 +185,43 @@ PeiFfsFvPpiFindSectionByType2 (
   OUT UINT32                             *AuthenticationStatus
   );
 
+/**
+  Find the next matching section in the firmware file.
+
+  This service enables PEI modules to discover sections
+  of a given instance and type within a valid file.
+
+  @param This                   Points to this instance of the
+                                EFI_PEI_FIRMWARE_VOLUME_PPI.
+  @param SearchType             A filter to find only sections of this
+                                type.
+  @param SearchInstance         A filter to find the specific instance
+                                of sections.
+  @param FileHandle             Handle of firmware file in which to
+                                search.
+  @param SectionData            Updated upon return to point to the
+                                section found.
+  @param SectionDataSize        Updated upon return to point to the
+                                section size found.
+  @param AuthenticationStatus   Updated upon return to point to the
+                                authentication status for this section.
+
+  @retval EFI_SUCCESS     Section was found.
+  @retval EFI_NOT_FOUND   Section of the specified type was not
+                          found. SectionData contains NULL.
+**/
+EFI_STATUS
+EFIAPI
+PeiFfsFvPpiFindSectionByType3 (
+  IN  CONST EFI_PEI_FIRMWARE_VOLUME_PPI    *This,
+  IN        EFI_SECTION_TYPE               SearchType,
+  IN        UINTN                          SearchInstance,
+  IN        EFI_PEI_FILE_HANDLE            FileHandle,
+  OUT VOID                                 **SectionData,
+  OUT UINT32                               *SectionDataSize,
+  OUT UINT32                               *AuthenticationStatus
+  );
+
 /**
   Returns information about a specific file.
 
diff --git a/MdeModulePkg/Core/Pei/Image/Image.c b/MdeModulePkg/Core/Pei/Image/Image.c
index cee9f09c6e..ca57bfaefc 100644
--- a/MdeModulePkg/Core/Pei/Image/Image.c
+++ b/MdeModulePkg/Core/Pei/Image/Image.c
@@ -18,40 +18,6 @@ EFI_PEI_PPI_DESCRIPTOR  gPpiLoadFilePpiList = {
   &mPeiLoadImagePpi
 };
 
-/**
-
-  Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file.
-  The function is used for XIP code to have optimized memory copy.
-
-  @param FileHandle      - The handle to the PE/COFF file
-  @param FileOffset      - The offset, in bytes, into the file to read
-  @param ReadSize        - The number of bytes to read from the file starting at FileOffset
-  @param Buffer          - A pointer to the buffer to read the data into.
-
-  @return EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
-
-**/
-EFI_STATUS
-EFIAPI
-PeiImageRead (
-  IN     VOID   *FileHandle,
-  IN     UINTN  FileOffset,
-  IN     UINTN  *ReadSize,
-  OUT    VOID   *Buffer
-  )
-{
-  CHAR8  *Destination8;
-  CHAR8  *Source8;
-
-  Destination8 = Buffer;
-  Source8      = (CHAR8 *)((UINTN)FileHandle + FileOffset);
-  if (Destination8 != Source8) {
-    CopyMem (Destination8, Source8, *ReadSize);
-  }
-
-  return EFI_SUCCESS;
-}
-
 /**
   To check memory usage bit map array to figure out if the memory range the image will be loaded in is available or not. If
   memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.
@@ -135,111 +101,36 @@ CheckAndMarkFixLoadingMemoryUsageBitMap (
 
 **/
 EFI_STATUS
-GetPeCoffImageFixLoadingAssignedAddress (
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,
-  IN     PEI_CORE_INSTANCE             *Private
+GetUefiImageFixLoadingAssignedAddress (
+  OUT EFI_PHYSICAL_ADDRESS  *LoadAddress,
+  IN  UINT64                ValueInSectionHeader,
+  IN  UINT32                ImageDestSize,
+  IN  PEI_CORE_INSTANCE     *Private
   )
 {
-  UINTN                            SectionHeaderOffset;
-  EFI_STATUS                       Status;
-  EFI_IMAGE_SECTION_HEADER         SectionHeader;
-  EFI_IMAGE_OPTIONAL_HEADER_UNION  *ImgHdr;
-  EFI_PHYSICAL_ADDRESS             FixLoadingAddress;
-  UINT16                           Index;
-  UINTN                            Size;
-  UINT16                           NumberOfSections;
-  UINT64                           ValueInSectionHeader;
+   EFI_STATUS           Status;
+   EFI_PHYSICAL_ADDRESS FixLoadingAddress;
 
-  FixLoadingAddress = 0;
-  Status            = EFI_NOT_FOUND;
-
-  //
-  // Get PeHeader pointer
-  //
-  ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8 *)ImageContext->Handle + ImageContext->PeCoffHeaderOffset);
-  if (ImageContext->IsTeImage) {
+  if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) > 0) {
     //
-    // for TE image, the fix loading address is saved in first section header that doesn't point
-    // to code section.
+    // When LMFA feature is configured as Load Module at Fixed Absolute Address mode, PointerToRelocations & PointerToLineNumbers field
+    // hold the absolute address of image base running in memory
     //
-    SectionHeaderOffset = sizeof (EFI_TE_IMAGE_HEADER);
-    NumberOfSections    = ImgHdr->Te.NumberOfSections;
+    FixLoadingAddress = ValueInSectionHeader;
   } else {
-    SectionHeaderOffset = ImageContext->PeCoffHeaderOffset +
-                          sizeof (UINT32) +
-                          sizeof (EFI_IMAGE_FILE_HEADER) +
-                          ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;
-    NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;
-  }
-
-  //
-  // Get base address from the first section header that doesn't point to code section.
-  //
-  for (Index = 0; Index < NumberOfSections; Index++) {
     //
-    // Read section header from file
+    // When LMFA feature is configured as Load Module at Fixed offset mode, PointerToRelocations & PointerToLineNumbers field
+    // hold the offset relative to a platform-specific top address.
     //
-    Size   = sizeof (EFI_IMAGE_SECTION_HEADER);
-    Status = ImageContext->ImageRead (
-                             ImageContext->Handle,
-                             SectionHeaderOffset,
-                             &Size,
-                             &SectionHeader
-                             );
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    Status = EFI_NOT_FOUND;
-
-    if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
-      //
-      // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
-      // that doesn't point to code section in image header, as well as ImageBase field of image header. A notable thing is
-      // that for PEIM, the value in ImageBase field may not be equal to the value in PointerToRelocations & PointerToLineNumbers because
-      // for XIP PEIM, ImageBase field holds the image base address running on the Flash. And PointerToRelocations & PointerToLineNumbers
-      // hold the image base address when it is shadow to the memory. And there is an assumption that when the feature is enabled, if a
-      // module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers fields should NOT be Zero, or
-      // else, these 2 fields should be set to Zero
-      //
-      ValueInSectionHeader = ReadUnaligned64 ((UINT64 *)&SectionHeader.PointerToRelocations);
-      if (ValueInSectionHeader != 0) {
-        //
-        // Found first section header that doesn't point to code section.
-        //
-        if ((INT64)PcdGet64 (PcdLoadModuleAtFixAddressEnable) > 0) {
-          //
-          // When LMFA feature is configured as Load Module at Fixed Absolute Address mode, PointerToRelocations & PointerToLineNumbers field
-          // hold the absolute address of image base running in memory
-          //
-          FixLoadingAddress = ValueInSectionHeader;
-        } else {
-          //
-          // When LMFA feature is configured as Load Module at Fixed offset mode, PointerToRelocations & PointerToLineNumbers field
-          // hold the offset relative to a platform-specific top address.
-          //
-          FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(Private->LoadModuleAtFixAddressTopAddress + (INT64)ValueInSectionHeader);
-        }
-
-        //
-        // Check if the memory range is available.
-        //
-        Status = CheckAndMarkFixLoadingMemoryUsageBitMap (Private, FixLoadingAddress, (UINT32)ImageContext->ImageSize);
-        if (!EFI_ERROR (Status)) {
-          //
-          // The assigned address is valid. Return the specified loading address
-          //
-          ImageContext->ImageAddress = FixLoadingAddress;
-        }
-      }
-
-      break;
-    }
-
-    SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
+    FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(Private->LoadModuleAtFixAddressTopAddress + ValueInSectionHeader);
   }
+  //
+  // Check if the memory range is available.
+  //
+  Status = CheckAndMarkFixLoadingMemoryUsageBitMap (Private, FixLoadingAddress, ImageDestSize);
+  *LoadAddress = FixLoadingAddress;
 
-  DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status= %r \n", (VOID *)(UINTN)FixLoadingAddress, Status));
+  DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status= %r \n", (VOID *)(UINTN)FixLoadingAddress, Status));
   return Status;
 }
 
@@ -262,38 +153,49 @@ GetPeCoffImageFixLoadingAssignedAddress (
 
 **/
 EFI_STATUS
-LoadAndRelocatePeCoffImage (
+LoadAndRelocateUefiImage (
   IN  EFI_PEI_FILE_HANDLE   FileHandle,
   IN  VOID                  *Pe32Data,
-  OUT EFI_PHYSICAL_ADDRESS  *ImageAddress,
-  OUT UINT64                *ImageSize,
-  OUT EFI_PHYSICAL_ADDRESS  *EntryPoint
+  IN  UINT32                                    Pe32DataSize,
+  OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT           *ImageContext,
+  OUT EFI_PHYSICAL_ADDRESS                      *ImageAddress
   )
 {
   EFI_STATUS                    Status;
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
+  BOOLEAN                       Success;
   PEI_CORE_INSTANCE             *Private;
-  UINT64                        AlignImageSize;
+  UINT32                                ImageSize;
+  UINT32                                ImageAlignment;
+  UINT64                                ValueInSectionHeader;
   BOOLEAN                       IsXipImage;
   EFI_STATUS                    ReturnStatus;
   BOOLEAN                       IsS3Boot;
   BOOLEAN                       IsPeiModule;
   BOOLEAN                       IsRegisterForShadow;
   EFI_FV_FILE_INFO              FileInfo;
+  UINT32                                DestinationPages;
+  UINT32                                DestinationSize;
+  EFI_PHYSICAL_ADDRESS                  Destination;
+  UINT16                                Machine;
+  BOOLEAN                               LoadDynamically;
 
   Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
 
   ReturnStatus = EFI_SUCCESS;
-  IsXipImage   = FALSE;
-  ZeroMem (&ImageContext, sizeof (ImageContext));
-  ImageContext.Handle    = Pe32Data;
-  ImageContext.ImageRead = PeiImageRead;
 
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);
+  Status = UefiImageInitializeContext (ImageContext, Pe32Data, Pe32DataSize);
   if (EFI_ERROR (Status)) {
     return Status;
   }
 
+  Machine = UefiImageGetMachine (ImageContext);
+
+  if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {
+    if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Machine)) {
+      return EFI_UNSUPPORTED;
+    }
+  }
+
   //
   // Initialize local IsS3Boot and IsRegisterForShadow variable
   //
@@ -312,9 +214,7 @@ LoadAndRelocatePeCoffImage (
   //
   // XIP image that ImageAddress is same to Image handle.
   //
-  if (ImageContext.ImageAddress == (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data) {
-    IsXipImage = TRUE;
-  }
+  IsXipImage = UefiImageImageIsInplace (ImageContext);
 
   //
   // Get file type first
@@ -336,7 +236,7 @@ LoadAndRelocatePeCoffImage (
   //
   // When Image has no reloc section, it can't be relocated into memory.
   //
-  if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) &&
+  if (UefiImageGetRelocsStripped (ImageContext) && (Private->PeiMemoryInstalled) &&
       ((!IsPeiModule) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
        (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) ||
        (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))
@@ -345,125 +245,95 @@ LoadAndRelocatePeCoffImage (
     DEBUG ((DEBUG_INFO|DEBUG_LOAD, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN)Pe32Data));
   }
 
-  //
-  // Set default base address to current image address.
-  //
-  ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data;
+  LoadDynamically  = FALSE;
+  ImageSize        = UefiImageGetImageSize (ImageContext);
+  DestinationPages = EFI_SIZE_TO_PAGES (ImageSize);
+  DestinationSize  = EFI_PAGES_TO_SIZE (DestinationPages);
 
   //
   // Allocate Memory for the image when memory is ready, and image is relocatable.
   // On normal boot, PcdShadowPeimOnBoot decides whether load PEIM or PeiCore into memory.
   // On S3 boot, PcdShadowPeimOnS3Boot decides whether load PEIM or PeiCore into memory.
   //
-  if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) &&
+  if ((!UefiImageGetRelocsStripped (ImageContext)) && (Private->PeiMemoryInstalled) &&
       ((!IsPeiModule) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
        (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) ||
        (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))
       )
   {
-    //
-    // Allocate more buffer to avoid buffer overflow.
-    //
-    if (ImageContext.IsTeImage) {
-      AlignImageSize = ImageContext.ImageSize + ((EFI_TE_IMAGE_HEADER *)Pe32Data)->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
-    } else {
-      AlignImageSize = ImageContext.ImageSize;
+    Success = FALSE;
+
+    if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
+      Status = UefiImageGetFixedAddress (ImageContext, &ValueInSectionHeader);
+      if (!RETURN_ERROR (Status)) {
+        Status = GetUefiImageFixLoadingAssignedAddress(&Destination, ValueInSectionHeader, DestinationSize, Private);
+      }
+
+      if (!EFI_ERROR (Status)){
+        Success = Destination == UefiImageGetPreferredAddress (ImageContext);
+
+        if (!Success) {
+          DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED ERROR: Loading module at fixed address failed since relocs have been stripped.\n"));
+        }
+      } else {
+        DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));
+      }
     }
 
-    if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
-      AlignImageSize += ImageContext.SectionAlignment;
+    if (!Success) {
+      //
+      // Allocate more buffer to avoid buffer overflow.
+      //
+      ImageAlignment = UefiImageGetSegmentAlignment (ImageContext);
+
+      Destination = (UINTN)AllocateAlignedCodePages (
+                             DestinationPages,
+                             ImageAlignment
+                             );
+      Success = Destination != 0;
     }
 
-    if ((PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
-      Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext, Private);
+    if (Success) {
+      LoadDynamically = TRUE;
+      //
+      // Load the image to our new buffer
+      //
+      Status = UefiImageLoadImageForExecution (
+                ImageContext,
+                (VOID *) (UINTN)Destination,
+                DestinationSize,
+                NULL,
+                0
+                );
       if (EFI_ERROR (Status)) {
-        DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));
-        //
-        // The PEIM is not assigned valid address, try to allocate page to load it.
-        //
-        Status = PeiServicesAllocatePages (
-                   EfiBootServicesCode,
-                   EFI_SIZE_TO_PAGES ((UINT32)AlignImageSize),
-                   &ImageContext.ImageAddress
-                   );
-      }
-    } else {
-      Status = PeiServicesAllocatePages (
-                 EfiBootServicesCode,
-                 EFI_SIZE_TO_PAGES ((UINT32)AlignImageSize),
-                 &ImageContext.ImageAddress
-                 );
-    }
-
-    if (!EFI_ERROR (Status)) {
-      //
-      // Adjust the Image Address to make sure it is section alignment.
-      //
-      if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
-        ImageContext.ImageAddress =
-          (ImageContext.ImageAddress + ImageContext.SectionAlignment - 1) &
-          ~((UINTN)ImageContext.SectionAlignment - 1);
-      }
-
-      //
-      // Fix alignment requirement when Load IPF TeImage into memory.
-      // Skip the reserved space for the stripped PeHeader when load TeImage into memory.
-      //
-      if (ImageContext.IsTeImage) {
-        ImageContext.ImageAddress = ImageContext.ImageAddress +
-                                    ((EFI_TE_IMAGE_HEADER *)Pe32Data)->StrippedSize -
-                                    sizeof (EFI_TE_IMAGE_HEADER);
+        return              Status;
       }
     } else {
       //
       // No enough memory resource.
       //
-      if (IsXipImage) {
-        //
-        // XIP image can still be invoked.
-        //
-        ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data;
-        ReturnStatus              = EFI_WARN_BUFFER_TOO_SMALL;
-      } else {
+      if (!IsXipImage) {
         //
         // Non XIP image can't be loaded because no enough memory is allocated.
         //
         ASSERT (FALSE);
         return EFI_OUT_OF_RESOURCES;
       }
+      //
+      // XIP image can still be invoked.
+      //
+      ReturnStatus = EFI_WARN_BUFFER_TOO_SMALL;
     }
   }
 
-  //
-  // Load the image to our new buffer
-  //
-  Status = PeCoffLoaderLoadImage (&ImageContext);
-  if (EFI_ERROR (Status)) {
-    if (ImageContext.ImageError == IMAGE_ERROR_INVALID_SECTION_ALIGNMENT) {
-      DEBUG ((DEBUG_ERROR, "PEIM Image Address 0x%11p doesn't meet with section alignment 0x%x.\n", (VOID *)(UINTN)ImageContext.ImageAddress, ImageContext.SectionAlignment));
+  if (!LoadDynamically) {
+    Status = UefiImageLoadImageInplace (ImageContext);
+    if (EFI_ERROR (Status)) {
+      return Status;
     }
-
-    return Status;
   }
 
-  //
-  // Relocate the image in our new buffer
-  //
-  Status = PeCoffLoaderRelocateImage (&ImageContext);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  //
-  // Flush the instruction cache so the image data is written before we execute it
-  //
-  if (ImageContext.ImageAddress != (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data) {
-    InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
-  }
-
-  *ImageAddress = ImageContext.ImageAddress;
-  *ImageSize    = ImageContext.ImageSize;
-  *EntryPoint   = ImageContext.EntryPoint;
+  *ImageAddress = UefiImageLoaderGetImageAddress (ImageContext);
 
   return ReturnStatus;
 }
@@ -479,50 +349,30 @@ LoadAndRelocatePeCoffImage (
 
 **/
 EFI_STATUS
-LoadAndRelocatePeCoffImageInPlace (
+LoadAndRelocateUefiImageInPlace (
   IN  VOID  *Pe32Data,
-  IN  VOID  *ImageAddress
+  IN  VOID    *ImageAddress,
+  IN  UINT32  ImageSize
   )
 {
   EFI_STATUS                    Status;
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext;
 
-  ZeroMem (&ImageContext, sizeof (ImageContext));
-  ImageContext.Handle    = Pe32Data;
-  ImageContext.ImageRead = PeiImageRead;
+  ASSERT (Pe32Data != ImageAddress);
 
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);
+  CopyMem (ImageAddress, Pe32Data, ImageSize);
+
+  Status = UefiImageInitializeContext (&ImageContext, ImageAddress, ImageSize);
   if (EFI_ERROR (Status)) {
     ASSERT_EFI_ERROR (Status);
     return Status;
   }
 
-  ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)ImageAddress;
-
   //
   // Load the image in place
   //
-  Status = PeCoffLoaderLoadImage (&ImageContext);
-  if (EFI_ERROR (Status)) {
-    ASSERT_EFI_ERROR (Status);
-    return Status;
-  }
-
-  //
-  // Relocate the image in place
-  //
-  Status = PeCoffLoaderRelocateImage (&ImageContext);
-  if (EFI_ERROR (Status)) {
-    ASSERT_EFI_ERROR (Status);
-    return Status;
-  }
-
-  //
-  // Flush the instruction cache so the image data is written before we execute it
-  //
-  if (ImageContext.ImageAddress != (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data) {
-    InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
-  }
+  Status = UefiImageRelocateImageInplaceForExecution (&ImageContext);
+  ASSERT_EFI_ERROR (Status);
 
   return Status;
 }
@@ -540,7 +390,8 @@ LoadAndRelocatePeCoffImageInPlace (
 EFI_STATUS
 PeiGetPe32Data (
   IN     EFI_PEI_FILE_HANDLE  FileHandle,
-  OUT    VOID                 **Pe32Data
+  OUT    VOID                 **Pe32Data,
+  OUT    UINT32               *Pe32DataSize
   )
 {
   EFI_STATUS        Status;
@@ -562,22 +413,24 @@ PeiGetPe32Data (
   // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst
   // is true, TE will be searched first).
   //
-  Status = PeiServicesFfsFindSectionData3 (
+  Status = PeiServicesFfsFindSectionData4 (
              SearchType1,
              0,
              FileHandle,
              Pe32Data,
+             Pe32DataSize,
              &AuthenticationState
              );
   //
   // If we didn't find a first exe section, try to find the second exe section.
   //
   if (EFI_ERROR (Status)) {
-    Status = PeiServicesFfsFindSectionData3 (
+    Status = PeiServicesFfsFindSectionData4 (
                SearchType2,
                0,
                FileHandle,
                Pe32Data,
+               Pe32DataSize,
                &AuthenticationState
                );
   }
@@ -617,15 +470,13 @@ PeiLoadImageLoadImage (
 {
   EFI_STATUS            Status;
   VOID                  *Pe32Data;
+  UINT32                      Pe32DataSize;
   EFI_PHYSICAL_ADDRESS  ImageAddress;
-  UINT64                ImageSize;
-  EFI_PHYSICAL_ADDRESS  ImageEntryPoint;
-  UINT16                Machine;
   EFI_SECTION_TYPE      SearchType1;
   EFI_SECTION_TYPE      SearchType2;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext;
 
   *EntryPoint          = 0;
-  ImageSize            = 0;
   *AuthenticationState = 0;
 
   if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) {
@@ -640,22 +491,24 @@ PeiLoadImageLoadImage (
   // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst
   // is true, TE will be searched first).
   //
-  Status = PeiServicesFfsFindSectionData3 (
+  Status = PeiServicesFfsFindSectionData4 (
              SearchType1,
              0,
              FileHandle,
              &Pe32Data,
+             &Pe32DataSize,
              AuthenticationState
              );
   //
   // If we didn't find a first exe section, try to find the second exe section.
   //
   if (EFI_ERROR (Status)) {
-    Status = PeiServicesFfsFindSectionData3 (
+    Status = PeiServicesFfsFindSectionData4 (
                SearchType2,
                0,
                FileHandle,
                &Pe32Data,
+               &Pe32DataSize,
                AuthenticationState
                );
     if (EFI_ERROR (Status)) {
@@ -672,12 +525,12 @@ PeiLoadImageLoadImage (
   //
   // If memory is installed, perform the shadow operations
   //
-  Status = LoadAndRelocatePeCoffImage (
+  Status = LoadAndRelocateUefiImage (
              FileHandle,
              Pe32Data,
-             &ImageAddress,
-             &ImageSize,
-             &ImageEntryPoint
+    Pe32DataSize,
+    &ImageContext,
+    &ImageAddress
              );
 
   if (EFI_ERROR (Status)) {
@@ -687,83 +540,47 @@ PeiLoadImageLoadImage (
   //
   // Got the entry point from the loaded Pe32Data
   //
-  Pe32Data    = (VOID *)((UINTN)ImageAddress);
-  *EntryPoint = ImageEntryPoint;
-
-  Machine = PeCoffLoaderGetMachineType (Pe32Data);
-
-  if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {
-    if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Machine)) {
-      return EFI_UNSUPPORTED;
-    }
-  }
+  *EntryPoint = UefiImageLoaderGetImageEntryPoint (&ImageContext);
 
   if (ImageAddressArg != NULL) {
     *ImageAddressArg = ImageAddress;
   }
 
   if (ImageSizeArg != NULL) {
-    *ImageSizeArg = ImageSize;
+    *ImageSizeArg =UefiImageGetImageSize (&ImageContext);
   }
 
   DEBUG_CODE_BEGIN ();
-  CHAR8  *AsciiString;
-  CHAR8  EfiFileName[512];
-  INT32  Index;
-  INT32  StartIndex;
+    CHAR8  EfiFileName[512];
+    UINT16 Machine;
+
+    Machine = UefiImageGetMachine (&ImageContext);
 
-  //
-  // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi
-  //
-  if (Machine != EFI_IMAGE_MACHINE_IA64) {
-    DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)*EntryPoint));
-  } else {
     //
-    // For IPF Image, the real entry point should be print.
+    // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi
     //
-    DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint)));
-  }
-
-  //
-  // Print Module Name by PeImage PDB file name.
-  //
-  AsciiString = PeCoffLoaderGetPdbPointer (Pe32Data);
-
-  if (AsciiString != NULL) {
-    StartIndex = 0;
-    for (Index = 0; AsciiString[Index] != 0; Index++) {
-      if ((AsciiString[Index] == '\\') || (AsciiString[Index] == '/')) {
-        StartIndex = Index + 1;
-      }
+    if (Machine != EFI_IMAGE_MACHINE_IA64) {
+      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)*EntryPoint));
+    } else {
+      //
+      // For IPF Image, the real entry point should be print.
+      //
+      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint)));
     }
 
     //
-    // Copy the PDB file name to our temporary string, and replace .pdb with .efi
-    // The PDB file name is limited in the range of 0~511.
-    // If the length is bigger than 511, trim the redundant characters to avoid overflow in array boundary.
+    // Print Module Name by PeImage PDB file name.
     //
-    for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {
-      EfiFileName[Index] = AsciiString[Index + StartIndex];
-      if (EfiFileName[Index] == 0) {
-        EfiFileName[Index] = '.';
-      }
+    Status = UefiImageGetModuleNameFromSymbolsPath (
+               &ImageContext,
+               EfiFileName,
+               sizeof (EfiFileName)
+               );
 
-      if (EfiFileName[Index] == '.') {
-        EfiFileName[Index + 1] = 'e';
-        EfiFileName[Index + 2] = 'f';
-        EfiFileName[Index + 3] = 'i';
-        EfiFileName[Index + 4] = 0;
-        break;
-      }
+    if (!RETURN_ERROR (Status)) {
+      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName));
     }
 
-    if (Index == sizeof (EfiFileName) - 4) {
-      EfiFileName[Index] = 0;
-    }
-
-    DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName));
-  }
-
   DEBUG_CODE_END ();
 
   DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n"));
@@ -814,7 +631,7 @@ PeiLoadImageLoadImageWrapper (
   @retval FALSE      Relocation is not stripped.
 
 **/
-BOOLEAN
+/*BOOLEAN
 RelocationIsStrip (
   IN VOID  *Pe32Data
   )
@@ -863,7 +680,7 @@ RelocationIsStrip (
   }
 
   return FALSE;
-}
+}*/
 
 /**
   Routine to load image file for subsequent execution by LoadFile Ppi.
@@ -896,9 +713,9 @@ PeiLoadImage (
   EFI_PEI_LOAD_FILE_PPI  *LoadFile;
   EFI_PHYSICAL_ADDRESS   ImageAddress;
   UINT64                 ImageSize;
-  BOOLEAN                IsStrip;
+  //BOOLEAN                 IsStrip;
 
-  IsStrip = FALSE;
+  //IsStrip = FALSE;
   //
   // If any instances of PEI_LOAD_FILE_PPI are installed, they are called.
   // one at a time, until one reports EFI_SUCCESS.
@@ -924,7 +741,9 @@ PeiLoadImage (
         //
         // The shadowed PEIM must be relocatable.
         //
-        if (PeimState == PEIM_STATE_REGISTER_FOR_SHADOW) {
+        // FIXME:
+        /*if (PeimState == PEIM_STATE_REGISTER_FOR_SHADOW) {
+          // FIXME: Assumes headers were loaded into the image memory
           IsStrip = RelocationIsStrip ((VOID *)(UINTN)ImageAddress);
           ASSERT (!IsStrip);
           if (IsStrip) {
@@ -935,10 +754,10 @@ PeiLoadImage (
         //
         // The image to be started must have the machine type supported by PeiCore.
         //
-        ASSERT (EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCoffLoaderGetMachineType ((VOID *)(UINTN)ImageAddress)));
-        if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCoffLoaderGetMachineType ((VOID *)(UINTN)ImageAddress))) {
+        ASSERT (EFI_IMAGE_MACHINE_TYPE_SUPPORTED (UefiImageLoaderGetMachineType ((VOID *)(UINTN)ImageAddress)));
+        if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (UefiImageLoaderGetMachineType ((VOID *)(UINTN)ImageAddress))) {
           return EFI_UNSUPPORTED;
-        }
+        }*/
 
         return EFI_SUCCESS;
       }
diff --git a/MdeModulePkg/Core/Pei/PeiMain.h b/MdeModulePkg/Core/Pei/PeiMain.h
index 278e5a1087..278b6692da 100644
--- a/MdeModulePkg/Core/Pei/PeiMain.h
+++ b/MdeModulePkg/Core/Pei/PeiMain.h
@@ -36,12 +36,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/PerformanceLib.h>
 #include <Library/PeiServicesLib.h>
 #include <Library/ReportStatusCodeLib.h>
-#include <Library/PeCoffLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/CacheMaintenanceLib.h>
 #include <Library/PcdLib.h>
-#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/PeImage2.h>
 #include <Library/PeiServicesTablePointerLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/TimerLib.h>
@@ -312,7 +311,7 @@ struct _PEI_CORE_INSTANCE {
   //
   // This field points to the shadowed image read function
   //
-  PE_COFF_LOADER_READ_FILE          ShadowedImageRead;
+  VOID          *ShadowedImageRead;
 
   UINTN                             TempPeimCount;
 
@@ -929,6 +928,8 @@ PeiFfsFindNextFile (
   @param SectionSize          The file size to search.
   @param OutputBuffer         A pointer to the discovered section, if successful.
                               NULL if section not found.
+  @param OutputSize        The size of the discovered section, if successful.
+                           0 if section not found
   @param AuthenticationStatus Updated upon return to point to the authentication status for this section.
   @param IsFfs3Fv             Indicates the FV format.
 
@@ -944,6 +945,7 @@ ProcessSection (
   IN EFI_COMMON_SECTION_HEADER  *Section,
   IN UINTN                      SectionSize,
   OUT VOID                      **OutputBuffer,
+  OUT UINT32                    *OutputSize,
   OUT UINT32                    *AuthenticationStatus,
   IN BOOLEAN                    IsFfs3Fv
   );
@@ -995,6 +997,33 @@ PeiFfsFindSectionData3 (
   OUT UINT32                  *AuthenticationStatus
   );
 
+/**
+  Searches for the next matching section within the specified file.
+
+  @param  PeiServices           An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
+  @param  SectionType           The value of the section type to find.
+  @param  SectionInstance       Section instance to find.
+  @param  FileHandle            Handle of the firmware file to search.
+  @param  SectionData           A pointer to the discovered section, if successful.
+  @param  SectionDataSize       The size of the discovered section, if successful.
+  @param  AuthenticationStatus  A pointer to the authentication status for this section.
+
+  @retval EFI_SUCCESS      The section was found.
+  @retval EFI_NOT_FOUND    The section was not found.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiFfsFindSectionData4 (
+  IN CONST EFI_PEI_SERVICES    **PeiServices,
+  IN     EFI_SECTION_TYPE      SectionType,
+  IN     UINTN                 SectionInstance,
+  IN     EFI_PEI_FILE_HANDLE   FileHandle,
+  OUT VOID                     **SectionData,
+  OUT UINT32                   *SectionDataSize,
+  OUT UINT32                   *AuthenticationStatus
+  );
+
 /**
   Search the firmware volumes by index
 
@@ -1417,9 +1446,10 @@ InitializeImageServices (
 
 **/
 EFI_STATUS
-LoadAndRelocatePeCoffImageInPlace (
+LoadAndRelocateUefiImageInPlace (
   IN  VOID  *Pe32Data,
-  IN  VOID  *ImageAddress
+  IN  VOID    *ImageAddress,
+  IN  UINT32  ImageSize
   );
 
 /**
@@ -1435,7 +1465,8 @@ LoadAndRelocatePeCoffImageInPlace (
 EFI_STATUS
 PeiGetPe32Data (
   IN     EFI_PEI_FILE_HANDLE  FileHandle,
-  OUT    VOID                 **Pe32Data
+  OUT    VOID                         **Pe32Data,
+  OUT    UINT32                       *Pe32DataSize
   );
 
 /**
diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf b/MdeModulePkg/Core/Pei/PeiMain.inf
index 4cd58ee3aa..46d7e1c453 100644
--- a/MdeModulePkg/Core/Pei/PeiMain.inf
+++ b/MdeModulePkg/Core/Pei/PeiMain.inf
@@ -53,7 +53,6 @@
 
 [LibraryClasses]
   BaseMemoryLib
-  PeCoffGetEntryPointLib
   ReportStatusCodeLib
   PeiServicesLib
   PerformanceLib
@@ -63,7 +62,7 @@
   DebugLib
   MemoryAllocationLib
   CacheMaintenanceLib
-  PeCoffLib
+  UefiImageLib
   PeiServicesTablePointerLib
   PcdLib
   TimerLib
diff --git a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
index ff65e69f52..fb1b989038 100644
--- a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
+++ b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
@@ -65,6 +65,7 @@ EFI_PEI_SERVICES  gPs = {
   PeiFfsGetFileInfo2,
   PeiResetSystem2,
   PeiFreePages,
+  PeiFfsFindSectionData4
 };
 
 /**
diff --git a/MdeModulePkg/Core/Pei/Ppi/Ppi.c b/MdeModulePkg/Core/Pei/Ppi/Ppi.c
index 0e85264ddb..0184f206b9 100644
--- a/MdeModulePkg/Core/Pei/Ppi/Ppi.c
+++ b/MdeModulePkg/Core/Pei/Ppi/Ppi.c
@@ -1082,14 +1082,16 @@ ConvertPeiCorePpiPointers (
   IN  PEI_CORE_FV_HANDLE  *CoreFvHandle
   )
 {
-  EFI_FV_FILE_INFO      FileInfo;
-  EFI_PHYSICAL_ADDRESS  OrgImageBase;
-  EFI_PHYSICAL_ADDRESS  MigratedImageBase;
-  UINTN                 PeiCoreModuleSize;
-  EFI_PEI_FILE_HANDLE   PeiCoreFileHandle;
-  VOID                  *PeiCoreImageBase;
-  VOID                  *PeiCoreEntryPoint;
-  EFI_STATUS            Status;
+  EFI_FV_FILE_INFO                FileInfo;
+  EFI_PHYSICAL_ADDRESS            OrgImageBase;
+  EFI_PHYSICAL_ADDRESS            MigratedImageBase;
+  UINTN                           PeiCoreModuleSize;
+  EFI_PEI_FILE_HANDLE             PeiCoreFileHandle;
+  VOID                            *PeiCoreImageBase;
+  UINT32                          PeiCoreImageSize;
+  //VOID                           *PeiCoreEntryPoint;
+  EFI_STATUS                      Status;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext;
 
   PeiCoreFileHandle = NULL;
 
@@ -1108,17 +1110,18 @@ ConvertPeiCorePpiPointers (
     Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeiCoreFileHandle, &FileInfo);
     ASSERT_EFI_ERROR (Status);
 
-    Status = PeiGetPe32Data (PeiCoreFileHandle, &PeiCoreImageBase);
+    Status = PeiGetPe32Data (PeiCoreFileHandle, &PeiCoreImageBase, &PeiCoreImageSize);
     ASSERT_EFI_ERROR (Status);
 
     //
     // Find PEI Core EntryPoint in the BFV in temporary memory.
     //
-    Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)PeiCoreImageBase, &PeiCoreEntryPoint);
+    // FIXME: "Assume" sanity and skip full initialisation?
+    Status = UefiImageInitializeContext (&ImageContext, (VOID *) (UINTN) PeiCoreImageBase, PeiCoreImageSize);
     ASSERT_EFI_ERROR (Status);
 
     OrgImageBase      = (UINTN)PeiCoreImageBase;
-    MigratedImageBase = (UINTN)_ModuleEntryPoint - ((UINTN)PeiCoreEntryPoint - (UINTN)PeiCoreImageBase);
+    MigratedImageBase = (UINTN)_ModuleEntryPoint - UefiImageGetEntryPointAddress (&ImageContext);
 
     //
     // Size of loaded PEI_CORE in permanent memory.
diff --git a/MdeModulePkg/Core/PiSmmCore/DebugImageInfo.c b/MdeModulePkg/Core/PiSmmCore/DebugImageInfo.c
new file mode 100644
index 0000000000..1812eacc2d
--- /dev/null
+++ b/MdeModulePkg/Core/PiSmmCore/DebugImageInfo.c
@@ -0,0 +1,153 @@
+/** @file
+  Support functions for managing debug image info table when loading and unloading
+  images.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PiSmmCore.h"
+
+// FIXME: Unify with DXE
+
+EFI_DEBUG_IMAGE_INFO_TABLE_HEADER  mDebugInfoTableHeader = {
+  0,          // volatile UINT32                 UpdateStatus;
+  0,          // UINT32                          TableSize;
+  NULL        // EFI_DEBUG_IMAGE_INFO            *EfiDebugImageInfoTable;
+};
+
+UINTN mMaxTableEntries = 0;
+
+#define EFI_DEBUG_TABLE_ENTRY_SIZE       (sizeof (VOID *))
+
+/**
+  Creates and initializes the DebugImageInfo Table.  Also creates the configuration
+  table and registers it into the system table.
+
+**/
+VOID
+SmmInitializeDebugImageInfoTable (
+  VOID
+  )
+{
+  EFI_STATUS Status;
+
+  //
+  // Install the EFI_SYSTEM_TABLE_POINTER structure in the EFI System
+  // Configuration Table
+  //
+  Status = SmmInstallConfigurationTable (
+             gSmst,
+             &gEfiDebugImageInfoTableGuid,
+             &mDebugInfoTableHeader,
+             sizeof (mDebugInfoTableHeader)
+             );
+  ASSERT_EFI_ERROR (Status);
+}
+
+
+/**
+  Adds a new DebugImageInfo structure to the DebugImageInfo Table.  Re-Allocates
+  the table if it's not large enough to accomidate another entry.
+
+  @param  ImageInfoType  type of debug image information
+  @param  LoadedImage    pointer to the loaded image protocol for the image being
+                         loaded
+  @param  ImageHandle    image handle for the image being loaded
+
+**/
+VOID
+SmmNewDebugImageInfoEntry (
+  IN     UINT32                           ImageInfoType,
+  IN     EFI_LOADED_IMAGE_PROTOCOL        *LoadedImage,
+  IN     EFI_HANDLE                       ImageHandle,
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
+  )
+{
+  EFI_DEBUG_IMAGE_INFO        *Table;
+  EFI_DEBUG_IMAGE_INFO        *NewTable;
+  UINTN                       Index;
+  UINTN                       TableSize;
+  EFI_DEBUG_IMAGE_INFO_NORMAL *NormalImage;
+  RETURN_STATUS               Status;
+  CONST CHAR8                 *PdbPath;
+  UINT32                      PdbPathSize;
+
+  //
+  // Set the flag indicating that we're in the process of updating the table.
+  //
+  mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+
+  Table = mDebugInfoTableHeader.EfiDebugImageInfoTable;
+
+  if (mDebugInfoTableHeader.TableSize < mMaxTableEntries) {
+    //
+    // We still have empty entires in the Table, find the first empty entry.
+    //
+    Index = 0;
+    while (Table[Index].NormalImage != NULL) {
+      Index++;
+    }
+    //
+    // There must be an empty entry in the in the table.
+    //
+    ASSERT (Index < mMaxTableEntries);
+  } else {
+    //
+    //  Table is full, so re-allocate another page for a larger table...
+    //
+    TableSize = mMaxTableEntries * EFI_DEBUG_TABLE_ENTRY_SIZE;
+    NewTable = AllocateZeroPool (TableSize + EFI_PAGE_SIZE);
+    if (NewTable == NULL) {
+      mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+      return;
+    }
+    //
+    // Copy the old table into the new one
+    //
+    CopyMem (NewTable, Table, TableSize);
+    mDebugInfoTableHeader.EfiDebugImageInfoTable = NewTable;
+    //
+    // Enlarge the max table entries.
+    //
+    mMaxTableEntries += EFI_PAGE_SIZE / EFI_DEBUG_TABLE_ENTRY_SIZE;
+    //
+    // Free the old table
+    //
+    SmmFreePool (Table);
+    //
+    // Update the table header
+    //
+    Table = NewTable;
+    //
+    // Set the first empty entry index to be the original max table entries.
+    //
+    Index             = mMaxTableEntries;
+  }
+
+  //
+  // Allocate data for new entry
+  //
+  NormalImage = AllocateZeroPool (sizeof (EFI_DEBUG_IMAGE_INFO_NORMAL));
+  if (NormalImage != NULL) {
+    //
+    // Update the entry
+    //
+    NormalImage->ImageInfoType               = (UINT32) ImageInfoType;
+    NormalImage->LoadedImageProtocolInstance = LoadedImage;
+    NormalImage->ImageHandle                 = ImageHandle;
+
+    Status = UefiImageGetSymbolsPath (ImageContext, &PdbPath, &PdbPathSize);
+    if (!RETURN_ERROR (Status)) {
+      NormalImage->PdbPath = AllocateCopyPool (PdbPathSize, PdbPath);
+    }
+    //
+    // Increase the number of EFI_DEBUG_IMAGE_INFO elements and set the mDebugInfoTable in modified status.
+    //
+    mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED;
+    Table[Index].NormalImage = NormalImage;
+    mDebugInfoTableHeader.TableSize++;
+  }
+  mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+}
diff --git a/MdeModulePkg/Core/PiSmmCore/Dispatcher.c b/MdeModulePkg/Core/PiSmmCore/Dispatcher.c
index bb789e5890..dc22b9a7a5 100644
--- a/MdeModulePkg/Core/PiSmmCore/Dispatcher.c
+++ b/MdeModulePkg/Core/PiSmmCore/Dispatcher.c
@@ -33,7 +33,9 @@
 
 **/
 
+#include "Library/UefiImageLib.h"
 #include "PiSmmCore.h"
+#include "Uefi/UefiBaseType.h"
 
 //
 // SMM Dispatcher Data structures
@@ -213,84 +215,18 @@ CheckAndMarkFixLoadingMemoryUsageBitMap (
 
 **/
 EFI_STATUS
-GetPeCoffImageFixLoadingAssignedAddress (
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+GetUefiImageFixLoadingAssignedAddress (
+  OUT    EFI_PHYSICAL_ADDRESS          *LoadAddress,
+  IN     UINT64                        ValueInSectionHeader,
+  IN     UINT32                        ImageDestSize
   )
 {
-  UINTN                            SectionHeaderOffset;
-  EFI_STATUS                       Status;
-  EFI_IMAGE_SECTION_HEADER         SectionHeader;
-  EFI_IMAGE_OPTIONAL_HEADER_UNION  *ImgHdr;
-  EFI_PHYSICAL_ADDRESS             FixLoadingAddress;
-  UINT16                           Index;
-  UINTN                            Size;
-  UINT16                           NumberOfSections;
-  UINT64                           ValueInSectionHeader;
+  RETURN_STATUS        Status;
+  EFI_PHYSICAL_ADDRESS FixLoadingAddress;
 
-  FixLoadingAddress = 0;
-  Status            = EFI_NOT_FOUND;
-
-  //
-  // Get PeHeader pointer
-  //
-  ImgHdr              = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8 *)ImageContext->Handle + ImageContext->PeCoffHeaderOffset);
-  SectionHeaderOffset = ImageContext->PeCoffHeaderOffset +
-                        sizeof (UINT32) +
-                        sizeof (EFI_IMAGE_FILE_HEADER) +
-                        ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;
-  NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;
-
-  //
-  // Get base address from the first section header that doesn't point to code section.
-  //
-  for (Index = 0; Index < NumberOfSections; Index++) {
-    //
-    // Read section header from file
-    //
-    Size   = sizeof (EFI_IMAGE_SECTION_HEADER);
-    Status = ImageContext->ImageRead (
-                             ImageContext->Handle,
-                             SectionHeaderOffset,
-                             &Size,
-                             &SectionHeader
-                             );
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    Status = EFI_NOT_FOUND;
-
-    if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
-      //
-      // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
-      // that doesn't point to code section in image header.So there is an assumption that when the feature is enabled,
-      // if a module with a loading address assigned by tools, the PointerToRelocations & PointerToLineNumbers fields
-      // should not be Zero, or else, these 2 fields should be set to Zero
-      //
-      ValueInSectionHeader = ReadUnaligned64 ((UINT64 *)&SectionHeader.PointerToRelocations);
-      if (ValueInSectionHeader != 0) {
-        //
-        // Found first section header that doesn't point to code section in which build tool saves the
-        // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields
-        //
-        FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressSmramBase + (INT64)ValueInSectionHeader);
-        //
-        // Check if the memory range is available.
-        //
-        Status = CheckAndMarkFixLoadingMemoryUsageBitMap (FixLoadingAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));
-        if (!EFI_ERROR (Status)) {
-          //
-          // The assigned address is valid. Return the specified loading address
-          //
-          ImageContext->ImageAddress = FixLoadingAddress;
-        }
-      }
-
-      break;
-    }
-
-    SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
-  }
+  FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressSmramBase + ValueInSectionHeader);
+  Status = CheckAndMarkFixLoadingMemoryUsageBitMap (FixLoadingAddress, ImageDestSize);
+  *LoadAddress = FixLoadingAddress;
 
   DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r\n", FixLoadingAddress, Status));
   return Status;
@@ -307,24 +243,29 @@ GetPeCoffImageFixLoadingAssignedAddress (
 EFI_STATUS
 EFIAPI
 SmmLoadImage (
-  IN OUT EFI_SMM_DRIVER_ENTRY  *DriverEntry
+  IN OUT EFI_SMM_DRIVER_ENTRY            *DriverEntry,
+     OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT *ImageContext
   )
 {
   UINT32                         AuthenticationStatus;
   UINTN                          FilePathSize;
   VOID                           *Buffer;
   UINTN                          Size;
-  UINTN                          PageCount;
+  UINT32                         DstBufferPages;
   EFI_GUID                       *NameGuid;
   EFI_STATUS                     Status;
   EFI_STATUS                     SecurityStatus;
   EFI_HANDLE                     DeviceHandle;
-  EFI_PHYSICAL_ADDRESS           DstBuffer;
+  UINT32                         ImageSize;
+  UINT32                         ImageAlignment;
+  UINT64                         ValueInSectionHeader;
+  VOID                           *DstBuffer;
+  UINT32                         DstBufferSize;
   EFI_DEVICE_PATH_PROTOCOL       *FilePath;
   EFI_DEVICE_PATH_PROTOCOL       *OriginalFilePath;
   EFI_DEVICE_PATH_PROTOCOL       *HandleFilePath;
   EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv;
-  PE_COFF_LOADER_IMAGE_CONTEXT   ImageContext;
+  EFI_PHYSICAL_ADDRESS           LoadAddress;
 
   PERF_LOAD_IMAGE_BEGIN (DriverEntry->ImageHandle);
 
@@ -413,6 +354,18 @@ SmmLoadImage (
     return Status;
   }
 
+  //
+  // Get information about the image being loaded
+  //
+  Status = UefiImageInitializeContextPreHash (ImageContext, Buffer, (UINT32) Size);
+  if (EFI_ERROR (Status)) {
+    if (Buffer != NULL) {
+      gBS->FreePool (Buffer);
+    }
+    return Status;
+  }
+
+  // FIXME: Context?
   //
   // Verify File Authentication through the Security2 Architectural Protocol
   //
@@ -420,8 +373,8 @@ SmmLoadImage (
     SecurityStatus = mSecurity2->FileAuthentication (
                                    mSecurity2,
                                    OriginalFilePath,
-                                   Buffer,
-                                   Size,
+                                  ImageContext,
+                                  sizeof (*ImageContext),
                                    FALSE
                                    );
   }
@@ -444,24 +397,23 @@ SmmLoadImage (
     return Status;
   }
 
-  //
-  // Initialize ImageContext
-  //
-  ImageContext.Handle    = Buffer;
-  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
-
-  //
-  // Get information about the image being loaded
-  //
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);
-  if (EFI_ERROR (Status)) {
-    if (Buffer != NULL) {
-      gBS->FreePool (Buffer);
-    }
-
+  Status = UefiImageInitializeContextPostHash (ImageContext);
+  if (RETURN_ERROR (Status)) {
     return Status;
   }
 
+  //
+  // Stripped relocations are not supported for both fixed-address and dynamic
+  // loading.
+  //
+  if (UefiImageGetRelocsStripped (ImageContext)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  ImageSize      = UefiImageGetImageSize (ImageContext);
+  DstBufferPages = EFI_SIZE_TO_PAGES (ImageSize);
+  DstBufferSize  = EFI_PAGES_TO_SIZE (DstBufferPages);
+  ImageAlignment = UefiImageGetSegmentAlignment (ImageContext);
   //
   // if Loading module at Fixed Address feature is enabled, then  cut out a memory range started from TESG BASE
   // to hold the Smm driver code
@@ -470,102 +422,68 @@ SmmLoadImage (
     //
     // Get the fixed loading address assigned by Build tool
     //
-    Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext);
+    Status = UefiImageGetFixedAddress (ImageContext, &ValueInSectionHeader);
+    if (!RETURN_ERROR (Status)) {
+      Status = GetUefiImageFixLoadingAssignedAddress (&LoadAddress, ValueInSectionHeader, DstBufferSize);
+    }
+
     if (!EFI_ERROR (Status)) {
       //
       // Since the memory range to load Smm core already been cut out, so no need to allocate and free this range
       // following statements is to bypass SmmFreePages
       //
-      PageCount = 0;
-      DstBuffer = (UINTN)gLoadModuleAtFixAddressSmramBase;
+      DstBufferPages = 0;
+      DstBuffer      = (VOID *)(UINTN)LoadAddress;
     } else {
       DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));
       //
       // allocate the memory to load the SMM driver
       //
-      PageCount = (UINTN)EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize + ImageContext.SectionAlignment);
-      DstBuffer = (UINTN)(-1);
-
-      Status = SmmAllocatePages (
-                 AllocateMaxAddress,
-                 EfiRuntimeServicesCode,
-                 PageCount,
-                 &DstBuffer
-                 );
-      if (EFI_ERROR (Status)) {
+      DstBuffer = AllocateAlignedCodePages (DstBufferPages, ImageAlignment);
+      if (DstBuffer == NULL) {
         if (Buffer != NULL) {
           gBS->FreePool (Buffer);
         }
 
-        return Status;
-      }
-
-      ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;
+         return EFI_OUT_OF_RESOURCES;
+       }
     }
   } else {
-    PageCount = (UINTN)EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize + ImageContext.SectionAlignment);
-    DstBuffer = (UINTN)(-1);
-
-    Status = SmmAllocatePages (
-               AllocateMaxAddress,
-               EfiRuntimeServicesCode,
-               PageCount,
-               &DstBuffer
-               );
-    if (EFI_ERROR (Status)) {
+    DstBuffer = AllocateAlignedCodePages (DstBufferPages, ImageAlignment);
+    if (DstBuffer == NULL) {
       if (Buffer != NULL) {
         gBS->FreePool (Buffer);
       }
 
-      return Status;
+      return EFI_OUT_OF_RESOURCES;
     }
-
-    ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;
   }
 
-  //
-  // Align buffer on section boundary
-  //
-  ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
-  ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);
-
   //
   // Load the image to our new buffer
   //
-  Status = PeCoffLoaderLoadImage (&ImageContext);
+  Status = UefiImageLoadImageForExecution (
+    ImageContext,
+    DstBuffer,
+    DstBufferSize,
+    NULL,
+    0
+    );
   if (EFI_ERROR (Status)) {
     if (Buffer != NULL) {
       gBS->FreePool (Buffer);
     }
 
-    SmmFreePages (DstBuffer, PageCount);
+    FreeAlignedPages (DstBuffer, DstBufferPages);
     return Status;
   }
 
-  //
-  // Relocate the image in our new buffer
-  //
-  Status = PeCoffLoaderRelocateImage (&ImageContext);
-  if (EFI_ERROR (Status)) {
-    if (Buffer != NULL) {
-      gBS->FreePool (Buffer);
-    }
-
-    SmmFreePages (DstBuffer, PageCount);
-    return Status;
-  }
-
-  //
-  // Flush the instruction cache so the image data are written before we execute it
-  //
-  InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
-
   //
   // Save Image EntryPoint in DriverEntry
   //
-  DriverEntry->ImageEntryPoint = ImageContext.EntryPoint;
-  DriverEntry->ImageBuffer     = DstBuffer;
-  DriverEntry->NumberOfPage    = PageCount;
+  DriverEntry->ImageEntryPoint  = UefiImageLoaderGetImageEntryPoint (ImageContext);
+  DriverEntry->ImageBuffer      = (UINTN)DstBuffer;
+  DriverEntry->NumberOfPage    = DstBufferPages;
 
   //
   // Allocate a Loaded Image Protocol in EfiBootServicesData
@@ -576,7 +494,7 @@ SmmLoadImage (
       gBS->FreePool (Buffer);
     }
 
-    SmmFreePages (DstBuffer, PageCount);
+    FreeAlignedPages (DstBuffer, DstBufferPages);
     return Status;
   }
 
@@ -604,14 +522,14 @@ SmmLoadImage (
       gBS->FreePool (Buffer);
     }
 
-    SmmFreePages (DstBuffer, PageCount);
+    FreeAlignedPages (DstBuffer, DstBufferPages);
     return Status;
   }
 
   CopyMem (DriverEntry->LoadedImage->FilePath, FilePath, GetDevicePathSize (FilePath));
 
-  DriverEntry->LoadedImage->ImageBase     = (VOID *)(UINTN)ImageContext.ImageAddress;
-  DriverEntry->LoadedImage->ImageSize     = ImageContext.ImageSize;
+  DriverEntry->LoadedImage->ImageBase     = DstBuffer;
+  DriverEntry->LoadedImage->ImageSize     = ImageSize;
   DriverEntry->LoadedImage->ImageCodeType = EfiRuntimeServicesCode;
   DriverEntry->LoadedImage->ImageDataType = EfiRuntimeServicesData;
 
@@ -625,14 +543,14 @@ SmmLoadImage (
     }
 
     gBS->FreePool (DriverEntry->LoadedImage->FilePath);
-    SmmFreePages (DstBuffer, PageCount);
+    FreeAlignedPages (DstBuffer, DstBufferPages);
     return Status;
   }
 
-  CopyMem (DriverEntry->SmmLoadedImage.FilePath, FilePath, GetDevicePathSize (FilePath));
+  CopyMem (DriverEntry->SmmLoadedImage.FilePath, FilePath, GetDevicePathSize(FilePath));
 
-  DriverEntry->SmmLoadedImage.ImageBase     = (VOID *)(UINTN)ImageContext.ImageAddress;
-  DriverEntry->SmmLoadedImage.ImageSize     = ImageContext.ImageSize;
+  DriverEntry->SmmLoadedImage.ImageBase = DstBuffer;
+  DriverEntry->SmmLoadedImage.ImageSize = ImageSize;
   DriverEntry->SmmLoadedImage.ImageCodeType = EfiRuntimeServicesCode;
   DriverEntry->SmmLoadedImage.ImageDataType = EfiRuntimeServicesData;
 
@@ -660,60 +578,42 @@ SmmLoadImage (
 
   PERF_LOAD_IMAGE_END (DriverEntry->ImageHandle);
 
+  SmmInsertImageRecord (&DriverEntry->SmmLoadedImage, ImageContext);
+
+  //
+  // Register the image in the Debug Image Info Table if the attribute is set
+  //
+  SmmNewDebugImageInfoEntry (
+    EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL,
+    &DriverEntry->SmmLoadedImage,
+    DriverEntry->SmmImageHandle,
+    ImageContext
+    );
+
   //
   // Print the load address and the PDB file name if it is available
   //
 
   DEBUG_CODE_BEGIN ();
 
-  UINTN  Index;
-  UINTN  StartIndex;
-  CHAR8  EfiFileName[256];
+  CHAR8 EfiFileName[256];
 
-  DEBUG ((
-    DEBUG_INFO | DEBUG_LOAD,
-    "Loading SMM driver at 0x%11p EntryPoint=0x%11p ",
-    (VOID *)(UINTN)ImageContext.ImageAddress,
-    FUNCTION_ENTRY_POINT (ImageContext.EntryPoint)
-    ));
+  DEBUG ((DEBUG_INFO | DEBUG_LOAD,
+         "Loading SMM driver at 0x%11p EntryPoint=0x%11p ",
+         DstBuffer,
+         FUNCTION_ENTRY_POINT (UefiImageLoaderGetImageEntryPoint (ImageContext))));
 
   //
   // Print Module Name by Pdb file path.
   // Windows and Unix style file path are all trimmed correctly.
   //
-  if (ImageContext.PdbPointer != NULL) {
-    StartIndex = 0;
-    for (Index = 0; ImageContext.PdbPointer[Index] != 0; Index++) {
-      if ((ImageContext.PdbPointer[Index] == '\\') || (ImageContext.PdbPointer[Index] == '/')) {
-        StartIndex = Index + 1;
-      }
-    }
-
-    //
-    // Copy the PDB file name to our temporary string, and replace .pdb with .efi
-    // The PDB file name is limited in the range of 0~255.
-    // If the length is bigger than 255, trim the redundant characters to avoid overflow in array boundary.
-    //
-    for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {
-      EfiFileName[Index] = ImageContext.PdbPointer[Index + StartIndex];
-      if (EfiFileName[Index] == 0) {
-        EfiFileName[Index] = '.';
-      }
-
-      if (EfiFileName[Index] == '.') {
-        EfiFileName[Index + 1] = 'e';
-        EfiFileName[Index + 2] = 'f';
-        EfiFileName[Index + 3] = 'i';
-        EfiFileName[Index + 4] = 0;
-        break;
-      }
-    }
-
-    if (Index == sizeof (EfiFileName) - 4) {
-      EfiFileName[Index] = 0;
-    }
-
-    DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName));   // &Image->ImageContext.PdbPointer[StartIndex]));
+  Status = UefiImageGetModuleNameFromSymbolsPath (
+               ImageContext,
+               EfiFileName,
+               sizeof (EfiFileName)
+               );
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName));
   }
 
   DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n"));
@@ -852,11 +752,12 @@ SmmDispatcher (
   VOID
   )
 {
-  EFI_STATUS            Status;
-  LIST_ENTRY            *Link;
-  EFI_SMM_DRIVER_ENTRY  *DriverEntry;
-  BOOLEAN               ReadyToRun;
-  BOOLEAN               PreviousSmmEntryPointRegistered;
+  EFI_STATUS                      Status;
+  LIST_ENTRY                      *Link;
+  EFI_SMM_DRIVER_ENTRY            *DriverEntry;
+  BOOLEAN                         ReadyToRun;
+  BOOLEAN                         PreviousSmmEntryPointRegistered;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext;
 
   if (!gRequestDispatch) {
     return EFI_NOT_FOUND;
@@ -889,8 +790,7 @@ SmmDispatcher (
       // skip the LoadImage
       //
       if (DriverEntry->ImageHandle == NULL) {
-        Status = SmmLoadImage (DriverEntry);
-
+        Status = SmmLoadImage (DriverEntry, &ImageContext);
         //
         // Update the driver state to reflect that it's been loaded
         //
@@ -929,7 +829,7 @@ SmmDispatcher (
       //
       // For each SMM driver, pass NULL as ImageHandle
       //
-      RegisterSmramProfileImage (DriverEntry, TRUE);
+      RegisterSmramProfileImage (&DriverEntry->FileName, TRUE, &ImageContext);
       PERF_START_IMAGE_BEGIN (DriverEntry->ImageHandle);
       Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)DriverEntry->ImageEntryPoint)(DriverEntry->ImageHandle, gST);
       PERF_START_IMAGE_END (DriverEntry->ImageHandle);
@@ -940,7 +840,12 @@ SmmDispatcher (
           DriverEntry->SmmLoadedImage.ImageBase,
           Status
           ));
-        UnregisterSmramProfileImage (DriverEntry, TRUE);
+        UnregisterSmramProfileImage (
+          &DriverEntry->FileName,
+          (UINTN) DriverEntry->LoadedImage->ImageBase,
+          DriverEntry->LoadedImage->ImageSize,
+          TRUE
+          );
         SmmFreePages (DriverEntry->ImageBuffer, DriverEntry->NumberOfPage);
         //
         // Uninstall LoadedImage
diff --git a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/MemoryAllocationLib.c b/MdeModulePkg/Core/PiSmmCore/MemoryAllocation.c
similarity index 96%
rename from MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/MemoryAllocationLib.c
rename to MdeModulePkg/Core/PiSmmCore/MemoryAllocation.c
index 9a4d5b8cac..b81d637aef 100644
--- a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/MemoryAllocationLib.c
+++ b/MdeModulePkg/Core/PiSmmCore/MemoryAllocation.c
@@ -22,7 +22,8 @@
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
-#include "PiSmmCoreMemoryAllocationServices.h"
+#include "PiSmmCore.h"
+#include "PiSmmCorePrivateData.h"
 
 #include <Library/MemoryProfileLib.h>
 
diff --git a/MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c b/MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c
index 28fe74ecc4..c06bb409d4 100644
--- a/MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c
+++ b/MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c
@@ -16,12 +16,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/PcdLib.h>
 #include <Library/ImagePropertiesRecordLib.h>
 
-#include <Library/PeCoffLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/UefiImageLib.h>
 
 #include <Guid/PiSmmMemoryAttributesTable.h>
 
 #include "PiSmmCore.h"
+#include "ProcessorBind.h"
 
 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
   ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
@@ -31,7 +31,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 typedef struct {
   UINT32        Signature;
   UINTN         ImageRecordCount;
-  UINTN         CodeSegmentCountMax;
+  UINT32        NumberOfSectionsMax;
   LIST_ENTRY    ImageRecordList;
 } IMAGE_PROPERTIES_PRIVATE_DATA;
 
@@ -212,7 +212,10 @@ SmmCoreGetMemoryMapMemoryAttributesTable (
     return EFI_INVALID_PARAMETER;
   }
 
-  AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 3) * mImagePropertiesPrivateData.ImageRecordCount;
+  //
+  // Per image, they may be one trailer. There may be prefixed data.
+  //
+  AdditionalRecordCount = (mImagePropertiesPrivateData.NumberOfSectionsMax + 1) * mImagePropertiesPrivateData.ImageRecordCount + 1;
 
   OldMemoryMapSize = *MemoryMapSize;
   Status           = SmmCoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
@@ -251,6 +254,98 @@ SmmCoreGetMemoryMapMemoryAttributesTable (
 // Below functions are for ImageRecord
 //
 
+/**
+  Set MemoryProtectionAttribute according to PE/COFF image section alignment.
+
+  @param[in]  SectionAlignment    PE/COFF section alignment
+**/
+STATIC
+VOID
+SetMemoryAttributesTableSectionAlignment (
+  IN UINT32  SectionAlignment
+  )
+{
+  if (((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) &&
+      ((mMemoryProtectionAttribute & EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) != 0))
+  {
+    DEBUG ((DEBUG_VERBOSE, "SMM SetMemoryAttributesTableSectionAlignment - Clear\n"));
+    mMemoryProtectionAttribute &= ~((UINT64)EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA);
+  }
+}
+
+/**
+  Sort image record based upon the ImageBase from low to high.
+**/
+STATIC
+VOID
+InsertSortImageRecord (
+  IN UEFI_IMAGE_RECORD        *NewImageRecord
+  )
+{
+  UEFI_IMAGE_RECORD            *ImageRecord;
+  LIST_ENTRY                   *PrevImageRecordLink;
+  LIST_ENTRY                   *ImageRecordLink;
+  LIST_ENTRY                   *ImageRecordList;
+
+  ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
+
+  PrevImageRecordLink = ImageRecordList;
+  for (
+    ImageRecordLink = GetFirstNode (ImageRecordList);
+    !IsNull (ImageRecordLink, ImageRecordList);
+    ImageRecordLink = GetNextNode (ImageRecordList, PrevImageRecordLink)
+    ) {
+    ImageRecord = CR (
+                    ImageRecordLink,
+                    UEFI_IMAGE_RECORD,
+                    Link,
+                    UEFI_IMAGE_RECORD_SIGNATURE
+                    );
+    if (NewImageRecord->StartAddress < ImageRecord->StartAddress) {
+      break;
+    }
+
+    PrevImageRecordLink = ImageRecordLink;
+  }
+
+  InsertHeadList (PrevImageRecordLink, &NewImageRecord->Link);
+  mImagePropertiesPrivateData.ImageRecordCount++;
+
+  if (mImagePropertiesPrivateData.NumberOfSectionsMax < NewImageRecord->NumSegments) {
+    mImagePropertiesPrivateData.NumberOfSectionsMax = NewImageRecord->NumSegments;
+  }
+}
+
+/**
+  Dump image record.
+**/
+STATIC
+VOID
+DumpImageRecord (
+  VOID
+  )
+{
+  UEFI_IMAGE_RECORD            *ImageRecord;
+  LIST_ENTRY               *ImageRecordLink;
+  LIST_ENTRY               *ImageRecordList;
+  UINTN                    Index;
+
+  ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
+
+  for (ImageRecordLink = ImageRecordList->ForwardLink, Index = 0;
+       ImageRecordLink != ImageRecordList;
+       ImageRecordLink = ImageRecordLink->ForwardLink, Index++)
+  {
+    ImageRecord = CR (
+                    ImageRecordLink,
+                    UEFI_IMAGE_RECORD,
+                    Link,
+                    UEFI_IMAGE_RECORD_SIGNATURE
+                    );
+    DEBUG ((DEBUG_VERBOSE, "SMM  Image[%d]: 0x%016lx - 0x%016lx\n", Index, ImageRecord->StartAddress, ImageRecord->EndAddress - ImageRecord->StartAddress));
+  }
+}
+
 /**
   Insert image record.
 
@@ -258,82 +353,60 @@ SmmCoreGetMemoryMapMemoryAttributesTable (
 **/
 VOID
 SmmInsertImageRecord (
-  IN EFI_SMM_DRIVER_ENTRY  *DriverEntry
+  IN EFI_LOADED_IMAGE_PROTOCOL        *LoadedImage,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
   )
 {
-  EFI_STATUS               Status;
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  CHAR8                    *PdbPointer;
-  UINT32                   RequiredAlignment;
+  RETURN_STATUS      PdbStatus;
+  PHYSICAL_ADDRESS   ImageBuffer;
+  UINTN              NumberOfPage;
+  UINT32             SectionAlignment;
+  UEFI_IMAGE_RECORD  *ImageRecord;
+  CONST CHAR8        *PdbPointer;
+  UINT32             PdbSize;
 
-  DEBUG ((DEBUG_VERBOSE, "SMM InsertImageRecord - 0x%x\n", DriverEntry));
+  ImageBuffer  = (UINTN)LoadedImage->ImageBase;
+  NumberOfPage = EFI_SIZE_TO_PAGES((UINTN)LoadedImage->ImageSize);
 
-  ImageRecord = AllocatePool (sizeof (*ImageRecord));
+  DEBUG ((DEBUG_VERBOSE, "SMM InsertImageRecord - 0x%016lx - 0x%08x\n", ImageBuffer, NumberOfPage));
+
+  DEBUG ((DEBUG_VERBOSE, "SMM ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
+
+  PdbStatus = UefiImageGetSymbolsPath (ImageContext, &PdbPointer, &PdbSize);
+  if (!RETURN_ERROR (PdbStatus)) {
+    DEBUG ((DEBUG_VERBOSE, "SMM   Image - %a\n", PdbPointer));
+  }
+
+  //
+  // Get SectionAlignment
+  //
+  SectionAlignment = UefiImageGetSegmentAlignment (ImageContext);
+
+  SetMemoryAttributesTableSectionAlignment (SectionAlignment);
+  if ((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {
+    DEBUG ((
+      DEBUG_WARN,
+      "SMM !!!!!!!!  InsertImageRecord - Section Alignment(0x%x) is not %dK  !!!!!!!!\n",
+      SectionAlignment, RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10));
+    if (!RETURN_ERROR (PdbStatus)) {
+      DEBUG ((DEBUG_WARN, "SMM !!!!!!!!  Image - %a  !!!!!!!!\n", PdbPointer));
+    }
+
+    return;
+  }
+
+  //
+  // The image headers are not recorded among the sections, allocate one more.
+  //
+  ImageRecord = UefiImageLoaderGetImageRecord (ImageContext);
   if (ImageRecord == NULL) {
     return;
   }
 
-  InitializeListHead (&ImageRecord->Link);
-  InitializeListHead (&ImageRecord->CodeSegmentList);
+  UefiImageDebugPrintSegments (ImageContext);
+  UefiImageDebugPrintImageRecord (ImageRecord);
 
-  PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)DriverEntry->ImageBuffer);
-  if (PdbPointer != NULL) {
-    DEBUG ((DEBUG_VERBOSE, "SMM   Image - %a\n", PdbPointer));
-  }
-
-  RequiredAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
-  Status            = CreateImagePropertiesRecord (
-                        (VOID *)(UINTN)DriverEntry->ImageBuffer,
-                        LShiftU64 (DriverEntry->NumberOfPage, EFI_PAGE_SHIFT),
-                        &RequiredAlignment,
-                        ImageRecord
-                        );
-
-  if (EFI_ERROR (Status)) {
-    if (Status == EFI_ABORTED) {
-      mMemoryProtectionAttribute &=
-        ~((UINT64)EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA);
-    }
-
-    goto Finish;
-  }
-
-  if (ImageRecord->CodeSegmentCount == 0) {
-    mMemoryProtectionAttribute &=
-      ~((UINT64)EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA);
-    DEBUG ((DEBUG_ERROR, "SMM !!!!!!!!  InsertImageRecord - CodeSegmentCount is 0  !!!!!!!!\n"));
-    if (PdbPointer != NULL) {
-      DEBUG ((DEBUG_ERROR, "SMM !!!!!!!!  Image - %a  !!!!!!!!\n", PdbPointer));
-    }
-
-    Status = EFI_ABORTED;
-    goto Finish;
-  }
-
-  //
-  // Check overlap all section in ImageBase/Size
-  //
-  if (!IsImageRecordCodeSectionValid (ImageRecord)) {
-    DEBUG ((DEBUG_ERROR, "SMM IsImageRecordCodeSectionValid - FAIL\n"));
-    Status = EFI_ABORTED;
-    goto Finish;
-  }
-
-  InsertTailList (&mImagePropertiesPrivateData.ImageRecordList, &ImageRecord->Link);
-  mImagePropertiesPrivateData.ImageRecordCount++;
-
-  if (mImagePropertiesPrivateData.CodeSegmentCountMax < ImageRecord->CodeSegmentCount) {
-    mImagePropertiesPrivateData.CodeSegmentCountMax = ImageRecord->CodeSegmentCount;
-  }
-
-  SortImageRecord (&mImagePropertiesPrivateData.ImageRecordList);
-
-Finish:
-  if (EFI_ERROR (Status) && (ImageRecord != NULL)) {
-    DeleteImagePropertiesRecord (ImageRecord);
-  }
-
-  return;
+  InsertSortImageRecord (ImageRecord);
 }
 
 /**
@@ -418,60 +491,6 @@ PublishMemoryAttributesTable (
   ASSERT_EFI_ERROR (Status);
 }
 
-/**
-  This function installs all SMM image record information.
-**/
-VOID
-SmmInstallImageRecord (
-  VOID
-  )
-{
-  EFI_STATUS                 Status;
-  UINTN                      NoHandles;
-  EFI_HANDLE                 *HandleBuffer;
-  EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage;
-  UINTN                      Index;
-  EFI_SMM_DRIVER_ENTRY       DriverEntry;
-
-  Status = SmmLocateHandleBuffer (
-             ByProtocol,
-             &gEfiLoadedImageProtocolGuid,
-             NULL,
-             &NoHandles,
-             &HandleBuffer
-             );
-  if (EFI_ERROR (Status)) {
-    return;
-  }
-
-  for (Index = 0; Index < NoHandles; Index++) {
-    Status = gSmst->SmmHandleProtocol (
-                      HandleBuffer[Index],
-                      &gEfiLoadedImageProtocolGuid,
-                      (VOID **)&LoadedImage
-                      );
-    if (EFI_ERROR (Status)) {
-      continue;
-    }
-
-    DEBUG ((DEBUG_VERBOSE, "LoadedImage - 0x%x 0x%x ", LoadedImage->ImageBase, LoadedImage->ImageSize));
-    {
-      VOID  *PdbPointer;
-      PdbPointer = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);
-      if (PdbPointer != NULL) {
-        DEBUG ((DEBUG_VERBOSE, "(%a) ", PdbPointer));
-      }
-    }
-    DEBUG ((DEBUG_VERBOSE, "\n"));
-    ZeroMem (&DriverEntry, sizeof (DriverEntry));
-    DriverEntry.ImageBuffer  = (UINTN)LoadedImage->ImageBase;
-    DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN)LoadedImage->ImageSize);
-    SmmInsertImageRecord (&DriverEntry);
-  }
-
-  FreePool (HandleBuffer);
-}
-
 /**
   Install MemoryAttributesTable.
 
@@ -489,8 +508,6 @@ SmmInstallMemoryAttributesTable (
   IN EFI_HANDLE      Handle
   )
 {
-  SmmInstallImageRecord ();
-
   DEBUG ((DEBUG_VERBOSE, "SMM MemoryProtectionAttribute - 0x%016lx\n", mMemoryProtectionAttribute));
   if ((mMemoryProtectionAttribute & EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) {
     return EFI_SUCCESS;
@@ -500,7 +517,7 @@ SmmInstallMemoryAttributesTable (
   if ( mImagePropertiesPrivateData.ImageRecordCount > 0) {
     DEBUG ((DEBUG_INFO, "SMM - Total Runtime Image Count - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
     DEBUG ((DEBUG_INFO, "SMM - Dump Runtime Image Records:\n"));
-    DumpImageRecords (&mImagePropertiesPrivateData.ImageRecordList);
+    DumpImageRecord ();
   }
 
   DEBUG_CODE_END ();
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
index e957cb67f8..9f3e9392e8 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
@@ -815,7 +815,7 @@ SmmCoreInstallLoadedImage (
   mSmmCoreLoadedImage->SystemTable  = gST;
 
   mSmmCoreLoadedImage->ImageBase     = (VOID *)(UINTN)gSmmCorePrivate->PiSmmCoreImageBase;
-  mSmmCoreLoadedImage->ImageSize     = gSmmCorePrivate->PiSmmCoreImageSize;
+  mSmmCoreLoadedImage->ImageSize     = UefiImageGetImageSize (&gSmmCorePrivate->PiSmmCoreImageContext);
   mSmmCoreLoadedImage->ImageCodeType = EfiRuntimeServicesCode;
   mSmmCoreLoadedImage->ImageDataType = EfiRuntimeServicesData;
 
@@ -847,13 +847,13 @@ SmmCoreInstallLoadedImage (
   mSmmCoreDriverEntry->SmmLoadedImage.SystemTable  = gST;
 
   mSmmCoreDriverEntry->SmmLoadedImage.ImageBase     = (VOID *)(UINTN)gSmmCorePrivate->PiSmmCoreImageBase;
-  mSmmCoreDriverEntry->SmmLoadedImage.ImageSize     = gSmmCorePrivate->PiSmmCoreImageSize;
+  mSmmCoreDriverEntry->SmmLoadedImage.ImageSize     = UefiImageGetImageSize (&gSmmCorePrivate->PiSmmCoreImageContext);
   mSmmCoreDriverEntry->SmmLoadedImage.ImageCodeType = EfiRuntimeServicesCode;
   mSmmCoreDriverEntry->SmmLoadedImage.ImageDataType = EfiRuntimeServicesData;
 
-  mSmmCoreDriverEntry->ImageEntryPoint = gSmmCorePrivate->PiSmmCoreEntryPoint;
+  mSmmCoreDriverEntry->ImageEntryPoint = UefiImageLoaderGetImageEntryPoint (&gSmmCorePrivate->PiSmmCoreImageContext);
   mSmmCoreDriverEntry->ImageBuffer     = gSmmCorePrivate->PiSmmCoreImageBase;
-  mSmmCoreDriverEntry->NumberOfPage    = EFI_SIZE_TO_PAGES ((UINTN)gSmmCorePrivate->PiSmmCoreImageSize);
+  mSmmCoreDriverEntry->NumberOfPage    = EFI_SIZE_TO_PAGES ((UINTN)UefiImageGetImageSize (&gSmmCorePrivate->PiSmmCoreImageContext));
 
   //
   // Create a new image handle in the SMM handle database for the SMM Driver
@@ -867,6 +867,21 @@ SmmCoreInstallLoadedImage (
                                           );
   ASSERT_EFI_ERROR (Status);
 
+  SmmInsertImageRecord (&mSmmCoreDriverEntry->SmmLoadedImage, &gSmmCorePrivate->PiSmmCoreImageContext);
+
+  //
+  // Create the aligned system table pointer structure that is used by external
+  // debuggers to locate the system table...  Also, install debug image info
+  // configuration table.
+  //
+  SmmInitializeDebugImageInfoTable ();
+  SmmNewDebugImageInfoEntry (
+    EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL,
+    &mSmmCoreDriverEntry->SmmLoadedImage,
+    mSmmCoreDriverEntry->SmmImageHandle,
+    &gSmmCorePrivate->PiSmmCoreImageContext
+    );
+
   return;
 }
 
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h
index 60073c78b4..6b33a9d34a 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h
@@ -37,11 +37,11 @@
 #include <Guid/SmiHandlerProfile.h>
 #include <Guid/EndOfS3Resume.h>
 #include <Guid/S3SmmInitDone.h>
+#include <Guid/DebugImageInfoTable.h>
 
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
-#include <Library/PeCoffLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/CacheMaintenanceLib.h>
 #include <Library/DebugLib.h>
 #include <Library/ReportStatusCodeLib.h>
@@ -55,6 +55,7 @@
 #include <Library/HobLib.h>
 #include <Library/SmmMemLib.h>
 #include <Library/SafeIntLib.h>
+#include <Library/SmmServicesTableLib.h>
 
 #include "PiSmmCorePrivateData.h"
 #include "HeapGuard.h"
@@ -1020,8 +1021,9 @@ SmramProfileInstallProtocol (
 **/
 EFI_STATUS
 RegisterSmramProfileImage (
-  IN EFI_SMM_DRIVER_ENTRY  *DriverEntry,
-  IN BOOLEAN               RegisterToDxe
+  IN EFI_GUID                     *FileName,
+  IN BOOLEAN                      RegisterToDxe,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *ImageContext
   );
 
 /**
@@ -1038,8 +1040,10 @@ RegisterSmramProfileImage (
 **/
 EFI_STATUS
 UnregisterSmramProfileImage (
-  IN EFI_SMM_DRIVER_ENTRY  *DriverEntry,
-  IN BOOLEAN               UnregisterToDxe
+  IN EFI_GUID                           *FileName,
+  IN PHYSICAL_ADDRESS                   ImageBase,
+  IN UINT64                             ImageSize,
+  IN BOOLEAN                            UnregisterFromDxe
   );
 
 /**
@@ -1352,4 +1356,50 @@ SmmEntryPointMemoryManagementHook (
   VOID
   );
 
+/**
+  Creates and initializes the DebugImageInfo Table.  Also creates the configuration
+  table and registers it into the system table.
+
+  Note:
+    This function allocates memory, frees it, and then allocates memory at an
+    address within the initial allocation. Since this function is called early
+    in DXE core initialization (before drivers are dispatched), this should not
+    be a problem.
+
+**/
+VOID
+SmmInitializeDebugImageInfoTable (
+  VOID
+  );
+
+
+/**
+  Adds a new DebugImageInfo structure to the DebugImageInfo Table.  Re-Allocates
+  the table if it's not large enough to accomidate another entry.
+
+  @param  ImageInfoType  type of debug image information
+  @param  LoadedImage    pointer to the loaded image protocol for the image being
+                         loaded
+  @param  ImageHandle    image handle for the image being loaded
+
+**/
+VOID
+SmmNewDebugImageInfoEntry (
+  IN  UINT32                      ImageInfoType,
+  IN  EFI_LOADED_IMAGE_PROTOCOL   *LoadedImage,
+  IN  EFI_HANDLE                  ImageHandle,
+  IN  UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
+  );
+
+/**
+  Insert image record.
+
+  @param[in]  DriverEntry    Driver information
+**/
+VOID
+SmmInsertImageRecord (
+  IN EFI_LOADED_IMAGE_PROTOCOL        *LoadedImage,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
+  );
+
 #endif
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
index 75a5934f0c..d14f76b65f 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
@@ -37,6 +37,8 @@
   SmiHandlerProfile.c
   HeapGuard.c
   HeapGuard.h
+  MemoryAllocation.c
+  DebugImageInfo.c
 
 [Packages]
   MdePkg/MdePkg.dec
@@ -46,8 +48,7 @@
   UefiDriverEntryPoint
   BaseLib
   BaseMemoryLib
-  PeCoffLib
-  PeCoffGetEntryPointLib
+  UefiImageLib
   CacheMaintenanceLib
   DebugLib
   ReportStatusCodeLib
@@ -99,6 +100,7 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPoolType                   ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask               ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable                        ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxEfiSystemTablePointerAddress     ## CONSUMES
 
 [Guids]
   gAprioriGuid                                  ## SOMETIMES_CONSUMES   ## File
@@ -120,6 +122,7 @@
   gSmiHandlerProfileGuid
   gEdkiiEndOfS3ResumeGuid ## SOMETIMES_PRODUCES ## GUID # Install protocol
   gEdkiiS3SmmInitDoneGuid ## SOMETIMES_PRODUCES ## GUID # Install protocol
+  gEfiDebugImageInfoTableGuid                   ## PRODUCES             ## SystemTable
 
 [UserExtensions.TianoCore."ExtraFiles"]
   PiSmmCoreExtra.uni
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCorePrivateData.h b/MdeModulePkg/Core/PiSmmCore/PiSmmCorePrivateData.h
index d8fe2dd9b9..301b9b4656 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmCorePrivateData.h
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCorePrivateData.h
@@ -22,6 +22,7 @@
 /// the SMM Entry Point enabling the use of SMM Mode.  In this case, the SMM Core
 /// should be notified again to dispatch more SMM Drivers using SMM Mode.
 ///
+#include "Library/UefiImageLib.h"
 #define COMM_BUFFER_SMM_DISPATCH_ERROR    0x00
 #define COMM_BUFFER_SMM_DISPATCH_SUCCESS  0x01
 #define COMM_BUFFER_SMM_DISPATCH_RESTART  0x02
@@ -112,8 +113,7 @@ typedef struct {
   EFI_STATUS               ReturnStatus;
 
   EFI_PHYSICAL_ADDRESS     PiSmmCoreImageBase;
-  UINT64                   PiSmmCoreImageSize;
-  EFI_PHYSICAL_ADDRESS     PiSmmCoreEntryPoint;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT    PiSmmCoreImageContext;
 } SMM_CORE_PRIVATE_DATA;
 
 #endif
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
index fbba868fd0..524a74bdc4 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
@@ -23,7 +23,7 @@
 
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/CacheMaintenanceLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/DebugLib.h>
@@ -36,6 +36,8 @@
 #include <Library/ReportStatusCodeLib.h>
 #include "PiSmmCorePrivateData.h"
 #include <Library/SafeIntLib.h>
+#include "ProcessorBind.h"
+#include "Uefi/UefiBaseType.h"
 
 #define SMRAM_CAPABILITIES  (EFI_MEMORY_WB | EFI_MEMORY_UC)
 
@@ -913,91 +915,41 @@ SmmIplSetVirtualAddressNotify (
   @retval EFI_NOT_FOUND             The image has no assigned fixed loading address.
 **/
 EFI_STATUS
-GetPeCoffImageFixLoadingAssignedAddress (
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
+GetUefiImageFixLoadingAssignedAddress (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext,
+  OUT    EFI_PHYSICAL_ADDRESS          *LoadAddress
   )
 {
-  UINTN                            SectionHeaderOffset;
-  EFI_STATUS                       Status;
-  EFI_IMAGE_SECTION_HEADER         SectionHeader;
-  EFI_IMAGE_OPTIONAL_HEADER_UNION  *ImgHdr;
-  EFI_PHYSICAL_ADDRESS             FixLoadingAddress;
-  UINT16                           Index;
-  UINTN                            Size;
-  UINT16                           NumberOfSections;
-  EFI_PHYSICAL_ADDRESS             SmramBase;
-  UINT64                           SmmCodeSize;
-  UINT64                           ValueInSectionHeader;
+  EFI_STATUS           Status;
+  UINT64               ValueInSectionHeader;
+  EFI_PHYSICAL_ADDRESS FixLoadingAddress;
+  UINT32               SizeOfImage;
+  EFI_PHYSICAL_ADDRESS SmramBase;
+  UINT64               SmmCodeSize;
 
+  Status = UefiImageGetFixedAddress (ImageContext, &ValueInSectionHeader);
+  if (RETURN_ERROR (Status)) {
+    return Status;
+  }
   //
   // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber
   //
-  SmmCodeSize = EFI_PAGES_TO_SIZE (PcdGet32 (PcdLoadFixAddressSmmCodePageNumber));
+  SmmCodeSize = EFI_PAGES_TO_SIZE (PcdGet32(PcdLoadFixAddressSmmCodePageNumber));
+  SmramBase = mLMFAConfigurationTable->SmramBase;
 
-  FixLoadingAddress = 0;
-  Status            = EFI_NOT_FOUND;
-  SmramBase         = mLMFAConfigurationTable->SmramBase;
-  //
-  // Get PeHeader pointer
-  //
-  ImgHdr              = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8 *)ImageContext->Handle + ImageContext->PeCoffHeaderOffset);
-  SectionHeaderOffset = ImageContext->PeCoffHeaderOffset +
-                        sizeof (UINT32) +
-                        sizeof (EFI_IMAGE_FILE_HEADER) +
-                        ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;
-  NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;
+  FixLoadingAddress = SmramBase + ValueInSectionHeader;
+  SizeOfImage = UefiImageGetImageSize (ImageContext);
 
-  //
-  // Get base address from the first section header that doesn't point to code section.
-  //
-  for (Index = 0; Index < NumberOfSections; Index++) {
+  if (SmramBase + SmmCodeSize >= FixLoadingAddress + SizeOfImage
+   && SmramBase <= FixLoadingAddress) {
     //
-    // Read section header from file
+    // The assigned address is valid. Return the specified loading address
     //
-    Size   = sizeof (EFI_IMAGE_SECTION_HEADER);
-    Status = ImageContext->ImageRead (
-                             ImageContext->Handle,
-                             SectionHeaderOffset,
-                             &Size,
-                             &SectionHeader
-                             );
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-
-    Status = EFI_NOT_FOUND;
-
-    if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
-      //
-      // Build tool saves the offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields in the
-      // first section header that doesn't point to code section in image header. And there is an assumption that when the
-      // feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers
-      // fields should NOT be Zero, or else, these 2 fields should be set to Zero
-      //
-      ValueInSectionHeader = ReadUnaligned64 ((UINT64 *)&SectionHeader.PointerToRelocations);
-      if (ValueInSectionHeader != 0) {
-        //
-        // Found first section header that doesn't point to code section in which build tool saves the
-        // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields
-        //
-        FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(SmramBase + (INT64)ValueInSectionHeader);
-
-        if ((SmramBase + SmmCodeSize > FixLoadingAddress) && (SmramBase <=  FixLoadingAddress)) {
-          //
-          // The assigned address is valid. Return the specified loading address
-          //
-          ImageContext->ImageAddress = FixLoadingAddress;
-          Status                     = EFI_SUCCESS;
-        }
-      }
-
-      break;
-    }
-
-    SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
+    *LoadAddress = FixLoadingAddress;
+    Status = EFI_SUCCESS;
   }
 
-  DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r \n", FixLoadingAddress, Status));
+  DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r \n", FixLoadingAddress, Status));
   return Status;
 }
 
@@ -1024,9 +976,14 @@ ExecuteSmmCoreFromSmram (
   EFI_STATUS                    Status;
   VOID                          *SourceBuffer;
   UINTN                         SourceSize;
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
+  UINT32                        ImageSize;
+  UINT32                        ImageAlignment;
+  UINT32                        DestinationPages;
+  UINT32                        DestinationSize;
+  UINT32                        AlignSubtrahend;
   UINTN                         PageCount;
   EFI_IMAGE_ENTRY_POINT         EntryPoint;
+  EFI_PHYSICAL_ADDRESS          LoadAddress;
 
   //
   // Search all Firmware Volumes for a PE/COFF image in a file of type SMM_CORE
@@ -1043,20 +1000,26 @@ ExecuteSmmCoreFromSmram (
     return Status;
   }
 
-  //
-  // Initialize ImageContext
-  //
-  ImageContext.Handle    = SourceBuffer;
-  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
-
   //
   // Get information about the image being loaded
   //
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);
+  Status = UefiImageInitializeContext (&gSmmCorePrivate->PiSmmCoreImageContext, SourceBuffer, (UINT32) SourceSize);
   if (EFI_ERROR (Status)) {
     return Status;
   }
 
+  //
+  // Stripped relocations are not supported for both fixed-address and dynamic
+  // loading.
+  //
+  if (UefiImageGetRelocsStripped (&gSmmCorePrivate->PiSmmCoreImageContext)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  ImageSize        = UefiImageGetImageSize (&gSmmCorePrivate->PiSmmCoreImageContext);
+  DestinationPages = EFI_SIZE_TO_PAGES (ImageSize);
+  DestinationSize  = EFI_PAGES_TO_SIZE (DestinationPages);
+  ImageAlignment   = UefiImageGetSegmentAlignment (&gSmmCorePrivate->PiSmmCoreImageContext);
   //
   // if Loading module at Fixed Address feature is enabled, the SMM core driver will be loaded to
   // the address assigned by build tool.
@@ -1065,7 +1028,7 @@ ExecuteSmmCoreFromSmram (
     //
     // Get the fixed loading address assigned by Build tool
     //
-    Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext);
+    Status = GetUefiImageFixLoadingAssignedAddress (&gSmmCorePrivate->PiSmmCoreImageContext, &LoadAddress);
     if (!EFI_ERROR (Status)) {
       //
       // Since the memory range to load SMM CORE will be cut out in SMM core, so no need to allocate and free this range
@@ -1081,7 +1044,11 @@ ExecuteSmmCoreFromSmram (
       // Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR
       // specified by SmramRange
       //
-      PageCount = (UINTN)EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize + ImageContext.SectionAlignment);
+      AlignSubtrahend = ALIGN_VALUE_SUBTRAHEND (
+                          SmramRange->CpuStart + SmramRange->PhysicalSize,
+                          ImageAlignment
+                          );
+      PageCount = (UINTN)DestinationPages + (UINTN)EFI_SIZE_TO_PAGES ((UINTN)AlignSubtrahend);
 
       ASSERT ((SmramRange->PhysicalSize & EFI_PAGE_MASK) == 0);
       ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));
@@ -1095,14 +1062,18 @@ ExecuteSmmCoreFromSmram (
       //
       // Align buffer on section boundary
       //
-      ImageContext.ImageAddress = SmramRangeSmmCore->CpuStart;
+      LoadAddress = SmramRangeSmmCore->CpuStart;
     }
   } else {
     //
     // Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR
     // specified by SmramRange
     //
-    PageCount = (UINTN)EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize + ImageContext.SectionAlignment);
+    AlignSubtrahend = ALIGN_VALUE_SUBTRAHEND (
+                        SmramRange->CpuStart + SmramRange->PhysicalSize,
+                        ImageAlignment
+                        );
+    PageCount = (UINTN)DestinationPages + (UINTN)EFI_SIZE_TO_PAGES ((UINTN)AlignSubtrahend);
 
     ASSERT ((SmramRange->PhysicalSize & EFI_PAGE_MASK) == 0);
     ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));
@@ -1116,50 +1087,34 @@ ExecuteSmmCoreFromSmram (
     //
     // Align buffer on section boundary
     //
-    ImageContext.ImageAddress = SmramRangeSmmCore->CpuStart;
+    LoadAddress = SmramRangeSmmCore->CpuStart;
   }
 
-  ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
-  ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);
-
   //
   // Print debug message showing SMM Core load address.
   //
-  DEBUG ((DEBUG_INFO, "SMM IPL loading SMM Core at SMRAM address %p\n", (VOID *)(UINTN)ImageContext.ImageAddress));
+  DEBUG ((DEBUG_INFO, "SMM IPL loading SMM Core at SMRAM destination %p\n", (VOID *)(UINTN)LoadAddress));
 
   //
   // Load the image to our new buffer
   //
-  Status = PeCoffLoaderLoadImage (&ImageContext);
+  Status = UefiImageLoadImageForExecution (&gSmmCorePrivate->PiSmmCoreImageContext, (VOID *)(UINTN)LoadAddress, DestinationSize, NULL, 0);
   if (!EFI_ERROR (Status)) {
+    LoadAddress = UefiImageLoaderGetImageAddress (&gSmmCorePrivate->PiSmmCoreImageContext);
     //
-    // Relocate the image in our new buffer
+    // Print debug message showing SMM Core entry point address.
     //
-    Status = PeCoffLoaderRelocateImage (&ImageContext);
-    if (!EFI_ERROR (Status)) {
-      //
-      // Flush the instruction cache so the image data are written before we execute it
-      //
-      InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
+    DEBUG ((DEBUG_INFO, "SMM IPL calling SMM Core at SMRAM address %p\n", (VOID *)(UINTN)(UefiImageLoaderGetImageEntryPoint (&gSmmCorePrivate->PiSmmCoreImageContext))));
 
-      //
-      // Print debug message showing SMM Core entry point address.
-      //
-      DEBUG ((DEBUG_INFO, "SMM IPL calling SMM Core at SMRAM address %p\n", (VOID *)(UINTN)ImageContext.EntryPoint));
+    gSmmCorePrivate->PiSmmCoreImageBase = LoadAddress;
+    DEBUG ((DEBUG_INFO, "PiSmmCoreImageBase - 0x%016lx\n", gSmmCorePrivate->PiSmmCoreImageBase));
+    DEBUG ((DEBUG_INFO, "PiSmmCoreImageSize - 0x%016lx\n", UefiImageGetImageSize (&gSmmCorePrivate->PiSmmCoreImageContext)));
 
-      gSmmCorePrivate->PiSmmCoreImageBase = ImageContext.ImageAddress;
-      gSmmCorePrivate->PiSmmCoreImageSize = ImageContext.ImageSize;
-      DEBUG ((DEBUG_INFO, "PiSmmCoreImageBase - 0x%016lx\n", gSmmCorePrivate->PiSmmCoreImageBase));
-      DEBUG ((DEBUG_INFO, "PiSmmCoreImageSize - 0x%016lx\n", gSmmCorePrivate->PiSmmCoreImageSize));
-
-      gSmmCorePrivate->PiSmmCoreEntryPoint = ImageContext.EntryPoint;
-
-      //
-      // Execute image
-      //
-      EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)ImageContext.EntryPoint;
-      Status     = EntryPoint ((EFI_HANDLE)Context, gST);
-    }
+    //
+    // Execute image
+    //
+    EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)(UefiImageLoaderGetImageEntryPoint (&gSmmCorePrivate->PiSmmCoreImageContext));
+    Status = EntryPoint ((EFI_HANDLE)Context, gST);
   }
 
   //
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
index ddeb39cee2..60d14cd59c 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
@@ -35,7 +35,7 @@
   UefiDriverEntryPoint
   BaseLib
   BaseMemoryLib
-  PeCoffLib
+  UefiImageLib
   CacheMaintenanceLib
   MemoryAllocationLib
   DebugLib
diff --git a/MdeModulePkg/Core/PiSmmCore/SmiHandlerProfile.c b/MdeModulePkg/Core/PiSmmCore/SmiHandlerProfile.c
index e48532c0fb..2944522ca7 100644
--- a/MdeModulePkg/Core/PiSmmCore/SmiHandlerProfile.c
+++ b/MdeModulePkg/Core/PiSmmCore/SmiHandlerProfile.c
@@ -17,7 +17,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/PrintLib.h>
 #include <Library/UefiLib.h>
 #include <Library/DevicePathLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
 #include <Protocol/LoadedImage.h>
 #include <Protocol/SmmAccess2.h>
 #include <Protocol/SmmReadyToLock.h>
@@ -74,7 +73,7 @@ BuildSmiHandlerProfileDatabase (
 
 **/
 RETURN_STATUS
-InternalPeCoffGetEntryPoint (
+InternalUefiImageGetEntryPoint (
   IN  VOID  *Pe32Data,
   OUT VOID  **EntryPoint
   );
@@ -264,7 +263,6 @@ GetSmmLoadedImage (
   CHAR16                     *PathStr;
   EFI_SMM_DRIVER_ENTRY       *LoadedImagePrivate;
   PHYSICAL_ADDRESS           EntryPoint;
-  VOID                       *EntryPointInImage;
   EFI_GUID                   Guid;
   CHAR8                      *PdbString;
   PHYSICAL_ADDRESS           RealImageBase;
@@ -324,15 +322,6 @@ GetSmmLoadedImage (
     RealImageBase      = (UINTN)LoadedImage->ImageBase;
     if (LoadedImagePrivate->Signature == EFI_SMM_DRIVER_ENTRY_SIGNATURE) {
       EntryPoint = LoadedImagePrivate->ImageEntryPoint;
-      if ((EntryPoint != 0) && ((EntryPoint < (UINTN)LoadedImage->ImageBase) || (EntryPoint >= ((UINTN)LoadedImage->ImageBase + LoadedImage->ImageSize)))) {
-        //
-        // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
-        // So patch ImageBuffer here to align the EntryPoint.
-        //
-        Status = InternalPeCoffGetEntryPoint (LoadedImage->ImageBase, &EntryPointInImage);
-        ASSERT_EFI_ERROR (Status);
-        RealImageBase = (UINTN)LoadedImage->ImageBase + EntryPoint - (UINTN)EntryPointInImage;
-      }
     }
 
     DEBUG ((DEBUG_INFO, "(0x%lx - 0x%lx", RealImageBase, LoadedImage->ImageSize));
@@ -342,10 +331,11 @@ GetSmmLoadedImage (
 
     DEBUG ((DEBUG_INFO, ")\n"));
 
-    if (RealImageBase != 0) {
-      PdbString = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)RealImageBase);
+    // FIXME:
+    /*if (RealImageBase != 0) {
+      PdbString = UefiImageLoaderGetPdbPointer ((VOID *)(UINTN)RealImageBase);
       DEBUG ((DEBUG_INFO, "       pdb - %a\n", PdbString));
-    } else {
+    } else*/ {
       PdbString = NULL;
     }
 
diff --git a/MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c b/MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
index b437e4c433..1fa33efbbe 100644
--- a/MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
+++ b/MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
@@ -128,8 +128,7 @@ EFIAPI
 SmramProfileProtocolRegisterImage (
   IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL  *This,
   IN EFI_DEVICE_PATH_PROTOCOL           *FilePath,
-  IN PHYSICAL_ADDRESS                   ImageBase,
-  IN UINT64                             ImageSize,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT    *ImageContext,
   IN EFI_FV_FILETYPE                    FileType
   );
 
@@ -249,110 +248,6 @@ GetSmramProfileContext (
   return mSmramProfileContextPtr;
 }
 
-/**
-  Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.
-  If Pe32Data is NULL, then ASSERT().
-
-  @param Pe32Data   The pointer to the PE/COFF image that is loaded in system memory.
-
-  @return The Subsystem of the PE/COFF image.
-
-**/
-UINT16
-InternalPeCoffGetSubsystem (
-  IN VOID  *Pe32Data
-  )
-{
-  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;
-  EFI_IMAGE_DOS_HEADER                 *DosHdr;
-  UINT16                               Magic;
-
-  ASSERT (Pe32Data != NULL);
-
-  DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
-  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
-    //
-    // DOS image header is present, so read the PE header after the DOS image header.
-    //
-    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));
-  } else {
-    //
-    // DOS image header is not present, so PE header is at the image base.
-    //
-    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
-  }
-
-  if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
-    return Hdr.Te->Subsystem;
-  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
-    Magic = Hdr.Pe32->OptionalHeader.Magic;
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-      return Hdr.Pe32->OptionalHeader.Subsystem;
-    } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
-      return Hdr.Pe32Plus->OptionalHeader.Subsystem;
-    }
-  }
-
-  return 0x0000;
-}
-
-/**
-  Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
-  into system memory with the PE/COFF Loader Library functions.
-
-  Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
-  point in EntryPoint.  If the entry point could not be retrieved from the PE/COFF image, then
-  return RETURN_INVALID_PARAMETER.  Otherwise return RETURN_SUCCESS.
-  If Pe32Data is NULL, then ASSERT().
-  If EntryPoint is NULL, then ASSERT().
-
-  @param  Pe32Data                  The pointer to the PE/COFF image that is loaded in system memory.
-  @param  EntryPoint                The pointer to entry point to the PE/COFF image to return.
-
-  @retval RETURN_SUCCESS            EntryPoint was returned.
-  @retval RETURN_INVALID_PARAMETER  The entry point could not be found in the PE/COFF image.
-
-**/
-RETURN_STATUS
-InternalPeCoffGetEntryPoint (
-  IN  VOID  *Pe32Data,
-  OUT VOID  **EntryPoint
-  )
-{
-  EFI_IMAGE_DOS_HEADER                 *DosHdr;
-  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;
-
-  ASSERT (Pe32Data   != NULL);
-  ASSERT (EntryPoint != NULL);
-
-  DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
-  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
-    //
-    // DOS image header is present, so read the PE header after the DOS image header.
-    //
-    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));
-  } else {
-    //
-    // DOS image header is not present, so PE header is at the image base.
-    //
-    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
-  }
-
-  //
-  // Calculate the entry point relative to the start of the image.
-  // AddressOfEntryPoint is common for PE32 & PE32+
-  //
-  if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
-    *EntryPoint = (VOID *)((UINTN)Pe32Data + (UINTN)(Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);
-    return RETURN_SUCCESS;
-  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
-    *EntryPoint = (VOID *)((UINTN)Pe32Data + (UINTN)(Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));
-    return RETURN_SUCCESS;
-  }
-
-  return RETURN_UNSUPPORTED;
-}
-
 /**
   Build driver info.
 
@@ -371,30 +266,26 @@ MEMORY_PROFILE_DRIVER_INFO_DATA *
 BuildDriverInfo (
   IN MEMORY_PROFILE_CONTEXT_DATA  *ContextData,
   IN EFI_GUID                     *FileName,
-  IN PHYSICAL_ADDRESS             ImageBase,
-  IN UINT64                       ImageSize,
-  IN PHYSICAL_ADDRESS             EntryPoint,
-  IN UINT16                       ImageSubsystem,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT   *ImageContext,
+  IN EFI_PHYSICAL_ADDRESS           LoadAddress,
   IN EFI_FV_FILETYPE              FileType
   )
 {
+  RETURN_STATUS                     PdbStatus;
   EFI_STATUS                       Status;
   MEMORY_PROFILE_DRIVER_INFO       *DriverInfo;
-  MEMORY_PROFILE_DRIVER_INFO_DATA  *DriverInfoData;
-  VOID                             *EntryPointInImage;
-  CHAR8                            *PdbString;
-  UINTN                            PdbSize;
-  UINTN                            PdbOccupiedSize;
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
+  CONST CHAR8                       *PdbString;
+  UINT32                            PdbSize;
+  UINTN                             PdbOccupiedSize;
 
-  PdbSize         = 0;
   PdbOccupiedSize = 0;
-  PdbString       = NULL;
-  if (ImageBase != 0) {
-    PdbString = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageBase);
-    if (PdbString != NULL) {
-      PdbSize         = AsciiStrSize (PdbString);
-      PdbOccupiedSize = GET_OCCUPIED_SIZE (PdbSize, sizeof (UINT64));
-    }
+
+  ASSERT (UefiImageLoaderGetImageAddress (ImageContext) != 0);
+
+  PdbStatus = UefiImageGetSymbolsPath (ImageContext, &PdbString, &PdbSize);
+  if (!EFI_ERROR (PdbStatus)) {
+    PdbOccupiedSize = GET_OCCUPIED_SIZE (PdbSize, sizeof (UINT64));
   }
 
   //
@@ -422,19 +313,10 @@ BuildDriverInfo (
     CopyMem (&DriverInfo->FileName, FileName, sizeof (EFI_GUID));
   }
 
-  DriverInfo->ImageBase      = ImageBase;
-  DriverInfo->ImageSize      = ImageSize;
-  DriverInfo->EntryPoint     = EntryPoint;
-  DriverInfo->ImageSubsystem = ImageSubsystem;
-  if ((EntryPoint != 0) && ((EntryPoint < ImageBase) || (EntryPoint >= (ImageBase + ImageSize)))) {
-    //
-    // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
-    // So patch ImageBuffer here to align the EntryPoint.
-    //
-    Status = InternalPeCoffGetEntryPoint ((VOID *)(UINTN)ImageBase, &EntryPointInImage);
-    ASSERT_EFI_ERROR (Status);
-    DriverInfo->ImageBase = ImageBase + EntryPoint - (PHYSICAL_ADDRESS)(UINTN)EntryPointInImage;
-  }
+  DriverInfo->ImageBase      = LoadAddress;
+  DriverInfo->ImageSize      = UefiImageGetImageSize (ImageContext);
+  DriverInfo->EntryPoint     = UefiImageLoaderGetImageEntryPoint (ImageContext);
+  DriverInfo->ImageSubsystem = UefiImageGetSubsystem (ImageContext);
 
   DriverInfo->FileType          = FileType;
   DriverInfoData->AllocInfoList = (LIST_ENTRY *)(DriverInfoData + 1);
@@ -442,7 +324,7 @@ BuildDriverInfo (
   DriverInfo->CurrentUsage     = 0;
   DriverInfo->PeakUsage        = 0;
   DriverInfo->AllocRecordCount = 0;
-  if (PdbSize != 0) {
+  if (!RETURN_ERROR (PdbStatus)) {
     DriverInfo->PdbStringOffset = (UINT16)sizeof (MEMORY_PROFILE_DRIVER_INFO);
     DriverInfoData->PdbString   = (CHAR8 *)(DriverInfoData->AllocInfoList + 1);
     CopyMem (DriverInfoData->PdbString, PdbString, PdbSize);
@@ -470,8 +352,7 @@ BuildDriverInfo (
 VOID
 RegisterImageToDxe (
   IN EFI_GUID          *FileName,
-  IN PHYSICAL_ADDRESS  ImageBase,
-  IN UINT64            ImageSize,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT   *ImageContext,
   IN EFI_FV_FILETYPE   FileType
   )
 {
@@ -490,8 +371,7 @@ RegisterImageToDxe (
       Status = ProfileProtocol->RegisterImage (
                                   ProfileProtocol,
                                   (EFI_DEVICE_PATH_PROTOCOL *)FilePath,
-                                  ImageBase,
-                                  ImageSize,
+                                  ImageContext,
                                   FileType
                                   );
     }
@@ -610,7 +490,6 @@ RegisterSmmCore (
   )
 {
   MEMORY_PROFILE_DRIVER_INFO_DATA    *DriverInfoData;
-  PHYSICAL_ADDRESS                   ImageBase;
   UINT8                              TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  *FilePath;
 
@@ -622,14 +501,11 @@ RegisterSmmCore (
     return FALSE;
   }
 
-  ImageBase      = gSmmCorePrivate->PiSmmCoreImageBase;
   DriverInfoData = BuildDriverInfo (
                      ContextData,
                      &gEfiCallerIdGuid,
-                     ImageBase,
-                     gSmmCorePrivate->PiSmmCoreImageSize,
-                     gSmmCorePrivate->PiSmmCoreEntryPoint,
-                     InternalPeCoffGetSubsystem ((VOID *)(UINTN)ImageBase),
+                     &gSmmCorePrivate->PiSmmCoreImageContext,
+                     gSmmCorePrivate->PiSmmCoreImageBase,
                      EFI_FV_FILETYPE_SMM_CORE
                      );
   if (DriverInfoData == NULL) {
@@ -652,8 +528,7 @@ SmramProfileInit (
 
   RegisterImageToDxe (
     &gEfiCallerIdGuid,
-    gSmmCorePrivate->PiSmmCoreImageBase,
-    gSmmCorePrivate->PiSmmCoreImageSize,
+    &gSmmCorePrivate->PiSmmCoreImageContext,
     EFI_FV_FILETYPE_SMM_CORE
     );
 
@@ -754,8 +629,9 @@ GetFileNameFromFilePath (
 **/
 EFI_STATUS
 RegisterSmramProfileImage (
-  IN EFI_SMM_DRIVER_ENTRY  *DriverEntry,
-  IN BOOLEAN               RegisterToDxe
+  IN EFI_GUID                     *FileName,
+  IN BOOLEAN                      RegisterToDxe,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT *ImageContext
   )
 {
   MEMORY_PROFILE_CONTEXT_DATA        *ContextData;
@@ -765,9 +641,8 @@ RegisterSmramProfileImage (
 
   if (RegisterToDxe) {
     RegisterImageToDxe (
-      &DriverEntry->FileName,
-      DriverEntry->ImageBuffer,
-      EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage),
+      FileName,
+      ImageContext,
       EFI_FV_FILETYPE_SMM
       );
   }
@@ -777,7 +652,7 @@ RegisterSmramProfileImage (
   }
 
   FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;
-  EfiInitializeFwVolDevicepathNode (FilePath, &DriverEntry->FileName);
+  EfiInitializeFwVolDevicepathNode (FilePath, FileName);
   SetDevicePathEndNode (FilePath + 1);
 
   if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *)FilePath)) {
@@ -791,11 +666,9 @@ RegisterSmramProfileImage (
 
   DriverInfoData = BuildDriverInfo (
                      ContextData,
-                     &DriverEntry->FileName,
-                     DriverEntry->ImageBuffer,
-                     EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage),
-                     DriverEntry->ImageEntryPoint,
-                     InternalPeCoffGetSubsystem ((VOID *)(UINTN)DriverEntry->ImageBuffer),
+                     FileName,
+                     ImageContext,
+                     UefiImageLoaderGetImageAddress (ImageContext),
                      EFI_FV_FILETYPE_SMM
                      );
   if (DriverInfoData == NULL) {
@@ -909,24 +782,22 @@ GetMemoryProfileDriverInfoFromAddress (
 **/
 EFI_STATUS
 UnregisterSmramProfileImage (
-  IN EFI_SMM_DRIVER_ENTRY  *DriverEntry,
-  IN BOOLEAN               UnregisterFromDxe
+  IN EFI_GUID                           *FileName,
+  IN PHYSICAL_ADDRESS                   ImageBase,
+  IN UINT64                             ImageSize,
+  IN BOOLEAN                            UnregisterFromDxe
   )
 {
-  EFI_STATUS                         Status;
   MEMORY_PROFILE_CONTEXT_DATA        *ContextData;
   MEMORY_PROFILE_DRIVER_INFO_DATA    *DriverInfoData;
-  EFI_GUID                           *FileName;
-  PHYSICAL_ADDRESS                   ImageAddress;
-  VOID                               *EntryPointInImage;
   UINT8                              TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  *FilePath;
 
   if (UnregisterFromDxe) {
     UnregisterImageFromDxe (
-      &DriverEntry->FileName,
-      DriverEntry->ImageBuffer,
-      EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage)
+      FileName,
+      ImageBase,
+      ImageSize
       );
   }
 
@@ -935,7 +806,7 @@ UnregisterSmramProfileImage (
   }
 
   FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;
-  EfiInitializeFwVolDevicepathNode (FilePath, &DriverEntry->FileName);
+  EfiInitializeFwVolDevicepathNode (FilePath, FileName);
   SetDevicePathEndNode (FilePath + 1);
 
   if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *)FilePath)) {
@@ -948,24 +819,13 @@ UnregisterSmramProfileImage (
   }
 
   DriverInfoData = NULL;
-  FileName       = &DriverEntry->FileName;
-  ImageAddress   = DriverEntry->ImageBuffer;
-  if ((DriverEntry->ImageEntryPoint < ImageAddress) || (DriverEntry->ImageEntryPoint >= (ImageAddress + EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage)))) {
-    //
-    // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
-    // So patch ImageAddress here to align the EntryPoint.
-    //
-    Status = InternalPeCoffGetEntryPoint ((VOID *)(UINTN)ImageAddress, &EntryPointInImage);
-    ASSERT_EFI_ERROR (Status);
-    ImageAddress = ImageAddress + (UINTN)DriverEntry->ImageEntryPoint - (UINTN)EntryPointInImage;
-  }
 
   if (FileName != NULL) {
-    DriverInfoData = GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData, FileName, ImageAddress);
+    DriverInfoData = GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData, FileName, ImageBase);
   }
 
   if (DriverInfoData == NULL) {
-    DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, ImageAddress);
+    DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, ImageBase);
   }
 
   if (DriverInfoData == NULL) {
@@ -1989,29 +1849,20 @@ EFIAPI
 SmramProfileProtocolRegisterImage (
   IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL  *This,
   IN EFI_DEVICE_PATH_PROTOCOL           *FilePath,
-  IN PHYSICAL_ADDRESS                   ImageBase,
-  IN UINT64                             ImageSize,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT    *ImageContext,
   IN EFI_FV_FILETYPE                    FileType
   )
 {
-  EFI_STATUS            Status;
-  EFI_SMM_DRIVER_ENTRY  DriverEntry;
-  VOID                  *EntryPointInImage;
-  EFI_GUID              *Name;
+  EFI_GUID *FileName;
+  EFI_GUID ZeroGuid;
 
-  ZeroMem (&DriverEntry, sizeof (DriverEntry));
-  Name = GetFileNameFromFilePath (FilePath);
-  if (Name != NULL) {
-    CopyMem (&DriverEntry.FileName, Name, sizeof (EFI_GUID));
+  FileName = GetFileNameFromFilePath (FilePath);
+  if (FileName == NULL) {
+    ZeroMem (&ZeroGuid, sizeof (ZeroGuid));
+    FileName = &ZeroGuid;
   }
 
-  DriverEntry.ImageBuffer  = ImageBase;
-  DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN)ImageSize);
-  Status                   = InternalPeCoffGetEntryPoint ((VOID *)(UINTN)DriverEntry.ImageBuffer, &EntryPointInImage);
-  ASSERT_EFI_ERROR (Status);
-  DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS)(UINTN)EntryPointInImage;
-
-  return RegisterSmramProfileImage (&DriverEntry, FALSE);
+  return RegisterSmramProfileImage (FileName, FALSE, ImageContext);
 }
 
 /**
@@ -2037,24 +1888,16 @@ SmramProfileProtocolUnregisterImage (
   IN UINT64                             ImageSize
   )
 {
-  EFI_STATUS            Status;
-  EFI_SMM_DRIVER_ENTRY  DriverEntry;
-  VOID                  *EntryPointInImage;
-  EFI_GUID              *Name;
+  EFI_GUID *FileName;
+  EFI_GUID ZeroGuid;
 
-  ZeroMem (&DriverEntry, sizeof (DriverEntry));
-  Name = GetFileNameFromFilePath (FilePath);
-  if (Name != NULL) {
-    CopyMem (&DriverEntry.FileName, Name, sizeof (EFI_GUID));
+  FileName = GetFileNameFromFilePath (FilePath);
+  if (FileName == NULL) {
+    ZeroMem (&ZeroGuid, sizeof (ZeroGuid));
+    FileName = &ZeroGuid;
   }
 
-  DriverEntry.ImageBuffer  = ImageBase;
-  DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN)ImageSize);
-  Status                   = InternalPeCoffGetEntryPoint ((VOID *)(UINTN)DriverEntry.ImageBuffer, &EntryPointInImage);
-  ASSERT_EFI_ERROR (Status);
-  DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS)(UINTN)EntryPointInImage;
-
-  return UnregisterSmramProfileImage (&DriverEntry, FALSE);
+  return UnregisterSmramProfileImage (FileName, ImageBase, ImageSize, FALSE);
 }
 
 /**
diff --git a/MdeModulePkg/Core/RuntimeDxe/Runtime.c b/MdeModulePkg/Core/RuntimeDxe/Runtime.c
index c66ed71e35..314a424e14 100644
--- a/MdeModulePkg/Core/RuntimeDxe/Runtime.c
+++ b/MdeModulePkg/Core/RuntimeDxe/Runtime.c
@@ -325,14 +325,12 @@ RuntimeDriverSetVirtualAddressMap (
       Status        = RuntimeDriverConvertPointer (0, (VOID **)&VirtImageBase);
       ASSERT_EFI_ERROR (Status);
 
-      PeCoffLoaderRelocateImageForRuntime (
-        (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase,
+      UefiImageRuntimeRelocateImageForExecution (
+        (VOID *)(UINTN)RuntimeImage->ImageBase,
+        (UINT32)RuntimeImage->ImageSize,
         VirtImageBase,
-        (UINTN)RuntimeImage->ImageSize,
         RuntimeImage->RelocationData
         );
-
-      InvalidateInstructionCacheRange (RuntimeImage->ImageBase, (UINTN)RuntimeImage->ImageSize);
     }
   }
 
diff --git a/MdeModulePkg/Core/RuntimeDxe/Runtime.h b/MdeModulePkg/Core/RuntimeDxe/Runtime.h
index 1e28b98d78..00ac1fe08d 100644
--- a/MdeModulePkg/Core/RuntimeDxe/Runtime.h
+++ b/MdeModulePkg/Core/RuntimeDxe/Runtime.h
@@ -22,7 +22,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiLib.h>
 #include <Library/CacheMaintenanceLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 
 //
 // Function Prototypes
diff --git a/MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf b/MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
index 694c7690fa..36d282d69a 100644
--- a/MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+++ b/MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
@@ -39,7 +39,7 @@
   MdePkg/MdePkg.dec
 
 [LibraryClasses]
-  PeCoffLib
+  UefiImageLib
   CacheMaintenanceLib
   UefiBootServicesTableLib
   UefiLib
diff --git a/MdeModulePkg/Include/Guid/MemoryProfile.h b/MdeModulePkg/Include/Guid/MemoryProfile.h
index 8194b06330..33a033bb00 100644
--- a/MdeModulePkg/Include/Guid/MemoryProfile.h
+++ b/MdeModulePkg/Include/Guid/MemoryProfile.h
@@ -11,6 +11,8 @@
 
 #include <Pi/PiFirmwareFile.h>
 
+#include <Library/UefiImageLib.h>
+
 //
 // For BIOS MemoryType (0 ~ EfiMaxMemoryType - 1), it is recorded in UsageByType[MemoryType]. (Each valid entry has one entry)
 // For OS MemoryType (0x80000000 ~ 0xFFFFFFFF), it is recorded in UsageByType[EfiMaxMemoryType]. (All types are combined into one entry)
@@ -242,8 +244,7 @@ EFI_STATUS
 (EFIAPI *EDKII_MEMORY_PROFILE_REGISTER_IMAGE)(
   IN EDKII_MEMORY_PROFILE_PROTOCOL      *This,
   IN EFI_DEVICE_PATH_PROTOCOL           *FilePath,
-  IN PHYSICAL_ADDRESS                   ImageBase,
-  IN UINT64                             ImageSize,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT       *ImageContext,
   IN EFI_FV_FILETYPE                    FileType
   );
 
diff --git a/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h b/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
index 87c94c7237..7207e9f763 100644
--- a/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
+++ b/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
@@ -11,25 +11,7 @@
 #ifndef IMAGE_PROPERTIES_RECORD_SUPPORT_LIB_H_
 #define IMAGE_PROPERTIES_RECORD_SUPPORT_LIB_H_
 
-#define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE  SIGNATURE_32 ('I','P','R','C')
-
-typedef struct {
-  UINT32                  Signature;
-  LIST_ENTRY              Link;
-  EFI_PHYSICAL_ADDRESS    CodeSegmentBase;
-  UINT64                  CodeSegmentSize;
-} IMAGE_PROPERTIES_RECORD_CODE_SECTION;
-
-#define IMAGE_PROPERTIES_RECORD_SIGNATURE  SIGNATURE_32 ('I','P','R','D')
-
-typedef struct {
-  UINT32                  Signature;
-  LIST_ENTRY              Link;
-  EFI_PHYSICAL_ADDRESS    ImageBase;
-  UINT64                  ImageSize;
-  UINTN                   CodeSegmentCount;
-  LIST_ENTRY              CodeSegmentList;
-} IMAGE_PROPERTIES_RECORD;
+#include <Library/UefiImageLib.h>
 
 /**
   Split the original memory map and add more entries to describe PE code
@@ -82,142 +64,6 @@ SplitTable (
   IN     UINTN                  NumberOfAdditionalDescriptors
   );
 
-/**
-  Sort the code sections in the input ImageRecord based upon CodeSegmentBase from low to high.
-
-  @param[in]  ImageRecord         IMAGE_PROPERTIES_RECORD to be sorted
-
-  @retval EFI_SUCCESS             The code sections in the input ImageRecord were sorted successfully
-  @retval EFI_ABORTED             An error occurred while sorting the code sections in the input ImageRecord
-  @retval EFI_INVALID_PARAMETER   ImageRecord is NULL
-**/
-EFI_STATUS
-EFIAPI
-SortImageRecordCodeSection (
-  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
-  );
-
-/**
-  Check if the code sections in the input ImageRecord are valid.
-  The code sections are valid if they don't overlap, are contained
-  within the the ImageRecord's ImageBase and ImageSize, and are
-  contained within the MAX_ADDRESS.
-
-  @param[in]  ImageRecord    IMAGE_PROPERTIES_RECORD to be checked
-
-  @retval TRUE  The code sections in the input ImageRecord are valid
-  @retval FALSE The code sections in the input ImageRecord are invalid
-**/
-BOOLEAN
-EFIAPI
-IsImageRecordCodeSectionValid (
-  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
-  );
-
-/**
-  Sort the input ImageRecordList based upon the ImageBase from low to high.
-
-  @param[in] ImageRecordList    Image record list to be sorted
-
-  @retval EFI_SUCCESS           The image record list was sorted successfully
-  @retval EFI_ABORTED           An error occurred while sorting the image record list
-  @retval EFI_INVALID_PARAMETER ImageRecordList is NULL
-**/
-EFI_STATUS
-EFIAPI
-SortImageRecord (
-  IN LIST_ENTRY  *ImageRecordList
-  );
-
-/**
-  Swap two image records.
-
-  @param[in]  FirstImageRecord   The first image record.
-  @param[in]  SecondImageRecord  The second image record.
-
-  @retval EFI_SUCCESS            The image records were swapped successfully
-  @retval EFI_INVALID_PARAMETER  FirstImageRecord or SecondImageRecord is NULL
-**/
-EFI_STATUS
-EFIAPI
-SwapImageRecord (
-  IN IMAGE_PROPERTIES_RECORD  *FirstImageRecord,
-  IN IMAGE_PROPERTIES_RECORD  *SecondImageRecord
-  );
-
-/**
-  Swap two code sections in a single IMAGE_PROPERTIES_RECORD.
-
-  @param[in]  FirstImageRecordCodeSection    The first code section
-  @param[in]  SecondImageRecordCodeSection   The second code section
-
-  @retval EFI_SUCCESS                        The code sections were swapped successfully
-  @retval EFI_INVALID_PARAMETER              FirstImageRecordCodeSection or SecondImageRecordCodeSection is NULL
-**/
-EFI_STATUS
-EFIAPI
-SwapImageRecordCodeSection (
-  IN IMAGE_PROPERTIES_RECORD_CODE_SECTION  *FirstImageRecordCodeSection,
-  IN IMAGE_PROPERTIES_RECORD_CODE_SECTION  *SecondImageRecordCodeSection
-  );
-
-/**
-  Find image properties record according to image base and size in the
-  input ImageRecordList.
-
-  @param[in]  ImageBase           Base of PE image
-  @param[in]  ImageSize           Size of PE image
-  @param[in]  ImageRecordList     Image record list to be searched
-
-  @retval    NULL             No IMAGE_PROPERTIES_RECORD matches ImageBase
-                              and ImageSize in the input ImageRecordList
-  @retval    Other            The found IMAGE_PROPERTIES_RECORD
-**/
-IMAGE_PROPERTIES_RECORD *
-EFIAPI
-FindImageRecord (
-  IN EFI_PHYSICAL_ADDRESS  ImageBase,
-  IN UINT64                ImageSize,
-  IN LIST_ENTRY            *ImageRecordList
-  );
-
-/**
-  Debug dumps the input list of IMAGE_PROPERTIES_RECORD structs.
-
-  @param[in]  ImageRecordList   Head of the IMAGE_PROPERTIES_RECORD list
-**/
-VOID
-EFIAPI
-DumpImageRecords (
-  IN LIST_ENTRY  *ImageRecordList
-  );
-
-/**
-  Creates an IMAGE_PROPERTIES_RECORD from a loaded PE image. The PE/COFF header will be found
-  and parsed to determine the number of code segments and their base addresses and sizes.
-
-  @param[in]      ImageBase               Base of the PE image
-  @param[in]      ImageSize               Size of the PE image
-  @param[in]      RequiredAlignment       If non-NULL, the alignment specified in the PE/COFF header
-                                          will be compared against this value.
-  @param[out]     ImageRecord             On out, a populated image properties record
-
-  @retval     EFI_INVALID_PARAMETER   This function ImageBase or ImageRecord was NULL, or the
-                                      image located at ImageBase was not a valid PE/COFF image
-  @retval     EFI_OUT_OF_RESOURCES    Failure to Allocate()
-  @retval     EFI_ABORTED             The input Alignment was non-NULL and did not match the
-                                      alignment specified in the PE/COFF header
-  @retval     EFI_SUCCESS             The image properties record was successfully created
-**/
-EFI_STATUS
-EFIAPI
-CreateImagePropertiesRecord (
-  IN  CONST   VOID                     *ImageBase,
-  IN  CONST   UINT64                   ImageSize,
-  IN  CONST   UINT32                   *Alignment OPTIONAL,
-  OUT         IMAGE_PROPERTIES_RECORD  *ImageRecord
-  );
-
 /**
   Deleted an image properties record. The function will also call
   RemoveEntryList() on each code segment and the input ImageRecord before
@@ -228,7 +74,7 @@ CreateImagePropertiesRecord (
 VOID
 EFIAPI
 DeleteImagePropertiesRecord (
-  IN  IMAGE_PROPERTIES_RECORD  *ImageRecord
+  IN  UEFI_IMAGE_RECORD  *ImageRecord
   );
 
 #endif
diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
index ef32771561..9825fdaeab 100644
--- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
+++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
@@ -462,9 +462,9 @@ GetModuleInfoFromHandle (
   EFI_STATUS                         Status;
   EFI_LOADED_IMAGE_PROTOCOL          *LoadedImage;
   EFI_DRIVER_BINDING_PROTOCOL        *DriverBinding;
-  CHAR8                              *PdbFileName;
+  //CHAR8                              *PdbFileName;
   EFI_GUID                           *TempGuid;
-  UINTN                              StartIndex;
+  //UINTN                              StartIndex;
   UINTN                              Index;
   INTN                               Count;
   BOOLEAN                            ModuleGuidIsGet;
@@ -558,7 +558,8 @@ GetModuleInfoFromHandle (
     //
     // Method 1 Get Module Name from PDB string.
     //
-    PdbFileName = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);
+    // FIXME:
+    /*PdbFileName = UefiImageLoaderGetPdbPointer (LoadedImage->ImageBase);
     if ((PdbFileName != NULL) && (BufferSize > 0)) {
       StartIndex = 0;
       for (Index = 0; PdbFileName[Index] != 0; Index++) {
@@ -587,7 +588,7 @@ GetModuleInfoFromHandle (
       // Module Name is got.
       //
       goto Done;
-    }
+    }*/
   }
 
   //
diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
index 599d4dea66..0a36591c63 100644
--- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
+++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
@@ -54,7 +54,6 @@
   UefiLib
   ReportStatusCodeLib
   DxeServicesLib
-  PeCoffGetEntryPointLib
   DevicePathLib
 
 [Protocols]
diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h
index 8f32018c06..155e71555a 100644
--- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h
+++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h
@@ -42,7 +42,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/UefiLib.h>
 #include <Library/ReportStatusCodeLib.h>
 #include <Library/DxeServicesLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
 
 /**
   Create performance record with event description and a timestamp.
diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
index 08e3311d15..22a1a7cc5a 100644
--- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
@@ -14,7 +14,6 @@
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
 #include <Library/MemoryAllocationLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
 #include <Library/ImagePropertiesRecordLib.h>
 
 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
@@ -60,39 +59,6 @@ EfiSizeToPages (
   return RShiftU64 (Size, EFI_PAGE_SHIFT) + ((((UINTN)Size) & EFI_PAGE_MASK) ? 1 : 0);
 }
 
-/**
-  Frees the memory for each ImageRecordCodeSection within an ImageRecord
-  and removes the entries from the list. It does not free the ImageRecord
-  itself.
-
-  @param[in]  ImageRecord The ImageRecord in which to free code sections
-**/
-STATIC
-VOID
-FreeImageRecordCodeSections (
-  IMAGE_PROPERTIES_RECORD  *ImageRecord
-  )
-{
-  LIST_ENTRY                            *CodeSegmentListHead;
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
-
-  if (ImageRecord == NULL) {
-    return;
-  }
-
-  CodeSegmentListHead = &ImageRecord->CodeSegmentList;
-  while (!IsListEmpty (CodeSegmentListHead)) {
-    ImageRecordCodeSection = CR (
-                               CodeSegmentListHead->ForwardLink,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
-                               Link,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
-                               );
-    RemoveEntryList (&ImageRecordCodeSection->Link);
-    FreePool (ImageRecordCodeSection);
-  }
-}
-
 /**
   Sort memory map entries based upon PhysicalStart from low to high.
 
@@ -146,15 +112,15 @@ SortMemoryMap (
   @retval The first image record covered by [Buffer, Length]
 **/
 STATIC
-IMAGE_PROPERTIES_RECORD *
+UEFI_IMAGE_RECORD *
 GetImageRecordByAddress (
   IN EFI_PHYSICAL_ADDRESS  Buffer,
   IN UINT64                Length,
   IN LIST_ENTRY            *ImageRecordList
   )
 {
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  LIST_ENTRY               *ImageRecordLink;
+  UEFI_IMAGE_RECORD  *ImageRecord;
+  LIST_ENTRY         *ImageRecordLink;
 
   for (ImageRecordLink = ImageRecordList->ForwardLink;
        ImageRecordLink != ImageRecordList;
@@ -162,13 +128,13 @@ GetImageRecordByAddress (
   {
     ImageRecord = CR (
                     ImageRecordLink,
-                    IMAGE_PROPERTIES_RECORD,
+                    UEFI_IMAGE_RECORD,
                     Link,
-                    IMAGE_PROPERTIES_RECORD_SIGNATURE
+                    UEFI_IMAGE_RECORD_SIGNATURE
                     );
 
-    if ((Buffer <= ImageRecord->ImageBase) &&
-        (Buffer + Length >= ImageRecord->ImageBase + ImageRecord->ImageSize))
+    if ((Buffer <= ImageRecord->StartAddress) &&
+        (Buffer + Length >= ImageRecord->EndAddress))
     {
       return ImageRecord;
     }
@@ -195,88 +161,48 @@ GetImageRecordByAddress (
 STATIC
 UINTN
 SetNewRecord (
-  IN IMAGE_PROPERTIES_RECORD    *ImageRecord,
+  IN UEFI_IMAGE_RECORD          *ImageRecord,
   IN OUT EFI_MEMORY_DESCRIPTOR  *NewRecord,
   IN EFI_MEMORY_DESCRIPTOR      *OldRecord,
   IN UINTN                      DescriptorSize
   )
 {
-  EFI_MEMORY_DESCRIPTOR                 TempRecord;
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
-  LIST_ENTRY                            *ImageRecordCodeSectionLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionList;
-  UINTN                                 NewRecordCount;
-  UINT64                                PhysicalEnd;
-  UINT64                                ImageEnd;
+  EFI_MEMORY_DESCRIPTOR      TempRecord;
+  UEFI_IMAGE_RECORD_SEGMENT  *ImageRecordSegment;
+  UINTN                      SectionAddress;
+  UINT32                     Index;
+  UINT32                     NewRecordCount;
 
   CopyMem (&TempRecord, OldRecord, sizeof (EFI_MEMORY_DESCRIPTOR));
-  PhysicalEnd    = TempRecord.PhysicalStart + EfiPagesToSize (TempRecord.NumberOfPages);
+  //
+  // Always create a new entry for non-PE image record
+  //
   NewRecordCount = 0;
-
-  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
-
-  ImageRecordCodeSectionLink    = ImageRecordCodeSectionList->ForwardLink;
-  ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
-  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
-    ImageRecordCodeSection = CR (
-                               ImageRecordCodeSectionLink,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
-                               Link,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
-                               );
-    ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
-
-    if (TempRecord.PhysicalStart <= ImageRecordCodeSection->CodeSegmentBase) {
-      //
-      // DATA
-      //
-      NewRecord->Type          = TempRecord.Type;
-      NewRecord->PhysicalStart = TempRecord.PhysicalStart;
-      NewRecord->VirtualStart  = 0;
-      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentBase - NewRecord->PhysicalStart);
-      NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
-      if (NewRecord->NumberOfPages != 0) {
-        NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
-        NewRecordCount++;
-      }
-
-      //
-      // CODE
-      //
-      NewRecord->Type          = TempRecord.Type;
-      NewRecord->PhysicalStart = ImageRecordCodeSection->CodeSegmentBase;
-      NewRecord->VirtualStart  = 0;
-      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize);
-      NewRecord->Attribute     = (TempRecord.Attribute & (~EFI_MEMORY_XP)) | EFI_MEMORY_RO;
-      if (NewRecord->NumberOfPages != 0) {
-        NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
-        NewRecordCount++;
-      }
-
-      TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize));
-      TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - TempRecord.PhysicalStart);
-      if (TempRecord.NumberOfPages == 0) {
-        break;
-      }
-    }
-  }
-
-  ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize;
-
-  //
-  // Final DATA
-  //
-  if (TempRecord.PhysicalStart < ImageEnd) {
+  if (ImageRecord->StartAddress > TempRecord.PhysicalStart) {
     NewRecord->Type          = TempRecord.Type;
     NewRecord->PhysicalStart = TempRecord.PhysicalStart;
     NewRecord->VirtualStart  = 0;
-    NewRecord->NumberOfPages = EfiSizeToPages (ImageEnd - TempRecord.PhysicalStart);
-    NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
-    NewRecordCount++;
+    NewRecord->NumberOfPages = EfiSizeToPages (ImageRecord->StartAddress - TempRecord.PhysicalStart);
+    NewRecord->Attribute     = TempRecord.Attribute;
+    NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
+    ++NewRecordCount;
   }
 
-  return NewRecordCount;
+  SectionAddress = ImageRecord->StartAddress;
+  for (Index = 0; Index < ImageRecord->NumSegments; ++Index) {
+    ImageRecordSegment = &ImageRecord->Segments[Index];
+
+    NewRecord->Type          = TempRecord.Type;
+    NewRecord->PhysicalStart = SectionAddress;
+    NewRecord->VirtualStart  = 0;
+    NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordSegment->Size);
+    NewRecord->Attribute     = (TempRecord.Attribute & ~(UINT64) EFI_MEMORY_ACCESS_MASK) | ImageRecordSegment->Attributes;
+    NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
+
+    SectionAddress += ImageRecordSegment->Size;
+  }
+
+  return NewRecordCount + ImageRecord->NumSegments;
 }
 
 /**
@@ -298,29 +224,32 @@ GetMaxSplitRecordCount (
   IN LIST_ENTRY             *ImageRecordList
   )
 {
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  UINTN                    SplitRecordCount;
-  UINT64                   PhysicalStart;
-  UINT64                   PhysicalEnd;
-
+  UEFI_IMAGE_RECORD  *ImageRecord;
+  UINTN              SplitRecordCount;
+  UINT64             PhysicalStart;
+  UINT64             PhysicalEnd;
+  //
+  // Per region, there may be one prefix, but the return value is the amount of
+  // new records in addition to the original one.
+  //
   SplitRecordCount = 0;
   PhysicalStart    = OldRecord->PhysicalStart;
   PhysicalEnd      = OldRecord->PhysicalStart + EfiPagesToSize (OldRecord->NumberOfPages);
 
   do {
+    // FIXME: Inline iteration to not always start anew?
     ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList);
     if (ImageRecord == NULL) {
       break;
     }
 
-    SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 3);
-    PhysicalStart     = ImageRecord->ImageBase + ImageRecord->ImageSize;
+    //
+    // Per image, they may be one trailer.
+    //
+    SplitRecordCount += ImageRecord->NumSegments + 1;
+    PhysicalStart     = ImageRecord->EndAddress;
   } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
 
-  if (SplitRecordCount != 0) {
-    SplitRecordCount--;
-  }
-
   return SplitRecordCount;
 }
 
@@ -350,13 +279,13 @@ SplitRecord (
   IN LIST_ENTRY                 *ImageRecordList
   )
 {
-  EFI_MEMORY_DESCRIPTOR    TempRecord;
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  IMAGE_PROPERTIES_RECORD  *NewImageRecord;
-  UINT64                   PhysicalStart;
-  UINT64                   PhysicalEnd;
-  UINTN                    NewRecordCount;
-  UINTN                    TotalNewRecordCount;
+  EFI_MEMORY_DESCRIPTOR  TempRecord;
+  UEFI_IMAGE_RECORD      *ImageRecord;
+  UEFI_IMAGE_RECORD      *NewImageRecord;
+  UINT64                 PhysicalStart;
+  UINT64                 PhysicalEnd;
+  UINTN                  NewRecordCount;
+  UINTN                  TotalNewRecordCount;
 
   if (MaxSplitRecordCount == 0) {
     CopyMem (NewRecord, OldRecord, DescriptorSize);
@@ -397,15 +326,15 @@ SplitRecord (
     //
     // Update PhysicalStart to exclude the portion before the image buffer
     //
-    if (TempRecord.PhysicalStart < ImageRecord->ImageBase) {
+    if (TempRecord.PhysicalStart < ImageRecord->StartAddress) {
       NewRecord->Type          = TempRecord.Type;
       NewRecord->PhysicalStart = TempRecord.PhysicalStart;
       NewRecord->VirtualStart  = 0;
-      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecord->ImageBase - TempRecord.PhysicalStart);
+      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecord->StartAddress - TempRecord.PhysicalStart);
       NewRecord->Attribute     = TempRecord.Attribute;
       TotalNewRecordCount++;
 
-      PhysicalStart            = ImageRecord->ImageBase;
+      PhysicalStart            = ImageRecord->StartAddress;
       TempRecord.PhysicalStart = PhysicalStart;
       TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
 
@@ -422,7 +351,7 @@ SplitRecord (
     //
     // Update PhysicalStart, in order to exclude the image buffer already splitted.
     //
-    PhysicalStart            = ImageRecord->ImageBase + ImageRecord->ImageSize;
+    PhysicalStart            = ImageRecord->EndAddress;
     TempRecord.PhysicalStart = PhysicalStart;
     TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
   } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
@@ -550,623 +479,6 @@ SplitTable (
   return EFI_SUCCESS;
 }
 
-/**
-  Swap two code sections in a single IMAGE_PROPERTIES_RECORD.
-
-  @param[in]  FirstImageRecordCodeSection    The first code section
-  @param[in]  SecondImageRecordCodeSection   The second code section
-
-  @retval EFI_SUCCESS                        The code sections were swapped successfully
-  @retval EFI_INVALID_PARAMETER              FirstImageRecordCodeSection or SecondImageRecordCodeSection is NULL
-**/
-EFI_STATUS
-EFIAPI
-SwapImageRecordCodeSection (
-  IN IMAGE_PROPERTIES_RECORD_CODE_SECTION  *FirstImageRecordCodeSection,
-  IN IMAGE_PROPERTIES_RECORD_CODE_SECTION  *SecondImageRecordCodeSection
-  )
-{
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  TempImageRecordCodeSection;
-
-  if ((FirstImageRecordCodeSection == NULL) || (SecondImageRecordCodeSection == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  TempImageRecordCodeSection.CodeSegmentBase = FirstImageRecordCodeSection->CodeSegmentBase;
-  TempImageRecordCodeSection.CodeSegmentSize = FirstImageRecordCodeSection->CodeSegmentSize;
-
-  FirstImageRecordCodeSection->CodeSegmentBase = SecondImageRecordCodeSection->CodeSegmentBase;
-  FirstImageRecordCodeSection->CodeSegmentSize = SecondImageRecordCodeSection->CodeSegmentSize;
-
-  SecondImageRecordCodeSection->CodeSegmentBase = TempImageRecordCodeSection.CodeSegmentBase;
-  SecondImageRecordCodeSection->CodeSegmentSize = TempImageRecordCodeSection.CodeSegmentSize;
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Sort the code sections in the input ImageRecord based upon CodeSegmentBase from low to high.
-
-  @param[in]  ImageRecord         IMAGE_PROPERTIES_RECORD to be sorted
-
-  @retval EFI_SUCCESS             The code sections in the input ImageRecord were sorted successfully
-  @retval EFI_ABORTED             An error occurred while sorting the code sections in the input ImageRecord
-  @retval EFI_INVALID_PARAMETER   ImageRecord is NULL
-**/
-EFI_STATUS
-EFIAPI
-SortImageRecordCodeSection (
-  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
-  )
-{
-  EFI_STATUS                            Status;
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *NextImageRecordCodeSection;
-  LIST_ENTRY                            *ImageRecordCodeSectionLink;
-  LIST_ENTRY                            *NextImageRecordCodeSectionLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionList;
-
-  if (ImageRecord == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
-
-  ImageRecordCodeSectionLink     = ImageRecordCodeSectionList->ForwardLink;
-  NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
-  ImageRecordCodeSectionEndLink  = ImageRecordCodeSectionList;
-  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
-    ImageRecordCodeSection = CR (
-                               ImageRecordCodeSectionLink,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
-                               Link,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
-                               );
-    while (NextImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
-      NextImageRecordCodeSection = CR (
-                                     NextImageRecordCodeSectionLink,
-                                     IMAGE_PROPERTIES_RECORD_CODE_SECTION,
-                                     Link,
-                                     IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
-                                     );
-      if (ImageRecordCodeSection->CodeSegmentBase > NextImageRecordCodeSection->CodeSegmentBase) {
-        Status = SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection);
-        if (EFI_ERROR (Status)) {
-          ASSERT_EFI_ERROR (Status);
-          return EFI_ABORTED;
-        }
-      }
-
-      NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink;
-    }
-
-    ImageRecordCodeSectionLink     = ImageRecordCodeSectionLink->ForwardLink;
-    NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Check if the code sections in the input ImageRecord are valid.
-  The code sections are valid if they don't overlap, are contained
-  within the the ImageRecord's ImageBase and ImageSize, and are
-  contained within the MAX_ADDRESS.
-
-  @param[in]  ImageRecord    IMAGE_PROPERTIES_RECORD to be checked
-
-  @retval TRUE  The code sections in the input ImageRecord are valid
-  @retval FALSE The code sections in the input ImageRecord are invalid
-**/
-BOOLEAN
-EFIAPI
-IsImageRecordCodeSectionValid (
-  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
-  )
-{
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *LastImageRecordCodeSection;
-  LIST_ENTRY                            *ImageRecordCodeSectionLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionList;
-
-  if (ImageRecord == NULL) {
-    return FALSE;
-  }
-
-  DEBUG ((DEBUG_VERBOSE, "ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount));
-
-  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
-
-  ImageRecordCodeSectionLink    = ImageRecordCodeSectionList->ForwardLink;
-  ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
-  LastImageRecordCodeSection    = NULL;
-  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
-    ImageRecordCodeSection = CR (
-                               ImageRecordCodeSectionLink,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
-                               Link,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
-                               );
-    if (ImageRecordCodeSection->CodeSegmentSize == 0) {
-      return FALSE;
-    }
-
-    if (ImageRecordCodeSection->CodeSegmentBase < ImageRecord->ImageBase) {
-      return FALSE;
-    }
-
-    if (ImageRecordCodeSection->CodeSegmentBase >= MAX_ADDRESS - ImageRecordCodeSection->CodeSegmentSize) {
-      return FALSE;
-    }
-
-    if ((ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize) > (ImageRecord->ImageBase + ImageRecord->ImageSize)) {
-      return FALSE;
-    }
-
-    if (LastImageRecordCodeSection != NULL) {
-      if ((LastImageRecordCodeSection->CodeSegmentBase + LastImageRecordCodeSection->CodeSegmentSize) > ImageRecordCodeSection->CodeSegmentBase) {
-        return FALSE;
-      }
-    }
-
-    LastImageRecordCodeSection = ImageRecordCodeSection;
-    ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
-  }
-
-  return TRUE;
-}
-
-/**
-  Swap two image records.
-
-  @param[in]  FirstImageRecord   The first image record.
-  @param[in]  SecondImageRecord  The second image record.
-
-  @retval EFI_SUCCESS            The image records were swapped successfully
-  @retval EFI_INVALID_PARAMETER  FirstImageRecord or SecondImageRecord is NULL
-**/
-EFI_STATUS
-EFIAPI
-SwapImageRecord (
-  IN IMAGE_PROPERTIES_RECORD  *FirstImageRecord,
-  IN IMAGE_PROPERTIES_RECORD  *SecondImageRecord
-  )
-{
-  IMAGE_PROPERTIES_RECORD  TempImageRecord;
-
-  if ((FirstImageRecord == NULL) || (SecondImageRecord == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  TempImageRecord.ImageBase        = FirstImageRecord->ImageBase;
-  TempImageRecord.ImageSize        = FirstImageRecord->ImageSize;
-  TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount;
-
-  FirstImageRecord->ImageBase        = SecondImageRecord->ImageBase;
-  FirstImageRecord->ImageSize        = SecondImageRecord->ImageSize;
-  FirstImageRecord->CodeSegmentCount = SecondImageRecord->CodeSegmentCount;
-
-  SecondImageRecord->ImageBase        = TempImageRecord.ImageBase;
-  SecondImageRecord->ImageSize        = TempImageRecord.ImageSize;
-  SecondImageRecord->CodeSegmentCount = TempImageRecord.CodeSegmentCount;
-
-  SwapListEntries (&FirstImageRecord->CodeSegmentList, &SecondImageRecord->CodeSegmentList);
-  return EFI_SUCCESS;
-}
-
-/**
-  Sort the input ImageRecordList based upon the ImageBase from low to high.
-
-  @param[in] ImageRecordList    Image record list to be sorted
-
-  @retval EFI_SUCCESS           The image record list was sorted successfully
-  @retval EFI_ABORTED           An error occurred while sorting the image record list
-  @retval EFI_INVALID_PARAMETER ImageRecordList is NULL
-**/
-EFI_STATUS
-EFIAPI
-SortImageRecord (
-  IN LIST_ENTRY  *ImageRecordList
-  )
-{
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  IMAGE_PROPERTIES_RECORD  *NextImageRecord;
-  LIST_ENTRY               *ImageRecordLink;
-  LIST_ENTRY               *NextImageRecordLink;
-  LIST_ENTRY               *ImageRecordEndLink;
-  EFI_STATUS               Status;
-
-  if (ImageRecordList == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  ImageRecordLink     = ImageRecordList->ForwardLink;
-  NextImageRecordLink = ImageRecordLink->ForwardLink;
-  ImageRecordEndLink  = ImageRecordList;
-  while (ImageRecordLink != ImageRecordEndLink) {
-    ImageRecord = CR (
-                    ImageRecordLink,
-                    IMAGE_PROPERTIES_RECORD,
-                    Link,
-                    IMAGE_PROPERTIES_RECORD_SIGNATURE
-                    );
-    while (NextImageRecordLink != ImageRecordEndLink) {
-      NextImageRecord = CR (
-                          NextImageRecordLink,
-                          IMAGE_PROPERTIES_RECORD,
-                          Link,
-                          IMAGE_PROPERTIES_RECORD_SIGNATURE
-
-                          );
-      if (ImageRecord->ImageBase > NextImageRecord->ImageBase) {
-        Status = SwapImageRecord (ImageRecord, NextImageRecord);
-        if (EFI_ERROR (Status)) {
-          ASSERT_EFI_ERROR (Status);
-          return EFI_ABORTED;
-        }
-      }
-
-      NextImageRecordLink = NextImageRecordLink->ForwardLink;
-    }
-
-    ImageRecordLink     = ImageRecordLink->ForwardLink;
-    NextImageRecordLink = ImageRecordLink->ForwardLink;
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Extract the .efi filename out of the input PDB.
-
-  @param[in]      PdbPointer      Pointer to the PDB file path.
-  @param[out]     EfiFileName     Pointer to the .efi filename.
-  @param[in]      EfiFileNameSize Size of the .efi filename buffer.
-**/
-STATIC
-VOID
-GetFilename (
-  IN CHAR8   *PdbPointer,
-  OUT CHAR8  *EfiFileName,
-  IN UINTN   EfiFileNameSize
-  )
-{
-  UINTN  Index;
-  UINTN  StartIndex;
-
-  if ((PdbPointer == NULL) || (EfiFileNameSize < 5)) {
-    return;
-  }
-
-  // Print Module Name by Pdb file path.
-  StartIndex = 0;
-  for (Index = 0; PdbPointer[Index] != 0; Index++) {
-    if ((PdbPointer[Index] == '\\') || (PdbPointer[Index] == '/')) {
-      StartIndex = Index + 1;
-    }
-  }
-
-  // Copy the PDB file name to EfiFileName and replace .pdb with .efi
-  for (Index = 0; Index < EfiFileNameSize - 4; Index++) {
-    EfiFileName[Index] = PdbPointer[Index + StartIndex];
-    if (EfiFileName[Index] == 0) {
-      EfiFileName[Index] = '.';
-    }
-
-    if (EfiFileName[Index] == '.') {
-      EfiFileName[Index + 1] = 'e';
-      EfiFileName[Index + 2] = 'f';
-      EfiFileName[Index + 3] = 'i';
-      EfiFileName[Index + 4] = 0;
-      break;
-    }
-  }
-
-  if (Index == sizeof (EfiFileName) - 4) {
-    EfiFileName[Index] = 0;
-  }
-}
-
-/**
-  Debug dumps the input list of IMAGE_PROPERTIES_RECORD structs.
-
-  @param[in]  ImageRecordList   Head of the IMAGE_PROPERTIES_RECORD list
-**/
-VOID
-EFIAPI
-DumpImageRecords (
-  IN LIST_ENTRY  *ImageRecordList
-  )
-{
-  LIST_ENTRY                            *ImageRecordLink;
-  IMAGE_PROPERTIES_RECORD               *CurrentImageRecord;
-  LIST_ENTRY                            *CodeSectionLink;
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *CurrentCodeSection;
-  CHAR8                                 *PdbPointer;
-  CHAR8                                 EfiFileName[256];
-
-  if (ImageRecordList == NULL) {
-    return;
-  }
-
-  ImageRecordLink = ImageRecordList->ForwardLink;
-
-  while (ImageRecordLink != ImageRecordList) {
-    CurrentImageRecord = CR (
-                           ImageRecordLink,
-                           IMAGE_PROPERTIES_RECORD,
-                           Link,
-                           IMAGE_PROPERTIES_RECORD_SIGNATURE
-                           );
-
-    PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)CurrentImageRecord->ImageBase);
-    if (PdbPointer != NULL) {
-      GetFilename (PdbPointer, EfiFileName, sizeof (EfiFileName));
-      DEBUG ((
-        DEBUG_INFO,
-        "%a: 0x%llx - 0x%llx\n",
-        EfiFileName,
-        CurrentImageRecord->ImageBase,
-        CurrentImageRecord->ImageBase + CurrentImageRecord->ImageSize
-        ));
-    } else {
-      DEBUG ((
-        DEBUG_INFO,
-        "Unknown Image: 0x%llx - 0x%llx\n",
-        CurrentImageRecord->ImageBase,
-        CurrentImageRecord->ImageBase + CurrentImageRecord->ImageSize
-        ));
-    }
-
-    CodeSectionLink = CurrentImageRecord->CodeSegmentList.ForwardLink;
-
-    while (CodeSectionLink != &CurrentImageRecord->CodeSegmentList) {
-      CurrentCodeSection = CR (
-                             CodeSectionLink,
-                             IMAGE_PROPERTIES_RECORD_CODE_SECTION,
-                             Link,
-                             IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
-                             );
-
-      DEBUG ((
-        DEBUG_INFO,
-        "  Code Section: 0x%llx - 0x%llx\n",
-        CurrentCodeSection->CodeSegmentBase,
-        CurrentCodeSection->CodeSegmentBase + CurrentCodeSection->CodeSegmentSize
-        ));
-
-      CodeSectionLink = CodeSectionLink->ForwardLink;
-    }
-
-    ImageRecordLink = ImageRecordLink->ForwardLink;
-  }
-}
-
-/**
-  Find image record according to image base and size.
-
-  @param[in]  ImageBase           Base of PE image
-  @param[in]  ImageSize           Size of PE image
-  @param[in]  ImageRecordList     Image record list to be searched
-
-  @retval    NULL             No IMAGE_PROPERTIES_RECORD matches ImageBase
-                              and ImageSize in the input ImageRecordList
-  @retval    Other            The found IMAGE_PROPERTIES_RECORD
-**/
-IMAGE_PROPERTIES_RECORD *
-EFIAPI
-FindImageRecord (
-  IN EFI_PHYSICAL_ADDRESS  ImageBase,
-  IN UINT64                ImageSize,
-  IN LIST_ENTRY            *ImageRecordList
-  )
-{
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  LIST_ENTRY               *ImageRecordLink;
-
-  if (ImageRecordList == NULL) {
-    return NULL;
-  }
-
-  for (ImageRecordLink = ImageRecordList->ForwardLink;
-       ImageRecordLink != ImageRecordList;
-       ImageRecordLink = ImageRecordLink->ForwardLink)
-  {
-    ImageRecord = CR (
-                    ImageRecordLink,
-                    IMAGE_PROPERTIES_RECORD,
-                    Link,
-                    IMAGE_PROPERTIES_RECORD_SIGNATURE
-                    );
-
-    if ((ImageBase == ImageRecord->ImageBase) &&
-        (ImageSize == ImageRecord->ImageSize))
-    {
-      return ImageRecord;
-    }
-  }
-
-  return NULL;
-}
-
-/**
-  Creates an IMAGE_PROPERTIES_RECORD from a loaded PE image. The PE/COFF header will be found
-  and parsed to determine the number of code segments and their base addresses and sizes.
-
-  @param[in]      ImageBase               Base of the PE image
-  @param[in]      ImageSize               Size of the PE image
-  @param[in]      RequiredAlignment       If non-NULL, the alignment specified in the PE/COFF header
-                                          will be compared against this value.
-  @param[out]     ImageRecord             On out, a populated image properties record
-
-  @retval     EFI_INVALID_PARAMETER   This function ImageBase or ImageRecord was NULL, or the
-                                      image located at ImageBase was not a valid PE/COFF image
-  @retval     EFI_OUT_OF_RESOURCES    Failure to Allocate()
-  @retval     EFI_ABORTED             The input Alignment was non-NULL and did not match the
-                                      alignment specified in the PE/COFF header
-  @retval     EFI_SUCCESS             The image properties record was successfully created
-**/
-EFI_STATUS
-EFIAPI
-CreateImagePropertiesRecord (
-  IN  CONST   VOID                     *ImageBase,
-  IN  CONST   UINT64                   ImageSize,
-  IN  CONST   UINT32                   *RequiredAlignment OPTIONAL,
-  OUT         IMAGE_PROPERTIES_RECORD  *ImageRecord
-  )
-{
-  EFI_STATUS                            Status;
-  EFI_IMAGE_DOS_HEADER                  *DosHdr;
-  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;
-  EFI_IMAGE_SECTION_HEADER              *Section;
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
-  UINTN                                 Index;
-  UINT8                                 *Name;
-  UINT32                                SectionAlignment;
-  UINT32                                PeCoffHeaderOffset;
-  CHAR8                                 *PdbPointer;
-
-  if ((ImageRecord == NULL) || (ImageBase == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  DEBUG ((
-    DEBUG_VERBOSE,
-    "Creating Image Properties Record: 0x%016lx - 0x%016lx\n",
-    (EFI_PHYSICAL_ADDRESS)(UINTN)ImageBase,
-    ImageSize
-    ));
-
-  //
-  // Step 1: record whole region
-  //
-  Status                        = EFI_SUCCESS;
-  ImageRecord->Signature        = IMAGE_PROPERTIES_RECORD_SIGNATURE;
-  ImageRecord->ImageBase        = (EFI_PHYSICAL_ADDRESS)(UINTN)ImageBase;
-  ImageRecord->ImageSize        = ImageSize;
-  ImageRecord->CodeSegmentCount = 0;
-  InitializeListHead (&ImageRecord->Link);
-  InitializeListHead (&ImageRecord->CodeSegmentList);
-
-  PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageBase);
-  if (PdbPointer != NULL) {
-    DEBUG ((DEBUG_VERBOSE, " Image - %a\n", PdbPointer));
-  }
-
-  // Check PE/COFF image
-  DosHdr             = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageBase;
-  PeCoffHeaderOffset = 0;
-  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
-    PeCoffHeaderOffset = DosHdr->e_lfanew;
-  }
-
-  Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *)(UINTN)ImageBase + PeCoffHeaderOffset);
-  if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
-    DEBUG ((DEBUG_VERBOSE, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr.Pe32->Signature));
-    return EFI_INVALID_PARAMETER;
-  }
-
-  // Get SectionAlignment
-  if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-    SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;
-  } else {
-    SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;
-  }
-
-  // Check RequiredAlignment
-  if ((RequiredAlignment != NULL) && ((SectionAlignment & (*RequiredAlignment - 1)) != 0)) {
-    DEBUG ((
-      DEBUG_WARN,
-      "!!!!!!!!  Image Section Alignment(0x%x) does not match Required Alignment (0x%x)  !!!!!!!!\n",
-      SectionAlignment,
-      *RequiredAlignment
-      ));
-
-    return EFI_ABORTED;
-  }
-
-  Section = (EFI_IMAGE_SECTION_HEADER *)(
-                                         (UINT8 *)(UINTN)ImageBase +
-                                         PeCoffHeaderOffset +
-                                         sizeof (UINT32) +
-                                         sizeof (EFI_IMAGE_FILE_HEADER) +
-                                         Hdr.Pe32->FileHeader.SizeOfOptionalHeader
-                                         );
-  for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
-    Name = Section[Index].Name;
-    DEBUG ((
-      DEBUG_VERBOSE,
-      "  Section - '%c%c%c%c%c%c%c%c'\n",
-      Name[0],
-      Name[1],
-      Name[2],
-      Name[3],
-      Name[4],
-      Name[5],
-      Name[6],
-      Name[7]
-      ));
-
-    if ((Section[Index].Characteristics & EFI_IMAGE_SCN_CNT_CODE) != 0) {
-      DEBUG ((DEBUG_VERBOSE, "  VirtualSize          - 0x%08x\n", Section[Index].Misc.VirtualSize));
-      DEBUG ((DEBUG_VERBOSE, "  VirtualAddress       - 0x%08x\n", Section[Index].VirtualAddress));
-      DEBUG ((DEBUG_VERBOSE, "  SizeOfRawData        - 0x%08x\n", Section[Index].SizeOfRawData));
-      DEBUG ((DEBUG_VERBOSE, "  PointerToRawData     - 0x%08x\n", Section[Index].PointerToRawData));
-      DEBUG ((DEBUG_VERBOSE, "  PointerToRelocations - 0x%08x\n", Section[Index].PointerToRelocations));
-      DEBUG ((DEBUG_VERBOSE, "  PointerToLinenumbers - 0x%08x\n", Section[Index].PointerToLinenumbers));
-      DEBUG ((DEBUG_VERBOSE, "  NumberOfRelocations  - 0x%08x\n", Section[Index].NumberOfRelocations));
-      DEBUG ((DEBUG_VERBOSE, "  NumberOfLinenumbers  - 0x%08x\n", Section[Index].NumberOfLinenumbers));
-      DEBUG ((DEBUG_VERBOSE, "  Characteristics      - 0x%08x\n", Section[Index].Characteristics));
-
-      // Record code section(s)
-      ImageRecordCodeSection = AllocatePool (sizeof (*ImageRecordCodeSection));
-      if (ImageRecordCodeSection == NULL) {
-        Status = EFI_OUT_OF_RESOURCES;
-        goto CreateImagePropertiesRecordEnd;
-      }
-
-      ImageRecordCodeSection->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
-
-      ImageRecordCodeSection->CodeSegmentBase = (UINTN)ImageBase + Section[Index].VirtualAddress;
-      // We still need to align the VirtualSize to the SectionAlignment because MSVC does not do
-      // this when creating a PE image. It expects the loader to do this.
-      ImageRecordCodeSection->CodeSegmentSize = ALIGN_VALUE (Section[Index].Misc.VirtualSize, SectionAlignment);
-
-      InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSection->Link);
-      ImageRecord->CodeSegmentCount++;
-    }
-  }
-
-  if (ImageRecord->CodeSegmentCount > 0) {
-    SortImageRecordCodeSection (ImageRecord);
-  }
-
-  //
-  // Check overlap all section in ImageBase/Size
-  //
-  if (!IsImageRecordCodeSectionValid (ImageRecord)) {
-    DEBUG ((DEBUG_ERROR, "IsImageRecordCodeSectionValid - FAIL\n"));
-    Status = EFI_INVALID_PARAMETER;
-    goto CreateImagePropertiesRecordEnd;
-  }
-
-  //
-  // Round up the ImageSize, some CPU arch may return EFI_UNSUPPORTED if ImageSize is not aligned.
-  // Given that the loader always allocates full pages, we know the space after the image is not used.
-  //
-  ImageRecord->ImageSize = ALIGN_VALUE (ImageRecord->ImageSize, EFI_PAGE_SIZE);
-
-CreateImagePropertiesRecordEnd:
-  if (EFI_ERROR (Status)) {
-    // we failed to create a valid record, free the section memory that was allocated
-    FreeImageRecordCodeSections (ImageRecord);
-  }
-
-  return Status;
-}
-
 /**
   Deleted an image properties record. The function will also call
   RemoveEntryList() on each code segment and the input ImageRecord before
@@ -1177,11 +489,9 @@ CreateImagePropertiesRecordEnd:
 VOID
 EFIAPI
 DeleteImagePropertiesRecord (
-  IN  IMAGE_PROPERTIES_RECORD  *ImageRecord
+  IN  UEFI_IMAGE_RECORD  *ImageRecord
   )
 {
-  FreeImageRecordCodeSections (ImageRecord);
-
   if (!IsListEmpty (&ImageRecord->Link)) {
     RemoveEntryList (&ImageRecord->Link);
   }
diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
index 1f82cc3e46..43310f5553 100644
--- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
@@ -24,7 +24,7 @@
   BaseMemoryLib
   DebugLib
   MemoryAllocationLib
-  PeCoffGetEntryPointLib
+  UefiImageLib
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf
index 5c51c48b0b..8812c96041 100644
--- a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf
+++ b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf
@@ -19,6 +19,9 @@
   VERSION_STRING                 = 1.0
   PI_SPECIFICATION_VERSION       = 0x0001000A
   LIBRARY_CLASS                  = MemoryAllocationLib|SMM_CORE
+  #
+  # This function is defined in PiSmmCore.
+  #
   CONSTRUCTOR                    = PiSmmCoreMemoryAllocationLibConstructor
 
 #
@@ -28,8 +31,6 @@
 #
 
 [Sources]
-  MemoryAllocationLib.c
-  PiSmmCoreMemoryAllocationServices.h
   PiSmmCoreMemoryProfileLibNull.c
 
 [Packages]
diff --git a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationProfileLib.inf b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationProfileLib.inf
index 89658c0f6c..c3b8a4fdce 100644
--- a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationProfileLib.inf
+++ b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationProfileLib.inf
@@ -19,6 +19,9 @@
   VERSION_STRING                 = 1.0
   PI_SPECIFICATION_VERSION       = 0x0001000A
   LIBRARY_CLASS                  = MemoryAllocationLib|SMM_CORE
+  #
+  # This function is defined in PiSmmCore.
+  #
   CONSTRUCTOR                    = PiSmmCoreMemoryAllocationLibConstructor
   LIBRARY_CLASS                  = MemoryProfileLib|SMM_CORE
   CONSTRUCTOR                    = PiSmmCoreMemoryProfileLibConstructor
@@ -30,8 +33,6 @@
 #
 
 [Sources]
-  MemoryAllocationLib.c
-  PiSmmCoreMemoryAllocationServices.h
   PiSmmCoreMemoryProfileLib.c
   PiSmmCoreMemoryProfileServices.h
 
@@ -43,6 +44,7 @@
   DebugLib
   BaseMemoryLib
   UefiBootServicesTableLib
+  MemoryAllocationLib
 
 [Guids]
   gEdkiiMemoryProfileGuid   ## SOMETIMES_CONSUMES   ## GUID # Locate protocol
diff --git a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationServices.h b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationServices.h
deleted file mode 100644
index 64429e028a..0000000000
--- a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationServices.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/** @file
-  Contains function prototypes for Memory Services in the SMM Core.
-
-  This header file borrows the PiSmmCore Memory Allocation services as the primitive
-  for memory allocation.
-
-  Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef _PI_SMM_CORE_MEMORY_ALLOCATION_SERVICES_H_
-#define _PI_SMM_CORE_MEMORY_ALLOCATION_SERVICES_H_
-
-//
-// It should be aligned with the definition in PiSmmCore.
-//
-typedef struct {
-  UINTN                   Signature;
-
-  ///
-  /// The ImageHandle passed into the entry point of the SMM IPL.  This ImageHandle
-  /// is used by the SMM Core to fill in the ParentImageHandle field of the Loaded
-  /// Image Protocol for each SMM Driver that is dispatched by the SMM Core.
-  ///
-  EFI_HANDLE              SmmIplImageHandle;
-
-  ///
-  /// The number of SMRAM ranges passed from the SMM IPL to the SMM Core.  The SMM
-  /// Core uses these ranges of SMRAM to initialize the SMM Core memory manager.
-  ///
-  UINTN                   SmramRangeCount;
-
-  ///
-  /// A table of SMRAM ranges passed from the SMM IPL to the SMM Core.  The SMM
-  /// Core uses these ranges of SMRAM to initialize the SMM Core memory manager.
-  ///
-  EFI_SMRAM_DESCRIPTOR    *SmramRanges;
-
-  ///
-  /// The SMM Foundation Entry Point.  The SMM Core fills in this field when the
-  /// SMM Core is initialized.  The SMM IPL is responsbile for registering this entry
-  /// point with the SMM Configuration Protocol.  The SMM Configuration Protocol may
-  /// not be available at the time the SMM IPL and SMM Core are started, so the SMM IPL
-  /// sets up a protocol notification on the SMM Configuration Protocol and registers
-  /// the SMM Foundation Entry Point as soon as the SMM Configuration Protocol is
-  /// available.
-  ///
-  EFI_SMM_ENTRY_POINT      SmmEntryPoint;
-
-  ///
-  /// Boolean flag set to TRUE while an SMI is being processed by the SMM Core.
-  ///
-  BOOLEAN                  SmmEntryPointRegistered;
-
-  ///
-  /// Boolean flag set to TRUE while an SMI is being processed by the SMM Core.
-  ///
-  BOOLEAN                  InSmm;
-
-  ///
-  /// This field is set by the SMM Core then the SMM Core is initialized.  This field is
-  /// used by the SMM Base 2 Protocol and SMM Communication Protocol implementations in
-  /// the SMM IPL.
-  ///
-  EFI_SMM_SYSTEM_TABLE2    *Smst;
-
-  ///
-  /// This field is used by the SMM Communicatioon Protocol to pass a buffer into
-  /// a software SMI handler and for the software SMI handler to pass a buffer back to
-  /// the caller of the SMM Communication Protocol.
-  ///
-  VOID                     *CommunicationBuffer;
-
-  ///
-  /// This field is used by the SMM Communicatioon Protocol to pass the size of a buffer,
-  /// in bytes, into a software SMI handler and for the software SMI handler to pass the
-  /// size, in bytes, of a buffer back to the caller of the SMM Communication Protocol.
-  ///
-  UINTN                    BufferSize;
-
-  ///
-  /// This field is used by the SMM Communication Protocol to pass the return status from
-  /// a software SMI handler back to the caller of the SMM Communication Protocol.
-  ///
-  EFI_STATUS               ReturnStatus;
-
-  EFI_PHYSICAL_ADDRESS     PiSmmCoreImageBase;
-  UINT64                   PiSmmCoreImageSize;
-  EFI_PHYSICAL_ADDRESS     PiSmmCoreEntryPoint;
-} SMM_CORE_PRIVATE_DATA;
-
-/**
-  Called to initialize the memory service.
-
-  @param   SmramRangeCount       Number of SMRAM Regions
-  @param   SmramRanges           Pointer to SMRAM Descriptors
-
-**/
-VOID
-SmmInitializeMemoryServices (
-  IN UINTN                 SmramRangeCount,
-  IN EFI_SMRAM_DESCRIPTOR  *SmramRanges
-  );
-
-/**
-  Allocates pages from the memory map.
-
-  @param  Type                   The type of allocation to perform
-  @param  MemoryType             The type of memory to turn the allocated pages
-                                 into
-  @param  NumberOfPages          The number of pages to allocate
-  @param  Memory                 A pointer to receive the base allocated memory
-                                 address
-
-  @retval EFI_INVALID_PARAMETER  Parameters violate checking rules defined in spec.
-  @retval EFI_NOT_FOUND          Could not allocate pages match the requirement.
-  @retval EFI_OUT_OF_RESOURCES   No enough pages to allocate.
-  @retval EFI_SUCCESS            Pages successfully allocated.
-
-**/
-EFI_STATUS
-EFIAPI
-SmmAllocatePages (
-  IN      EFI_ALLOCATE_TYPE     Type,
-  IN      EFI_MEMORY_TYPE       MemoryType,
-  IN      UINTN                 NumberOfPages,
-  OUT     EFI_PHYSICAL_ADDRESS  *Memory
-  );
-
-/**
-  Frees previous allocated pages.
-
-  @param  Memory                 Base address of memory being freed
-  @param  NumberOfPages          The number of pages to free
-
-  @retval EFI_NOT_FOUND          Could not find the entry that covers the range
-  @retval EFI_INVALID_PARAMETER  Address not aligned
-  @return EFI_SUCCESS            Pages successfully freed.
-
-**/
-EFI_STATUS
-EFIAPI
-SmmFreePages (
-  IN      EFI_PHYSICAL_ADDRESS  Memory,
-  IN      UINTN                 NumberOfPages
-  );
-
-/**
-  Allocate pool of a particular type.
-
-  @param  PoolType               Type of pool to allocate
-  @param  Size                   The amount of pool to allocate
-  @param  Buffer                 The address to return a pointer to the allocated
-                                 pool
-
-  @retval EFI_INVALID_PARAMETER  PoolType not valid
-  @retval EFI_OUT_OF_RESOURCES   Size exceeds max pool size or allocation failed.
-  @retval EFI_SUCCESS            Pool successfully allocated.
-
-**/
-EFI_STATUS
-EFIAPI
-SmmAllocatePool (
-  IN      EFI_MEMORY_TYPE  PoolType,
-  IN      UINTN            Size,
-  OUT     VOID             **Buffer
-  );
-
-/**
-  Frees pool.
-
-  @param  Buffer                 The allocated pool entry to free
-
-  @retval EFI_INVALID_PARAMETER  Buffer is not a valid value.
-  @retval EFI_SUCCESS            Pool successfully freed.
-
-**/
-EFI_STATUS
-EFIAPI
-SmmFreePool (
-  IN      VOID  *Buffer
-  );
-
-#endif
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
index 2700f5adbc..2b6cd76d7f 100644
--- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
+++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
@@ -272,9 +272,9 @@ GetModuleInfoFromHandle (
   EFI_STATUS                         Status;
   EFI_LOADED_IMAGE_PROTOCOL          *LoadedImage;
   EFI_DRIVER_BINDING_PROTOCOL        *DriverBinding;
-  CHAR8                              *PdbFileName;
+  //CHAR8                              *PdbFileName;
   EFI_GUID                           *TempGuid;
-  UINTN                              StartIndex;
+  //UINTN                              StartIndex;
   UINTN                              Index;
   INTN                               Count;
   BOOLEAN                            ModuleGuidIsGet;
@@ -367,7 +367,8 @@ GetModuleInfoFromHandle (
     //
     // Method 1 Get Module Name from PDB string.
     //
-    PdbFileName = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);
+    // FIXME:
+    /*PdbFileName = UefiImageLoaderGetPdbPointer (LoadedImage->ImageBase);
     if ((PdbFileName != NULL) && (BufferSize > 0)) {
       StartIndex = 0;
       for (Index = 0; PdbFileName[Index] != 0; Index++) {
@@ -396,7 +397,7 @@ GetModuleInfoFromHandle (
       // Module Name is got.
       //
       goto Done;
-    }
+    }*/
   }
 
   if (ModuleGuidIsGet) {
@@ -426,7 +427,7 @@ GetModuleInfoFromHandle (
     }
   }
 
-Done:
+//Done:
   //
   // Copy Module Guid
   //
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf
index 9a7e14e80c..cb8ab4897e 100644
--- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf
+++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf
@@ -53,7 +53,6 @@
   SmmMemLib
   UefiLib
   ReportStatusCodeLib
-  PeCoffGetEntryPointLib
   DxeServicesLib
 
 [Protocols]
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLibInternal.h b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLibInternal.h
index 62b496484c..2f24117069 100644
--- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLibInternal.h
+++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLibInternal.h
@@ -33,7 +33,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/SmmMemLib.h>
 #include <Library/ReportStatusCodeLib.h>
 #include <Library/DxeServicesLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
 
 #include <Protocol/SmmBase2.h>
 #include <Protocol/LoadedImage.h>
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c b/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c
index 83a2f893e4..0e8154ae07 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c
@@ -1213,82 +1213,6 @@ EfiBootManagerFreeLoadOptions (
   return EFI_SUCCESS;
 }
 
-/**
-  Return whether the PE header of the load option is valid or not.
-
-  @param[in] Type       The load option type.
-                        It's used to check whether the load option is valid.
-                        When it's LoadOptionTypeMax, the routine only guarantees
-                        the load option is a valid PE image but doesn't guarantee
-                        the PE's subsystem type is valid.
-  @param[in] FileBuffer The PE file buffer of the load option.
-  @param[in] FileSize   The size of the load option file.
-
-  @retval TRUE  The PE header of the load option is valid.
-  @retval FALSE The PE header of the load option is not valid.
-**/
-BOOLEAN
-BmIsLoadOptionPeHeaderValid (
-  IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE  Type,
-  IN VOID                               *FileBuffer,
-  IN UINTN                              FileSize
-  )
-{
-  EFI_IMAGE_DOS_HEADER             *DosHeader;
-  EFI_IMAGE_OPTIONAL_HEADER_UNION  *PeHeader;
-  EFI_IMAGE_OPTIONAL_HEADER32      *OptionalHeader;
-  UINT16                           Subsystem;
-
-  if ((FileBuffer == NULL) || (FileSize == 0)) {
-    return FALSE;
-  }
-
-  //
-  // Read dos header
-  //
-  DosHeader = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
-  if ((FileSize >= sizeof (EFI_IMAGE_DOS_HEADER)) &&
-      (FileSize > DosHeader->e_lfanew) && (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE)
-      )
-  {
-    //
-    // Read and check PE signature
-    //
-    PeHeader = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINT8 *)FileBuffer + DosHeader->e_lfanew);
-    if ((FileSize >= DosHeader->e_lfanew + sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION)) &&
-        (PeHeader->Pe32.Signature == EFI_IMAGE_NT_SIGNATURE)
-        )
-    {
-      //
-      // Check PE32 or PE32+ magic, and machine type
-      //
-      OptionalHeader = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHeader->Pe32.OptionalHeader;
-      if ((OptionalHeader->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) ||
-          (OptionalHeader->Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC))
-      {
-        //
-        // Check the Subsystem:
-        //   Driver#### must be of type BootServiceDriver or RuntimeDriver
-        //   SysPrep####, Boot####, OsRecovery####, PlatformRecovery#### must be of type Application
-        //
-        Subsystem = OptionalHeader->Subsystem;
-        if ((Type == LoadOptionTypeMax) ||
-            ((Type == LoadOptionTypeDriver) && (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)) ||
-            ((Type == LoadOptionTypeDriver) && (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) ||
-            ((Type == LoadOptionTypeSysPrep) && (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)) ||
-            ((Type == LoadOptionTypeBoot) && (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)) ||
-            ((Type == LoadOptionTypePlatformRecovery) && (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION))
-            )
-        {
-          return TRUE;
-        }
-      }
-    }
-  }
-
-  return FALSE;
-}
-
 /**
   Return the next matched load option buffer.
   The routine keeps calling BmGetNextLoadOptionDevicePath() until a valid
@@ -1322,7 +1246,6 @@ BmGetNextLoadOptionBuffer (
   EFI_DEVICE_PATH_PROTOCOL  *CurFullPath;
   UINTN                     LocalFileSize;
   UINT32                    AuthenticationStatus;
-  EFI_DEVICE_PATH_PROTOCOL  *RamDiskDevicePath;
 
   LocalFileSize = 0;
   FileBuffer    = NULL;
@@ -1342,22 +1265,6 @@ BmGetNextLoadOptionBuffer (
     }
 
     FileBuffer = GetFileBufferByFilePath (TRUE, CurFullPath, &LocalFileSize, &AuthenticationStatus);
-    if ((FileBuffer != NULL) && !BmIsLoadOptionPeHeaderValid (Type, FileBuffer, LocalFileSize)) {
-      //
-      // Free the RAM disk file system if the load option is invalid.
-      //
-      RamDiskDevicePath = BmGetRamDiskDevicePath (FilePath);
-      if (RamDiskDevicePath != NULL) {
-        BmDestroyRamDisk (RamDiskDevicePath);
-        FreePool (RamDiskDevicePath);
-      }
-
-      //
-      // Free the invalid load option buffer.
-      //
-      FreePool (FileBuffer);
-      FileBuffer = NULL;
-    }
   } while (FileBuffer == NULL);
 
   if (FileBuffer == NULL) {
@@ -1399,6 +1306,7 @@ EfiBootManagerProcessLoadOption (
   EFI_LOADED_IMAGE_PROTOCOL  *ImageInfo;
   VOID                       *FileBuffer;
   UINTN                      FileSize;
+  EFI_DEVICE_PATH_PROTOCOL   *RamDiskDevicePath;
 
   if ((UINT32)LoadOption->OptionType >= LoadOptionTypeMax) {
     return EFI_INVALID_PARAMETER;
@@ -1476,6 +1384,15 @@ EfiBootManagerProcessLoadOption (
       if (Status == EFI_SECURITY_VIOLATION) {
         gBS->UnloadImage (ImageHandle);
       }
+
+      //
+      // Free the RAM disk file system if the load option is invalid.
+      //
+      RamDiskDevicePath = BmGetRamDiskDevicePath (LoadOption->FilePath);
+      if (RamDiskDevicePath != NULL) {
+        BmDestroyRamDisk (RamDiskDevicePath);
+        FreePool (RamDiskDevicePath);
+      }
     } else {
       Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&ImageInfo);
       ASSERT_EFI_ERROR (Status);
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
index 76ee0a83bf..a2782f0cbc 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
+++ b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
@@ -14,7 +14,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <PiDxe.h>
 
 #include <IndustryStandard/Pci.h>
-#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/PeImage2.h>
 #include <IndustryStandard/Atapi.h>
 #include <IndustryStandard/Scsi.h>
 #include <IndustryStandard/Nvme.h>
@@ -64,7 +64,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/DevicePathLib.h>
 #include <Library/PerformanceLib.h>
 #include <Library/PcdLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
 #include <Library/UefiBootManagerLib.h>
 #include <Library/DxeServicesLib.h>
 #include <Library/ReportStatusCodeLib.h>
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
index 2fc0a80a4e..6a32f5128d 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+++ b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
@@ -52,7 +52,6 @@
   BaseMemoryLib
   DevicePathLib
   PerformanceLib
-  PeCoffGetEntryPointLib
   UefiBootServicesTableLib
   UefiRuntimeServicesTableLib
   DxeServicesTableLib
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index b9bc7041f2..263435caf2 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -587,7 +587,7 @@
   ## Load File protocol provides capability to load and unload EFI image into memory and execute it.
   #  Include/Protocol/LoadPe32Image.h
   #  This protocol is deprecated. Native EDKII module should NOT use this protocol to load/unload image.
-  #  If developer need implement such functionality, they should use BasePeCoffLib.
+  #  If developer need implement such functionality, they should use BasePeCoffLib2.
   gEfiLoadPeImageProtocolGuid    = { 0x5CB5C776, 0x60D5, 0x45EE, { 0x88, 0x3C, 0x45, 0x27, 0x08, 0xCD, 0x74, 0x3F }}
 
   ## Print protocols define basic print functions to print the format unicode and ascii string.
@@ -1516,7 +1516,7 @@
   # e.g. 0x7BD4 can be used for all memory except Code and ACPINVS/Reserved. <BR>
   #
   # @Prompt Set DXE memory protection policy.
-  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x0000000|UINT64|0x00001048
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFFD5|UINT64|0x00001048
 
   ## PCI Serial Device Info. It is an array of Device, Function, and Power Management
   #  information that describes the path that contains zero or more PCI to PCI bridges
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index ebceafcdd0..08c2530d11 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -43,8 +43,8 @@
   PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
   PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
   CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
   #
   # UEFI & PI
@@ -81,7 +81,7 @@
   DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
   DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
   ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
   PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
index fb149c2f02..22a28df8e6 100644
--- a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
+++ b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
@@ -49,7 +49,7 @@
   UefiDriverEntryPoint
   BaseLib
   S3BootScriptLib
-  PeCoffLib
+  UefiImageLib
   DxeServicesLib
   UefiBootServicesTableLib
   CacheMaintenanceLib
@@ -59,6 +59,7 @@
   CpuExceptionHandlerLib
   DevicePathLib
   DxeServicesTableLib
+  MemoryAllocationLib
 
 [Guids]
   gEfiBootScriptExecutorVariableGuid    ## PRODUCES ## UNDEFINED # SaveLockBox
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c
index 98c5abecf8..4599425859 100644
--- a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c
+++ b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c
@@ -227,8 +227,7 @@ S3BootScriptExecutorEntryFunction (
 VOID
 RegisterMemoryProfileImage (
   IN EFI_GUID          *FileName,
-  IN PHYSICAL_ADDRESS  ImageBase,
-  IN UINT64            ImageSize,
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT   *ImageContext,
   IN EFI_FV_FILETYPE   FileType
   )
 {
@@ -247,8 +246,7 @@ RegisterMemoryProfileImage (
       Status = ProfileProtocol->RegisterImage (
                                   ProfileProtocol,
                                   (EFI_DEVICE_PATH_PROTOCOL *)FilePath,
-                                  ImageBase,
-                                  ImageSize,
+                                  ImageContext,
                                   FileType
                                   );
     }
@@ -275,9 +273,11 @@ ReadyToLockEventNotify (
   UINTN                            BufferSize;
   EFI_HANDLE                       NewImageHandle;
   UINTN                            Pages;
-  EFI_PHYSICAL_ADDRESS             FfsBuffer;
-  PE_COFF_LOADER_IMAGE_CONTEXT     ImageContext;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT  ImageContext;
+  UINT32                           ImageSize;
+  UINT32                           ImageAlignment;
   EFI_GCD_MEMORY_SPACE_DESCRIPTOR  MemDesc;
+  EFI_PHYSICAL_ADDRESS             LoadAddress;
 
   Status = gBS->LocateProtocol (&gEfiDxeSmmReadyToLockProtocolGuid, NULL, &Interface);
   if (EFI_ERROR (Status)) {
@@ -307,56 +307,40 @@ ReadyToLockEventNotify (
              &BufferSize
              );
   ASSERT_EFI_ERROR (Status);
-  ImageContext.Handle    = Buffer;
-  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
   //
   // Get information about the image being loaded
   //
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);
+  Status = UefiImageInitializeContext (&ImageContext, Buffer, (UINT32) BufferSize);
   ASSERT_EFI_ERROR (Status);
-  if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
-    Pages = EFI_SIZE_TO_PAGES ((UINTN)(ImageContext.ImageSize + ImageContext.SectionAlignment));
-  } else {
-    Pages = EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize);
-  }
-
-  FfsBuffer = 0xFFFFFFFF;
-  Status    = gBS->AllocatePages (
-                     AllocateMaxAddress,
-                     EfiReservedMemoryType,
-                     Pages,
-                     &FfsBuffer
-                     );
+  ImageSize      = UefiImageGetImageSize (&ImageContext);
+  ImageAlignment = UefiImageGetSegmentAlignment (&ImageContext);
+  Pages = EFI_SIZE_TO_PAGES (ImageSize);
+  LoadAddress = 0xFFFFFFFF;
+  Status    = AllocateAlignedPagesEx (
+                AllocateMaxAddress,
+                EfiReservedMemoryType,
+                Pages,
+                ImageAlignment,
+                &LoadAddress
+                );
   ASSERT_EFI_ERROR (Status);
 
   //
   // Make sure that the buffer can be used to store code.
   //
-  Status = gDS->GetMemorySpaceDescriptor (FfsBuffer, &MemDesc);
+  Status = gDS->GetMemorySpaceDescriptor (LoadAddress, &MemDesc);
   if (!EFI_ERROR (Status) && ((MemDesc.Attributes & EFI_MEMORY_XP) != 0)) {
     gDS->SetMemorySpaceAttributes (
-           FfsBuffer,
+           LoadAddress,
            EFI_PAGES_TO_SIZE (Pages),
            MemDesc.Attributes & (~EFI_MEMORY_XP)
            );
   }
 
-  ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;
-  //
-  // Align buffer on section boundary
-  //
-  ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
-  ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);
   //
   // Load the image to our new buffer
   //
-  Status = PeCoffLoaderLoadImage (&ImageContext);
-  ASSERT_EFI_ERROR (Status);
-
-  //
-  // Relocate the image in our new buffer
-  //
-  Status = PeCoffLoaderRelocateImage (&ImageContext);
+  Status = UefiImageLoadImageForExecution (&ImageContext, (VOID *)(UINTN)LoadAddress, ImageSize, NULL, 0);
   ASSERT_EFI_ERROR (Status);
 
   //
@@ -364,19 +348,13 @@ ReadyToLockEventNotify (
   //
   gBS->FreePool (Buffer);
 
-  //
-  // Flush the instruction cache so the image data is written before we execute it
-  //
-  InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
-
   RegisterMemoryProfileImage (
     &gEfiCallerIdGuid,
-    ImageContext.ImageAddress,
-    ImageContext.ImageSize,
+    &ImageContext,
     EFI_FV_FILETYPE_DRIVER
     );
 
-  Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint))(NewImageHandle, gST);
+  Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(UefiImageLoaderGetImageEntryPoint (&ImageContext)))(NewImageHandle, gST);
   ASSERT_EFI_ERROR (Status);
 
   //
@@ -385,8 +363,8 @@ ReadyToLockEventNotify (
   //
   Status = SaveLockBox (
              &mBootScriptExecutorImageGuid,
-             (VOID *)(UINTN)ImageContext.ImageAddress,
-             (UINTN)ImageContext.ImageSize
+             (VOID *)(UINTN)LoadAddress,
+             (UINTN)UefiImageGetImageSize (&ImageContext)
              );
   ASSERT_EFI_ERROR (Status);
 
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.h b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.h
index 0ea38223d7..c18e6ed551 100644
--- a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.h
+++ b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.h
@@ -21,7 +21,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
 #include <Library/S3BootScriptLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/DxeServicesLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiRuntimeServicesTableLib.h>
@@ -34,6 +34,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/CpuExceptionHandlerLib.h>
 #include <Library/DevicePathLib.h>
 #include <Library/DxeServicesTableLib.h>
+#include <Library/MemoryAllocationLibEx.h>
 
 #include <Guid/AcpiS3Context.h>
 #include <Guid/BootScriptExecutorVariable.h>
diff --git a/MdeModulePkg/Universal/CapsulePei/Capsule.h b/MdeModulePkg/Universal/CapsulePei/Capsule.h
index c16f83a07a..7e3ee64d5f 100644
--- a/MdeModulePkg/Universal/CapsulePei/Capsule.h
+++ b/MdeModulePkg/Universal/CapsulePei/Capsule.h
@@ -25,13 +25,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/HobLib.h>
 #include <Library/PeiServicesTablePointerLib.h>
 #include <Library/PrintLib.h>
-#include <Library/PeCoffLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/PcdLib.h>
 #include <Library/ReportStatusCodeLib.h>
 #include <Library/DebugAgentLib.h>
 #include <Library/MemoryAllocationLib.h>
-#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/PeImage2.h>
 #include "Common/CommonHeader.h"
 
 #ifdef MDE_CPU_IA32
diff --git a/MdeModulePkg/Universal/CapsulePei/CapsulePei.inf b/MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
index e5078c7986..832f97683a 100644
--- a/MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
+++ b/MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
@@ -53,7 +53,6 @@
   ReportStatusCodeLib
 
 [LibraryClasses.IA32]
-  PeCoffGetEntryPointLib
   PcdLib
   DebugAgentLib
 
diff --git a/MdeModulePkg/Universal/CapsulePei/UefiCapsule.c b/MdeModulePkg/Universal/CapsulePei/UefiCapsule.c
index 8e26a7d795..a155078ed8 100644
--- a/MdeModulePkg/Universal/CapsulePei/UefiCapsule.c
+++ b/MdeModulePkg/Universal/CapsulePei/UefiCapsule.c
@@ -542,7 +542,9 @@ FindCapsuleCoalesceImage (
         return Status;
       }
 
-      *CoalesceImageMachineType = PeCoffLoaderGetMachineType ((VOID *)(UINTN)CoalesceImageAddress);
+      *CoalesceImageMachineType = EFI_IMAGE_MACHINE_X64;
+      // FIXME: Get machine type from context once PPI is adapted
+      //*CoalesceImageMachineType = UefiImageLoaderGetMachineType ((VOID *)(UINTN)CoalesceImageAddress);
       break;
     } else {
       continue;
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf b/MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf
index e942317603..ef0ed4936c 100644
--- a/MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf
@@ -85,7 +85,6 @@
   DebugLib
   BaseLib
   CacheMaintenanceLib
-  PeCoffLib
 
 [Protocols]
   gEfiDebugSupportProtocolGuid                  ## PRODUCES
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c
index 834c90e32a..cf8ff3d371 100644
--- a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c
@@ -759,107 +759,6 @@ EdbLoadSymbol (
   return EFI_SUCCESS;
 }
 
-/**
-
-  Located PDB path name in PE image.
-
-  @param  ImageBase - base of PE to search
-
-  @return Pointer into image at offset of PDB file name if PDB file name is found,
-  Otherwise a pointer to an empty string.
-
-**/
-CHAR8 *
-GetPdbPath (
-  VOID  *ImageBase
-  )
-{
-  CHAR8                            *PdbPath;
-  UINT32                           DirCount;
-  EFI_IMAGE_DOS_HEADER             *DosHdr;
-  EFI_IMAGE_OPTIONAL_HEADER_UNION  *NtHdr;
-  EFI_IMAGE_OPTIONAL_HEADER32      *OptionalHdr32;
-  EFI_IMAGE_OPTIONAL_HEADER64      *OptionalHdr64;
-  EFI_IMAGE_DATA_DIRECTORY         *DirectoryEntry;
-  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY  *DebugEntry;
-  VOID                             *CodeViewEntryPointer;
-
-  //
-  // Init value
-  //
-  CodeViewEntryPointer = NULL;
-  PdbPath              = NULL;
-  DosHdr               = ImageBase;
-
-  //
-  // Check magic
-  //
-  if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
-    return NULL;
-  }
-
-  NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINT8 *)DosHdr + DosHdr->e_lfanew);
-  //
-  // Check Machine, filter for EBC
-  //
-  if (NtHdr->Pe32.FileHeader.Machine != EFI_IMAGE_MACHINE_EBC) {
-    //
-    // If not EBC, return NULL
-    //
-    return NULL;
-  }
-
-  //
-  // Get DirectoryEntry
-  // EBC spec says PE32+, but implementation uses PE32. So check dynamically here.
-  //
-  if (NtHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-    OptionalHdr32  = (VOID *)&NtHdr->Pe32.OptionalHeader;
-    DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(OptionalHdr32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
-  } else if (NtHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
-    OptionalHdr64  = (VOID *)&NtHdr->Pe32Plus.OptionalHeader;
-    DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(OptionalHdr64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
-  } else {
-    return NULL;
-  }
-
-  if (DirectoryEntry->VirtualAddress == 0) {
-    return NULL;
-  }
-
-  //
-  // Go through DirectoryEntry
-  //
-  for (DirCount = 0;
-       (DirCount < DirectoryEntry->Size / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) && CodeViewEntryPointer == NULL;
-       DirCount++
-       )
-  {
-    DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(DirectoryEntry->VirtualAddress + (UINTN)ImageBase + DirCount * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
-    if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
-      //
-      // Match DebugEntry, only CODEVIEW_SIGNATURE_NB10 and CODEVIEW_SIGNATURE_RSDS are supported.
-      //
-      CodeViewEntryPointer = (VOID *)((UINTN)DebugEntry->RVA + (UINTN)ImageBase);
-      switch (*(UINT32 *)CodeViewEntryPointer) {
-        case CODEVIEW_SIGNATURE_NB10:
-          PdbPath = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
-          break;
-        case CODEVIEW_SIGNATURE_RSDS:
-          PdbPath = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
-          break;
-        default:
-          break;
-      }
-    }
-  }
-
-  //
-  // Done successfully
-  //
-  return PdbPath;
-}
-
 /**
 
   Check whether PDB file and MAP file have same name.
@@ -873,14 +772,14 @@ GetPdbPath (
 **/
 BOOLEAN
 MatchPdbAndMap (
-  IN CHAR8   *PdbFileName,
-  IN CHAR16  *MapFileName
+  IN CONST CHAR8   *PdbFileName,
+  IN CONST CHAR16  *MapFileName
   )
 {
-  UINTN  PdbNameSize;
-  UINTN  MapNameSize;
-  CHAR8  *PurePdbFileName;
-  UINTN  Index;
+  UINTN       PdbNameSize;
+  UINTN       MapNameSize;
+  CONST CHAR8 *PurePdbFileName;
+  UINTN       Index;
 
   //
   // remove dir name
@@ -1003,7 +902,7 @@ EdbPatchSymbolRVA (
   EFI_STATUS                  Status;
   UINTN                       ImageNumber;
   EFI_DEBUG_IMAGE_INFO        *ImageTable;
-  CHAR8                       *PdbPath;
+  CONST CHAR8           *PdbPath;
   VOID                        *ImageBase;
   VOID                        *CandidateImageBase;
   EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
@@ -1058,7 +957,7 @@ EdbPatchSymbolRVA (
     //
     // Get PDB path
     //
-    PdbPath = GetPdbPath (ImageBase);
+    PdbPath   = ImageTable[ImageNumber].NormalImage->PdbPath;
     if (PdbPath == NULL) {
       continue;
     }
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf b/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
index 8f5fcbeb82..9ca18d8ec6 100644
--- a/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
@@ -53,7 +53,6 @@
 [LibraryClasses]
   CacheMaintenanceLib
   MemoryAllocationLib
-  PeCoffLib
   UefiBootServicesTableLib
   BaseMemoryLib
   UefiDriverEntryPoint
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcInt.c b/MdeModulePkg/Universal/EbcDxe/EbcInt.c
index d2254c2765..46c4020102 100644
--- a/MdeModulePkg/Universal/EbcDxe/EbcInt.c
+++ b/MdeModulePkg/Universal/EbcDxe/EbcInt.c
@@ -405,27 +405,6 @@ EbcRegisterImage (
   IN  OUT EFI_IMAGE_ENTRY_POINT                 *EntryPoint
   )
 {
-  DEBUG_CODE_BEGIN ();
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
-  EFI_STATUS                    Status;
-
-  ZeroMem (&ImageContext, sizeof (ImageContext));
-
-  ImageContext.Handle    = (VOID *)(UINTN)ImageBase;
-  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
-
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  ASSERT (ImageContext.Machine == EFI_IMAGE_MACHINE_EBC);
-  ASSERT (
-    ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ||
-    ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
-    );
-  DEBUG_CODE_END ();
-
   EbcRegisterICacheFlush (
     NULL,
     (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcInt.h b/MdeModulePkg/Universal/EbcDxe/EbcInt.h
index 646e3a613b..df3f11b1d4 100644
--- a/MdeModulePkg/Universal/EbcDxe/EbcInt.h
+++ b/MdeModulePkg/Universal/EbcDxe/EbcInt.h
@@ -12,6 +12,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 
 #include <Uefi.h>
 
+#include <IndustryStandard/PeImage2.h>
+
 #include <Protocol/DebugSupport.h>
 #include <Protocol/Ebc.h>
 #include <Protocol/EbcVmTest.h>
@@ -21,7 +23,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/BaseLib.h>
 #include <Library/CacheMaintenanceLib.h>
 #include <Library/DebugLib.h>
-#include <Library/PeCoffLib.h>
 #include <Library/UefiDriverEntryPoint.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/UefiBootServicesTableLib.h>
diff --git a/MdePkg/Include/Guid/DebugImageInfoTable.h b/MdePkg/Include/Guid/DebugImageInfoTable.h
index 6661c4dd6a..82f337f67e 100644
--- a/MdePkg/Include/Guid/DebugImageInfoTable.h
+++ b/MdePkg/Include/Guid/DebugImageInfoTable.h
@@ -47,6 +47,7 @@ typedef struct {
   /// Indicates the image handle of the associated image.
   ///
   EFI_HANDLE                   ImageHandle;
+  CHAR8                      *PdbPath;
 } EFI_DEBUG_IMAGE_INFO_NORMAL;
 
 typedef union {
diff --git a/MdePkg/Include/Guid/WinCertificate.h b/MdePkg/Include/Guid/WinCertificate.h
index 3b81a8a769..d29dc0ed17 100644
--- a/MdePkg/Include/Guid/WinCertificate.h
+++ b/MdePkg/Include/Guid/WinCertificate.h
@@ -56,7 +56,7 @@ typedef struct {
 /// WIN_CERTIFICATE_UEFI_GUID.CertData
 ///
 typedef struct {
-  EFI_GUID    HashType;
+  GUID      HashType;
   UINT8       PublicKey[256];
   UINT8       Signature[256];
 } EFI_CERT_BLOCK_RSA_2048_SHA256;
@@ -74,14 +74,14 @@ typedef struct {
   /// This is the unique id which determines the
   /// format of the CertData. .
   ///
-  EFI_GUID           CertType;
+  GUID              CertType;
   ///
   /// The following is the certificate data. The format of
   /// the data is determined by the CertType.
   /// If CertType is EFI_CERT_TYPE_RSA2048_SHA256_GUID,
   /// the CertData will be EFI_CERT_BLOCK_RSA_2048_SHA256 structure.
   ///
-  UINT8              CertData[1];
+  UINT8             CertData[];
 } WIN_CERTIFICATE_UEFI_GUID;
 
 ///
@@ -102,7 +102,7 @@ typedef struct {
   /// This is the hashing algorithm which was performed on the
   /// UEFI executable when creating the digital signature.
   ///
-  EFI_GUID           HashAlgorithm;
+  GUID            HashAlgorithm;
   ///
   /// The following is the actual digital signature. The
   /// size of the signature is the same size as the key
@@ -111,10 +111,9 @@ typedef struct {
   /// from the total length of the certificate as found in
   /// Hdr.dwLength.
   ///
-  /// UINT8 Signature[];
-  ///
+  UINT8           Signature[];
 } WIN_CERTIFICATE_EFI_PKCS1_15;
 
-extern EFI_GUID  gEfiCertTypeRsa2048Sha256Guid;
+extern GUID gEfiCertTypeRsa2048Sha256Guid;
 
 #endif
diff --git a/MdePkg/Include/IndustryStandard/PeImage.h b/MdePkg/Include/IndustryStandard/PeImage.h
index 596c2fc3cd..cfcabad63f 100644
--- a/MdePkg/Include/IndustryStandard/PeImage.h
+++ b/MdePkg/Include/IndustryStandard/PeImage.h
@@ -1,3 +1,5 @@
+#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
+
 /** @file
   EFI image format for PE32, PE32+ and TE. Please note some data structures are
   different for PE32 and PE32+. EFI_IMAGE_NT_HEADERS32 is for PE32 and
@@ -25,7 +27,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION          10
 #define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER  11
 #define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER       12
-#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER       13///< defined PI Specification, 1.0
+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER       13 ///< defined PI Specification, 1.0
 
 //
 // PE32+ Machine type for EFI images
@@ -191,7 +193,7 @@ typedef struct {
 /// EFI_IMAGE_OPTIONAL_HEADER64 must be used. The data structures only vary
 /// after NT additional fields.
 ///
-#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC  0x20b
+#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
 
 ///
 /// Optional Header Standard Fields for PE32+.
@@ -232,32 +234,33 @@ typedef struct {
   UINT64                      SizeOfHeapCommit;
   UINT32                      LoaderFlags;
   UINT32                      NumberOfRvaAndSizes;
-  EFI_IMAGE_DATA_DIRECTORY    DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
+  EFI_IMAGE_DATA_DIRECTORY  DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
 } EFI_IMAGE_OPTIONAL_HEADER64;
 
+
 ///
 /// @attention
 /// EFI_IMAGE_NT_HEADERS32 is for use ONLY by tools.
 ///
 typedef struct {
-  UINT32                         Signature;
-  EFI_IMAGE_FILE_HEADER          FileHeader;
-  EFI_IMAGE_OPTIONAL_HEADER32    OptionalHeader;
+  UINT32                      Signature;
+  EFI_IMAGE_FILE_HEADER       FileHeader;
+  EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader;
 } EFI_IMAGE_NT_HEADERS32;
 
-#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER  sizeof (EFI_IMAGE_NT_HEADERS32)
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32)
 
 ///
 /// @attention
 /// EFI_IMAGE_HEADERS64 is for use ONLY by tools.
 ///
 typedef struct {
-  UINT32                         Signature;
-  EFI_IMAGE_FILE_HEADER          FileHeader;
-  EFI_IMAGE_OPTIONAL_HEADER64    OptionalHeader;
+  UINT32                      Signature;
+  EFI_IMAGE_FILE_HEADER       FileHeader;
+  EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader;
 } EFI_IMAGE_NT_HEADERS64;
 
-#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER  sizeof (EFI_IMAGE_NT_HEADERS64)
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64)
 
 //
 // Other Windows Subsystem Values
@@ -293,10 +296,10 @@ typedef struct {
 /// Section Table. This table immediately follows the optional header.
 ///
 typedef struct {
-  UINT8     Name[EFI_IMAGE_SIZEOF_SHORT_NAME];
+  UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME];
   union {
-    UINT32    PhysicalAddress;
-    UINT32    VirtualSize;
+    UINT32  PhysicalAddress;
+    UINT32  VirtualSize;
   } Misc;
   UINT32    VirtualAddress;
   UINT32    SizeOfRawData;
@@ -311,7 +314,7 @@ typedef struct {
 ///
 /// Size of EFI_IMAGE_SECTION_HEADER.
 ///
-#define EFI_IMAGE_SIZEOF_SECTION_HEADER  40
+#define EFI_IMAGE_SIZEOF_SECTION_HEADER       40
 
 //
 // Section Flags Values
@@ -518,9 +521,9 @@ typedef struct {
 ///
 /// Relocation types of RISC-V processor.
 ///
-#define EFI_IMAGE_REL_BASED_RISCV_HI20    5
-#define EFI_IMAGE_REL_BASED_RISCV_LOW12I  7
-#define EFI_IMAGE_REL_BASED_RISCV_LOW12S  8
+#define EFI_IMAGE_REL_BASED_RISCV_HI20      5
+#define EFI_IMAGE_REL_BASED_RISCV_LOW12I    7
+#define EFI_IMAGE_REL_BASED_RISCV_LOW12S    8
 
 //
 // Relocation types of LoongArch processor.
@@ -572,6 +575,7 @@ typedef struct {
 ///
 #define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR  60
 
+
 //
 // DLL Support
 //
@@ -634,6 +638,7 @@ typedef struct {
   EFI_IMAGE_THUNK_DATA    *FirstThunk;
 } EFI_IMAGE_IMPORT_DESCRIPTOR;
 
+
 ///
 /// Debug Directory Format.
 ///
@@ -681,6 +686,7 @@ typedef struct {
   //
 } EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY;
 
+
 ///
 /// Debug Data Structure defined by Apple Mach-O to Coff utility.
 ///
@@ -725,12 +731,12 @@ typedef struct {
 /// Resource format.
 ///
 typedef struct {
-  UINT32    Characteristics;
-  UINT32    TimeDateStamp;
-  UINT16    MajorVersion;
-  UINT16    MinorVersion;
-  UINT16    NumberOfNamedEntries;
-  UINT16    NumberOfIdEntries;
+  UINT32  Characteristics;
+  UINT32  TimeDateStamp;
+  UINT16  MajorVersion;
+  UINT16  MinorVersion;
+  UINT16  NumberOfNamedEntries;
+  UINT16  NumberOfIdEntries;
   //
   // Array of EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY entries goes here.
   //
@@ -789,6 +795,7 @@ typedef struct {
   EFI_IMAGE_DATA_DIRECTORY    DataDirectory[2];    ///< Only base relocation and debug directory.
 } EFI_TE_IMAGE_HEADER;
 
+
 #define EFI_TE_IMAGE_HEADER_SIGNATURE  SIGNATURE_16('V', 'Z')
 
 //
@@ -797,20 +804,23 @@ typedef struct {
 #define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC  0
 #define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG      1
 
+
 ///
 /// Union of PE32, PE32+, and TE headers.
 ///
 typedef union {
-  EFI_IMAGE_NT_HEADERS32    Pe32;
-  EFI_IMAGE_NT_HEADERS64    Pe32Plus;
-  EFI_TE_IMAGE_HEADER       Te;
+  EFI_IMAGE_NT_HEADERS32   Pe32;
+  EFI_IMAGE_NT_HEADERS64   Pe32Plus;
+  EFI_TE_IMAGE_HEADER      Te;
 } EFI_IMAGE_OPTIONAL_HEADER_UNION;
 
 typedef union {
-  EFI_IMAGE_NT_HEADERS32             *Pe32;
-  EFI_IMAGE_NT_HEADERS64             *Pe32Plus;
-  EFI_TE_IMAGE_HEADER                *Te;
-  EFI_IMAGE_OPTIONAL_HEADER_UNION    *Union;
+  EFI_IMAGE_NT_HEADERS32            *Pe32;
+  EFI_IMAGE_NT_HEADERS64            *Pe32Plus;
+  EFI_TE_IMAGE_HEADER               *Te;
+  EFI_IMAGE_OPTIONAL_HEADER_UNION   *Union;
 } EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION;
 
 #endif
+
+#endif // DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/MdePkg/Include/IndustryStandard/PeImage2.h b/MdePkg/Include/IndustryStandard/PeImage2.h
new file mode 100644
index 0000000000..d5a69f7886
--- /dev/null
+++ b/MdePkg/Include/IndustryStandard/PeImage2.h
@@ -0,0 +1,761 @@
+/** @file
+  EFI image format for PE32, PE32+ and TE. Please note some data structures are
+  different for PE32 and PE32+. EFI_IMAGE_NT_HEADERS32 is for PE32 and
+  EFI_IMAGE_NT_HEADERS64 is for PE32+.
+  This file is coded to the Visual Studio, Microsoft Portable Executable and
+  Common Object File Format Specification, Revision 8.3 - February 6, 2013.
+  This file also includes some definitions in PI Specification, Revision 1.0.
+
+  Copyright (c) 2020, Marvin Häuser. All rights reserved.<BR>
+  Copyright (c) 2020, Vitaly Cheptsov. All rights reserved.<BR>
+  Copyright (c) 2020, ISP RAS. All rights reserved.<BR>
+  Portions copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+  Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+  Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-3-Clause
+**/
+
+#ifndef PE_COFF_IMAGE2_H_
+#define PE_COFF_IMAGE2_H_
+
+//
+// PE32+ Subsystem type for EFI images
+//
+#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION         10
+#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
+#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER      12
+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER      13 ///< defined PI Specification, 1.0
+
+
+//
+// PE32+ Machine type for EFI images
+//
+#define IMAGE_FILE_MACHINE_I386            0x014c
+#define IMAGE_FILE_MACHINE_IA64            0x0200
+#define IMAGE_FILE_MACHINE_EBC             0x0EBC
+#define IMAGE_FILE_MACHINE_X64             0x8664
+#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED  0x01c2
+#define IMAGE_FILE_MACHINE_ARM64           0xAA64
+#define IMAGE_FILE_MACHINE_RISCV32         0x5032
+#define IMAGE_FILE_MACHINE_RISCV64         0x5064
+#define IMAGE_FILE_MACHINE_RISCV128        0x5128
+
+//
+// EXE file formats
+//
+#define EFI_IMAGE_DOS_SIGNATURE     SIGNATURE_16('M', 'Z')
+#define EFI_IMAGE_OS2_SIGNATURE     SIGNATURE_16('N', 'E')
+#define EFI_IMAGE_OS2_SIGNATURE_LE  SIGNATURE_16('L', 'E')
+#define EFI_IMAGE_NT_SIGNATURE      SIGNATURE_32('P', 'E', '\0', '\0')
+
+///
+/// PE images can start with an optional DOS header, so if an image is run
+/// under DOS it can print an error message.
+///
+typedef struct {
+  UINT16  e_magic;    ///< Magic number.
+  UINT16  e_cblp;     ///< Bytes on last page of file.
+  UINT16  e_cp;       ///< Pages in file.
+  UINT16  e_crlc;     ///< Relocations.
+  UINT16  e_cparhdr;  ///< Size of header in paragraphs.
+  UINT16  e_minalloc; ///< Minimum extra paragraphs needed.
+  UINT16  e_maxalloc; ///< Maximum extra paragraphs needed.
+  UINT16  e_ss;       ///< Initial (relative) SS value.
+  UINT16  e_sp;       ///< Initial SP value.
+  UINT16  e_csum;     ///< Checksum.
+  UINT16  e_ip;       ///< Initial IP value.
+  UINT16  e_cs;       ///< Initial (relative) CS value.
+  UINT16  e_lfarlc;   ///< File address of relocation table.
+  UINT16  e_ovno;     ///< Overlay number.
+  UINT16  e_res[4];   ///< Reserved words.
+  UINT16  e_oemid;    ///< OEM identifier (for e_oeminfo).
+  UINT16  e_oeminfo;  ///< OEM information; e_oemid specific.
+  UINT16  e_res2[10]; ///< Reserved words.
+  UINT32  e_lfanew;   ///< File address of new exe header.
+} EFI_IMAGE_DOS_HEADER;
+
+///
+/// COFF File Header (Object and Image).
+///
+typedef struct {
+  UINT16  Machine;
+  UINT16  NumberOfSections;
+  UINT32  TimeDateStamp;
+  UINT32  PointerToSymbolTable;
+  UINT32  NumberOfSymbols;
+  UINT16  SizeOfOptionalHeader;
+  UINT16  Characteristics;
+} EFI_IMAGE_FILE_HEADER;
+
+///
+/// Size of EFI_IMAGE_FILE_HEADER.
+///
+#define EFI_IMAGE_SIZEOF_FILE_HEADER        20
+
+//
+// Characteristics
+//
+#define EFI_IMAGE_FILE_RELOCS_STRIPPED      BIT0     ///< 0x0001  Relocation info stripped from file.
+#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE     BIT1     ///< 0x0002  File is executable  (i.e. no unresolved externel references).
+#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED   BIT2     ///< 0x0004  Line numbers stripped from file.
+#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED  BIT3     ///< 0x0008  Local symbols stripped from file.
+#define EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE  BIT5     ///< 0x0020  Supports addresses > 2-GB
+#define EFI_IMAGE_FILE_BYTES_REVERSED_LO    BIT7     ///< 0x0080  Bytes of machine word are reversed.
+#define EFI_IMAGE_FILE_32BIT_MACHINE        BIT8     ///< 0x0100  32 bit word machine.
+#define EFI_IMAGE_FILE_DEBUG_STRIPPED       BIT9     ///< 0x0200  Debugging info stripped from file in .DBG file.
+#define EFI_IMAGE_FILE_SYSTEM               BIT12    ///< 0x1000  System File.
+#define EFI_IMAGE_FILE_DLL                  BIT13    ///< 0x2000  File is a DLL.
+#define EFI_IMAGE_FILE_BYTES_REVERSED_HI    BIT15    ///< 0x8000  Bytes of machine word are reversed.
+
+///
+/// Header Data Directories.
+///
+typedef struct {
+  UINT32  VirtualAddress;
+  UINT32  Size;
+} EFI_IMAGE_DATA_DIRECTORY;
+
+//
+// Directory Entries
+//
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT      0
+#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT      1
+#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE    2
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION   3
+#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY    4
+#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC   5
+#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG       6
+#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT   7
+#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR   8
+#define EFI_IMAGE_DIRECTORY_ENTRY_TLS         9
+#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
+
+#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16
+
+///
+/// @attention
+/// EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC means PE32 and
+/// EFI_IMAGE_OPTIONAL_HEADER32 must be used. The data structures only vary
+/// after NT additional fields.
+///
+#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
+
+///
+/// @attention
+/// EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC means PE32+ and
+/// EFI_IMAGE_OPTIONAL_HEADER64 must be used. The data structures only vary
+/// after NT additional fields.
+///
+#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
+
+
+///
+/// @attention
+/// EFI_IMAGE_NT_HEADERS32 is for use ONLY by tools.
+///
+typedef struct {
+  UINT32                      Signature;
+  EFI_IMAGE_FILE_HEADER       FileHeader;
+} EFI_IMAGE_NT_HEADERS_COMMON_HDR;
+
+STATIC_ASSERT (
+  sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR) == sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER),
+  "Unsupported padding."
+  );
+
+///
+/// @attention
+/// EFI_IMAGE_NT_HEADERS32 is for use ONLY by tools.
+///
+typedef struct {
+  EFI_IMAGE_NT_HEADERS_COMMON_HDR CommonHeader;
+  ///
+  /// Standard fields.
+  ///
+  UINT16                    Magic;
+  UINT8                     MajorLinkerVersion;
+  UINT8                     MinorLinkerVersion;
+  UINT32                    SizeOfCode;
+  UINT32                    SizeOfInitializedData;
+  UINT32                    SizeOfUninitializedData;
+  UINT32                    AddressOfEntryPoint;
+  UINT32                    BaseOfCode;
+  UINT32                    BaseOfData;  ///< PE32 contains this additional field, which is absent in PE32+.
+  ///
+  /// Optional Header Windows-Specific Fields.
+  ///
+  UINT32                    ImageBase;
+  UINT32                    SectionAlignment;
+  UINT32                    FileAlignment;
+  UINT16                    MajorOperatingSystemVersion;
+  UINT16                    MinorOperatingSystemVersion;
+  UINT16                    MajorImageVersion;
+  UINT16                    MinorImageVersion;
+  UINT16                    MajorSubsystemVersion;
+  UINT16                    MinorSubsystemVersion;
+  UINT32                    Win32VersionValue;
+  UINT32                    SizeOfImage;
+  UINT32                    SizeOfHeaders;
+  UINT32                    CheckSum;
+  UINT16                    Subsystem;
+  UINT16                    DllCharacteristics;
+  UINT32                    SizeOfStackReserve;
+  UINT32                    SizeOfStackCommit;
+  UINT32                    SizeOfHeapReserve;
+  UINT32                    SizeOfHeapCommit;
+  UINT32                    LoaderFlags;
+  UINT32                    NumberOfRvaAndSizes;
+  EFI_IMAGE_DATA_DIRECTORY  DataDirectory[];
+} EFI_IMAGE_NT_HEADERS32;
+
+///
+/// @attention
+/// EFI_IMAGE_HEADERS64 is for use ONLY by tools.
+///
+typedef struct {
+  EFI_IMAGE_NT_HEADERS_COMMON_HDR CommonHeader;
+  ///
+  /// Standard fields.
+  ///
+  UINT16                    Magic;
+  UINT8                     MajorLinkerVersion;
+  UINT8                     MinorLinkerVersion;
+  UINT32                    SizeOfCode;
+  UINT32                    SizeOfInitializedData;
+  UINT32                    SizeOfUninitializedData;
+  UINT32                    AddressOfEntryPoint;
+  UINT32                    BaseOfCode;
+  ///
+  /// Optional Header Windows-Specific Fields.
+  ///
+  UINT64                    ImageBase;
+  UINT32                    SectionAlignment;
+  UINT32                    FileAlignment;
+  UINT16                    MajorOperatingSystemVersion;
+  UINT16                    MinorOperatingSystemVersion;
+  UINT16                    MajorImageVersion;
+  UINT16                    MinorImageVersion;
+  UINT16                    MajorSubsystemVersion;
+  UINT16                    MinorSubsystemVersion;
+  UINT32                    Win32VersionValue;
+  UINT32                    SizeOfImage;
+  UINT32                    SizeOfHeaders;
+  UINT32                    CheckSum;
+  UINT16                    Subsystem;
+  UINT16                    DllCharacteristics;
+  UINT64                    SizeOfStackReserve;
+  UINT64                    SizeOfStackCommit;
+  UINT64                    SizeOfHeapReserve;
+  UINT64                    SizeOfHeapCommit;
+  UINT32                    LoaderFlags;
+  UINT32                    NumberOfRvaAndSizes;
+  EFI_IMAGE_DATA_DIRECTORY  DataDirectory[];
+} EFI_IMAGE_NT_HEADERS64;
+
+//
+// Other Windows Subsystem Values
+//
+#define EFI_IMAGE_SUBSYSTEM_UNKNOWN     0
+#define EFI_IMAGE_SUBSYSTEM_NATIVE      1
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3
+#define EFI_IMAGE_SUBSYSTEM_OS2_CUI     5
+#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI   7
+
+///
+/// Length of ShortName.
+///
+#define EFI_IMAGE_SIZEOF_SHORT_NAME 8
+
+///
+/// Section Table. This table immediately follows the optional header.
+///
+typedef struct {
+  UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME];
+  UINT32  VirtualSize;
+  UINT32  VirtualAddress;
+  UINT32  SizeOfRawData;
+  UINT32  PointerToRawData;
+  UINT32  PointerToRelocations;
+  UINT32  PointerToLinenumbers;
+  UINT16  NumberOfRelocations;
+  UINT16  NumberOfLinenumbers;
+  UINT32  Characteristics;
+} EFI_IMAGE_SECTION_HEADER;
+
+//
+// Section Flags Values
+//
+#define EFI_IMAGE_SCN_TYPE_NO_PAD                  BIT3   ///< 0x00000008  ///< Reserved.
+#define EFI_IMAGE_SCN_CNT_CODE                     BIT5   ///< 0x00000020
+#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA         BIT6   ///< 0x00000040
+#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA       BIT7   ///< 0x00000080
+
+#define EFI_IMAGE_SCN_LNK_OTHER                    BIT8   ///< 0x00000100  ///< Reserved.
+#define EFI_IMAGE_SCN_LNK_INFO                     BIT9   ///< 0x00000200  ///< Section contains comments or some other type of information.
+#define EFI_IMAGE_SCN_LNK_REMOVE                   BIT11  ///< 0x00000800  ///< Section contents will not become part of image.
+#define EFI_IMAGE_SCN_LNK_COMDAT                   BIT12  ///< 0x00001000
+
+#define EFI_IMAGE_SCN_ALIGN_1BYTES                 BIT20  ///< 0x00100000
+#define EFI_IMAGE_SCN_ALIGN_2BYTES                 BIT21  ///< 0x00200000
+#define EFI_IMAGE_SCN_ALIGN_4BYTES          (BIT20|BIT21) ///< 0x00300000
+#define EFI_IMAGE_SCN_ALIGN_8BYTES                 BIT22  ///< 0x00400000
+#define EFI_IMAGE_SCN_ALIGN_16BYTES         (BIT20|BIT22) ///< 0x00500000
+#define EFI_IMAGE_SCN_ALIGN_32BYTES         (BIT21|BIT22) ///< 0x00600000
+#define EFI_IMAGE_SCN_ALIGN_64BYTES   (BIT20|BIT21|BIT22) ///< 0x00700000
+
+#define EFI_IMAGE_SCN_MEM_DISCARDABLE              BIT25  ///< 0x02000000
+#define EFI_IMAGE_SCN_MEM_NOT_CACHED               BIT26  ///< 0x04000000
+#define EFI_IMAGE_SCN_MEM_NOT_PAGED                BIT27  ///< 0x08000000
+#define EFI_IMAGE_SCN_MEM_SHARED                   BIT28  ///< 0x10000000
+#define EFI_IMAGE_SCN_MEM_EXECUTE                  BIT29  ///< 0x20000000
+#define EFI_IMAGE_SCN_MEM_READ                     BIT30  ///< 0x40000000
+#define EFI_IMAGE_SCN_MEM_WRITE                    BIT31  ///< 0x80000000
+
+///
+/// Size of a Symbol Table Record.
+///
+#define EFI_IMAGE_SIZEOF_SYMBOL 18
+
+//
+// Symbols have a section number of the section in which they are
+// defined. Otherwise, section numbers have the following meanings:
+//
+#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0  ///< Symbol is undefined or is common.
+#define EFI_IMAGE_SYM_ABSOLUTE  (UINT16) -1 ///< Symbol is an absolute value.
+#define EFI_IMAGE_SYM_DEBUG     (UINT16) -2 ///< Symbol is a special debug item.
+
+//
+// Symbol Type (fundamental) values.
+//
+#define EFI_IMAGE_SYM_TYPE_NULL   0   ///< no type.
+#define EFI_IMAGE_SYM_TYPE_VOID   1   ///< no valid type.
+#define EFI_IMAGE_SYM_TYPE_CHAR   2   ///< type character.
+#define EFI_IMAGE_SYM_TYPE_SHORT  3   ///< type short integer.
+#define EFI_IMAGE_SYM_TYPE_INT    4
+#define EFI_IMAGE_SYM_TYPE_LONG   5
+#define EFI_IMAGE_SYM_TYPE_FLOAT  6
+#define EFI_IMAGE_SYM_TYPE_DOUBLE 7
+#define EFI_IMAGE_SYM_TYPE_STRUCT 8
+#define EFI_IMAGE_SYM_TYPE_UNION  9
+#define EFI_IMAGE_SYM_TYPE_ENUM   10  ///< enumeration.
+#define EFI_IMAGE_SYM_TYPE_MOE    11  ///< member of enumeration.
+#define EFI_IMAGE_SYM_TYPE_BYTE   12
+#define EFI_IMAGE_SYM_TYPE_WORD   13
+#define EFI_IMAGE_SYM_TYPE_UINT   14
+#define EFI_IMAGE_SYM_TYPE_DWORD  15
+
+//
+// Symbol Type (derived) values.
+//
+#define EFI_IMAGE_SYM_DTYPE_NULL      0 ///< no derived type.
+#define EFI_IMAGE_SYM_DTYPE_POINTER   1
+#define EFI_IMAGE_SYM_DTYPE_FUNCTION  2
+#define EFI_IMAGE_SYM_DTYPE_ARRAY     3
+
+//
+// Storage classes.
+//
+#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION   ((UINT8) -1)
+#define EFI_IMAGE_SYM_CLASS_NULL              0
+#define EFI_IMAGE_SYM_CLASS_AUTOMATIC         1
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL          2
+#define EFI_IMAGE_SYM_CLASS_STATIC            3
+#define EFI_IMAGE_SYM_CLASS_REGISTER          4
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF      5
+#define EFI_IMAGE_SYM_CLASS_LABEL             6
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL   7
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT  8
+#define EFI_IMAGE_SYM_CLASS_ARGUMENT          9
+#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG        10
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION   11
+#define EFI_IMAGE_SYM_CLASS_UNION_TAG         12
+#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION   13
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC  14
+#define EFI_IMAGE_SYM_CLASS_ENUM_TAG          15
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM    16
+#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM    17
+#define EFI_IMAGE_SYM_CLASS_BIT_FIELD         18
+#define EFI_IMAGE_SYM_CLASS_BLOCK             100
+#define EFI_IMAGE_SYM_CLASS_FUNCTION          101
+#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT     102
+#define EFI_IMAGE_SYM_CLASS_FILE              103
+#define EFI_IMAGE_SYM_CLASS_SECTION           104
+#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL     105
+
+//
+// type packing constants
+//
+#define EFI_IMAGE_N_BTMASK  017
+#define EFI_IMAGE_N_TMASK   060
+#define EFI_IMAGE_N_TMASK1  0300
+#define EFI_IMAGE_N_TMASK2  0360
+#define EFI_IMAGE_N_BTSHFT  4
+#define EFI_IMAGE_N_TSHIFT  2
+
+//
+// Communal selection types.
+//
+#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES    1
+#define EFI_IMAGE_COMDAT_SELECT_ANY             2
+#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE       3
+#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH     4
+#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE     5
+
+//
+// the following values only be referred in PeCoff, not defined in PECOFF.
+//
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY  1
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY    2
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS      3
+
+///
+/// Relocation format.
+///
+typedef struct {
+  UINT32  VirtualAddress;
+  UINT32  SymbolTableIndex;
+  UINT16  Type;
+} EFI_IMAGE_RELOCATION;
+
+///
+/// Size of EFI_IMAGE_RELOCATION
+///
+#define EFI_IMAGE_SIZEOF_RELOCATION 10
+
+//
+// I386 relocation types.
+//
+#define EFI_IMAGE_REL_I386_ABSOLUTE 0x0000  ///< Reference is absolute, no relocation is necessary.
+#define EFI_IMAGE_REL_I386_DIR16    0x0001  ///< Direct 16-bit reference to the symbols virtual address.
+#define EFI_IMAGE_REL_I386_REL16    0x0002  ///< PC-relative 16-bit reference to the symbols virtual address.
+#define EFI_IMAGE_REL_I386_DIR32    0x0006  ///< Direct 32-bit reference to the symbols virtual address.
+#define EFI_IMAGE_REL_I386_DIR32NB  0x0007  ///< Direct 32-bit reference to the symbols virtual address, base not included.
+#define EFI_IMAGE_REL_I386_SEG12    0x0009  ///< Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address.
+#define EFI_IMAGE_REL_I386_SECTION  0x000A
+#define EFI_IMAGE_REL_I386_SECREL   0x000B
+#define EFI_IMAGE_REL_I386_REL32    0x0014  ///< PC-relative 32-bit reference to the symbols virtual address.
+
+//
+// x64 processor relocation types.
+//
+#define IMAGE_REL_AMD64_ABSOLUTE  0x0000
+#define IMAGE_REL_AMD64_ADDR64    0x0001
+#define IMAGE_REL_AMD64_ADDR32    0x0002
+#define IMAGE_REL_AMD64_ADDR32NB  0x0003
+#define IMAGE_REL_AMD64_REL32     0x0004
+#define IMAGE_REL_AMD64_REL32_1   0x0005
+#define IMAGE_REL_AMD64_REL32_2   0x0006
+#define IMAGE_REL_AMD64_REL32_3   0x0007
+#define IMAGE_REL_AMD64_REL32_4   0x0008
+#define IMAGE_REL_AMD64_REL32_5   0x0009
+#define IMAGE_REL_AMD64_SECTION   0x000A
+#define IMAGE_REL_AMD64_SECREL    0x000B
+#define IMAGE_REL_AMD64_SECREL7   0x000C
+#define IMAGE_REL_AMD64_TOKEN     0x000D
+#define IMAGE_REL_AMD64_SREL32    0x000E
+#define IMAGE_REL_AMD64_PAIR      0x000F
+#define IMAGE_REL_AMD64_SSPAN32   0x0010
+
+/**
+  Returns the type of a Base Relocation.
+
+  @param[in] Relocation  The composite Base Relocation value.
+**/
+#define IMAGE_RELOC_TYPE(Relocation)    ((Relocation) >> 12U)
+
+/**
+  Returns the target offset of a Base Relocation.
+
+  @param[in] Relocation  The composite Base Relocation value.
+**/
+#define IMAGE_RELOC_OFFSET(Relocation)  ((Relocation) & 0x0FFFU)
+
+///
+/// Based relocation format.
+///
+typedef struct {
+  UINT32  VirtualAddress;
+  UINT32  SizeOfBlock;
+  UINT16  Relocations[];
+} EFI_IMAGE_BASE_RELOCATION_BLOCK;
+
+//
+// Based relocation types.
+//
+#define EFI_IMAGE_REL_BASED_ABSOLUTE        0
+#define EFI_IMAGE_REL_BASED_HIGH            1
+#define EFI_IMAGE_REL_BASED_LOW             2
+#define EFI_IMAGE_REL_BASED_HIGHLOW         3
+#define EFI_IMAGE_REL_BASED_HIGHADJ         4
+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR    5
+#define EFI_IMAGE_REL_BASED_ARM_MOV32A      5
+#define EFI_IMAGE_REL_BASED_ARM_MOV32T      7
+#define EFI_IMAGE_REL_BASED_IA64_IMM64      9
+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR16  9
+#define EFI_IMAGE_REL_BASED_DIR64           10
+
+///
+/// Relocation types of RISC-V processor.
+///
+#define EFI_IMAGE_REL_BASED_RISCV_HI20      5
+#define EFI_IMAGE_REL_BASED_RISCV_LOW12I    7
+#define EFI_IMAGE_REL_BASED_RISCV_LOW12S    8
+
+///
+/// Line number format.
+///
+typedef struct {
+  union {
+    UINT32  SymbolTableIndex; ///< Symbol table index of function name if Linenumber is 0.
+    UINT32  VirtualAddress;   ///< Virtual address of line number.
+  } Type;
+  UINT16  Linenumber;         ///< Line number.
+} EFI_IMAGE_LINENUMBER;
+
+///
+/// Size of EFI_IMAGE_LINENUMBER.
+///
+#define EFI_IMAGE_SIZEOF_LINENUMBER 6
+
+//
+// Archive format.
+//
+#define EFI_IMAGE_ARCHIVE_START_SIZE        8
+#define EFI_IMAGE_ARCHIVE_START             "!<arch>\n"
+#define EFI_IMAGE_ARCHIVE_END               "`\n"
+#define EFI_IMAGE_ARCHIVE_PAD               "\n"
+#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER     "/               "
+#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER  "//              "
+
+///
+/// Archive Member Headers
+///
+typedef struct {
+  UINT8 Name[16];     ///< File member name - `/' terminated.
+  UINT8 Date[12];     ///< File member date - decimal.
+  UINT8 UserID[6];    ///< File member user id - decimal.
+  UINT8 GroupID[6];   ///< File member group id - decimal.
+  UINT8 Mode[8];      ///< File member mode - octal.
+  UINT8 Size[10];     ///< File member size - decimal.
+  UINT8 EndHeader[2]; ///< String to end header. (0x60 0x0A).
+} EFI_IMAGE_ARCHIVE_MEMBER_HEADER;
+
+///
+/// Size of EFI_IMAGE_ARCHIVE_MEMBER_HEADER.
+///
+#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
+
+
+//
+// DLL Support
+//
+
+///
+/// Export Directory Table.
+///
+typedef struct {
+  UINT32  Characteristics;
+  UINT32  TimeDateStamp;
+  UINT16  MajorVersion;
+  UINT16  MinorVersion;
+  UINT32  Name;
+  UINT32  Base;
+  UINT32  NumberOfFunctions;
+  UINT32  NumberOfNames;
+  UINT32  AddressOfFunctions;
+  UINT32  AddressOfNames;
+  UINT32  AddressOfNameOrdinals;
+} EFI_IMAGE_EXPORT_DIRECTORY;
+
+///
+/// Hint/Name Table.
+///
+typedef struct {
+  UINT16  Hint;
+  UINT8   Name[1];
+} EFI_IMAGE_IMPORT_BY_NAME;
+
+///
+/// Import Address Table RVA (Thunk Table).
+///
+typedef struct {
+  union {
+    UINT32                    Function;
+    UINT32                    Ordinal;
+    EFI_IMAGE_IMPORT_BY_NAME  *AddressOfData;
+  } u1;
+} EFI_IMAGE_THUNK_DATA;
+
+#define EFI_IMAGE_ORDINAL_FLAG              BIT31    ///< Flag for PE32.
+#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal)  ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0)
+#define EFI_IMAGE_ORDINAL(Ordinal)          (Ordinal & 0xffff)
+
+///
+/// Import Directory Table
+///
+typedef struct {
+  UINT32                Characteristics;
+  UINT32                TimeDateStamp;
+  UINT32                ForwarderChain;
+  UINT32                Name;
+  EFI_IMAGE_THUNK_DATA  *FirstThunk;
+} EFI_IMAGE_IMPORT_DESCRIPTOR;
+
+
+///
+/// Debug Directory Format.
+///
+typedef struct {
+  UINT32  Characteristics;
+  UINT32  TimeDateStamp;
+  UINT16  MajorVersion;
+  UINT16  MinorVersion;
+  UINT32  Type;
+  UINT32  SizeOfData;
+  UINT32  RVA;           ///< The address of the debug data when loaded, relative to the image base.
+  UINT32  FileOffset;    ///< The file pointer to the debug data.
+} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY;
+
+#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2     ///< The Visual C++ debug information.
+
+///
+/// Debug Data Structure defined in Microsoft C++.
+///
+#define CODEVIEW_SIGNATURE_NB10  SIGNATURE_32('N', 'B', '1', '0')
+typedef struct {
+  UINT32  Signature;                        ///< "NB10"
+  UINT32  Unknown;
+  UINT32  Unknown2;
+  UINT32  Unknown3;
+  //
+  // Filename of .PDB goes here
+  //
+} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY;
+
+///
+/// Debug Data Structure defined in Microsoft C++.
+/// FIXME:
+/// Documentation available at: https://github.com/dotnet/runtime/blob/main/docs/design/specs/PE-COFF.md
+///
+#define CODEVIEW_SIGNATURE_RSDS  SIGNATURE_32('R', 'S', 'D', 'S')
+typedef struct {
+  //
+  // 0x52 0x53 0x44 0x53 (ASCII string: "RSDS")
+  //
+  UINT32  Signature;                        ///< "RSDS".
+  //
+  // GUID (Globally Unique Identifier) of the associated PDB.
+  //
+  UINT8   Guid[16];
+  //
+  // Iteration of the PDB. The first iteration is 1. The iteration is
+  // incremented each time the PDB content is augmented.
+  //
+  UINT32  Age;
+  //
+  // UTF-8 NUL-terminated path to the associated .pdb file
+  //
+} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY;
+
+
+///
+/// Debug Data Structure defined by Apple Mach-O to Coff utility.
+///
+#define CODEVIEW_SIGNATURE_MTOC  SIGNATURE_32('M', 'T', 'O', 'C')
+typedef struct {
+  UINT32    Signature;                       ///< "MTOC".
+  UINT8     Uuid[16];
+  //
+  //  Filename of .DLL (Mach-O with debug info) goes here
+  //
+} EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY;
+
+///
+/// Resource directory entry format.
+///
+typedef struct {
+  union {
+    struct {
+      UINT32  NameOffset:31;
+      UINT32  NameIsString:1;
+    } s;
+    UINT32  Id;
+  } u1;
+  union {
+    UINT32  OffsetToData;
+    struct {
+      UINT32  OffsetToDirectory:31;
+      UINT32  DataIsDirectory:1;
+    } s;
+  } u2;
+} EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY;
+
+///
+/// Resource format.
+///
+typedef struct {
+  UINT32  Characteristics;
+  UINT32  TimeDateStamp;
+  UINT16  MajorVersion;
+  UINT16  MinorVersion;
+  UINT16  NumberOfNamedEntries;
+  UINT16  NumberOfIdEntries;
+  EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY Entries[];
+} EFI_IMAGE_RESOURCE_DIRECTORY;
+
+///
+/// Resource directory entry for string.
+///
+typedef struct {
+  UINT16  Length;
+  CHAR16  String[];
+} EFI_IMAGE_RESOURCE_DIRECTORY_STRING;
+
+///
+/// Resource directory entry for data array.
+///
+typedef struct {
+  UINT32  OffsetToData;
+  UINT32  Size;
+  UINT32  CodePage;
+  UINT32  Reserved;
+} EFI_IMAGE_RESOURCE_DATA_ENTRY;
+
+///
+/// Header format for TE images, defined in the PI Specification, 1.0.
+///
+typedef struct {
+  UINT16                    Signature;            ///< The signature for TE format = "VZ".
+  UINT16                    Machine;              ///< From the original file header.
+  UINT8                     NumberOfSections;     ///< From the original file header.
+  UINT8                     Subsystem;            ///< From original optional header.
+  UINT16                    StrippedSize;         ///< Number of bytes we removed from the header.
+  UINT32                    AddressOfEntryPoint;  ///< Offset to entry point -- from original optional header.
+  UINT32                    BaseOfCode;           ///< From original image -- required for ITP debug.
+  UINT64                    ImageBase;            ///< From original file header.
+  EFI_IMAGE_DATA_DIRECTORY  DataDirectory[2];     ///< Only base relocation and debug directory.
+} EFI_TE_IMAGE_HEADER;
+
+
+#define EFI_TE_IMAGE_HEADER_SIGNATURE  SIGNATURE_16('V', 'Z')
+
+//
+// Data directory indexes in our TE image header
+//
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC  0
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG      1
+
+
+///
+/// Union of PE32, PE32+, and TE headers.
+///
+typedef union {
+  EFI_IMAGE_NT_HEADERS_COMMON_HDR PeCommon;
+  EFI_IMAGE_NT_HEADERS32          Pe32;
+  EFI_IMAGE_NT_HEADERS64          Pe32Plus;
+  EFI_TE_IMAGE_HEADER             Te;
+} EFI_IMAGE_OPTIONAL_HEADER_UNION;
+
+#endif // PE_COFF_IMAGE2_H_
diff --git a/MdePkg/Include/Library/PeCoffExtraActionLib.h b/MdePkg/Include/Library/PeCoffExtraActionLib.h
index efe5133922..8950f1a604 100644
--- a/MdePkg/Include/Library/PeCoffExtraActionLib.h
+++ b/MdePkg/Include/Library/PeCoffExtraActionLib.h
@@ -1,3 +1,5 @@
+#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
+
 /** @file
   Provides services to perform additional actions when a PE/COFF image is loaded
   or unloaded.  This is useful for environment where symbols need to be loaded
@@ -45,3 +47,5 @@ PeCoffLoaderUnloadImageExtraAction (
   );
 
 #endif
+
+#endif // DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/MdePkg/Include/Library/PeCoffLib.h b/MdePkg/Include/Library/PeCoffLib.h
index 74cceb37bf..f644fdeddc 100644
--- a/MdePkg/Include/Library/PeCoffLib.h
+++ b/MdePkg/Include/Library/PeCoffLib.h
@@ -1,3 +1,5 @@
+#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
+
 /** @file
   Provides services to load and relocate a PE/COFF image.
 
@@ -76,127 +78,127 @@ typedef struct {
   ///
   /// Set by PeCoffLoaderGetImageInfo() to the ImageBase in the PE/COFF header.
   ///
-  PHYSICAL_ADDRESS            ImageAddress;
+  PHYSICAL_ADDRESS                  ImageAddress;
   ///
   /// Set by PeCoffLoaderGetImageInfo() to the SizeOfImage in the PE/COFF header.
   /// Image size includes the size of Debug Entry if it is present.
   ///
-  UINT64                      ImageSize;
+  UINT64                            ImageSize;
   ///
   /// Is set to zero by PeCoffLoaderGetImageInfo(). If DestinationAddress is non-zero,
   /// PeCoffLoaderRelocateImage() will relocate the image using this base address.
   /// If the DestinationAddress is zero, the ImageAddress will be used as the base
   /// address of relocation.
   ///
-  PHYSICAL_ADDRESS            DestinationAddress;
+  PHYSICAL_ADDRESS                  DestinationAddress;
   ///
   /// PeCoffLoaderLoadImage() sets EntryPoint to to the entry point of the PE/COFF image.
   ///
-  PHYSICAL_ADDRESS            EntryPoint;
+  PHYSICAL_ADDRESS                  EntryPoint;
   ///
   /// Passed in by the caller to PeCoffLoaderGetImageInfo() and PeCoffLoaderLoadImage()
   /// to abstract accessing the image from the library.
   ///
-  PE_COFF_LOADER_READ_FILE    ImageRead;
+  PE_COFF_LOADER_READ_FILE          ImageRead;
   ///
   /// Used as the FileHandle passed into the ImageRead function when it's called.
   ///
-  VOID                        *Handle;
+  VOID                              *Handle;
   ///
   /// Caller allocated buffer of size FixupDataSize that can be optionally allocated
   /// prior to calling PeCoffLoaderRelocateImage().
   /// This buffer is filled with the information used to fix up the image.
   /// The fixups have been applied to the image and this entry is just for information.
   ///
-  VOID                        *FixupData;
+  VOID                              *FixupData;
   ///
   /// Set by PeCoffLoaderGetImageInfo() to the Section Alignment in the PE/COFF header.
   /// If the image is a TE image, then this field is set to 0.
   ///
-  UINT32                      SectionAlignment;
+  UINT32                            SectionAlignment;
   ///
   /// Set by PeCoffLoaderGetImageInfo() to offset to the PE/COFF header.
   /// If the PE/COFF image does not start with a DOS header, this value is zero.
   /// Otherwise, it's the offset to the PE/COFF header.
   ///
-  UINT32                      PeCoffHeaderOffset;
+  UINT32                            PeCoffHeaderOffset;
   ///
   /// Set by PeCoffLoaderGetImageInfo() to the Relative Virtual Address of the debug directory,
   /// if it exists in the image
   ///
-  UINT32                      DebugDirectoryEntryRva;
+  UINT32                            DebugDirectoryEntryRva;
   ///
   /// Set by PeCoffLoaderLoadImage() to CodeView area of the PE/COFF Debug directory.
   ///
-  VOID                        *CodeView;
+  VOID                              *CodeView;
   ///
   /// Set by PeCoffLoaderLoadImage() to point to the PDB entry contained in the CodeView area.
   /// The PdbPointer points to the filename of the PDB file used for source-level debug of
   /// the image by a debugger.
   ///
-  CHAR8                       *PdbPointer;
+  CHAR8                             *PdbPointer;
   ///
   /// Is set by PeCoffLoaderGetImageInfo() to the Section Alignment in the PE/COFF header.
   ///
-  UINTN                       SizeOfHeaders;
+  UINTN                             SizeOfHeaders;
   ///
   /// Not used by this library class. Other library classes that layer on  top of this library
   /// class fill in this value as part of their GetImageInfo call.
   /// This allows the caller of the library to know what type of memory needs to be allocated
   /// to load and relocate the image.
   ///
-  UINT32                      ImageCodeMemoryType;
+  UINT32                            ImageCodeMemoryType;
   ///
   /// Not used by this library class. Other library classes that layer on top of this library
   /// class fill in this value as part of their GetImageInfo call.
   /// This allows the caller of the library to know what type of memory needs to be allocated
   /// to load and relocate the image.
   ///
-  UINT32                      ImageDataMemoryType;
+  UINT32                            ImageDataMemoryType;
   ///
   /// Set by any of the library functions if they encounter an error.
   ///
-  UINT32                      ImageError;
+  UINT32                            ImageError;
   ///
   /// Set by PeCoffLoaderLoadImage() to indicate the size of FixupData that the caller must
   /// allocate before calling PeCoffLoaderRelocateImage().
   ///
-  UINTN                       FixupDataSize;
+  UINTN                             FixupDataSize;
   ///
   /// Set by PeCoffLoaderGetImageInfo() to the machine type stored in the PE/COFF header.
   ///
-  UINT16                      Machine;
+  UINT16                            Machine;
   ///
   /// Set by PeCoffLoaderGetImageInfo() to the subsystem type stored in the PE/COFF header.
   ///
-  UINT16                      ImageType;
+  UINT16                            ImageType;
   ///
   /// Set by PeCoffLoaderGetImageInfo() to the DLL flags stored in the PE/COFF header and
   /// in the DllCharacteristicsEx debug table.
   ///
-  UINT16                      DllCharacteristics;
-  UINT32                      DllCharacteristicsEx;
+  UINT16                            DllCharacteristics;
+  UINT32                            DllCharacteristicsEx;
   ///
   /// Set by PeCoffLoaderGetImageInfo() to TRUE if the PE/COFF image does not contain
   /// relocation information.
   ///
-  BOOLEAN                     RelocationsStripped;
+  BOOLEAN                           RelocationsStripped;
   ///
   /// Set by PeCoffLoaderGetImageInfo() to TRUE if the image is a TE image.
   /// For a definition of the TE Image format, see the Platform Initialization Pre-EFI
   /// Initialization Core Interface Specification.
   ///
-  BOOLEAN                     IsTeImage;
+  BOOLEAN                           IsTeImage;
   ///
   /// Set by PeCoffLoaderLoadImage() to the HII resource offset
   /// if the image contains a custom PE/COFF resource with the type 'HII'.
   /// Otherwise, the entry remains to be 0.
   ///
-  PHYSICAL_ADDRESS            HiiResourceData;
+  PHYSICAL_ADDRESS                  HiiResourceData;
   ///
   /// Private storage for implementation specific data.
   ///
-  UINT64                      Context;
+  UINT64                            Context;
 } PE_COFF_LOADER_IMAGE_CONTEXT;
 
 /**
@@ -302,6 +304,7 @@ PeCoffLoaderLoadImage (
   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
   );
 
+
 /**
   Reads contents of a PE/COFF image from a buffer in system memory.
 
@@ -328,12 +331,13 @@ PeCoffLoaderLoadImage (
 RETURN_STATUS
 EFIAPI
 PeCoffLoaderImageReadFromMemory (
-  IN     VOID   *FileHandle,
-  IN     UINTN  FileOffset,
-  IN OUT UINTN  *ReadSize,
-  OUT    VOID   *Buffer
+  IN     VOID    *FileHandle,
+  IN     UINTN   FileOffset,
+  IN OUT UINTN   *ReadSize,
+  OUT    VOID    *Buffer
   );
 
+
 /**
   Reapply fixups on a fixed up PE32/PE32+ image to allow virtual calling at EFI
   runtime.
@@ -359,11 +363,11 @@ PeCoffLoaderImageReadFromMemory (
 **/
 VOID
 EFIAPI
-PeCoffLoaderRelocateImageForRuntime (
-  IN  PHYSICAL_ADDRESS  ImageBase,
-  IN  PHYSICAL_ADDRESS  VirtImageBase,
-  IN  UINTN             ImageSize,
-  IN  VOID              *RelocationData
+PeCoffLoaderRuntimeRelocateImage (
+  IN  PHYSICAL_ADDRESS        ImageBase,
+  IN  PHYSICAL_ADDRESS        VirtImageBase,
+  IN  UINTN                   ImageSize,
+  IN  VOID                    *RelocationData
   );
 
 /**
@@ -387,5 +391,6 @@ EFIAPI
 PeCoffLoaderUnloadImage (
   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
   );
-
 #endif
+
+#endif // DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/MdePkg/Include/Library/PeCoffLib2.h b/MdePkg/Include/Library/PeCoffLib2.h
new file mode 100644
index 0000000000..0985a0bc1e
--- /dev/null
+++ b/MdePkg/Include/Library/PeCoffLib2.h
@@ -0,0 +1,597 @@
+/** @file
+  Provides APIs to inspect, load, and relocate PE/COFF Images.
+
+  No implementation of this library may use global variable pointers, as this
+  may cause the emission of Image relocations for this address. This is
+  incompatible with the concept of Image self-relocation, where the Image is
+  loaded in a similar fashion to XIP Images into the memory at an address
+  unknown at compile-time. As such, Image relocation must be safe to perform
+  without any Image relocations applied earlier.
+
+  Copyright (c) 2020 - 2021, Marvin Häuser. All rights reserved.<BR>
+  Copyright (c) 2020, Vitaly Cheptsov. All rights reserved.<BR>
+  Copyright (c) 2020, ISP RAS. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-3-Clause
+**/
+
+#ifndef PE_COFF_LIB2_H_
+#define PE_COFF_LIB2_H_
+
+#include <IndustryStandard/PeImage2.h>
+
+#include <Guid/WinCertificate.h>
+
+// FIXME: Where to put this?
+//
+// PcdImageLoaderAlignmentPolicy bits.
+//
+
+///
+/// If set, unaligned Image sections are permitted.
+///
+#define PCD_ALIGNMENT_POLICY_CONTIGUOUS_SECTIONS     BIT0
+///
+/// If set, unaligned Image Relocation Block sizes are permitted.
+///
+#define PCD_ALIGNMENT_POLICY_RELOCATION_BLOCK_SIZES  BIT1
+///
+/// If set, unaligned Image certificate sizes are permitted.
+///
+#define PCD_ALIGNMENT_POLICY_CERTIFICATE_SIZES       BIT2
+
+// FIXME: Rework docs to consider Inplace dependencies
+
+/**
+  Returns whether the Image targets the UEFI Subsystem.
+
+  @param[in] Subsystem  The Subsystem value from the Image Headers.
+**/
+#define IMAGE_IS_EFI_SUBYSYSTEM(Subsystem) \
+  ((Subsystem) >= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION && \
+   (Subsystem) <= EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER)
+
+///
+/// Image type enumeration for Image format identification from the context.
+///
+typedef enum {
+  PeCoffLoaderTypeTe,
+  PeCoffLoaderTypePe32,
+  PeCoffLoaderTypePe32Plus,
+  PeCoffLoaderTypeMax
+} PE_COFF_LOADER_IMAGE_TYPE;
+
+///
+/// Image context structure used for abstraction and bookkeeping.
+/// This structure is publicly exposed for memory allocation reasons and must
+/// not be accessed directly outside of the library implementation.
+///
+typedef struct {
+  ///
+  /// The preferred load address of the Image.
+  ///
+  UINT64     ImageBase;
+  ///
+  /// A pointer to the Image raw file buffer.
+  ///
+  CONST VOID *FileBuffer;
+  ///
+  /// The size, in Bytes, of FileBuffer.
+  ///
+  UINT32     FileSize;
+  ///
+  /// A pointer to the loaded Image destination.
+  ///
+  VOID       *ImageBuffer;
+  ///
+  /// The offset of the Section Headers from the beginning of the raw file.
+  ///
+  UINT32     SectionsOffset;
+  ///
+  /// The number of Sections in the Image.
+  ///
+  UINT16     NumberOfSections;
+  ///
+  /// The size, in Bytes, required to load the Image.
+  ///
+  UINT32     SizeOfImage;
+  ///
+  /// The alignment, in Bytes, of Image Sections virtual addresses.
+  ///
+  UINT32     SectionAlignment;
+  ///
+  /// The offset of the Image Header from the beginning of the raw file.
+  ///
+  UINT32     ExeHdrOffset;
+  ///
+  /// The combined size, in Bytes, of all Image Headers.
+  ///
+  UINT32     SizeOfHeaders;
+  ///
+  /// The RVA of the Image entry point.
+  ///
+  UINT32     AddressOfEntryPoint;
+  ///
+  /// Indicates whether relocation information has been stripped from the Image.
+  ///
+  BOOLEAN    RelocsStripped;
+  ///
+  /// The file format of the Image raw file, refer to PE_COFF_LOADER_IMAGE_TYPE.
+  ///
+  UINT8      ImageType;
+  ///
+  /// The Subsystem value from the Image Header.
+  ///
+  UINT16     Subsystem;
+  ///
+  /// The Machine value from the Image Header.
+  ///
+  UINT16     Machine;
+  ///
+  /// The size, in Bytes, stripped from the beginning of the Image raw file
+  /// during TE file generation. Always 0 for PE Images.
+  ///
+  UINT16     TeStrippedOffset;
+  ///
+  /// The RVA of the Relocation Directory.
+  ///
+  UINT32     RelocDirRva;
+  ///
+  /// The size, in Bytes, of the Relocation Directory.
+  ///
+  UINT32     RelocDirSize;
+  ///
+  /// The RVA of the Security Directory.
+  ///
+  UINT32     SecDirOffset;
+  ///
+  /// The size, in Bytes, of the Security Directory.
+  ///
+  UINT32     SecDirSize;
+} PE_COFF_LOADER_IMAGE_CONTEXT;
+
+///
+/// Image runtime context used to relocate the Image during runtime.
+///
+typedef struct PE_COFF_LOADER_RUNTIME_CONTEXT_ PE_COFF_LOADER_RUNTIME_CONTEXT;
+
+/**
+  Adds the digest of Data to HashContext. This function can be called multiple
+  times to compute the digest of discontinuous data.
+
+  @param[in,out] HashContext  The context of the current hash.
+  @param[in]     Data         The data to be hashed.
+  @param[in]     DataSize     The size, in Bytes, of Data.
+
+  @returns  Whether hashing has been successful.
+**/
+typedef
+BOOLEAN
+(EFIAPI *PE_COFF_LOADER_HASH_UPDATE)(
+  IN OUT VOID        *HashContext,
+  IN     CONST VOID  *Data,
+  IN     UINTN       DataSize
+  );
+
+/**
+  Verify the TE, PE32, or PE32+ Image and initialise Context.
+
+  Used offsets and ranges must be aligned and in the bounds of the raw file.
+  Image Section Headers and basic Relocation information must be well-formed.
+
+  FileBuffer must remain valid for the entire lifetime of Context.
+
+  @param[out] Context     The context describing the Image.
+  @param[in]  FileBuffer  The file data to parse as TE or PE Image.
+  @param[in]  FileSize    The size, in Bytes, of FileBuffer.
+
+  @retval RETURN_SUCCESS  The Image context has been initialised successfully.
+  @retval other           The file data is malformed.
+**/
+RETURN_STATUS
+PeCoffInitializeContext (
+  OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  IN  CONST VOID                    *FileBuffer,
+  IN  UINT32                        FileSize
+  );
+
+/**
+  Hashes the Image using the Authenticode (PE/COFF Specification 8.1 Appendix A)
+  algorithm.
+
+  @param[in,out] Context      The context describing the Image. Must have been
+                              initialised by PeCoffInitializeContext().
+  @param[in,out] HashContext  The context of the current hash. Must have been
+                              initialised for usage with the HashUpdate
+                              function.
+  @param[in]     HashUpdate   The data hashing function.
+
+  @returns  Whether hashing has been successful.
+**/
+BOOLEAN
+PeCoffHashImageAuthenticode (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  IN OUT VOID                          *HashContext,
+  IN     PE_COFF_LOADER_HASH_UPDATE    HashUpdate
+  );
+
+/**
+  Load the Image into the destination memory space.
+
+  @param[in,out] Context          The context describing the Image. Must have
+                                  been initialised by PeCoffInitializeContext().
+  @param[out]    Destination      The Image destination memory. Must be
+                                  allocated from page memory.
+  @param[in]     DestinationSize  The size, in Bytes, of Destination. Must be
+                                  sufficent to load the Image with regards to
+                                  its Image section alignment.
+
+  @retval RETURN_SUCCESS  The Image was loaded successfully.
+  @retval other           The Image could not be loaded successfully.
+**/
+RETURN_STATUS
+PeCoffLoadImage (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    VOID                          *Destination,
+  IN     UINT32                        DestinationSize
+  );
+
+// FIXME: Docs
+BOOLEAN
+PeCoffImageIsInplace (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Equivalent to the PeCoffLoadImage() function for inplace-loading. Ensures that
+  all important raw file offsets match the respective RVAs.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by PeCoffInitializeContext().
+
+  @retval RETURN_SUCCESS  The Image has been inplace-loaded successfully.
+  @retval other           The Image is not suitable for inplace-loading.
+**/
+RETURN_STATUS
+PeCoffLoadImageInplace (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+// FIXME: Docs
+RETURN_STATUS
+PeCoffRelocateImageInplace (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the size required to bookkeep Image runtime relocation information.
+
+  May only be called when PeCoffGetRelocsStripped() returns FALSE.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          loaded by PeCoffLoadImage().
+  @param[out]    Size     On output, the size, in Bytes, required for the
+                          bookkeeping buffer.
+
+  @retval RETURN_SUCCESS  The Image runtime context size for the Image was
+                          retrieved successfully.
+  @retval other           The Image runtime context size for the Image could not
+                          be retrieved successfully.
+**/
+RETURN_STATUS
+PeCoffLoaderGetRuntimeContextSize (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    UINT32                        *Size
+  );
+
+/**
+  Relocate the Image for boot-time usage.
+
+  May only be called when PeCoffGetRelocsStripped() returns FALSE, or with
+  BaseAddress == PeCoffGetImageBase().
+
+  @param[in,out] Context             The context describing the Image. Must have
+                                     been loaded by PeCoffLoadImage().
+  @param[in]     BaseAddress         The address to relocate the Image to.
+  @param[out]    RuntimeContext      If not NULL, on output, a bookkeeping data
+                                     required for Image runtime relocation.
+  @param[in]     RuntimeContextSize  The size, in Bytes, of RuntimeContext. Must
+                                     be at least as big as the size returned by
+                                     PeCoffLoaderGetRuntimeContextSize().
+
+  @retval RETURN_SUCCESS  The Image has been relocated successfully.
+  @retval other           The Image Relocation Directory is malformed.
+**/
+RETURN_STATUS
+PeCoffRelocateImage (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT    *Context,
+  IN     UINT64                          BaseAddress,
+  OUT    PE_COFF_LOADER_RUNTIME_CONTEXT  *RuntimeContext OPTIONAL,
+  IN     UINT32                          RuntimeContextSize
+  );
+
+/**
+  Relocate Image for Runtime usage.
+
+  May only be called when PeCoffGetRelocsStripped() returns FALSE, or with
+  BaseAddress == PeCoffGetImageBase().
+
+  @param[in,out] Image           The Image destination memory. Must have been
+                                 relocated by PeCoffRelocateImage().
+  @param[in]     ImageSize       The size, in Bytes, of Image.
+  @param[in]     BaseAddress     The address to relocate the Image to.
+  @param[in]     RuntimeContext  The Relocation context obtained by
+                                 PeCoffRelocateImage().
+
+  @retval RETURN_SUCCESS  The Image has been relocated successfully.
+  @retval other           The Image could not be relocated successfully.
+**/
+RETURN_STATUS
+PeCoffRuntimeRelocateImage (
+  IN OUT VOID                                  *Image,
+  IN     UINT32                                ImageSize,
+  IN     UINT64                                BaseAddress,
+  IN     CONST PE_COFF_LOADER_RUNTIME_CONTEXT  *RuntimeContext
+  );
+
+/**
+  Discards optional Image Sections to disguise sensitive data.
+
+  This may destruct the Image Relocation Directory and as such, no function that
+  performs Image relocation may be called after this function has been invoked.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          loaded by PeCoffLoadImage().
+**/
+VOID
+PeCoffDiscardSections (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the Image PDB path.
+
+  @param[in,out] Context      The context describing the Image. Must have been
+                              initialised by PeCoffInitializeContext().
+  @param[out]    PdbPath      On output, a pointer to the Image PDB path.
+  @param[out]    PdbPathSize  On output, the size, in Bytes, of *PdbPath.
+
+  @retval RETURN_SUCCESS  The Image PDB path was retrieved successfully.
+  @retval other           The Image PDB path could not be retrieved
+                          successfully.
+**/
+RETURN_STATUS
+PeCoffGetPdbPath (
+  IN  CONST PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  OUT CONST CHAR8                         **PdbPath,
+  OUT UINT32                              *PdbPathSize
+  );
+
+/**
+  Retrieves the first certificate from the Image Certificate Directory.
+
+  @param[in,out] Context      The context describing the Image. Must have been
+                              initialised by PeCoffInitializeContext().
+  @param[out]    Certificate  On output, the first certificate of the Image.
+
+  @retval RETURN_SUCCESS    The certificate has been retrieved successfully.
+  @retval RETURN_NOT_FOUND  There is no such certificate.
+  @retval other             The Image Certificate Directory is malformed.
+**/
+RETURN_STATUS
+PeCoffGetFirstCertificate (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    CONST WIN_CERTIFICATE         **Certificate
+  );
+
+/**
+  Retrieves the next certificate from the Image Certificate Directory.
+
+  @param[in,out] Context      The context describing the Image. Must have been
+                              initialised by PeCoffInitializeContext().
+  @param[out]    Certificate  On input, the current certificate of the Image.
+                              Must have been retrieved by
+                              PeCoffGetFirstCertificate().
+                              On output, the next certificate of the Image.
+
+  @retval RETURN_SUCCESS    The certificate has been retrieved successfully.
+  @retval RETURN_NOT_FOUND  There is no such certificate.
+  @retval other             The Image Certificate Directory is malformed.
+**/
+RETURN_STATUS
+PeCoffGetNextCertificate (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  IN OUT CONST WIN_CERTIFICATE         **Certificate
+  );
+
+/**
+  Retrieves the Image Section Table.
+
+  @param[in,out] Context   The context describing the Image. Must have been
+                           initialised by PeCoffInitializeContext().
+  @param[out]    Sections  On output, points to the Image Section Table.
+
+  @returns  The number of sections in the Image Section Table.
+**/
+UINT16
+PeCoffGetSectionTable (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT    *Context,
+  OUT    CONST EFI_IMAGE_SECTION_HEADER  **Sections
+  );
+
+/**
+  Retrieves the Image HII data RVA.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by PeCoffInitializeContext().
+  @param[out]    HiiRva   On output, the RVA of the HII resource data.
+  @param[out]    HiiSize  On output, the size, in Bytes, of HiiRva.
+
+  @retval RETURN_SUCCESS    The Image HII data has been retrieved successfully.
+  @retval RETURN_NOT_FOUND  The Image HII data could not be found.
+  @retval other             The Image Resource Directory is malformed.
+**/
+RETURN_STATUS
+PeCoffGetHiiDataRva (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    UINT32                        *HiiRva,
+  OUT    UINT32                        *HiiSize
+  );
+
+/**
+  Retrieve the Image entry point RVA.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by PeCoffInitializeContext().
+
+  @returns  The Image entry point RVA.
+**/
+UINT32
+PeCoffGetAddressOfEntryPoint (
+  IN CONST PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the Image machine type.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by PeCoffInitializeContext().
+
+  @returns  The Image machine type.
+**/
+UINT16
+PeCoffGetMachine (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the Image subsystem type.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by PeCoffInitializeContext().
+
+  @returns  The Image subsystem type.
+**/
+UINT16
+PeCoffGetSubsystem (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the Image section alignment.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by PeCoffInitializeContext().
+
+  @returns  The Image section alignment.
+**/
+UINT32
+PeCoffGetSectionAlignment (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the size, in Bytes, of the Image memory space.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by PeCoffInitializeContext().
+
+  @returns  The size of the Image memory space.
+**/
+UINT32
+PeCoffGetSizeOfImage (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the size, in Bytes, of the Image memory space for in-place loading.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by PeCoffInitializeContext().
+
+  @returns  The size of the Image memory space for in-place loading.
+**/
+UINT32
+PeCoffGetSizeOfImageInplace (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the Image preferred load address.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by PeCoffInitializeContext().
+
+  @returns  The Image preferred load address.
+**/
+UINT64
+PeCoffGetImageBase (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the size, in Bytes, of the Image Headers.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by PeCoffInitializeContext().
+
+  @returns  The size of the Image Headers.
+**/
+UINT32
+PeCoffGetSizeOfHeaders (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Returns whether the Image relocations have been stripped.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by PeCoffInitializeContext().
+
+  @returns  Whether the Image relocations have been stripped.
+**/
+BOOLEAN
+PeCoffGetRelocsStripped (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the Image load address PeCoffLoadImage() has loaded the Image to.
+
+  May be called only after PeCoffLoadImage() has succeeded.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by PeCoffInitializeContext().
+
+  @returns  The Image load address.
+**/
+UINTN
+PeCoffLoaderGetImageAddress (
+  IN CONST PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieve the immediate data encoded in an ARM MOVW/MOVT instruciton pair.
+
+  @param[in] Instructions  Pointer to an ARM MOVW/MOVT insturction pair.
+
+  @returns  The Immediate address encoded in the instructions.
+**/
+UINT32
+PeCoffThumbMovwMovtImmediateAddress (
+  IN CONST VOID  *Instructions
+  );
+
+/**
+  Relocate an ARM MOVW/MOVT immediate instruction instruction pair.
+
+  @param[in,out] Instructions  Pointer to ARM MOVW/MOVT instruction pair.
+  @param[in]     Adjust        The delta to add to the addresses.
+**/
+VOID
+PeCoffThumbMovwMovtImmediateFixup (
+  IN OUT VOID    *Instructions,
+  IN     UINT64  Adjust
+  );
+
+#endif // PE_COFF_LIB2_H_
diff --git a/MdePkg/Include/Library/PeiServicesLib.h b/MdePkg/Include/Library/PeiServicesLib.h
index 0ca032e411..3ed1fd72f7 100644
--- a/MdePkg/Include/Library/PeiServicesLib.h
+++ b/MdePkg/Include/Library/PeiServicesLib.h
@@ -238,6 +238,32 @@ PeiServicesFfsFindSectionData3 (
   OUT UINT32              *AuthenticationStatus
   );
 
+/**
+  This service enables PEIMs to discover sections of a given instance and type within a valid FFS file.
+
+  @param  SectionType           The value of the section type to find.
+  @param  SectionInstance       Section instance to find.
+  @param  FileHandle            A pointer to the file header that contains the set
+                                of sections to be searched.
+  @param  SectionData           A pointer to the discovered section, if successful.
+  @param  SectionDataSize       The size of the discovered section, if successful.
+  @param  AuthenticationStatus  A pointer to the authentication status for this section.
+
+  @retval EFI_SUCCESS           The section was found.
+  @retval EFI_NOT_FOUND         The section was not found.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiServicesFfsFindSectionData4 (
+  IN EFI_SECTION_TYPE           SectionType,
+  IN UINTN                      SectionInstance,
+  IN EFI_PEI_FILE_HANDLE        FileHandle,
+  OUT VOID                      **SectionData,
+  OUT UINT32                    *SectionDataSize,
+  OUT UINT32                    *AuthenticationStatus
+  );
+
 /**
   This service enables PEIMs to register the permanent memory configuration
   that has been initialized with the PEI Foundation.
diff --git a/MdePkg/Include/Library/UefiImageExtraActionLib.h b/MdePkg/Include/Library/UefiImageExtraActionLib.h
new file mode 100644
index 0000000000..4aa7193527
--- /dev/null
+++ b/MdePkg/Include/Library/UefiImageExtraActionLib.h
@@ -0,0 +1,47 @@
+/** @file
+  Provides services to perform additional actions when an UEFI image is loaded
+  or unloaded.  This is useful for environment where symbols need to be loaded
+  and unloaded to support source level debugging.
+
+  Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __UEFI_IMAGE_EXTRA_ACTION_LIB_H__
+#define __UEFI_IMAGE_EXTRA_ACTION_LIB_H__
+
+#include <Library/UefiImageLib.h>
+
+/**
+  Performs additional actions after a UEFI image has been loaded and relocated.
+
+  If ImageContext is NULL, then ASSERT().
+
+  @param  ImageContext  Pointer to the image context structure that describes the
+                        UEFI image that has already been loaded and relocated.
+
+**/
+VOID
+EFIAPI
+UefiImageLoaderRelocateImageExtraAction (
+  IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
+  );
+
+/**
+  Performs additional actions just before a UEFI image is unloaded.  Any resources
+  that were allocated by UefiImageLoaderRelocateImageExtraAction() must be freed.
+
+  If ImageContext is NULL, then ASSERT().
+
+  @param  ImageContext  Pointer to the image context structure that describes the
+                        UEFI image that is being unloaded.
+
+**/
+VOID
+EFIAPI
+UefiImageLoaderUnloadImageExtraAction (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
+  );
+
+#endif
diff --git a/MdePkg/Include/Library/UefiImageLib.h b/MdePkg/Include/Library/UefiImageLib.h
new file mode 100644
index 0000000000..b0de4b317c
--- /dev/null
+++ b/MdePkg/Include/Library/UefiImageLib.h
@@ -0,0 +1,642 @@
+// FIXME: Docs
+#ifndef UEFI_IMAGE_LIB_H_
+#define UEFI_IMAGE_LIB_H_
+
+// FIXME: Work on reasonable abstraction
+#ifndef UEFI_IMAGE_LOADER_IMAGE_CONTEXT
+  #include <Library/PeCoffLib2.h>
+
+  #define UEFI_IMAGE_LOADER_IMAGE_CONTEXT    PE_COFF_LOADER_IMAGE_CONTEXT
+  #define UEFI_IMAGE_LOADER_RUNTIME_CONTEXT  PE_COFF_LOADER_RUNTIME_CONTEXT
+#endif
+
+///
+/// Image record segment that desribes the UEFI memory permission configuration
+/// for one segment of the Image.
+///
+typedef struct {
+  ///
+  /// The size, in Bytes, of the Image record segment.
+  ///
+  UINT32 Size;
+  ///
+  /// The UEFI memory permission attributes corresponding to this Image record
+  /// segment.
+  ///
+  UINT32 Attributes;
+} UEFI_IMAGE_RECORD_SEGMENT;
+
+///
+/// The 32-bit signature that identifies a UEFI_IMAGE_RECORD structure.
+///
+#define UEFI_IMAGE_RECORD_SIGNATURE  SIGNATURE_32 ('U','I','I','R')
+
+///
+/// Image record that describes the UEFI memory permission configuration for
+/// every segment of the Image.
+///
+typedef struct {
+  ///
+  /// The signature of the Image record structure. Must be set to
+  /// UEFI_IMAGE_RECORD_SIGNATURE.
+  ///
+  UINT32                       Signature;
+  ///
+  /// The number of Image records. Must be at least 1.
+  ///
+  UINT32                       NumSegments;
+  ///
+  /// A link to allow insertion of the Image record into a doubly-linked list.
+  ///
+  LIST_ENTRY                   Link;
+  ///
+  /// The start address of the Image memory space.
+  ///
+  UINTN                        StartAddress;
+  ///
+  /// The end address of the Image memory space. Must be equal to StartAddress
+  /// plus the sum of Segments[i].Size for 0 <= i < NumSegments.
+  ///
+  UINTN                        EndAddress;
+  ///
+  /// The Image record segments with their corresponding memory permission
+  /// attributes. All Image record segments are contiguous and cover the entire
+  /// Image memory space. The address of an Image record segment can be
+  /// determined by adding the sum of all previous sizes to StartAddress.
+  ///
+  UEFI_IMAGE_RECORD_SEGMENT    Segments[];
+} UEFI_IMAGE_RECORD;
+
+/**
+  Adds the digest of Data to HashContext. This function can be called multiple
+  times to compute the digest of discontinuous data.
+
+  @param[in,out] HashContext  The context of the current hash.
+  @param[in]     Data         The data to be hashed.
+  @param[in]     DataSize     The size, in Bytes, of Data.
+
+  @returns  Whether hashing has been successful.
+**/
+typedef
+BOOLEAN
+(EFIAPI *UEFI_IMAGE_LOADER_HASH_UPDATE)(
+  IN OUT VOID        *HashContext,
+  IN     CONST VOID  *Data,
+  IN     UINTN       DataSize
+  );
+
+// FIXME: Docs
+RETURN_STATUS
+UefiImageInitializeContextPreHash (
+  OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  IN  CONST VOID                       *FileBuffer,
+  IN  UINT32                           FileSize
+  );
+
+RETURN_STATUS
+UefiImageInitializeContextPostHash (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Verify the UEFI Image and initialise Context.
+
+  Used offsets and ranges must be aligned and in the bounds of the raw file.
+  Image headers and basic Relocation information must be well-formed.
+
+  FileBuffer must remain valid for the entire lifetime of Context.
+
+  @param[out] Context     The context describing the Image.
+  @param[in]  FileBuffer  The file data to parse as UEFI Image.
+  @param[in]  FileSize    The size, in Bytes, of FileBuffer.
+
+  @retval RETURN_SUCCESS  The Image context has been initialised successfully.
+  @retval other           The file data is malformed.
+**/
+RETURN_STATUS
+UefiImageInitializeContext (
+  OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  IN  CONST VOID                       *FileBuffer,
+  IN  UINT32                           FileSize
+  );
+
+/**
+  Retrieves the UefiImageLib Image format identifier.
+
+  @param[out] Context     The context describing the Image.
+
+  @returns  The UefiImageLib format identifier.
+**/
+UINT8
+UefiImageGetFormat (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Hashes the Image using the format's default hashing algorithm.
+
+  @param[in,out] Context      The context describing the Image. Must have been
+                              initialised by UefiImageInitializeContext().
+  @param[in,out] HashContext  The context of the current hash. Must have been
+                              initialised for usage with the HashUpdate
+                              function.
+  @param[in]     HashUpdate   The data hashing function.
+
+  @returns  Whether hashing has been successful.
+**/
+BOOLEAN
+UefiImageHashImageDefault (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  IN OUT VOID                             *HashContext,
+  IN     UEFI_IMAGE_LOADER_HASH_UPDATE    HashUpdate
+  );
+
+/**
+  Load the Image into the destination memory space.
+
+  @param[in,out] Context       The context describing the Image. Must have been
+                               initialised by UefiImageInitializeContext().
+  @param[out] Destination      The Image destination memory. Must be allocated
+                               from page memory.
+  @param[in]  DestinationSize  The size, in Bytes, of Destination. Must be at
+                               least as large as the size returned by
+                               UefiImageGetImageSize().
+
+  @retval RETURN_SUCCESS  The Image was loaded successfully.
+  @retval other           The Image could not be loaded successfully.
+**/
+RETURN_STATUS
+UefiImageLoadImage (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    VOID                             *Destination,
+  IN     UINT32                           DestinationSize
+  );
+
+// FIXME: Docs
+BOOLEAN
+UefiImageImageIsInplace (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Equivalent to the UefiImageLoadImage() function for inplace-loading. Ensures that
+  all important raw file offsets match the respective RVAs.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by UefiImageInitializeContext().
+
+  @retval RETURN_SUCCESS  The Image has been inplace-loaded successfully.
+  @retval other           The Image is not suitable for inplace-loading.
+**/
+RETURN_STATUS
+UefiImageLoadImageInplace (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+// FIXME: Docs
+RETURN_STATUS
+UefiImageRelocateImageInplace (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+// FIXME:
+RETURN_STATUS
+UefiImageRelocateImageInplaceForExecution (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the size required to bookkeep Image runtime relocation information.
+
+  May only be called when UefiImageGetRelocsStripped() returns FALSE.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          loaded by UefiImageLoadImage().
+  @param[out]    Size     On output, the size, in Bytes, required for the
+                          bookkeeping buffer.
+
+  @retval RETURN_SUCCESS  The Image runtime context size for the Image was
+                          retrieved successfully.
+  @retval other           The Image runtime context size for the Image could not
+                          be retrieved successfully.
+**/
+RETURN_STATUS
+UefiImageLoaderGetRuntimeContextSize (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    UINT32                           *Size
+  );
+
+/**
+  Relocate the Image for boot-time usage.
+
+  May only be called when UefiImageGetRelocsStripped() returns FALSE, or with
+  BaseAddress == UefiImageGetPreferredAddress().
+
+  @param[in,out] Context             The context describing the Image. Must have
+                                     been loaded by UefiImageLoadImage().
+  @param[in]     BaseAddress         The address to relocate the Image to.
+  @param[out]    RuntimeContext      If not NULL, on output, a bookkeeping data
+                                     required for Image runtime relocation.
+  @param[in]     RuntimeContextSize  The size, in Bytes, of RuntimeContext. Must
+                                     be at least as big as the size returned by
+                                     UefiImageLoaderGetRuntimeContextSize().
+
+  @retval RETURN_SUCCESS  The Image has been relocated successfully.
+  @retval other           The Image Relocation Directory is malformed.
+**/
+RETURN_STATUS
+UefiImageRelocateImage (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT    *Context,
+  IN     UINT64                             BaseAddress,
+  OUT    UEFI_IMAGE_LOADER_RUNTIME_CONTEXT  *RuntimeContext OPTIONAL,
+  IN     UINT32                             RuntimeContextSize
+  );
+
+/**
+  Load the Image into the destination memory space, relocate Image for boot-time
+  usage, and perform environment-specific actions required to execute code from
+  the Image.
+
+  May only be called when UefiImageGetRelocsStripped() returns FALSE, or with
+  BaseAddress == UefiImageGetPreferredAddress().
+
+  @param[in,out] Context             The context describing the Image. Must have
+                                     been initialised by
+                                     UefiImageInitializeContext().
+  @param[out]    Destination         The Image destination memory. Must be
+                                     allocated from page memory.
+  @param[in]     DestinationSize     The size, in Bytes, of Destination. Must be
+                                     at least as large as the size returned by
+                                     UefiImageGetImageSize().
+  @param[out]    RuntimeContext      If not NULL, on output, a buffer
+                                     bookkeeping data required for Image runtime
+                                     relocation.
+  @param[in]     RuntimeContextSize  The size, in Bytes, of RuntimeContext. Must
+                                     be at least as big as the size returned by
+                                     UefiImageLoaderGetRuntimeContextSize().
+
+  @retval RETURN_SUCCESS  The Image was loaded successfully.
+  @retval other           The Image could not be loaded successfully.
+**/
+RETURN_STATUS
+UefiImageLoadImageForExecution (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT    *Context,
+  OUT    VOID                               *Destination,
+  IN     UINT32                             DestinationSize,
+  OUT    UEFI_IMAGE_LOADER_RUNTIME_CONTEXT  *RuntimeContext OPTIONAL,
+  IN     UINT32                             RuntimeContextSize
+  );
+
+/**
+  Relocate Image for Runtime usage.
+
+  May only be called when UefiImageGetRelocsStripped() returns FALSE, or with
+  BaseAddress == UefiImageGetPreferredAddress().
+
+  @param[in,out] Image           The Image destination memory. Must have been
+                                 relocated by UefiImageRelocateImage().
+  @param[in]     ImageSize       The size, in Bytes, of Image.
+  @param[in]     BaseAddress     The address to relocate the Image to.
+  @param[in]     RuntimeContext  The Relocation context obtained by
+                                 UefiImageRelocateImage().
+
+  @retval RETURN_SUCCESS  The Image has been relocated successfully.
+  @retval other           The Image could not be relocated successfully.
+**/
+RETURN_STATUS
+UefiImageRuntimeRelocateImage (
+  IN OUT VOID                                     *Image,
+  IN     UINT32                                   ImageSize,
+  IN     UINT64                                   BaseAddress,
+  IN     CONST UEFI_IMAGE_LOADER_RUNTIME_CONTEXT  *RuntimeContext
+  );
+
+/**
+  Relocate Image for Runtime usage, and perform environment-specific actions
+  required to execute code from the Image.
+
+  May only be called when UefiImageGetRelocsStripped() returns FALSE, or with
+  BaseAddress == UefiImageGetPreferredAddress().
+
+  @param[in,out] Image           The Image destination memory. Must have been
+                                 relocated by UefiImageRelocateImage().
+  @param[in]     ImageSize       The size, in Bytes, of Image.
+  @param[in]     BaseAddress     The address to relocate the Image to.
+  @param[in]     RuntimeContext  The Relocation context obtained by
+                                 UefiImageRelocateImage().
+
+  @retval RETURN_SUCCESS  The Image has been relocated successfully.
+  @retval other           The Image could not be relocated successfully.
+**/
+RETURN_STATUS
+UefiImageRuntimeRelocateImageForExecution (
+  IN OUT VOID                                     *Image,
+  IN     UINT32                                   ImageSize,
+  IN     UINT64                                   BaseAddress,
+  IN     CONST UEFI_IMAGE_LOADER_RUNTIME_CONTEXT  *RuntimeContext
+  );
+
+/**
+  Discards optional Image segments to disguise sensitive data.
+
+  This may destruct the Image Relocation Directory and as such, no function that
+  performs Image relocation may be called after this function has been invoked.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          loaded by UefiImageLoadImage().
+**/
+VOID
+UefiImageDiscardSegments (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the Image symbols path.
+
+  @param[in,out] Context          The context describing the Image. Must have
+                                  been initialised by
+                                  UefiImageInitializeContext().
+  @param[out]    SymbolsPath      On output, a pointer to the Image symbols
+                                  path.
+  @param[out]    SymbolsPathSize  On output, the size, in Bytes, of *
+                                  SymbolsPath.
+
+  @retval RETURN_SUCCESS  The Image symbols path was retrieved successfully.
+  @retval other           The Image symbols path could not be retrieved
+                          successfully.
+**/
+RETURN_STATUS
+UefiImageGetSymbolsPath (
+  IN  CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  OUT CONST CHAR8                            **SymbolsPath,
+  OUT UINT32                                 *SymbolsPathSize
+  );
+
+/**
+  Retrieves the Image module name from the Image symbols path.
+
+  @param[in,out] Context         The context describing the Image. Must have
+                                 been initialised by
+                                 UefiImageInitializeContext().
+  @param[out]    ModuleName      Buffer the Image module name is written into.
+                                 If the name exceeds ModuleNameSize, it will be
+                                 truncated.
+  @param[out]    ModuleNameSize  The size, in Bytes, of ModuleName.
+
+  @retval RETURN_SUCCESS  The Image module name was retrieved successfully.
+  @retval other           The Image module name could not be retrieved
+                          successfully.
+**/
+RETURN_STATUS
+UefiImageGetModuleNameFromSymbolsPath (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    CHAR8                            *ModuleName,
+  IN     UINT32                           ModuleNameSize
+  );
+
+// FIXME: Abstract certificates somehow?
+/**
+  Retrieves the first certificate from the Image Certificate Directory.
+
+  @param[in,out] Context      The context describing the Image. Must have been
+                              initialised by UefiImageInitializeContext().
+  @param[out]    Certificate  On output, the first certificate of the Image.
+
+  @retval RETURN_SUCCESS    The certificate has been retrieved successfully.
+  @retval RETURN_NOT_FOUND  There is no such certificate.
+  @retval other             The Image Certificate Directory is malformed.
+**/
+RETURN_STATUS
+UefiImageGetFirstCertificate (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    CONST WIN_CERTIFICATE            **Certificate
+  );
+
+/**
+  Retrieves the next certificate from the Image Certificate Directory.
+
+  @param[in,out] Context      The context describing the Image. Must have been
+                              initialised by UefiImageInitializeContext().
+  @param[out]    Certificate  On input, the current certificate of the Image.
+                              Must have been retrieved by
+                              UefiImageGetFirstCertificate().
+                              On output, the next certificate of the Image.
+
+  @retval RETURN_SUCCESS    The certificate has been retrieved successfully.
+  @retval RETURN_NOT_FOUND  There is no such certificate.
+  @retval other             The Image Certificate Directory is malformed.
+**/
+RETURN_STATUS
+UefiImageGetNextCertificate (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  IN OUT CONST WIN_CERTIFICATE            **Certificate
+  );
+
+/**
+  Retrieves the Image HII data RVA.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by UefiImageInitializeContext().
+  @param[out]    HiiRva   On output, the RVA of the HII resource data.
+  @param[out]    HiiSize  On output, the size, in Bytes, of HiiRva.
+
+  @retval RETURN_SUCCESS    The Image HII data has been retrieved successfully.
+  @retval RETURN_NOT_FOUND  The Image HII data could not be found.
+  @retval other             The Image Resource Directory is malformed.
+**/
+RETURN_STATUS
+UefiImageGetHiiDataRva (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    UINT32                           *HiiRva,
+  OUT    UINT32                           *HiiSize
+  );
+
+/**
+  Retrieve the Image entry point RVA.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by UefiImageInitializeContext().
+
+  @returns  The Image entry point RVA.
+**/
+UINT32
+UefiImageGetEntryPointAddress (
+  IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the Image machine type.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by UefiImageInitializeContext().
+
+  @returns  The Image machine type.
+**/
+UINT16
+UefiImageGetMachine (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the Image subsystem type.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by UefiImageInitializeContext().
+
+  @returns  The Image subsystem type.
+**/
+UINT16
+UefiImageGetSubsystem (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the Image segment alignment.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by UefiImageInitializeContext().
+
+  @returns  The Image segment alignment.
+**/
+UINT32
+UefiImageGetSegmentAlignment (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the size, in Bytes, of the Image memory space.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by UefiImageInitializeContext().
+
+  @returns  The size of the Image memory space.
+**/
+UINT32
+UefiImageGetImageSize (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+// FIXME: Docs
+UINT32
+UefiImageGetImageSizeInplace (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the Image preferred load address.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by UefiImageInitializeContext().
+
+  @returns  The Image preferred load address.
+**/
+UINT64
+UefiImageGetPreferredAddress (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Returns whether the Image relocations have been stripped.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by UefiImageInitializeContext().
+
+  @returns  Whether the Image relocations have been stripped.
+**/
+BOOLEAN
+UefiImageGetRelocsStripped (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieves the Image load address UefiImageLoadImage() has loaded the Image to.
+
+  May be called only after UefiImageLoadImage() has succeeded.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by UefiImageInitializeContext().
+
+  @returns  The Image load address.
+**/
+UINTN
+UefiImageLoaderGetImageAddress (
+  IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Retrieve the Image entry point address.
+
+  May be called only after UefiImageLoadImage() has succeeded.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by UefiImageInitializeContext().
+
+  @returns  The Image entry point addres.
+**/
+UINTN
+UefiImageLoaderGetImageEntryPoint (
+  IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+/**
+  Constructs an Image record from the Image. Any headers, gaps, or trailers are
+  described as read-only data.
+
+  May be called only after UefiImageLoadImage() has succeeded.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by UefiImageInitializeContext().
+
+  @retval NULL   The Image record could not constructed successfully.
+  @retval other  The Image record was constructed successfully and is returned.
+                 It is allocated using the AllocatePool() API and is
+                 caller-owned as soon as this function returns.
+**/
+UEFI_IMAGE_RECORD *
+UefiImageLoaderGetImageRecord (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+// FIXME: Docs
+RETURN_STATUS
+UefiImageDebugLocateImage (
+  OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  IN  UINTN                            Address
+  );
+
+/**
+  Retrieve the Image fixed loading address.
+
+  This function is only guaranteed to function correctly if the Image was built
+  by a tool with this feature enabled.
+
+  @param[in,out] Context  The context describing the Image. Must have been
+                          initialised by UefiImageInitializeContext().
+  @param[out]    Address  On output, the fixed loading address of the Image.
+                          *Address is guaranteed to by aligned by the Image
+                          segment alignment, and thus the size returned by
+                          UefiImageGetImageSize is sufficient to hold the
+                          Image.
+
+  @retval RETURN_SUCCESS      The Image has a fixed loading address.
+  @retval RETURN_NOT_FOUND    The Image does not have a fixed loading address.
+  @retval RETURN_UNSUPPORTED  The Image fixed loading address is unaligned.
+**/
+RETURN_STATUS
+UefiImageGetFixedAddress (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    UINT64                           *Address
+  );
+
+// FIXME: Docs
+VOID
+UefiImageDebugPrintSegments (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+VOID
+UefiImageDebugPrintImageRecord (
+  IN CONST UEFI_IMAGE_RECORD  *ImageRecord
+  );
+
+#endif // UEFI_IMAGE_LIB_H_
diff --git a/MdePkg/Include/Pi/PiPeiCis.h b/MdePkg/Include/Pi/PiPeiCis.h
index ad4be384bc..d8c13bd928 100644
--- a/MdePkg/Include/Pi/PiPeiCis.h
+++ b/MdePkg/Include/Pi/PiPeiCis.h
@@ -419,6 +419,40 @@ EFI_STATUS
   OUT UINT32                           *AuthenticationStatus
   );
 
+/**
+  Searches for the next matching section within the specified file.
+
+  This service enables PEI modules to discover the section of a given type within a valid file.
+  This service will search within encapsulation sections (compression and GUIDed) as well. It will
+  search inside of a GUIDed section or a compressed section, but may not, for example, search a
+  GUIDed section inside a GUIDes section.
+  This service will not search within compression sections or GUIDed sections that require
+  extraction if memory is not present.
+
+  @param  PeiServices           An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
+  @param  SectionType           The value of the section type to find.
+  @param  SectionInstance       Section instance to find.
+  @param  FileHandle            Handle of the firmware file to search.
+  @param  SectionData           A pointer to the discovered section, if successful.
+  @param  SectionDataSize       The size of the discovered section, if successful.
+  @param  AuthenticationStatus  A pointer to the authentication status for this section.
+
+  @retval EFI_SUCCESS      The section was found.
+  @retval EFI_NOT_FOUND    The section was not found.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PEI_FFS_FIND_SECTION_DATA4)(
+  IN CONST EFI_PEI_SERVICES            **PeiServices,
+  IN EFI_SECTION_TYPE                  SectionType,
+  IN UINTN                             SectionInstance,
+  IN EFI_PEI_FILE_HANDLE               FileHandle,
+  OUT VOID                             **SectionData,
+  OUT UINT32                           *SectionDataSize,
+  OUT UINT32                           *AuthenticationStatus
+  );
+
 /**
   This function registers the found memory configuration with the PEI Foundation.
 
@@ -944,6 +978,7 @@ struct _EFI_PEI_SERVICES {
   EFI_PEI_FFS_GET_FILE_INFO2        FfsGetFileInfo2;
   EFI_PEI_RESET2_SYSTEM             ResetSystem2;
   EFI_PEI_FREE_PAGES                FreePages;
+  EFI_PEI_FFS_FIND_SECTION_DATA4  FindSectionData4;
 };
 
 ///
diff --git a/MdePkg/Include/Ppi/FirmwareVolume.h b/MdePkg/Include/Ppi/FirmwareVolume.h
index e789970edb..0b7a2727c6 100644
--- a/MdePkg/Include/Ppi/FirmwareVolume.h
+++ b/MdePkg/Include/Ppi/FirmwareVolume.h
@@ -255,8 +255,43 @@ EFI_STATUS
   OUT UINT32                               *AuthenticationStatus
   );
 
+/**
+  Find the next matching section in the firmware file.
+
+  This service enables PEI modules to discover sections
+  of a given instance and type within a valid file.
+
+  @param This                   Points to this instance of the
+                                EFI_PEI_FIRMWARE_VOLUME_PPI.
+  @param SearchType             A filter to find only sections of this
+                                type.
+  @param SearchInstance         A filter to find the specific instance
+                                of sections.
+  @param FileHandle             Handle of firmware file in which to
+                                search.
+  @param SectionData            Updated upon return to point to the
+                                section found.
+  @param AuthenticationStatus   Updated upon return to point to the
+                                authentication status for this section.
+
+  @retval EFI_SUCCESS     Section was found.
+  @retval EFI_NOT_FOUND   Section of the specified type was not
+                          found. SectionData contains NULL.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PEI_FV_FIND_SECTION3)(
+  IN  CONST EFI_PEI_FIRMWARE_VOLUME_PPI    *This,
+  IN  EFI_SECTION_TYPE                     SearchType,
+  IN  UINTN                                SearchInstance,
+  IN  EFI_PEI_FILE_HANDLE                  FileHandle,
+  OUT VOID                                 **SectionData,
+  OUT UINT32                               *SectionDataSize,
+  OUT UINT32                               *AuthenticationStatus
+);
+
 #define EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE  SIGNATURE_32 ('P', 'F', 'V', 'P')
-#define EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION   0x00010030
+#define EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION   0x00010031
 
 ///
 /// This PPI provides functions for accessing a memory-mapped firmware volume of a specific format.
@@ -278,6 +313,7 @@ struct _EFI_PEI_FIRMWARE_VOLUME_PPI {
   /// Revision for further extension.
   ///
   UINT32                       Revision;
+  EFI_PEI_FV_FIND_SECTION3    FindSectionByType3;
 };
 
 extern EFI_GUID  gEfiPeiFirmwareVolumePpiGuid;
diff --git a/MdePkg/Include/Protocol/DebugSupport.h b/MdePkg/Include/Protocol/DebugSupport.h
index fced5c759f..5b7e331780 100644
--- a/MdePkg/Include/Protocol/DebugSupport.h
+++ b/MdePkg/Include/Protocol/DebugSupport.h
@@ -16,8 +16,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #ifndef __DEBUG_SUPPORT_H__
 #define __DEBUG_SUPPORT_H__
 
-#include <IndustryStandard/PeImage.h>
-
 typedef struct _EFI_DEBUG_SUPPORT_PROTOCOL EFI_DEBUG_SUPPORT_PROTOCOL;
 
 ///
@@ -845,12 +843,12 @@ VOID
 /// Machine type definition
 ///
 typedef enum {
-  IsaIa32    = IMAGE_FILE_MACHINE_I386,           ///< 0x014C
-  IsaX64     = IMAGE_FILE_MACHINE_X64,            ///< 0x8664
-  IsaIpf     = IMAGE_FILE_MACHINE_IA64,           ///< 0x0200
-  IsaEbc     = IMAGE_FILE_MACHINE_EBC,            ///< 0x0EBC
-  IsaArm     = IMAGE_FILE_MACHINE_ARMTHUMB_MIXED, ///< 0x01c2
-  IsaAArch64 = IMAGE_FILE_MACHINE_ARM64           ///< 0xAA64
+  IsaIa32     = EFI_IMAGE_MACHINE_IA32,           ///< 0x014C
+  IsaX64      = EFI_IMAGE_MACHINE_X64,            ///< 0x8664
+  IsaIpf      = EFI_IMAGE_MACHINE_IA64,           ///< 0x0200
+  IsaEbc      = EFI_IMAGE_MACHINE_EBC,            ///< 0x0EBC
+  IsaArm      = EFI_IMAGE_MACHINE_ARMTHUMB_MIXED, ///< 0x01c2
+  IsaAArch64  = EFI_IMAGE_MACHINE_AARCH64         ///< 0xAA64
 } EFI_INSTRUCTION_SET_ARCHITECTURE;
 
 //
diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
index f853c84827..022020b4c6 100644
--- a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
+++ b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
@@ -1743,7 +1743,7 @@ PeCoffLoaderLoadImage (
 **/
 VOID
 EFIAPI
-PeCoffLoaderRelocateImageForRuntime (
+PeCoffLoaderRuntimeRelocateImage (
   IN  PHYSICAL_ADDRESS  ImageBase,
   IN  PHYSICAL_ADDRESS  VirtImageBase,
   IN  UINTN             ImageSize,
diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h b/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h
index aa86a54850..3ee56e0e5f 100644
--- a/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h
+++ b/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h
@@ -20,12 +20,13 @@
 //
 // Macro definitions for RISC-V architecture.
 //
-#define RV_X(x, s, n)  (((x) >> (s)) & ((1<<(n))-1))
-#define RISCV_IMM_BITS   12
-#define RISCV_IMM_REACH  (1LL<<RISCV_IMM_BITS)
+#define RV_X(x, s, n) (((x) >> (s)) & ((1<<(n))-1))
+#define RISCV_IMM_BITS 12
+#define RISCV_IMM_REACH (1LL<<RISCV_IMM_BITS)
 #define RISCV_CONST_HIGH_PART(VALUE) \
   (((VALUE) + (RISCV_IMM_REACH/2)) & ~(RISCV_IMM_REACH-1))
 
+
 /**
   Performs an Itanium-based specific relocation fixup and is a no-op on other
   instruction sets.
@@ -40,12 +41,13 @@
 **/
 RETURN_STATUS
 PeCoffLoaderRelocateImageEx (
-  IN UINT16     *Reloc,
-  IN OUT CHAR8  *Fixup,
-  IN OUT CHAR8  **FixupData,
-  IN UINT64     Adjust
+  IN UINT16      *Reloc,
+  IN OUT CHAR8   *Fixup,
+  IN OUT CHAR8   **FixupData,
+  IN UINT64      Adjust
   );
 
+
 /**
   Performs an Itanium-based specific re-relocation fixup and is a no-op on other
   instruction sets. This is used to re-relocated the image into the EFI virtual
@@ -61,12 +63,13 @@ PeCoffLoaderRelocateImageEx (
 **/
 RETURN_STATUS
 PeHotRelocateImageEx (
-  IN UINT16     *Reloc,
-  IN OUT CHAR8  *Fixup,
-  IN OUT CHAR8  **FixupData,
-  IN UINT64     Adjust
+  IN UINT16      *Reloc,
+  IN OUT CHAR8   *Fixup,
+  IN OUT CHAR8   **FixupData,
+  IN UINT64      Adjust
   );
 
+
 /**
   Returns TRUE if the machine type of PE/COFF image is supported. Supported
   does not mean the image can be executed it means the PE/COFF loader supports
@@ -125,9 +128,9 @@ PeCoffLoaderGetPeHeader (
 **/
 VOID *
 PeCoffLoaderImageAddress (
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,
-  IN     UINTN                         Address,
-  IN     UINTN                         TeStrippedOffset
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT          *ImageContext,
+  IN     UINTN                                 Address,
+  IN     UINTN                                 TeStrippedOffset
   );
 
 #endif
diff --git a/MdePkg/Library/BasePeCoffLib/PeCoffLoad.h b/MdePkg/Library/BasePeCoffLib/PeCoffLoad.h
new file mode 100644
index 0000000000..833b8d44ca
--- /dev/null
+++ b/MdePkg/Library/BasePeCoffLib/PeCoffLoad.h
@@ -0,0 +1,50 @@
+/** @file
+  Provides APIs to load PE/COFF Images.
+
+  Copyright (c) 2020, Marvin Häuser. All rights reserved.<BR>
+  Copyright (c) 2020, Vitaly Cheptsov. All rights reserved.<BR>
+  Copyright (c) 2020, ISP RAS. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-3-Clause
+**/
+
+#ifndef PE_COFF_LOAD_H_
+#define PE_COFF_LOAD_H_
+
+/**
+  Load the Image into the destination memory space.
+
+  @param[in]  Context          The context describing the Image. Must have been
+                               initialised by PeCoffInitializeContext().
+  @param[out] Destination      The Image destination memory. Must be allocated
+                               from page memory.
+  @param[in]  DestinationSize  The size, in bytes, of Destination.
+                               Must be at least
+                               Context->SizeOfImage +
+                               Context->SizeOfImageDebugAdd. If the Section
+                               Alignment exceeds 4 KB, must be at least
+                               Context->SizeOfImage +
+                               Context->SizeOfImageDebugAdd
+                               Context->SectionAlignment.
+
+  @retval RETURN_SUCCESS  The Image was loaded successfully.
+  @retval other           The Image could not be loaded successfully.
+**/
+RETURN_STATUS
+PeCoffLoadImage (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    VOID                   *Destination,
+  IN     UINT32                 DestinationSize
+  );
+
+/**
+  Discards optional Image Sections to disguise sensitive data.
+
+  @param[in] Context  The context describing the Image. Must have been loaded by
+                      PeCoffLoadImage().
+**/
+VOID
+PeCoffDiscardSections (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+#endif // PE_COFF_LOAD_H_
diff --git a/MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf b/MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
new file mode 100644
index 0000000000..4d375e2506
--- /dev/null
+++ b/MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
@@ -0,0 +1,47 @@
+## @file
+#  PE/COFF Loader Library implementation.
+#
+#  Copyright (c) 2020 - 2021, Marvin Häuser. All rights reserved.<BR>
+#  Copyright (c) 2020, Vitaly Cheptsov. All rights reserved.<BR>
+#  Copyright (c) 2020, ISP RAS. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-3-Clause
+##
+
+[Defines]
+  INF_VERSION    = 0x00010005
+  BASE_NAME      = BasePeCoffLib2
+  FILE_GUID      = 454A346E-3064-464E-8285-99DF1E220E0F
+  MODULE_TYPE    = BASE
+  VERSION_STRING = 1.0
+  LIBRARY_CLASS  = PeCoffLib2
+
+[Sources]
+  PeCoffDebug.c
+  PeCoffHash.c
+  PeCoffHii.c
+  PeCoffInfo.c
+  PeCoffInit.c
+  PeCoffLoad.c
+  PeCoffRelocate.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  BaseOverflowLib
+  DebugLib
+  MemoryAllocationLib
+
+[FixedPcd]
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderRtRelocAllowTargetMismatch
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderHashProhibitOverlap
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderLoadHeader
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderRelocTypePolicy
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAlignmentPolicy
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderWXorX
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderDebugSupport
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderProhibitTe
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAllowMisalignedOffset
diff --git a/MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2Internals.h b/MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2Internals.h
new file mode 100644
index 0000000000..97f2d4b5c8
--- /dev/null
+++ b/MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2Internals.h
@@ -0,0 +1,55 @@
+/** @file
+  Provides shared private definitions across this library.
+
+  Copyright (c) 2020 - 2021, Marvin Häuser. All rights reserved.<BR>
+  Copyright (c) 2020, Vitaly Cheptsov. All rights reserved.<BR>
+  Copyright (c) 2020, ISP RAS. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-3-Clause
+**/
+
+#ifndef BASE_PE_COFF_LIB2_INTERNALS_H_
+#define BASE_PE_COFF_LIB2_INTERNALS_H_
+
+//
+// PcdImageLoaderRelocTypePolicy bits.
+//
+
+///
+/// If set, ARM Thumb Image relocations are supported.
+///
+#define PCD_RELOC_TYPE_POLICY_ARM  BIT0
+
+///
+/// Denotes the alignment requirement for Image certificate sizes.
+///
+#define IMAGE_CERTIFICATE_ALIGN  8U
+
+//
+// The PE/COFF specification guarantees an 8 Byte alignment for certificate
+// sizes. This is larger than the alignment requirement for WIN_CERTIFICATE
+// implied by the UEFI ABI. ASSERT this holds.
+//
+STATIC_ASSERT (
+  ALIGNOF (WIN_CERTIFICATE) <= IMAGE_CERTIFICATE_ALIGN,
+  "The PE/COFF specification guarantee does not suffice."
+  );
+
+//
+// The 4 Byte alignment guaranteed by the PE/COFF specification has been
+// replaced with ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK) for proof simplicity.
+// This obviously was the original intention of the specification. ASSERT in
+// case the equality is not given.
+//
+STATIC_ASSERT (
+  sizeof (UINT32) == ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK),
+  "The current model violates the PE/COFF specification"
+  );
+
+// FIXME:
+RETURN_STATUS
+PeCoffLoadImageInplaceNoBase (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+#endif // BASE_PE_COFF_LIB_INTERNALS_H_
diff --git a/MdePkg/Library/BasePeCoffLib2/Documentation.md b/MdePkg/Library/BasePeCoffLib2/Documentation.md
new file mode 100644
index 0000000000..0c8ef63e07
--- /dev/null
+++ b/MdePkg/Library/BasePeCoffLib2/Documentation.md
@@ -0,0 +1,40 @@
+# EDK II Image Loader documentation
+
+**Please note that this is an early work-in-progress. Correctness and completeness are not guaranteed.**
+
+## 1. Image Section Table well-formedness
+An Image Section Table is considered well-formed if and only if:
+1. The Image Section Table is sorted by Image section RVA in ascending order.
+2. All Image sections are disjoint in the Image memory space.
+3. For PE/COFF Images, all Image sections are in bounds of the Image memory space defined by the Image headers.
+   * For TE Images, the Image memory space is implicitly defined by the Image Section Table.
+4. All Image sections are in bounds of the raw file.
+
+Additionally, based on PCD policy values, the following constraints may be added:
+
+5. All Image sections are aligned by the Image section alignment.
+6. The first Image section is adjacent to the aligned Image headers, or it is the start of the Image memory space.
+7. All Image sections are pairwise adjacent (considering aligned size) in the Image memory space.
+8. All Image sections are not executable and writable at the same time.
+
+### 1.2. Rationales
+
+|| Origin | Rationale | Known violations |
+|---|---|---|---|
+|1 | PE | Allows for efficient verification of constraint 2. | None |
+|2 | PE | Mitigates accidental Image corruption and ensures the same deterministic Image memory space contents invariant of Image section load order. | None |
+|3 | PE | Provides hardening against (otherwise potentially incorrect) assumptions regarding the Image header information. | None |
+|4 | PE | Mitigates out-of-bounds accesses. | None |
+|5 | PE | Ensures data is aligned at their optimal boundary and provides hardening against (otherwise potentially incorrect) assumptions regarding the Image header information. | Old Apple Mac OS X bootloaders, old iPXE OPROMs |
+|6 | EDK II | Allows both the Image Headers to be or to not be loaded. Loading the Image Headers is the default behaviour for all common PE/COFF Image loaders, however it is not required, and the data may be used to more easily identify locations within the Image memory space. | See 5 |
+|7 | PE | Provides hardening against unintentional gaps in the Image memory space that may be handled incorrectly. | See 5 |
+|8 | EDK II | Provides hardening against accidental and malicious code modifications. The concept is well-known as W^X. | None |
+
+## 2. Image memory permissions
+The Image memory space is protected as follows:
+1. Image Headers are protected as read-only data.
+2. Image sections are protected according to their defined permissions.
+3. Any gaps between Image sections are protected as read-only data.
+4. The Image trailer is protected as read-only data.
+
+Due to the explicit handling of Image Headers, gaps, and Image trailer, the full Image memory space has well-defined permissions. To embrace the W^X pattern, and to mitigate attacks (e.g. format string exploits), the tightest permissions are chosen for all Image memory permission segments.
diff --git a/MdePkg/Library/BasePeCoffLib2/PeCoffDebug.c b/MdePkg/Library/BasePeCoffLib2/PeCoffDebug.c
new file mode 100644
index 0000000000..8109b65f57
--- /dev/null
+++ b/MdePkg/Library/BasePeCoffLib2/PeCoffDebug.c
@@ -0,0 +1,264 @@
+/** @file
+  Implements APIs to load PE/COFF debug information.
+
+  Copyright (c) 2020 - 2021, Marvin Häuser. All rights reserved.<BR>
+  Copyright (c) 2020, Vitaly Cheptsov. All rights reserved.<BR>
+  Copyright (c) 2020, ISP RAS. All rights reserved.<BR>
+  Portions copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+  Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+  Portions copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-3-Clause
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+
+#include <IndustryStandard/PeImage2.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseOverflowLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffLib2.h>
+
+#include "BasePeCoffLib2Internals.h"
+
+RETURN_STATUS
+PeCoffGetPdbPath (
+  IN  CONST PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  OUT CONST CHAR8                         **PdbPath,
+  OUT UINT32                              *PdbPathSize
+  )
+{
+  BOOLEAN                               Overflow;
+
+  CONST EFI_IMAGE_DATA_DIRECTORY        *DebugDir;
+  CONST EFI_TE_IMAGE_HEADER             *TeHdr;
+  CONST EFI_IMAGE_NT_HEADERS32          *Pe32Hdr;
+  CONST EFI_IMAGE_NT_HEADERS64          *Pe32PlusHdr;
+
+  CONST EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntries;
+  UINT32                                NumDebugEntries;
+  UINT32                                DebugIndex;
+  CONST EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *CodeViewEntry;
+
+  UINT32                                DebugDirTop;
+  UINT32                                DebugEntryFileOffset;
+  UINT32                                DebugEntryFileOffsetTop;
+
+  CONST CHAR8                           *CodeView;
+  UINT32                                PdbOffset;
+  CONST CHAR8                           *PdbName;
+  UINT32                                PdbNameSize;
+
+  ASSERT (Context != NULL);
+  ASSERT (PdbPath != NULL);
+  ASSERT (PdbPathSize != NULL);
+
+  if (!PcdGetBool (PcdImageLoaderDebugSupport)) {
+    return RETURN_NOT_FOUND;
+  }
+  //
+  // Retrieve the Debug Directory of the Image.
+  //
+  switch (Context->ImageType) {
+    case PeCoffLoaderTypeTe:
+      if (PcdGetBool (PcdImageLoaderProhibitTe)) {
+        ASSERT (FALSE);
+        return RETURN_UNSUPPORTED;
+      }
+
+      TeHdr = (CONST EFI_TE_IMAGE_HEADER *) (CONST VOID *) (
+                (CONST CHAR8 *) Context->FileBuffer
+                );
+
+      DebugDir = &TeHdr->DataDirectory[1];
+      break;
+
+    case PeCoffLoaderTypePe32:
+      Pe32Hdr = (CONST EFI_IMAGE_NT_HEADERS32 *) (CONST VOID *) (
+                  (CONST CHAR8 *) Context->FileBuffer + Context->ExeHdrOffset
+                  );
+
+      if (Pe32Hdr->NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
+        return RETURN_NOT_FOUND;
+      }
+
+      DebugDir = Pe32Hdr->DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_DEBUG;
+      break;
+
+    case PeCoffLoaderTypePe32Plus:
+      Pe32PlusHdr = (CONST EFI_IMAGE_NT_HEADERS64 *) (CONST VOID *) (
+                      (CONST CHAR8 *) Context->FileBuffer + Context->ExeHdrOffset
+                      );
+
+      if (Pe32PlusHdr->NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
+        return RETURN_NOT_FOUND;
+      }
+
+      DebugDir = Pe32PlusHdr->DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_DEBUG;
+      break;
+
+    default:
+      ASSERT (FALSE);
+      return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Verify the Debug Directory is not empty.
+  //
+  if (DebugDir->Size == 0) {
+    return RETURN_NOT_FOUND;
+  }
+  //
+  // Verify the Debug Directory has a well-formed size.
+  //
+  if (DebugDir->Size % sizeof (*DebugEntries) != 0) {
+    //
+    // Some Apple-made images contain a sum of EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
+    // and EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY sizes in DebugDir size.
+    // Since this violates the spec and nobody but Apple has access
+    // to the DEBUG symbols, just ignore this debug information.
+    //
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Verify the Debug Directory is in bounds of the Image buffer.
+  //
+  Overflow = BaseOverflowAddU32 (
+               DebugDir->VirtualAddress,
+               DebugDir->Size,
+               &DebugDirTop
+               );
+  if (Overflow || DebugDirTop > Context->SizeOfImage) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Verify the Debug Directory Image address is sufficiently aligned.
+  //
+  if (!IS_ALIGNED (DebugDir->VirtualAddress, ALIGNOF (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY))) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  DebugEntries = (CONST EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (CONST VOID *) (
+                   (CONST CHAR8 *) Context->ImageBuffer + DebugDir->VirtualAddress
+                   );
+
+  NumDebugEntries = DebugDir->Size / sizeof (*DebugEntries);
+
+  for (DebugIndex = 0; DebugIndex < NumDebugEntries; ++DebugIndex) {
+    if (DebugEntries[DebugIndex].Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
+      break;
+    }
+  }
+  //
+  // Verify the CodeView entry has been found in the Debug Directory.
+  //
+  if (DebugIndex == NumDebugEntries) {
+    return RETURN_NOT_FOUND;
+  }
+  //
+  // Verify the CodeView entry has sufficient space for the signature.
+  //
+  CodeViewEntry = &DebugEntries[DebugIndex];
+
+  if (CodeViewEntry->SizeOfData < sizeof (UINT32)) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  DebugEntryFileOffset = CodeViewEntry->FileOffset;
+
+  if (!PcdGetBool (PcdImageLoaderProhibitTe)) {
+    Overflow = BaseOverflowSubU32 (
+                 DebugEntryFileOffset,
+                 Context->TeStrippedOffset,
+                 &DebugEntryFileOffset
+                 );
+    if (Overflow) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+  } else {
+    ASSERT (Context->TeStrippedOffset == 0);
+  }
+  //
+  // Verify the CodeView entry is in bounds of the raw file, and the
+  // CodeView entry raw file offset is sufficiently aligned.
+  //
+  Overflow = BaseOverflowAddU32 (
+               DebugEntryFileOffset,
+               CodeViewEntry->SizeOfData,
+               &DebugEntryFileOffsetTop
+               );
+  if (Overflow || DebugEntryFileOffsetTop > Context->FileSize
+   || !IS_ALIGNED (DebugEntryFileOffset, ALIGNOF (UINT32))) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  CodeView = (CONST CHAR8 *) Context->FileBuffer + DebugEntryFileOffset;
+  //
+  // This memory access is safe because we know that
+  //   1) IS_ALIGNED (DebugEntryFileOffset, ALIGNOF (UINT32))
+  //   2) sizeof (UINT32) <= CodeViewEntry->SizeOfData.
+  //
+  switch (*(CONST UINT32 *) (CONST VOID *) CodeView) {
+    case CODEVIEW_SIGNATURE_NB10:
+      PdbOffset = sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
+
+      STATIC_ASSERT (
+        ALIGNOF (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) <= ALIGNOF (UINT32),
+        "The structure may be misalignedd."
+        );
+      break;
+
+    case CODEVIEW_SIGNATURE_RSDS:
+      PdbOffset = sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
+
+      STATIC_ASSERT (
+        ALIGNOF (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY) <= ALIGNOF (UINT32),
+        "The structure may be misalignedd."
+        );
+      break;
+
+    case CODEVIEW_SIGNATURE_MTOC:
+      PdbOffset = sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY);
+
+      STATIC_ASSERT (
+        ALIGNOF (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY) <= ALIGNOF (UINT32),
+        "The structure may be misalignedd."
+        );
+      break;
+
+    default:
+      return RETURN_UNSUPPORTED;
+  }
+  //
+  // Verify the PDB path exists and is in bounds of the Image buffer.
+  //
+  Overflow = BaseOverflowSubU32 (
+               CodeViewEntry->SizeOfData,
+               PdbOffset,
+               &PdbNameSize
+               );
+  if (Overflow || PdbNameSize == 0) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Verify the PDB path is correctly terminated.
+  //
+  PdbName = CodeView + PdbOffset;
+  if (PdbName[PdbNameSize - 1] != 0) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  *PdbPath     = PdbName;
+  *PdbPathSize = PdbNameSize;
+
+  return RETURN_SUCCESS;
+}
diff --git a/MdePkg/Library/BasePeCoffLib2/PeCoffHash.c b/MdePkg/Library/BasePeCoffLib2/PeCoffHash.c
new file mode 100644
index 0000000000..12a9495d05
--- /dev/null
+++ b/MdePkg/Library/BasePeCoffLib2/PeCoffHash.c
@@ -0,0 +1,487 @@
+/** @file
+  Implements APIs to verify the Authenticode Signature of PE/COFF Images.
+
+  Copyright (c) 2020 - 2021, Marvin Häuser. All rights reserved.<BR>
+  Copyright (c) 2020, Vitaly Cheptsov. All rights reserved.<BR>
+  Copyright (c) 2020, ISP RAS. All rights reserved.<BR>
+  Portions copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+  Portions copyright (c) 2016, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-3-Clause
+**/
+
+#include <Base.h>
+
+#include <IndustryStandard/PeImage2.h>
+
+#include <Guid/WinCertificate.h>
+
+#include <Library/BaseOverflowLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffLib2.h>
+
+#include "BasePeCoffLib2Internals.h"
+
+/**
+  Hashes the Image section data in ascending order of raw file appearance.
+
+  @param[in]     Context      The context describing the Image. Must have been
+                              initialised by PeCoffInitializeContext().
+  @param[in]     HashUpdate   The data hashing function.
+  @param[in,out] HashContext  The context of the current hash.
+
+  @returns  Whether hashing has been successful.
+**/
+STATIC
+BOOLEAN
+InternalHashSections (
+  IN     CONST PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  IN OUT VOID                                *HashContext,
+  IN     PE_COFF_LOADER_HASH_UPDATE          HashUpdate,
+  IN OUT UINT32                              *SumBytesHashed
+  )
+{
+  BOOLEAN                        Result;
+  BOOLEAN                        Overflow;
+
+  CONST EFI_IMAGE_SECTION_HEADER *Sections;
+  CONST EFI_IMAGE_SECTION_HEADER **SortedSections;
+  UINT16                         SectionIndex;
+  UINT16                         SectionPos;
+  UINT32                         SectionTop;
+  UINT32                         CurHashSize;
+  //
+  // 9. Build a temporary table of pointers to all of the section headers in the
+  //   image. The NumberOfSections field of COFF File Header indicates how big
+  //   the table should be. Do not include any section headers in the table
+  //   whose SizeOfRawData field is zero.
+  //
+  SortedSections = AllocatePool (
+                     (UINT32) Context->NumberOfSections * sizeof (*SortedSections)
+                     );
+  if (SortedSections == NULL) {
+    return FALSE;
+  }
+
+  Sections = (CONST EFI_IMAGE_SECTION_HEADER *) (CONST VOID *) (
+               (CONST CHAR8 *) Context->FileBuffer + Context->SectionsOffset
+               );
+  //
+  // 10. Using the PointerToRawData field (offset 20) in the referenced
+  //     SectionHeader structure as a key, arrange the table's elements in
+  //     ascending order. In other words, sort the section headers in ascending
+  //     order according to the disk-file offset of the sections.
+  //
+  SortedSections[0] = Sections;
+  //
+  // Perform Insertion Sort to order the Sections by their raw file offset.
+  //
+  for (SectionIndex = 1; SectionIndex < Context->NumberOfSections; ++SectionIndex) {
+    for (SectionPos = SectionIndex;
+     0 < SectionPos
+     && SortedSections[SectionPos - 1]->PointerToRawData > Sections[SectionIndex].PointerToRawData;
+     --SectionPos) {
+      SortedSections[SectionPos] = SortedSections[SectionPos - 1];
+    }
+
+    SortedSections[SectionPos] = Sections + SectionIndex;
+  }
+
+  Result      = TRUE;
+  SectionTop  = 0;
+  CurHashSize = 0;
+  //
+  // 13. Repeat steps 11 and 12 for all of the sections in the sorted table.
+  //
+  ASSERT (Context->TeStrippedOffset == 0);
+  for (SectionIndex = 0; SectionIndex < Context->NumberOfSections; ++SectionIndex) {
+    //
+    // Verify the Image section does not overlap with the previous one if the
+    // policy demands it. Overlapping Sections could dramatically increase the
+    // hashing time.
+    // FIXME: Move to init, along with a trailing data policy.
+    //
+    if (PcdGetBool (PcdImageLoaderHashProhibitOverlap)) {
+      if (SectionTop > SortedSections[SectionIndex]->PointerToRawData) {
+        Result = FALSE;
+        break;
+      }
+
+      SectionTop = SortedSections[SectionIndex]->PointerToRawData + SortedSections[SectionIndex]->SizeOfRawData;
+    }
+    //
+    // Skip Sections that contain no data.
+    //
+    if (SortedSections[SectionIndex]->SizeOfRawData > 0) {
+      //
+      // 11. Walk through the sorted table, load the corresponding section into
+      //     memory, and hash the entire section. Use the SizeOfRawData field in the
+      //     SectionHeader structure to determine the amount of data to hash.
+      //
+      Result = HashUpdate (
+                 HashContext,
+                 (CONST CHAR8 *) Context->FileBuffer + SortedSections[SectionIndex]->PointerToRawData,
+                 SortedSections[SectionIndex]->SizeOfRawData
+                 );
+      if (!Result) {
+        break;
+      }
+      //
+      // 12. Add the section’s SizeOfRawData value to SUM_OF_BYTES_HASHED.
+      //
+      // If and only if the Sections do not overlap, we know their sizes are at
+      // most MAX_UINT32 in sum because the file size is at most MAX_UINT32.
+      //
+      if (PcdGetBool (PcdImageLoaderHashProhibitOverlap)) {
+        CurHashSize += SortedSections[SectionIndex]->SizeOfRawData;
+      } else {
+        //
+        // Verify the hash size does not overflow.
+        //
+        Overflow = BaseOverflowAddU32 (
+                     CurHashSize,
+                     SortedSections[SectionIndex]->SizeOfRawData,
+                     &CurHashSize
+                     );
+        if (Overflow) {
+          Result = FALSE;
+          break;
+        }
+      }
+    }
+  }
+
+  *SumBytesHashed = CurHashSize;
+  FreePool ((VOID *) SortedSections);
+
+  return Result;
+}
+
+BOOLEAN
+PeCoffHashImageAuthenticode (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  IN OUT VOID                          *HashContext,
+  IN     PE_COFF_LOADER_HASH_UPDATE    HashUpdate
+  )
+{
+  BOOLEAN                      Result;
+  BOOLEAN                      Overflow;
+  UINT32                       NumberOfRvaAndSizes;
+  UINT32                       ChecksumOffset;
+  UINT32                       SecurityDirOffset;
+  UINT32                       SecurityDirSize;
+  UINT32                       CurrentOffset;
+  UINT32                       HashSize;
+  CONST EFI_IMAGE_NT_HEADERS32 *Pe32;
+  CONST EFI_IMAGE_NT_HEADERS64 *Pe32Plus;
+  UINT32                       SumBytesHashed;
+  UINT32                       FileSize;
+
+  //
+  // These conditions must be met by the caller prior to calling this function.
+  //
+  // 1. Load the image header into memory.
+  // 2. Initialize a hash algorithm context.
+  //
+
+  //
+  // This step can be moved here because steps 1 to 5 do not modify the Image.
+  //
+  // 6. Get the Attribute Certificate Table address and size from the
+  //    Certificate Table entry. For details, see section 5.7 of the PE/COFF
+  //    specification.
+  //
+  // Additionally, retrieve important offsets for later steps.
+  //
+  switch (Context->ImageType) {
+    case PeCoffLoaderTypeTe:
+      if (PcdGetBool (PcdImageLoaderProhibitTe)) {
+        ASSERT (FALSE);
+        return FALSE;
+      }
+      //
+      // Authenticode does not define a hashing algorithm for TE Images.
+      //
+      DEBUG_RAISE ();
+      return FALSE;
+
+    case PeCoffLoaderTypePe32:
+      Pe32 = (CONST EFI_IMAGE_NT_HEADERS32 *) (CONST VOID *) (
+               (CONST CHAR8 *) Context->FileBuffer + Context->ExeHdrOffset
+               );
+      ChecksumOffset      = Context->ExeHdrOffset + (UINT32) OFFSET_OF (EFI_IMAGE_NT_HEADERS32, CheckSum);
+      SecurityDirOffset   = Context->ExeHdrOffset + (UINT32) OFFSET_OF (EFI_IMAGE_NT_HEADERS32, DataDirectory) + (UINT32) (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY * sizeof (EFI_IMAGE_DATA_DIRECTORY));
+      NumberOfRvaAndSizes = Pe32->NumberOfRvaAndSizes;
+      //
+      // Retrieve the Security Directory size depending on existence.
+      //
+      if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY < NumberOfRvaAndSizes) {
+        SecurityDirSize = Pe32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
+      } else {
+        SecurityDirSize = 0;
+      }
+
+      break;
+
+    case PeCoffLoaderTypePe32Plus:
+      Pe32Plus = (CONST EFI_IMAGE_NT_HEADERS64 *) (CONST VOID *) (
+                   (CONST CHAR8 *) Context->FileBuffer + Context->ExeHdrOffset
+                   );
+      ChecksumOffset      = Context->ExeHdrOffset + (UINT32) OFFSET_OF (EFI_IMAGE_NT_HEADERS64, CheckSum);
+      SecurityDirOffset   = Context->ExeHdrOffset + (UINT32) OFFSET_OF (EFI_IMAGE_NT_HEADERS64, DataDirectory) + (UINT32) (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY * sizeof (EFI_IMAGE_DATA_DIRECTORY));
+      NumberOfRvaAndSizes = Pe32Plus->NumberOfRvaAndSizes;
+      //
+      // Retrieve the Security Directory size depending on existence.
+      //
+      if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY < NumberOfRvaAndSizes) {
+        SecurityDirSize = Pe32Plus->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
+      } else {
+        SecurityDirSize = 0;
+      }
+
+      break;
+
+    default:
+      ASSERT (FALSE);
+      return FALSE;
+  }
+  //
+  // 3. Hash the image header from its base to immediately before the start of
+  //    the checksum address, as specified in Optional Header Windows-Specific
+  //    Fields.
+  //
+  Result = HashUpdate (HashContext, Context->FileBuffer, ChecksumOffset);
+  if (!Result) {
+    DEBUG_RAISE ();
+    return FALSE;
+  }
+  //
+  // 4. Skip over the checksum, which is a 4-byte field.
+  //
+  CurrentOffset = ChecksumOffset + sizeof (UINT32);
+  //
+  // 5. Hash everything from the end of the checksum field to immediately before
+  //    the start of the Certificate Table entry, as specified in Optional
+  //    Header Data Directories.
+  //
+  if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY < NumberOfRvaAndSizes) {
+    HashSize = SecurityDirOffset - CurrentOffset;
+    Result = HashUpdate (
+               HashContext,
+               (CONST CHAR8 *) Context->FileBuffer + CurrentOffset,
+               HashSize
+               );
+    if (!Result) {
+      DEBUG_RAISE ();
+      return FALSE;
+    }
+    //
+    // Skip over the Security Directory.
+    //
+    CurrentOffset = SecurityDirOffset + sizeof (EFI_IMAGE_DATA_DIRECTORY);
+  }
+  //
+  // 7. Exclude the Certificate Table entry from the calculation and hash
+  //    everything from the end of the Certificate Table entry to the end of
+  //    image header, including Section Table (headers).The Certificate Table
+  //    entry is 8 Bytes long, as specified in Optional Header Data Directories.
+  //
+  HashSize = Context->SizeOfHeaders - CurrentOffset;
+  Result = HashUpdate (
+             HashContext,
+             (CONST CHAR8 *) Context->FileBuffer + CurrentOffset,
+             HashSize
+             );
+  if (!Result) {
+    DEBUG_RAISE ();
+    return FALSE;
+  }
+  //
+  // Perform the Section-related steps of the algorithm.
+  //
+  Result = InternalHashSections (
+             Context,
+             HashContext,
+             HashUpdate,
+             &SumBytesHashed
+             );
+  if (!Result) {
+    DEBUG_RAISE ();
+    return FALSE;
+  }
+  //
+  // 8. Create a counter called SUM_OF_BYTES_HASHED, which is not part of the
+  //    signature. Set this counter to the SizeOfHeaders field, as specified in
+  //    Optional Header Windows-Specific Field.
+  //
+  Overflow = BaseOverflowAddU32 (
+               SumBytesHashed,
+               Context->SizeOfHeaders,
+               &SumBytesHashed
+               );
+  if (Overflow) {
+    DEBUG_RAISE ();
+    return FALSE;
+  }
+  //
+  // 14. Create a value called FILE_SIZE, which is not part of the signature.
+  //     Set this value to the image’s file size, acquired from the underlying
+  //     file system. If FILE_SIZE is greater than SUM_OF_BYTES_HASHED, the file
+  //     contains extra data that must be added to the hash. This data begins at
+  //     the SUM_OF_BYTES_HASHED file offset, and its length is:
+  //     (File Size) - ((Size of AttributeCertificateTable) + SUM_OF_BYTES_HASHED)
+  //
+  //     Note: The size of Attribute Certificate Table is specified in the
+  //     second ULONG value in the Certificate Table entry (32 bit: offset 132,
+  //     64 bit: offset 148) in Optional Header Data Directories.
+  //
+  FileSize = Context->FileSize - SecurityDirSize;
+  if (SumBytesHashed < FileSize) {
+    Result = HashUpdate (
+               HashContext,
+               (CONST CHAR8 *) Context->FileBuffer + SumBytesHashed,
+               FileSize - SumBytesHashed
+               );
+  }
+  //
+  // This step must be performed by the caller after this function succeeded.
+  //
+  // 15. Finalize the hash algorithm context.
+  //
+  return Result;
+}
+
+RETURN_STATUS
+PeCoffGetFirstCertificate (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    CONST WIN_CERTIFICATE         **Certificate
+  )
+{
+  CONST WIN_CERTIFICATE *WinCertificate;
+  //
+  // These conditions are verified by PeCoffInitializeContext().
+  //
+  ASSERT (Context->SecDirOffset % ALIGNOF (WIN_CERTIFICATE));
+  ASSERT (Context->SecDirSize == 0 || sizeof (WIN_CERTIFICATE) <= Context->SecDirSize);
+  //
+  // Verify the Security Directory is not empty.
+  //
+  if (Context->SecDirSize == 0) {
+    return RETURN_NOT_FOUND;
+  }
+  //
+  // Verify the certificate size is well-formed and that it is in bounds of the
+  // Security Directory.
+  //
+  WinCertificate = (CONST WIN_CERTIFICATE *) (CONST VOID *) (
+                     (CONST UINT8 *) Context->FileBuffer + Context->SecDirOffset
+                     );
+  if (WinCertificate->dwLength < sizeof (WIN_CERTIFICATE)
+   || WinCertificate->dwLength > Context->SecDirSize) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Verify the certificate size is sufficiently aligned, if the policy demands
+  // it. This has been observed to not be the case with images signed with
+  // pesign, such as GRUB.
+  //
+  if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_CERTIFICATE_SIZES) == 0) {
+    if (!IS_ALIGNED (WinCertificate->dwLength, IMAGE_CERTIFICATE_ALIGN)) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+  }
+
+  *Certificate = WinCertificate;
+
+  return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+PeCoffGetNextCertificate (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  IN OUT CONST WIN_CERTIFICATE         **Certificate
+  )
+{
+  BOOLEAN               Overflow;
+  UINT32                CertOffset;
+  UINT32                CertSize;
+  UINT32                CertEnd;
+  CONST WIN_CERTIFICATE *WinCertificate;
+  //
+  // This condition is verified by PeCoffInitializeContext().
+  //
+  ASSERT (IS_ALIGNED (Context->SecDirSize, IMAGE_CERTIFICATE_ALIGN));
+  //
+  // Retrieve the current certificate.
+  //
+  WinCertificate = *Certificate;
+  CertOffset     = (UINT32) ((UINTN) WinCertificate - ((UINTN) Context->FileBuffer + Context->SecDirOffset));
+  //
+  // Retrieve the offset of the next certificate.
+  //
+  if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_CERTIFICATE_SIZES) == 0) {
+    CertSize = WinCertificate->dwLength;
+  } else {
+    CertSize = ALIGN_VALUE (WinCertificate->dwLength, IMAGE_CERTIFICATE_ALIGN);
+  }
+
+  CertOffset += CertSize;
+  //
+  // This invariant is ensured by the certificate iteration functions.
+  //
+  ASSERT (CertOffset <= Context->SecDirSize);
+  //
+  // If the next offset is the end of the Directory, signal it's the end of
+  // the certificate list.
+  //
+  if (CertOffset == Context->SecDirSize) {
+    return RETURN_NOT_FOUND;
+  }
+  //
+  // Verify the Directory fits another certificate.
+  //
+  if (Context->SecDirSize - CertOffset < sizeof (WIN_CERTIFICATE)) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Verify the certificate has a well-formed size.
+  //
+  WinCertificate = (CONST WIN_CERTIFICATE *) (CONST VOID *) (
+                     (CONST UINT8 *) Context->FileBuffer + Context->SecDirOffset + CertOffset
+                     );
+  if (WinCertificate->dwLength < sizeof (WIN_CERTIFICATE)) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Verify the certificate size is sufficiently aligned, if the policy demands
+  // it.
+  //
+  if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_CERTIFICATE_SIZES) == 0) {
+    if (!IS_ALIGNED (WinCertificate->dwLength, IMAGE_CERTIFICATE_ALIGN)) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+  }
+  //
+  // Verify the certificate is in bounds of the Security Directory.
+  //
+  Overflow = BaseOverflowAddU32 (
+               CertOffset,
+               WinCertificate->dwLength,
+               &CertEnd
+               );
+  if (Overflow || CertEnd > Context->SecDirSize) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  *Certificate = WinCertificate;
+
+  return RETURN_SUCCESS;
+}
diff --git a/MdePkg/Library/BasePeCoffLib2/PeCoffHii.c b/MdePkg/Library/BasePeCoffLib2/PeCoffHii.c
new file mode 100644
index 0000000000..a877031ca9
--- /dev/null
+++ b/MdePkg/Library/BasePeCoffLib2/PeCoffHii.c
@@ -0,0 +1,286 @@
+/** @file
+  Implements APIs to retrieve UEFI HII data from PE/COFF Images.
+
+  Copyright (c) 2020 - 2021, Marvin Häuser. All rights reserved.<BR>
+  Copyright (c) 2020, Vitaly Cheptsov. All rights reserved.<BR>
+  Copyright (c) 2020, ISP RAS. All rights reserved.<BR>
+  Portions copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+  Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+  Portions copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-3-Clause
+**/
+
+#include <Base.h>
+
+#include <IndustryStandard/PeImage2.h>
+
+#include <Library/BaseOverflowLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffLib2.h>
+
+#include "BasePeCoffLib2Internals.h"
+
+RETURN_STATUS
+PeCoffGetHiiDataRva (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    UINT32                        *HiiRva,
+  OUT    UINT32                        *HiiSize
+  )
+{
+  UINT16                                    Index;
+  CONST EFI_IMAGE_NT_HEADERS32              *Pe32Hdr;
+  CONST EFI_IMAGE_NT_HEADERS64              *Pe32PlusHdr;
+  CONST EFI_IMAGE_DATA_DIRECTORY            *ResDirTable;
+  CONST EFI_IMAGE_RESOURCE_DIRECTORY        *ResourceDir;
+  CONST EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY  *ResourceDirEntry;
+  CONST EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirString;
+  CONST EFI_IMAGE_RESOURCE_DATA_ENTRY       *ResourceDataEntry;
+  BOOLEAN                                   Overflow;
+  UINT32                                    Offset;
+  UINT32                                    TopOffset;
+  UINT8                                     ResourceLevel;
+  UINT32                                    HiiRvaEnd;
+
+  ASSERT (Context != NULL);
+  ASSERT (HiiRva != NULL);
+  ASSERT (HiiSize != NULL);
+  //
+  // Retrieve the Image's Resource Directory Table.
+  //
+  switch (Context->ImageType) {
+    case PeCoffLoaderTypeTe:
+      if (PcdGetBool (PcdImageLoaderProhibitTe)) {
+        ASSERT (FALSE);
+        return RETURN_UNSUPPORTED;
+      }
+      //
+      // TE Images do not contain a Resource Directory Table.
+      //
+      return RETURN_NOT_FOUND;
+
+    case PeCoffLoaderTypePe32:
+      Pe32Hdr = (CONST EFI_IMAGE_NT_HEADERS32 *) (CONST VOID *) (
+                  (CONST CHAR8 *) Context->FileBuffer + Context->ExeHdrOffset
+                  );
+      if (Pe32Hdr->NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE) {
+        return RETURN_NOT_FOUND;
+      }
+
+      ResDirTable = &Pe32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE];
+      break;
+
+    case PeCoffLoaderTypePe32Plus:
+      Pe32PlusHdr = (CONST EFI_IMAGE_NT_HEADERS64 *) (CONST VOID *) (
+                      (CONST CHAR8 *) Context->FileBuffer + Context->ExeHdrOffset
+                      );
+      if (Pe32PlusHdr->NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE) {
+        return RETURN_NOT_FOUND;
+      }
+
+      ResDirTable = &Pe32PlusHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE];
+      break;
+
+    default:
+      ASSERT (FALSE);
+      return RETURN_UNSUPPORTED;
+  }
+  //
+  // Verify the Resource Directory Table contains at least one entry.
+  //
+  if (ResDirTable->Size < sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + sizeof (*ResourceDir->Entries)) {
+    return RETURN_NOT_FOUND;
+  }
+  //
+  // Verify the start of the Resource Directory Table is sufficiently aligned.
+  //
+  if (!IS_ALIGNED (ResDirTable->VirtualAddress, ALIGNOF (EFI_IMAGE_RESOURCE_DIRECTORY))) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  // FIXME: Verify against first Image section / Headers due to XIP TE.
+  //
+  // Verify the Resource Directory Table is in bounds of the Image buffer.
+  //
+  Overflow = BaseOverflowAddU32 (
+               ResDirTable->VirtualAddress,
+               ResDirTable->Size,
+               &TopOffset
+               );
+  if (Overflow || TopOffset > Context->SizeOfImage) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  ResourceDir = (CONST EFI_IMAGE_RESOURCE_DIRECTORY *) (CONST VOID *) (
+                  (CONST CHAR8 *) Context->ImageBuffer + ResDirTable->VirtualAddress
+                  );
+  //
+  // Verify the Resource Directory Table can hold all of its entries.
+  //
+  STATIC_ASSERT (
+    sizeof (*ResourceDirEntry) * MAX_UINT16 <= ((UINT64) MAX_UINT32 + 1U) / 2 - sizeof (EFI_IMAGE_RESOURCE_DIRECTORY),
+    "The following arithmetic may overflow."
+    );
+  TopOffset = sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + sizeof (*ResourceDirEntry) *
+                ((UINT32) ResourceDir->NumberOfNamedEntries + ResourceDir->NumberOfIdEntries);
+  if (TopOffset > ResDirTable->Size) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Try to locate the "HII" Resource entry.
+  //
+  for (Index = 0; Index < ResourceDir->NumberOfNamedEntries; ++Index) {
+    ResourceDirEntry = &ResourceDir->Entries[Index];
+    //
+    // Filter entries with a non-Unicode name entry.
+    //
+    if (ResourceDirEntry->u1.s.NameIsString == 0) {
+      continue;
+    }
+    //
+    // Verify the Resource Directory String header is in bounds of the Resource
+    // Directory Table.
+    //
+    Overflow = BaseOverflowAddU32 (
+                 ResourceDirEntry->u1.s.NameOffset,
+                 sizeof (*ResourceDirString),
+                 &TopOffset
+                 );
+    if (Overflow || TopOffset > ResDirTable->Size) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+    //
+    // Verify the Resource Directory String offset is sufficiently aligned.
+    //
+    Offset = ResDirTable->VirtualAddress + ResourceDirEntry->u1.s.NameOffset;
+    if (!IS_ALIGNED (Offset, ALIGNOF (EFI_IMAGE_RESOURCE_DIRECTORY_STRING))) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+
+    ResourceDirString = (CONST EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (CONST VOID *) (
+                          (CONST CHAR8 *) Context->ImageBuffer + Offset
+                          );
+    //
+    // Verify the Resource Directory String is in bounds of the Resource
+    // Directory Table.
+    //
+    Overflow = BaseOverflowAddU32 (
+                 TopOffset,
+                 (UINT32) ResourceDirString->Length * sizeof (CHAR16),
+                 &TopOffset
+                 );
+    if (Overflow || TopOffset > ResDirTable->Size) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+    //
+    // Verify the type name matches "HII".
+    //
+    if (ResourceDirString->Length == 3
+     && ResourceDirString->String[0] == L'H'
+     && ResourceDirString->String[1] == L'I'
+     && ResourceDirString->String[2] == L'I') {
+      break;
+    }
+  }
+  //
+  // Verify the "HII" Type Resource Directory Entry exists.
+  //
+  if (Index == ResourceDir->NumberOfNamedEntries) {
+    return RETURN_NOT_FOUND;
+  }
+  //
+  // Walk down the conventional "Name" and "Language" levels to reach the
+  // data directory.
+  //
+  for (ResourceLevel = 0; ResourceLevel < 2; ++ResourceLevel) {
+    //
+    // Succeed early if one of the levels is omitted.
+    //
+    if (ResourceDirEntry->u2.s.DataIsDirectory == 0) {
+      break;
+    }
+    //
+    // Verify the Resource Directory Table fits at least the Resource Directory
+    // with and one Relocation Directory Entry.
+    //
+    if (ResourceDirEntry->u2.s.OffsetToDirectory > ResDirTable->Size - sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + sizeof (*ResourceDir->Entries)) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+    //
+    // Verify the next Relocation Directory offset is sufficiently aligned.
+    //
+    Offset = ResDirTable->VirtualAddress + ResourceDirEntry->u2.s.OffsetToDirectory;
+    if (!IS_ALIGNED (Offset, ALIGNOF (EFI_IMAGE_RESOURCE_DIRECTORY))) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+    //
+    // Verify the Resource Directory has at least one entry.
+    //
+    ResourceDir = (CONST EFI_IMAGE_RESOURCE_DIRECTORY *) (CONST VOID *) (
+                    (CONST CHAR8 *) Context->ImageBuffer + Offset
+                    );
+    if ((UINT32) ResourceDir->NumberOfIdEntries + ResourceDir->NumberOfNamedEntries == 0) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+    //
+    // Always take the first entry for simplicity.
+    //
+    ResourceDirEntry = &ResourceDir->Entries[0];
+  }
+  //
+  // Verify the final Resource Directory Entry is of a data type.
+  //
+  if (ResourceDirEntry->u2.s.DataIsDirectory != 0) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Verify the Resource Directory Table fits at least the Resource Directory.
+  //
+  STATIC_ASSERT (
+    sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY) <= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY),
+    "The following arithmetic may overflow."
+    );
+  if (ResourceDirEntry->u2.OffsetToData > ResDirTable->Size - sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY)) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Verify the Relocation Directory Entry offset is sufficiently aligned.
+  //
+  Offset = ResDirTable->VirtualAddress + ResourceDirEntry->u2.OffsetToData;
+  if (!IS_ALIGNED (Offset, ALIGNOF (EFI_IMAGE_RESOURCE_DATA_ENTRY))) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  ResourceDataEntry = (CONST EFI_IMAGE_RESOURCE_DATA_ENTRY *) (CONST VOID *) (
+                        (CONST CHAR8 *) Context->ImageBuffer + Offset
+                        );
+  //
+  // Verify the "HII" data is in bounds of the Image buffer.
+  //
+  Overflow = BaseOverflowAddU32 (
+               ResourceDataEntry->OffsetToData,
+               ResourceDataEntry->Size,
+               &HiiRvaEnd
+               );
+  if (Overflow || HiiRvaEnd > Context->SizeOfImage) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  *HiiRva  = ResourceDataEntry->OffsetToData;
+  *HiiSize = ResourceDataEntry->Size;
+
+  return RETURN_SUCCESS;
+}
diff --git a/MdePkg/Library/BasePeCoffLib2/PeCoffInfo.c b/MdePkg/Library/BasePeCoffLib2/PeCoffInfo.c
new file mode 100644
index 0000000000..38211f1c89
--- /dev/null
+++ b/MdePkg/Library/BasePeCoffLib2/PeCoffInfo.c
@@ -0,0 +1,152 @@
+/** @file
+  Implements APIs to retrieve general information about PE/COFF Images.
+
+  Copyright (c) 2020 - 2021, Marvin Häuser. All rights reserved.<BR>
+  Copyright (c) 2020, Vitaly Cheptsov. All rights reserved.<BR>
+  Copyright (c) 2020, ISP RAS. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-3-Clause
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiSpec.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseOverflowLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffLib2.h>
+
+#include "BasePeCoffLib2Internals.h"
+
+UINT32
+PeCoffGetAddressOfEntryPoint (
+  IN CONST PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  ASSERT (Context != NULL);
+
+  return Context->AddressOfEntryPoint;
+}
+
+UINT16
+PeCoffGetMachine (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  ASSERT (Context != NULL);
+
+  return Context->Machine;
+}
+
+UINT16
+PeCoffGetSubsystem (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  ASSERT (Context != NULL);
+
+  return Context->Subsystem;
+}
+
+UINT32
+PeCoffGetSectionAlignment (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  ASSERT (Context != NULL);
+
+  return Context->SectionAlignment;
+}
+
+UINT32
+PeCoffGetSizeOfImage (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  ASSERT (Context != NULL);
+
+  return Context->SizeOfImage;
+}
+
+UINT32
+PeCoffGetSizeOfImageInplace (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  UINT32 SizeOfImage;
+
+  ASSERT (Context != NULL);
+
+  SizeOfImage = Context->SizeOfImage;
+  //
+  // SizeOfImage is defined with the full Image header size pre-stripping. As
+  // XIP TE Images always have a stripped Image header, subtract the difference.
+  //
+  if (!PcdGetBool (PcdImageLoaderProhibitTe)) {
+    ASSERT (Context->TeStrippedOffset < SizeOfImage);
+    SizeOfImage -= Context->TeStrippedOffset;
+  } else {
+    ASSERT (Context->TeStrippedOffset == 0);
+  }
+
+  return SizeOfImage;
+}
+
+UINT64
+PeCoffGetImageBase (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  ASSERT (Context != NULL);
+
+  return Context->ImageBase;
+}
+
+UINT32
+PeCoffGetSizeOfHeaders (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  ASSERT (Context != NULL);
+
+  return Context->SizeOfHeaders;
+}
+
+UINT16
+PeCoffGetSectionTable (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT    *Context,
+  OUT    CONST EFI_IMAGE_SECTION_HEADER  **Sections
+  )
+{
+  ASSERT (Context != NULL);
+  ASSERT (Sections != NULL);
+
+  *Sections = (CONST EFI_IMAGE_SECTION_HEADER *) (CONST VOID *) (
+                (CONST CHAR8 *) Context->FileBuffer + Context->SectionsOffset
+                );
+  return Context->NumberOfSections;
+}
+
+BOOLEAN
+PeCoffGetRelocsStripped (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  ASSERT (Context != NULL);
+
+  return Context->RelocsStripped;
+}
+
+// FIXME: Distinguish between base and buffer (XIP TE)
+UINTN
+PeCoffLoaderGetImageAddress (
+  IN CONST PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  ASSERT (Context != NULL);
+  ASSERT (Context->ImageBuffer != NULL);
+
+  return (UINTN) Context->ImageBuffer;
+}
diff --git a/MdePkg/Library/BasePeCoffLib2/PeCoffInit.c b/MdePkg/Library/BasePeCoffLib2/PeCoffInit.c
new file mode 100644
index 0000000000..11b8237599
--- /dev/null
+++ b/MdePkg/Library/BasePeCoffLib2/PeCoffInit.c
@@ -0,0 +1,896 @@
+/** @file
+  Implements APIs to verify PE/COFF Images for further processing.
+
+  Copyright (c) 2020 - 2021, Marvin Häuser. All rights reserved.<BR>
+  Copyright (c) 2020, Vitaly Cheptsov. All rights reserved.<BR>
+  Copyright (c) 2020, ISP RAS. All rights reserved.<BR>
+  Portions copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+  Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+  Portions copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-3-Clause
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+
+#include <IndustryStandard/PeImage2.h>
+
+#include <Guid/WinCertificate.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseOverflowLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffLib2.h>
+
+#include "BasePeCoffLib2Internals.h"
+
+//
+// FIXME: Provide an API to destruct the context?
+//
+
+/**
+  Verify the Image section Headers and initialise the Image memory space size.
+
+  The first Image section must be the beginning of the memory space, or be
+  contiguous to the aligned Image Headers.
+  Sections must be disjoint and, depending on the policy, contiguous in the
+  memory space space.
+  The section data must be in bounds bounds of the file buffer.
+
+  @param[in,out] Context       The context describing the Image. Must have been
+                               initialised by PeCoffInitializeContext().
+  @param[in]     FileSize      The size, in Bytes, of Context->FileBuffer.
+  @param[out]    StartAddress  On output, the RVA of the first Image section.
+
+  @retval RETURN_SUCCESS  The Image section Headers are well-formed.
+  @retval other           The Image section Headers are malformed.
+**/
+STATIC
+RETURN_STATUS
+InternalVerifySections (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  IN     UINT32                        FileSize,
+  OUT    UINT32                        *StartAddress
+  )
+{
+  BOOLEAN                        Overflow;
+  UINT32                         NextSectRva;
+  UINT32                         SectRawEnd;
+  UINT32                         EffectiveSectRawEnd;
+  UINT16                         SectionIndex;
+  CONST EFI_IMAGE_SECTION_HEADER *Sections;
+
+  ASSERT (Context != NULL);
+  ASSERT (Context->TeStrippedOffset <= Context->SizeOfHeaders);
+  ASSERT (IS_POW2 (Context->SectionAlignment));
+  ASSERT (StartAddress != NULL);
+  //
+  // Images without Sections have no usable data, disallow them.
+  //
+  if (Context->NumberOfSections == 0) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  Sections = (CONST EFI_IMAGE_SECTION_HEADER *) (CONST VOID *) (
+               (CONST CHAR8 *) Context->FileBuffer + Context->SectionsOffset
+               );
+  //
+  // The first Image section must begin the Image memory space, or it must be
+  // adjacent to the Image Headers.
+  //
+  if (Sections[0].VirtualAddress == 0) {
+    // FIXME: Add PCD to disallow.
+    //
+    // TE Images cannot support loading the Image Headers as part of the first
+    // Image section due to its StrippedSize sematics.
+    //
+    if (!PcdGetBool (PcdImageLoaderProhibitTe)) {
+      if (Context->ImageType == PeCoffLoaderTypeTe) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+    } else {
+      ASSERT (Context->ImageType != PeCoffLoaderTypeTe);
+    }
+
+    NextSectRva = 0;
+  } else {
+    //
+    // Choose the raw or aligned Image Headers size depending on whether loading
+    // unaligned Sections is allowed.
+    //
+    if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_CONTIGUOUS_SECTIONS) == 0) {
+      Overflow = BaseOverflowAlignUpU32 (
+                   Context->SizeOfHeaders,
+                   Context->SectionAlignment,
+                   &NextSectRva
+                   );
+      if (Overflow) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+    } else {
+      NextSectRva = Context->SizeOfHeaders;
+    }
+  }
+
+  *StartAddress = NextSectRva;
+  //
+  // Verify all Image sections are valid.
+  //
+  for (SectionIndex = 0; SectionIndex < Context->NumberOfSections; ++SectionIndex) {
+    //
+    // Verify the Image section adheres to the W^X principle, if the policy
+    // demands it.
+    //
+    if (PcdGetBool (PcdImageLoaderWXorX)) {
+      if ((Sections[SectionIndex].Characteristics & (EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_MEM_WRITE)) == (EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_MEM_WRITE)) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+    }
+    //
+    // Verify the Image sections are disjoint (relaxed) or adjacent (strict)
+    // depending on whether unaligned Image sections may be loaded or not.
+    // Unaligned Image sections have been observed with iPXE Option ROMs and old
+    // Apple Mac OS X bootloaders.
+    //
+    if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_CONTIGUOUS_SECTIONS) == 0) {
+      if (Sections[SectionIndex].VirtualAddress != NextSectRva) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+    } else {
+      if (Sections[SectionIndex].VirtualAddress < NextSectRva) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+      //
+      // If the Image section address is not aligned by the Image section
+      // alignment, fall back to important architecture-specific page sizes if
+      // possible, to ensure the Image can have memory protection applied.
+      // Otherwise, report no alignment for the Image.
+      //
+      if (!IS_ALIGNED (Sections[SectionIndex].VirtualAddress, Context->SectionAlignment)) {
+        STATIC_ASSERT (
+          DEFAULT_PAGE_ALLOCATION_GRANULARITY <= RUNTIME_PAGE_ALLOCATION_GRANULARITY,
+          "This code must be adapted to consider the reversed order."
+          );
+
+        if (IS_ALIGNED (Sections[SectionIndex].VirtualAddress, RUNTIME_PAGE_ALLOCATION_GRANULARITY)) {
+          Context->SectionAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
+        } else if (DEFAULT_PAGE_ALLOCATION_GRANULARITY < RUNTIME_PAGE_ALLOCATION_GRANULARITY
+         && IS_ALIGNED (Sections[SectionIndex].VirtualAddress, DEFAULT_PAGE_ALLOCATION_GRANULARITY)) {
+          Context->SectionAlignment = DEFAULT_PAGE_ALLOCATION_GRANULARITY;
+        } else {
+          Context->SectionAlignment = 1;
+        }
+      }
+    }
+    //
+    // Verify the Image sections with data are in bounds of the file buffer.
+    //
+    if (Sections[SectionIndex].SizeOfRawData > 0) {
+      if (!PcdGetBool (PcdImageLoaderProhibitTe)) {
+        if (Context->TeStrippedOffset > Sections[SectionIndex].PointerToRawData) {
+          DEBUG_RAISE ();
+          return RETURN_VOLUME_CORRUPTED;
+        }
+      } else {
+        ASSERT (Context->TeStrippedOffset == 0);
+      }
+
+      Overflow = BaseOverflowAddU32 (
+                   Sections[SectionIndex].PointerToRawData,
+                   Sections[SectionIndex].SizeOfRawData,
+                   &SectRawEnd
+                   );
+      if (Overflow) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+
+      if (!PcdGetBool (PcdImageLoaderProhibitTe)) {
+        EffectiveSectRawEnd = SectRawEnd - Context->TeStrippedOffset;
+      } else {
+        ASSERT (Context->TeStrippedOffset == 0);
+        EffectiveSectRawEnd = SectRawEnd;
+      }
+
+      if (EffectiveSectRawEnd > FileSize) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+    }
+    //
+    // Determine the end of the current Image section.
+    //
+    Overflow = BaseOverflowAddU32 (
+                 Sections[SectionIndex].VirtualAddress,
+                 Sections[SectionIndex].VirtualSize,
+                 &NextSectRva
+                 );
+    if (Overflow) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+    //
+    // VirtualSize does not need to be aligned, so align the result if needed.
+    //
+    if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_CONTIGUOUS_SECTIONS) == 0) {
+      Overflow = BaseOverflowAlignUpU32 (
+                   NextSectRva,
+                   Context->SectionAlignment,
+                   &NextSectRva
+                   );
+      if (Overflow) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+    }
+  }
+  //
+  // Set SizeOfImage to the aligned end address of the last ImageSection.
+  //
+  if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_CONTIGUOUS_SECTIONS) == 0) {
+    Context->SizeOfImage = NextSectRva;
+  } else {
+    //
+    // Because VirtualAddress is aligned by SectionAlignment for all Image
+    // sections, and they are disjoint and ordered by VirtualAddress,
+    // VirtualAddress + VirtualSize must be safe to align by SectionAlignment for
+    // all but the last Image section.
+    // Determine the strictest common alignment that the last section's end is
+    // safe to align to.
+    //
+    Overflow = BaseOverflowAlignUpU32 (
+                NextSectRva,
+                Context->SectionAlignment,
+                &Context->SizeOfImage
+                );
+    if (Overflow) {
+      Context->SectionAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
+      Overflow = BaseOverflowAlignUpU32 (
+                  NextSectRva,
+                  Context->SectionAlignment,
+                  &Context->SizeOfImage
+                  );
+      if (DEFAULT_PAGE_ALLOCATION_GRANULARITY < RUNTIME_PAGE_ALLOCATION_GRANULARITY
+      && Overflow) {
+        Context->SectionAlignment = DEFAULT_PAGE_ALLOCATION_GRANULARITY;
+        Overflow = BaseOverflowAlignUpU32 (
+                    NextSectRva,
+                    Context->SectionAlignment,
+                    &Context->SizeOfImage
+                    );
+      }
+
+      if (Overflow) {
+        Context->SectionAlignment = 1;
+      }
+    }
+  }
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  Verify the basic Image Relocation information.
+
+  The preferred Image load address must be aligned by the section alignment.
+  The Relocation Directory must be contained within the Image section memory.
+  The Relocation Directory must be sufficiently aligned in memory.
+
+  @param[in] Context       The context describing the Image. Must have been
+                           initialised by PeCoffInitializeContext().
+  @param[in] StartAddress  The RVA of the first Image section.
+
+  @retval RETURN_SUCCESS  The basic Image Relocation information is well-formed.
+  @retval other           The basic Image Relocation information is malformed.
+**/
+STATIC
+RETURN_STATUS
+InternalValidateRelocInfo (
+  IN CONST PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  IN UINT32                              StartAddress
+  )
+{
+  BOOLEAN Overflow;
+  UINT32  SectRvaEnd;
+
+  ASSERT (Context != NULL);
+  ASSERT (!Context->RelocsStripped || Context->RelocDirSize == 0);
+  //
+  // If the Base Relocations have not been stripped, verify their Directory.
+  //
+  if (Context->RelocDirSize != 0) {
+    //
+    // Verify the Relocation Directory is not empty.
+    //
+    if (sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK) > Context->RelocDirSize) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+    //
+    // Verify the Relocation Directory does not overlap with the Image Headers.
+    //
+    if (StartAddress > Context->RelocDirRva) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+    //
+    // Verify the Relocation Directory is contained in the Image memory space.
+    //
+    Overflow = BaseOverflowAddU32 (
+                 Context->RelocDirRva,
+                 Context->RelocDirSize,
+                 &SectRvaEnd
+                 );
+    if (Overflow || SectRvaEnd > Context->SizeOfImage) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+    //
+    // Verify the Relocation Directory start is sufficiently aligned.
+    //
+    if (!IS_ALIGNED (Context->RelocDirRva, ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK))) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+  }
+  //
+  // Verify the preferred Image load address is sufficiently aligned.
+  //
+  // FIXME: Only with force-aligned sections? What to do with XIP?
+  if (!IS_ALIGNED (Context->ImageBase, (UINT64) Context->SectionAlignment)) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  Verify the TE Image and initialise Context.
+
+  Used offsets and ranges must be aligned and in the bounds of the raw file.
+  Image section Headers and basic Relocation information must be well-formed.
+
+  @param[in,out] Context   The context describing the Image. Must have been
+                           initialised by PeCoffInitializeContext().
+  @param[in]     FileSize  The size, in Bytes, of Context->FileBuffer.
+
+  @retval RETURN_SUCCESS  The TE Image is well-formed.
+  @retval other           The TE Image is malformed.
+**/
+STATIC
+RETURN_STATUS
+InternalInitializeTe (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  IN     UINT32                        FileSize
+  )
+{
+  RETURN_STATUS             Status;
+  BOOLEAN                   Overflow;
+  CONST EFI_TE_IMAGE_HEADER *TeHdr;
+  UINT32                    StartAddress;
+
+  ASSERT (Context != NULL);
+  ASSERT (Context->ExeHdrOffset == 0);
+  ASSERT (sizeof (EFI_TE_IMAGE_HEADER) <= FileSize);
+
+  if (PcdGetBool (PcdImageLoaderProhibitTe)) {
+    ASSERT (FALSE);
+    return RETURN_UNSUPPORTED;
+  }
+
+  TeHdr = (CONST EFI_TE_IMAGE_HEADER *) (CONST VOID *) (
+            (CONST CHAR8 *) Context->FileBuffer
+            );
+
+  Context->ImageType = PeCoffLoaderTypeTe;
+  //
+  // Calculate the size, in Bytes, stripped from the Image Headers.
+  //
+  Overflow = BaseOverflowSubU16 (
+               TeHdr->StrippedSize,
+               sizeof (*TeHdr),
+               &Context->TeStrippedOffset
+               );
+  if (Overflow) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  STATIC_ASSERT (
+    MAX_UINT8 * sizeof (EFI_IMAGE_SECTION_HEADER) <= MAX_UINT32 - MAX_UINT16,
+    "The following arithmetic may overflow."
+    );
+  //
+  // Calculate SizeOfHeaders in a way that is equivalent to what the size would
+  // be if this was the original (unstripped) PE32 binary. As the TE image
+  // creation doesn't fix fields up, values work the same way as for PE32.
+  // When referencing raw data however, the TE stripped size must be subracted.
+  //
+  Context->SizeOfHeaders = (UINT32) TeHdr->StrippedSize + (UINT32) TeHdr->NumberOfSections * sizeof (EFI_IMAGE_SECTION_HEADER);
+  //
+  // Verify that the Image Headers are in bounds of the file buffer.
+  //
+  if (Context->SizeOfHeaders - Context->TeStrippedOffset > FileSize) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  STATIC_ASSERT (
+    IS_ALIGNED (sizeof (*TeHdr), ALIGNOF (EFI_IMAGE_SECTION_HEADER)),
+    "The Image section alignment requirements are violated."
+    );
+  //
+  // TE Image sections start right after the Image Headers.
+  //
+  Context->SectionsOffset = sizeof (EFI_TE_IMAGE_HEADER);
+  //
+  // TE Images do not store their section alignment. Assume the UEFI Page size
+  // by default, as it is the minimum to guarantee memory permission support.
+  //
+  Context->SectionAlignment = EFI_PAGE_SIZE;
+  Context->NumberOfSections = TeHdr->NumberOfSections;
+  //
+  // Validate the sections.
+  // TE images do not have a field to explicitly describe the image size.
+  // Set it to the top of the Image's memory space.
+  //
+  Status = InternalVerifySections (
+             Context,
+             FileSize,
+             &StartAddress
+             );
+  if (Status != RETURN_SUCCESS) {
+    DEBUG_RAISE ();
+    return Status;
+  }
+  //
+  // Verify the Image entry point is in bounds of the Image buffer.
+  //
+  if (TeHdr->AddressOfEntryPoint >= Context->SizeOfImage) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  Context->Machine             = TeHdr->Machine;
+  Context->Subsystem           = TeHdr->Subsystem;
+  Context->ImageBase           = TeHdr->ImageBase;
+  Context->AddressOfEntryPoint = TeHdr->AddressOfEntryPoint;
+  Context->RelocDirRva         = TeHdr->DataDirectory[0].VirtualAddress;
+  Context->RelocDirSize        = TeHdr->DataDirectory[0].Size;
+  //
+  // TE Images do not explicitly store whether their Relocations have been
+  // stripped. Relocations have been stripped if and only if both the RVA and
+  // size of the Relocation Directory are zero.
+  //
+  Context->RelocsStripped = TeHdr->DataDirectory[0].VirtualAddress == 0 && TeHdr->DataDirectory[0].Size == 0;
+  //
+  // Verify basic sanity of the Relocation Directory.
+  //
+  return InternalValidateRelocInfo (Context, StartAddress);
+}
+
+/**
+  Verify the PE32 or PE32+ Image and initialise Context.
+
+  Used offsets and ranges must be aligned and in the bounds of the raw file.
+  Image section Headers and basic Relocation information must be Well-formed.
+
+  @param[in,out] Context   The context describing the Image. Must have been
+                           initialised by PeCoffInitializeContext().
+  @param[in]     FileSize  The size, in Bytes, of Context->FileBuffer.
+
+  @retval RETURN_SUCCESS  The PE Image is Well-formed.
+  @retval other           The PE Image is malformed.
+**/
+STATIC
+RETURN_STATUS
+InternalInitializePe (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  IN     UINT32                        FileSize
+  )
+{
+  BOOLEAN                               Overflow;
+  CONST EFI_IMAGE_NT_HEADERS_COMMON_HDR *PeCommon;
+  CONST EFI_IMAGE_NT_HEADERS32          *Pe32;
+  CONST EFI_IMAGE_NT_HEADERS64          *Pe32Plus;
+  CONST CHAR8                           *OptHdrPtr;
+  UINT32                                HdrSizeWithoutDataDir;
+  UINT32                                MinSizeOfOptionalHeader;
+  UINT32                                MinSizeOfHeaders;
+  CONST EFI_IMAGE_DATA_DIRECTORY        *RelocDir;
+  CONST EFI_IMAGE_DATA_DIRECTORY        *SecDir;
+  UINT32                                SecDirEnd;
+  UINT32                                NumberOfRvaAndSizes;
+  RETURN_STATUS                         Status;
+  UINT32                                StartAddress;
+
+  ASSERT (Context != NULL);
+  ASSERT (sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR) + sizeof (UINT16) <= FileSize - Context->ExeHdrOffset);
+  if (!PcdGetBool (PcdImageLoaderAllowMisalignedOffset)) {
+    ASSERT (IS_ALIGNED (Context->ExeHdrOffset, ALIGNOF (EFI_IMAGE_NT_HEADERS_COMMON_HDR)));
+  }
+  //
+  // Locate the PE Optional Header.
+  //
+  OptHdrPtr = (CONST CHAR8 *) Context->FileBuffer + Context->ExeHdrOffset;
+  OptHdrPtr += sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR);
+
+  STATIC_ASSERT (
+    IS_ALIGNED (ALIGNOF (EFI_IMAGE_NT_HEADERS_COMMON_HDR), ALIGNOF (UINT16))
+   && IS_ALIGNED (sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR), ALIGNOF (UINT16)),
+    "The following operation might be an unaligned access."
+    );
+  //
+  // Determine the type of and retrieve data from the PE Optional Header.
+  // Do not retrieve SizeOfImage as the value usually does not follow the
+  // specification. Even if the value is large enough to hold the last Image
+  // section, it may not be aligned, or it may be too large. No data can
+  // possibly be loaded past the last Image section anyway.
+  //
+  switch (*(CONST UINT16 *) (CONST VOID *) OptHdrPtr) {
+    case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC:
+      //
+      // Verify the PE32 header is in bounds of the file buffer.
+      //
+      if (sizeof (*Pe32) > FileSize - Context->ExeHdrOffset) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+      //
+      // The PE32 header offset is always sufficiently aligned.
+      //
+      STATIC_ASSERT (
+        ALIGNOF (EFI_IMAGE_NT_HEADERS32) <= ALIGNOF (EFI_IMAGE_NT_HEADERS_COMMON_HDR),
+        "The following operations may be unaligned."
+        );
+      //
+      // Populate the common data with information from the Optional Header.
+      //
+      Pe32 = (CONST EFI_IMAGE_NT_HEADERS32 *) (CONST VOID *) (
+               (CONST CHAR8 *) Context->FileBuffer + Context->ExeHdrOffset
+               );
+
+      Context->ImageType           = PeCoffLoaderTypePe32;
+      Context->Subsystem           = Pe32->Subsystem;
+      Context->SizeOfHeaders       = Pe32->SizeOfHeaders;
+      Context->ImageBase           = Pe32->ImageBase;
+      Context->AddressOfEntryPoint = Pe32->AddressOfEntryPoint;
+      Context->SectionAlignment    = Pe32->SectionAlignment;
+
+      RelocDir = Pe32->DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC;
+      SecDir   = Pe32->DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_SECURITY;
+
+      PeCommon              = &Pe32->CommonHeader;
+      NumberOfRvaAndSizes   = Pe32->NumberOfRvaAndSizes;
+      HdrSizeWithoutDataDir = sizeof (EFI_IMAGE_NT_HEADERS32) - sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR);
+
+      break;
+
+    case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+      //
+      // Verify the PE32+ header is in bounds of the file buffer.
+      //
+      if (sizeof (*Pe32Plus) > FileSize - Context->ExeHdrOffset) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+      //
+      // Verify the PE32+ header offset is sufficiently aligned.
+      //
+      if (!PcdGetBool (PcdImageLoaderAllowMisalignedOffset)
+        && !IS_ALIGNED (Context->ExeHdrOffset, ALIGNOF (EFI_IMAGE_NT_HEADERS64))) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+      //
+      // Populate the common data with information from the Optional Header.
+      //
+      Pe32Plus = (CONST EFI_IMAGE_NT_HEADERS64 *) (CONST VOID *) (
+                   (CONST CHAR8 *) Context->FileBuffer + Context->ExeHdrOffset
+                   );
+
+      Context->ImageType           = PeCoffLoaderTypePe32Plus;
+      Context->Subsystem           = Pe32Plus->Subsystem;
+      Context->SizeOfHeaders       = Pe32Plus->SizeOfHeaders;
+      Context->ImageBase           = Pe32Plus->ImageBase;
+      Context->AddressOfEntryPoint = Pe32Plus->AddressOfEntryPoint;
+      Context->SectionAlignment    = Pe32Plus->SectionAlignment;
+
+      RelocDir = Pe32Plus->DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC;
+      SecDir   = Pe32Plus->DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_SECURITY;
+
+      PeCommon              = &Pe32Plus->CommonHeader;
+      NumberOfRvaAndSizes   = Pe32Plus->NumberOfRvaAndSizes;
+      HdrSizeWithoutDataDir = sizeof (EFI_IMAGE_NT_HEADERS64) - sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR);
+
+      break;
+
+    default:
+      //
+      // Disallow Images with unknown PE Optional Header signatures.
+      //
+      DEBUG_RAISE ();
+      return RETURN_UNSUPPORTED;
+  }
+  //
+  // Disallow Images with unknown directories.
+  //
+  if (NumberOfRvaAndSizes > EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Verify the Image alignment is a power of 2.
+  //
+  if (!IS_POW2 (Context->SectionAlignment)) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  STATIC_ASSERT (
+    sizeof (EFI_IMAGE_DATA_DIRECTORY) <= MAX_UINT32 / EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES,
+    "The following arithmetic may overflow."
+    );
+  //
+  // Calculate the offset of the Image sections.
+  //
+  // Context->ExeHdrOffset + sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR) cannot overflow because
+  //   * ExeFileSize > sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR) and
+  //   * Context->ExeHdrOffset + ExeFileSize = FileSize
+  //
+  Overflow = BaseOverflowAddU32 (
+               Context->ExeHdrOffset + sizeof (*PeCommon),
+               PeCommon->FileHeader.SizeOfOptionalHeader,
+               &Context->SectionsOffset
+               );
+  if (Overflow) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Verify the Section Headers offset is sufficiently aligned.
+  //
+  if (!PcdGetBool (PcdImageLoaderAllowMisalignedOffset)
+    && !IS_ALIGNED (Context->SectionsOffset, ALIGNOF (EFI_IMAGE_SECTION_HEADER))) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // This arithmetic cannot overflow because all values are sufficiently
+  // bounded.
+  //
+  MinSizeOfOptionalHeader = HdrSizeWithoutDataDir +
+                              NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY);
+
+  ASSERT (MinSizeOfOptionalHeader >= HdrSizeWithoutDataDir);
+
+  STATIC_ASSERT (
+    sizeof (EFI_IMAGE_SECTION_HEADER) <= (MAX_UINT32 + 1ULL) / (MAX_UINT16 + 1ULL),
+    "The following arithmetic may overflow."
+    );
+  //
+  // Calculate the minimum size of the Image Headers.
+  //
+  Overflow = BaseOverflowAddU32 (
+               Context->SectionsOffset,
+               (UINT32) PeCommon->FileHeader.NumberOfSections * sizeof (EFI_IMAGE_SECTION_HEADER),
+               &MinSizeOfHeaders
+               );
+  if (Overflow) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Verify the Image Header sizes are sane. SizeOfHeaders contains all header
+  // components (DOS, PE Common and Optional Header).
+  //
+  if (MinSizeOfOptionalHeader > PeCommon->FileHeader.SizeOfOptionalHeader) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  if (MinSizeOfHeaders > Context->SizeOfHeaders) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Verify the Image Headers are in bounds of the file buffer.
+  //
+  if (Context->SizeOfHeaders > FileSize) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Populate the Image context with information from the Common Header.
+  //
+  Context->NumberOfSections = PeCommon->FileHeader.NumberOfSections;
+  Context->Machine          = PeCommon->FileHeader.Machine;
+  Context->RelocsStripped   =
+    (
+      PeCommon->FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED
+    ) != 0;
+
+  if (EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC < NumberOfRvaAndSizes) {
+    Context->RelocDirRva  = RelocDir->VirtualAddress;
+    Context->RelocDirSize = RelocDir->Size;
+
+    if (Context->RelocsStripped && Context->RelocDirSize != 0) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+  } else {
+    ASSERT (Context->RelocDirRva == 0);
+    ASSERT (Context->RelocDirSize == 0);
+  }
+
+  if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY < NumberOfRvaAndSizes) {
+    Context->SecDirOffset = SecDir->VirtualAddress;
+    Context->SecDirSize   = SecDir->Size;
+    //
+    // Verify the Security Directory is in bounds of the Image buffer.
+    //
+    Overflow = BaseOverflowAddU32 (
+                 Context->SecDirOffset,
+                 Context->SecDirSize,
+                 &SecDirEnd
+                 );
+    if (Overflow || SecDirEnd > FileSize) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+    //
+    // Verify the Security Directory is sufficiently aligned.
+    //
+    if (!IS_ALIGNED (Context->SecDirOffset, IMAGE_CERTIFICATE_ALIGN)) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+    //
+    // Verify the Security Directory size is sufficiently aligned, and that if
+    // it is not empty, it can fit at least one certificate.
+    //
+    if (Context->SecDirSize != 0
+     && (!IS_ALIGNED (Context->SecDirSize, IMAGE_CERTIFICATE_ALIGN)
+      || Context->SecDirSize < sizeof (WIN_CERTIFICATE))) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+  } else {
+    //
+    // The Image context is zero'd on allocation.
+    //
+    ASSERT (Context->SecDirOffset == 0);
+    ASSERT (Context->SecDirSize == 0);
+  }
+
+  ASSERT (Context->TeStrippedOffset == 0);
+  //
+  // Verify the Image sections are Well-formed.
+  //
+  Status = InternalVerifySections (
+             Context,
+             FileSize,
+             &StartAddress
+             );
+  if (Status != RETURN_SUCCESS) {
+    DEBUG_RAISE ();
+    return Status;
+  }
+  //
+  // Verify the entry point is in bounds of the Image buffer.
+  //
+  if (Context->AddressOfEntryPoint >= Context->SizeOfImage) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Verify the basic Relocation information is well-formed.
+  //
+  Status = InternalValidateRelocInfo (Context, StartAddress);
+  if (Status != RETURN_SUCCESS) {
+    DEBUG_RAISE ();
+  }
+
+  return Status;
+}
+
+RETURN_STATUS
+PeCoffInitializeContext (
+  OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  IN  CONST VOID                    *FileBuffer,
+  IN  UINT32                        FileSize
+  )
+{
+  RETURN_STATUS               Status;
+  CONST EFI_IMAGE_DOS_HEADER *DosHdr;
+
+  ASSERT (Context != NULL);
+  ASSERT (FileBuffer != NULL || FileSize == 0);
+  //
+  // Initialise the Image context with 0-values.
+  //
+  ZeroMem (Context, sizeof (*Context));
+
+  Context->FileBuffer = FileBuffer;
+  Context->FileSize   = FileSize;
+  //
+  // Check whether the DOS Image Header is present.
+  //
+  if (sizeof (*DosHdr) <= FileSize
+   && *(CONST UINT16 *) (CONST VOID *) FileBuffer == EFI_IMAGE_DOS_SIGNATURE) {
+    DosHdr = (CONST EFI_IMAGE_DOS_HEADER *) (CONST VOID *) (
+               (CONST CHAR8 *) FileBuffer
+               );
+    //
+    // Verify the DOS Image Header and the Executable Header are in bounds of
+    // the file buffer, and that they are disjoint.
+    //
+    if (sizeof (EFI_IMAGE_DOS_HEADER) > DosHdr->e_lfanew
+     || DosHdr->e_lfanew > FileSize) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+
+    Context->ExeHdrOffset = DosHdr->e_lfanew;
+    //
+    // Verify the Execution Header offset is sufficiently aligned.
+    //
+    if (!PcdGetBool (PcdImageLoaderAllowMisalignedOffset)
+      && !IS_ALIGNED (Context->ExeHdrOffset, ALIGNOF (EFI_IMAGE_NT_HEADERS_COMMON_HDR))) {
+      return RETURN_UNSUPPORTED;
+    }
+  } else if (!PcdGetBool (PcdImageLoaderProhibitTe)) {
+    //
+    // Assume the Image starts with the Executable Header, determine whether it
+    // is a TE Image.
+    //
+    if (sizeof (EFI_TE_IMAGE_HEADER) <= FileSize
+     && *(CONST UINT16 *) (CONST VOID *) FileBuffer == EFI_TE_IMAGE_HEADER_SIGNATURE) {
+      //
+      // Verify the TE Image Header is well-formed.
+      //
+      Status = InternalInitializeTe (Context, FileSize);
+      if (Status != RETURN_SUCCESS) {
+        DEBUG_RAISE ();
+        return Status;
+      }
+
+      return RETURN_SUCCESS;
+    }
+  }
+  //
+  // Verify the file buffer can hold a PE Common Header.
+  //
+  if (FileSize - Context->ExeHdrOffset < sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR) + sizeof (UINT16)) {
+    return RETURN_UNSUPPORTED;
+  }
+
+  STATIC_ASSERT (
+    ALIGNOF (UINT32) <= ALIGNOF (EFI_IMAGE_NT_HEADERS_COMMON_HDR),
+    "The following access may be performed unaligned"
+    );
+  //
+  // Verify the Image Executable Header has a PE signature.
+  //
+  if (*(CONST UINT32 *) (CONST VOID *) ((CONST CHAR8 *) FileBuffer + Context->ExeHdrOffset) != EFI_IMAGE_NT_SIGNATURE) {
+    return RETURN_UNSUPPORTED;
+  }
+  //
+  // Verify the PE Image Header is well-formed.
+  //
+  Status = InternalInitializePe (Context, FileSize);
+  if (Status != RETURN_SUCCESS) {
+    return Status;
+  }
+
+  return RETURN_SUCCESS;
+}
diff --git a/MdePkg/Library/BasePeCoffLib2/PeCoffLoad.c b/MdePkg/Library/BasePeCoffLib2/PeCoffLoad.c
new file mode 100644
index 0000000000..6aa1acb38f
--- /dev/null
+++ b/MdePkg/Library/BasePeCoffLib2/PeCoffLoad.c
@@ -0,0 +1,259 @@
+/** @file
+  Implements APIs to load PE/COFF Images.
+
+  Copyright (c) 2020 - 2021, Marvin Häuser. All rights reserved.<BR>
+  Copyright (c) 2020, Vitaly Cheptsov. All rights reserved.<BR>
+  Copyright (c) 2020, ISP RAS. All rights reserved.<BR>
+  Portions copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+  Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+  Portions copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-3-Clause
+**/
+
+#include <Base.h>
+
+#include <IndustryStandard/PeImage2.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffLib2.h>
+
+#include "BasePeCoffLib2Internals.h"
+
+/**
+  Loads the Image sections into the memory space and initialises any padding
+  with zeros.
+
+  @param[in]  Context           The context describing the Image. Must have been
+                                initialised by PeCoffInitializeContext().
+  @param[in]  LoadedHeaderSize  The size, in Bytes, of the loaded Image Headers.
+  @param[in]  DestinationSize   The size, in Bytes, of Destination. Must be
+                                sufficent to load the Image with regards to its
+                                Image section alignment.
+**/
+STATIC
+VOID
+InternalLoadSections (
+  IN  CONST PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  IN  UINT32                              LoadedHeaderSize,
+  IN  UINT32                              DestinationSize
+  )
+{
+  CONST EFI_IMAGE_SECTION_HEADER *Sections;
+  UINT16                         SectionIndex;
+  UINT32                         EffectivePointerToRawData;
+  UINT32                         DataSize;
+  UINT32                         PreviousTopRva;
+
+  Sections = (CONST EFI_IMAGE_SECTION_HEADER *) (CONST VOID *) (
+               (CONST CHAR8 *) Context->FileBuffer + Context->SectionsOffset
+               );
+  //
+  // As the loop zero's the data from the end of the previous section, start
+  // with the size of the loaded Image Headers to zero their trailing data.
+  //
+  PreviousTopRva = LoadedHeaderSize;
+
+  for (SectionIndex = 0; SectionIndex < Context->NumberOfSections; ++SectionIndex) {
+    //
+    // Zero from the end of the previous section to the start of this section.
+    //
+    ZeroMem (
+      (CHAR8 *) Context->ImageBuffer + PreviousTopRva,
+      Sections[SectionIndex].VirtualAddress - PreviousTopRva
+      );
+    //
+    // Copy the maximum amount of data that fits both sizes.
+    //
+    if (Sections[SectionIndex].SizeOfRawData <= Sections[SectionIndex].VirtualSize) {
+      DataSize = Sections[SectionIndex].SizeOfRawData;
+    } else {
+      DataSize = Sections[SectionIndex].VirtualSize;
+    }
+    //
+    // Load the current Image section into the memory space.
+    //
+    if (!PcdGetBool (PcdImageLoaderProhibitTe)) {
+      EffectivePointerToRawData = Sections[SectionIndex].PointerToRawData - Context->TeStrippedOffset;
+    } else {
+      ASSERT (Context->TeStrippedOffset == 0);
+      EffectivePointerToRawData = Sections[SectionIndex].PointerToRawData;
+    }
+
+    CopyMem (
+      (CHAR8 *) Context->ImageBuffer + Sections[SectionIndex].VirtualAddress,
+      (CONST CHAR8 *) Context->FileBuffer + EffectivePointerToRawData,
+      DataSize
+      );
+
+    PreviousTopRva = Sections[SectionIndex].VirtualAddress + DataSize;
+  }
+  //
+  // Zero the trailing data after the last Image section.
+  //
+  ZeroMem (
+    (CHAR8 *) Context->ImageBuffer + PreviousTopRva,
+    DestinationSize - PreviousTopRva
+    );
+}
+
+RETURN_STATUS
+PeCoffLoadImage (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    VOID                          *Destination,
+  IN     UINT32                        DestinationSize
+  )
+{
+  UINT32                         LoadedHeaderSize;
+  CONST EFI_IMAGE_SECTION_HEADER *Sections;
+
+  ASSERT (Context != NULL);
+  ASSERT (Destination != NULL);
+  ASSERT (ADDRESS_IS_ALIGNED (Destination, Context->SectionAlignment));
+  ASSERT (Context->SizeOfImage <= DestinationSize);
+
+  Context->ImageBuffer = Destination;
+  //
+  // Load the Image Headers into the memory space, if the policy demands it.
+  //
+  Sections = (CONST EFI_IMAGE_SECTION_HEADER *) (CONST VOID *) (
+               (CONST CHAR8 *) Context->FileBuffer + Context->SectionsOffset
+               );
+  if (PcdGetBool (PcdImageLoaderLoadHeader) && Sections[0].VirtualAddress != 0) {
+    LoadedHeaderSize = Context->SizeOfHeaders - Context->TeStrippedOffset;
+    CopyMem (Context->ImageBuffer, Context->FileBuffer, LoadedHeaderSize);
+  } else {
+    LoadedHeaderSize = 0;
+  }
+  //
+  // Load all Image sections into the memory space.
+  //
+  InternalLoadSections (Context, LoadedHeaderSize, DestinationSize);
+
+  return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+PeCoffLoadImageInplaceNoBase (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  UINT32                         NumberOfSections;
+  CONST EFI_IMAGE_SECTION_HEADER *Sections;
+  UINT32                         AlignedSize;
+  UINT16                         SectionIndex;
+  CHAR8                          *ImageBuffer;
+
+  ASSERT (Context != NULL);
+
+  NumberOfSections = PeCoffGetSectionTable (Context, &Sections);
+  //
+  // Verify all RVAs and raw file offsets are identical for XIP Images.
+  //
+  for (SectionIndex = 0; SectionIndex < NumberOfSections; ++SectionIndex) {
+    AlignedSize = ALIGN_VALUE (
+                    Sections[SectionIndex].VirtualSize,
+                    Context->SectionAlignment
+                    );
+    if (Sections[SectionIndex].PointerToRawData != Sections[SectionIndex].VirtualAddress
+     || Sections[SectionIndex].SizeOfRawData != AlignedSize) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+  }
+
+  ImageBuffer = (CHAR8 *) Context->FileBuffer;
+  if (!PcdGetBool (PcdImageLoaderProhibitTe)) {
+    // FIXME: Abstract all accesses to ImageBuffer for safety?
+    //
+    // TE XIP Images are padded to be aligned such that their Image sections
+    // are correctly aligned. ImageBuffer is used exclusively to accesses RVAs,
+    // which for TE XIP Images are always off by Context->TeStrippedOffset.
+    // There is no other way but to treat the data in front of the TE Image
+    // Header as a part of the TE Image Header.
+    //
+    ImageBuffer -= Context->TeStrippedOffset;
+  } else {
+    ASSERT (Context->ImageType != PeCoffLoaderTypeTe);
+  }
+
+  Context->ImageBuffer = ImageBuffer;
+
+  return RETURN_SUCCESS;
+}
+
+BOOLEAN
+PeCoffImageIsInplace (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  UINT64 ImageBase;
+
+  ASSERT (Context != NULL);
+
+  ImageBase = PeCoffGetImageBase (Context);
+
+  if (!PcdGetBool (PcdImageLoaderProhibitTe)) {
+    ImageBase += Context->TeStrippedOffset;
+  } else {
+    ASSERT (Context->TeStrippedOffset == 0);
+  }
+  //
+  // Verify the Image is located at its preferred load address.
+  //
+  return ImageBase == (UINTN) Context->FileBuffer;
+}
+
+RETURN_STATUS
+PeCoffLoadImageInplace (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  BOOLEAN Result;
+
+  ASSERT (Context != NULL);
+
+  Result = PeCoffImageIsInplace (Context);
+  if (!Result) {
+    DEBUG_RAISE ();
+    return RETURN_UNSUPPORTED;
+  }
+
+  return PeCoffLoadImageInplaceNoBase (Context);
+}
+
+//
+// FIXME: Provide a runtime version of this API as well.
+//
+VOID
+PeCoffDiscardSections (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  CONST EFI_IMAGE_SECTION_HEADER *Sections;
+  UINT32                         SectionIndex;
+
+  ASSERT (Context != NULL);
+  //
+  // By the PE/COFF specification, the .reloc section is supposed to be
+  // discardable, so we must assume it is no longer valid.
+  //
+  Context->RelocDirRva  = 0;
+  Context->RelocDirSize = 0;
+  //
+  // Zero all Image sections that are flagged as discardable.
+  //
+  Sections = (CONST EFI_IMAGE_SECTION_HEADER *) (CONST VOID *) (
+               (CONST CHAR8 *) Context->FileBuffer + Context->SectionsOffset
+               );
+  for (SectionIndex = 0; SectionIndex < Context->NumberOfSections; ++SectionIndex) {
+    if ((Sections[SectionIndex].Characteristics & EFI_IMAGE_SCN_MEM_DISCARDABLE) != 0) {
+      ZeroMem (
+        (CHAR8 *) Context->ImageBuffer + Sections[SectionIndex].VirtualAddress,
+        Sections[SectionIndex].VirtualSize
+        );
+    }
+  }
+}
diff --git a/MdePkg/Library/BasePeCoffLib2/PeCoffRelocate.c b/MdePkg/Library/BasePeCoffLib2/PeCoffRelocate.c
new file mode 100644
index 0000000000..78527b0ac3
--- /dev/null
+++ b/MdePkg/Library/BasePeCoffLib2/PeCoffRelocate.c
@@ -0,0 +1,938 @@
+/** @file
+  Implements APIs to relocate PE/COFF Images.
+
+  Copyright (c) 2020 - 2021, Marvin Häuser. All rights reserved.<BR>
+  Copyright (c) 2020, Vitaly Cheptsov. All rights reserved.<BR>
+  Copyright (c) 2020, ISP RAS. All rights reserved.<BR>
+  Portions copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+  Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+  Portions copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-3-Clause
+**/
+
+#include <Base.h>
+
+#include <IndustryStandard/PeImage2.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseOverflowLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffLib2.h>
+
+#include "BasePeCoffLib2Internals.h"
+
+struct PE_COFF_LOADER_RUNTIME_CONTEXT_ {
+  ///
+  /// The RVA of the Relocation Directory.
+  ///
+  UINT32 RelocDirRva;
+  ///
+  /// The size, in Bytes, of the Relocation Directory.
+  ///
+  UINT32 RelocDirSize;
+  ///
+  /// Information bookkept during the initial Image relocation.
+  ///
+  UINT64 FixupData[];
+};
+
+// FIXME: Add RISC-V support.
+/**
+  Returns whether the Base Relocation type is supported by this loader.
+
+  @param[in] Type  The type of the Base Relocation.
+**/
+#define IMAGE_RELOC_TYPE_SUPPORTED(Type) \
+  (((Type) == EFI_IMAGE_REL_BASED_ABSOLUTE) || \
+  ((Type) == EFI_IMAGE_REL_BASED_HIGHLOW) || \
+  ((Type) == EFI_IMAGE_REL_BASED_DIR64) || \
+  ((PcdGet32 (PcdImageLoaderRelocTypePolicy) & PCD_RELOC_TYPE_POLICY_ARM) != 0 && (Type) == EFI_IMAGE_REL_BASED_ARM_MOV32T))
+
+/**
+  Returns whether the Base Relocation is supported by this loader.
+
+  @param[in] Relocation  The composite Base Relocation value.
+**/
+#define IMAGE_RELOC_SUPPORTED(Relocation) \
+  IMAGE_RELOC_TYPE_SUPPORTED (IMAGE_RELOC_TYPE (Reloc))
+
+/**
+  Retrieve the immediate data encoded in an ARM MOVT or MOVW immediate
+  instruciton.
+
+  @param[in] Instruction  Pointer to an ARM MOVT or MOVW immediate instruction.
+
+  @returns  The Immediate address encoded in the instruction.
+**/
+STATIC
+UINT16
+ThumbMovtImmediateAddress (
+  IN CONST VOID  *Instruction
+  )
+{
+  UINT32 Movt;
+  UINT16 Movt1;
+  UINT16 Movt2;
+  UINT16 Address;
+  //
+  // Thumb2 is two separate 16-bit instructions working together, e.g.
+  // MOVT R0, #0 is 0x0000f2c0 or 0xf2c0 0x0000
+  //
+  Movt1 = *(CONST UINT16 *) (CONST VOID *) Instruction;
+  Movt2 = *(CONST UINT16 *) (CONST VOID *) ((CONST CHAR8 *) Instruction + sizeof (UINT16));
+  Movt  = ((UINT32) Movt1 << 16U) | (UINT32) Movt2;
+  //
+  // imm16 = imm4:i:imm3:imm8
+  //         imm4 -> Bit19:Bit16
+  //         i    -> Bit26
+  //         imm3 -> Bit14:Bit12
+  //         imm8 -> Bit7:Bit0
+  //
+  Address  = (UINT16) (Movt & 0x000000FFU);         // imm8
+  Address |= (UINT16) ((Movt >> 4U) & 0x0000F700U); // imm4 imm3
+  Address |= (UINT16) ((Movt & BIT26) >> 15U);      // i, Bit26->11
+
+  return Address;
+}
+
+/**
+  Update an ARM MOVT or MOVW immediate instruction immediate data.
+
+  @param[in,out] Instruction  Pointer to an ARM MOVT or MOVW immediate
+                              instruction.
+  @param[in]     Address      New address to patch into the instruction.
+**/
+STATIC
+VOID
+ThumbMovtImmediatePatch (
+  IN OUT VOID    *Instruction,
+  IN     UINT16  Address
+  )
+{
+  UINT16 Patch;
+  UINT16 PatchedInstruction;
+  //
+  // First 16-bit chunk of instruction.
+  //
+  Patch  = (Address & 0xF000U) >> 12U; // imm4
+  Patch |= (Address & BIT11) >> 1U;    // i, Bit11->10
+  //
+  // Mask out instruction bits and or in address.
+  //
+  PatchedInstruction = *(CONST UINT16 *) (CONST VOID *) Instruction;
+  *(UINT16 *) (VOID *) Instruction = (PatchedInstruction & ~(UINT16) 0x040FU) | Patch;
+  //
+  // Second 16-bit chunk of instruction.
+  //
+  Patch  = Address & 0x000000FFU;                  // imm8
+  Patch |= ((UINT32) Address << 4U) & 0x00007000U; // imm3
+  //
+  // Mask out instruction bits and or in address.
+  //
+  PatchedInstruction = *(CONST UINT16 *) (CONST VOID *) ((CHAR8 *) Instruction + sizeof (UINT16));
+  *(UINT16 *) (VOID *) ((CHAR8 *) Instruction + sizeof (UINT16)) =
+    (PatchedInstruction & ~(UINT16) 0x70FFU) | Patch;
+}
+
+UINT32
+PeCoffThumbMovwMovtImmediateAddress (
+  IN CONST VOID  *Instructions
+  )
+{
+  CONST CHAR8 *Word;
+  CONST CHAR8 *Top;
+  //
+  // Calculate the encoded address of the instruction pair.
+  //
+  Word = Instructions;                                        // MOVW
+  Top  = (CONST CHAR8 *) Instructions + 2 * sizeof (UINT16);  // MOVT
+
+  return (UINT32) (((UINT32) ThumbMovtImmediateAddress (Top) << 16U) | ThumbMovtImmediateAddress (Word));
+}
+
+/**
+  Update an ARM MOVW/MOVT immediate instruction instruction pair.
+
+  @param[in,out] Instructions  Pointer to ARM MOVW/MOVT instruction pair.
+  @param[in]     Address       New address to patch into the instructions.
+**/
+STATIC
+VOID
+ThumbMovwMovtImmediatePatch (
+  IN OUT VOID    *Instructions,
+  IN     UINT32  Address
+  )
+{
+  CHAR8 *Word;
+  CHAR8 *Top;
+  //
+  // Patch the instruction pair's encoded address.
+  //
+  Word = Instructions;                                  // MOVW
+  Top  = (CHAR8 *) Instructions + 2 * sizeof (UINT16);  // MOVT
+
+  ThumbMovtImmediatePatch (Word, (UINT16) (Address & 0x0000FFFFU));
+  ThumbMovtImmediatePatch (Top, (UINT16) ((Address & 0xFFFF0000U) >> 16U));
+}
+
+/**
+  Relocate an ARM MOVW/MOVT immediate instruction instruction pair.
+
+  @param[in,out] Instructions  Pointer to ARM MOVW/MOVT instruction pair.
+  @param[in]     Adjust        The delta to add to the addresses.
+**/
+VOID
+PeCoffThumbMovwMovtImmediateFixup (
+  IN OUT VOID    *Instructions,
+  IN     UINT64  Adjust
+  )
+{
+  UINT32 Fixup32;
+  //
+  // Relocate the instruction pair.
+  //
+  Fixup32 = PeCoffThumbMovwMovtImmediateAddress (Instructions) + (UINT32) Adjust;
+  ThumbMovwMovtImmediatePatch (Instructions, Fixup32);
+}
+
+/**
+  Apply an Image Base Relocation.
+
+  Only a subset of the PE/COFF Base Relocation types are permited.
+  The Base Relocation target must be in bounds, aligned, and must not overlap
+  with the Relocation Directory.
+
+  @param[in]  Context     The context describing the Image. Must have been
+                          loaded by PeCoffLoadImage().
+  @param[in]  RelocBlock  The Base Relocation Block to apply from.
+  @param[in]  RelocIndex  The index of the Base Relocation to apply.
+  @param[in]  Adjust      The delta to add to the addresses.
+  @param[out] FixupData   On input, a pointer to a bookkeeping value or NULL.
+                          On output, a value to preserve for Image runtime
+                          relocation.
+
+  @retval RETURN_SUCCESS  The Base Relocation has been applied successfully.
+  @retval other           The Base Relocation could not be applied successfully.
+**/
+STATIC
+RETURN_STATUS
+InternalApplyRelocation (
+  IN  CONST PE_COFF_LOADER_IMAGE_CONTEXT     *Context,
+  IN  CONST EFI_IMAGE_BASE_RELOCATION_BLOCK  *RelocBlock,
+  IN  UINT32                                 RelocIndex,
+  IN  UINT64                                 Adjust,
+  OUT UINT64                                 *FixupData OPTIONAL
+  )
+{
+  BOOLEAN Overflow;
+
+  UINT16  RelocType;
+  UINT16  RelocOffset;
+  UINT32  RelocTargetRva;
+  UINT32  RemRelocTargetSize;
+
+  CHAR8   *Fixup;
+  UINT32  Fixup32;
+  UINT64  Fixup64;
+
+  RelocType   = IMAGE_RELOC_TYPE (RelocBlock->Relocations[RelocIndex]);
+  RelocOffset = IMAGE_RELOC_OFFSET (RelocBlock->Relocations[RelocIndex]);
+  //
+  // Absolute Base Relocations are used for padding any must be skipped.
+  //
+  if (RelocType == EFI_IMAGE_REL_BASED_ABSOLUTE) {
+    if (FixupData != NULL) {
+      FixupData[RelocIndex] = 0;
+    }
+
+    return RETURN_SUCCESS;
+  }
+  //
+  // Verify the Base Relocation target address is in bounds of the Image buffer.
+  //
+  Overflow = BaseOverflowAddU32 (
+               RelocBlock->VirtualAddress,
+               RelocOffset,
+               &RelocTargetRva
+               );
+  if (Overflow) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  Overflow = BaseOverflowSubU32 (
+               Context->SizeOfImage,
+               RelocTargetRva,
+               &RemRelocTargetSize
+               );
+  if (Overflow) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+
+  Fixup = (CHAR8 *) Context->ImageBuffer + RelocTargetRva;
+  //
+  // Apply the Base Relocation fixup per type.
+  // If RuntimeContext is not NULL, store the current value of the fixup
+  // target to determine whether it has been changed during runtime
+  // execution.
+  //
+  // It is not clear how EFI_IMAGE_REL_BASED_HIGH and
+  // EFI_IMAGE_REL_BASED_LOW are supposed to be handled. While the PE
+  // specification suggests to just add the high or low part of the
+  // displacement, there are concerns about how it's supposed to deal with
+  // wraparounds. As they are virtually non-existent, they are unsupported for
+  // the time being.
+  //
+  switch (RelocType) {
+    case EFI_IMAGE_REL_BASED_HIGHLOW:
+      //
+      // Verify the Base Relocation target is in bounds of the Image buffer.
+      //
+      if (sizeof (UINT32) > RemRelocTargetSize) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+      //
+      // Verify the Image Base Relocation does not target the Image Relocation
+      // Directory.
+      //
+      if (RelocTargetRva + sizeof (UINT32) > Context->RelocDirRva
+       && Context->RelocDirRva + Context->RelocDirSize > RelocTargetRva) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+      //
+      // Relocate the target instruction.
+      //
+      Fixup32  = ReadUnaligned32 ((CONST VOID *) Fixup);
+      Fixup32 += (UINT32) Adjust;
+      WriteUnaligned32 ((VOID *) Fixup, Fixup32);
+      //
+      // Record the relocated value for Image runtime relocation.
+      //
+      if (FixupData != NULL) {
+        FixupData[RelocIndex] = Fixup32;
+      }
+
+      break;
+
+    case EFI_IMAGE_REL_BASED_DIR64:
+      //
+      // Verify the Image Base Relocation target is in bounds of the Image
+      // buffer.
+      //
+      if (sizeof (UINT64) > RemRelocTargetSize) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+      //
+      // Verify the Image Base Relocation does not target the Image Relocation
+      // Directory.
+      //
+      if (RelocTargetRva + sizeof (UINT64) > Context->RelocDirRva
+       && Context->RelocDirRva + Context->RelocDirSize > RelocTargetRva) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+      //
+      // Relocate target the instruction.
+      //
+      Fixup64  = ReadUnaligned64 ((CONST VOID *) Fixup);
+      Fixup64 += Adjust;
+      WriteUnaligned64 ((VOID *) Fixup, Fixup64);
+      //
+      // Record the relocated value for Image runtime relocation.
+      //
+      if (FixupData != NULL) {
+        FixupData[RelocIndex] = Fixup64;
+      }
+
+      break;
+
+    case EFI_IMAGE_REL_BASED_ARM_MOV32T:
+      //
+      // Verify ARM Thumb mode Base Relocations are supported.
+      //
+      if ((PcdGet32 (PcdImageLoaderRelocTypePolicy) & PCD_RELOC_TYPE_POLICY_ARM) == 0) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+      //
+      // Verify the Base Relocation target is in bounds of the Image buffer.
+      //
+      if (sizeof (UINT64) > RemRelocTargetSize) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+      //
+      // Verify the Base Relocation target is sufficiently aligned.
+      // The ARM Thumb instruction pair must start on a 16-bit boundary.
+      //
+      if (!IS_ALIGNED (RelocTargetRva, ALIGNOF (UINT16))) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+      //
+      // Verify the Base Relocation does not target the Relocation Directory.
+      //
+      if (RelocTargetRva + sizeof (UINT64) > Context->RelocDirRva
+       && Context->RelocDirRva + Context->RelocDirSize > RelocTargetRva) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+      //
+      // Relocate the target instruction.
+      //
+      PeCoffThumbMovwMovtImmediateFixup (Fixup, Adjust);
+      //
+      // Record the relocated value for Image runtime relocation.
+      //
+      if (FixupData != NULL) {
+        FixupData[RelocIndex] = ReadUnaligned64 ((CONST VOID *) Fixup);
+      }
+
+      break;
+
+    default:
+      //
+      // The Image Base Relocation type is unknown, disallow the Image.
+      //
+      DEBUG_RAISE ();
+      return RETURN_UNSUPPORTED;
+  }
+
+  return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+PeCoffRelocateImage (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT    *Context,
+  IN     UINT64                          BaseAddress,
+  OUT    PE_COFF_LOADER_RUNTIME_CONTEXT  *RuntimeContext OPTIONAL,
+  IN     UINT32                          RuntimeContextSize
+  )
+{
+  RETURN_STATUS                         Status;
+  BOOLEAN                               Overflow;
+
+  UINT64                                Adjust;
+
+  UINT32                                RelocBlockOffsetMax;
+  UINT32                                TopOfRelocDir;
+
+  UINT32                                RelocBlockOffset;
+  CONST EFI_IMAGE_BASE_RELOCATION_BLOCK *RelocBlock;
+  UINT32                                RelocBlockSize;
+  UINT32                                SizeOfRelocs;
+  UINT32                                NumRelocs;
+  UINT32                                RelocIndex;
+  UINT32                                FixupDataIndex;
+  UINT64                                *CurrentFixupData;
+
+  ASSERT (Context != NULL);
+  ASSERT (!Context->RelocsStripped || BaseAddress == Context->ImageBase);
+  ASSERT (RuntimeContext != NULL || RuntimeContextSize == 0);
+  ASSERT (RuntimeContext == NULL || RuntimeContextSize >= sizeof (PE_COFF_LOADER_RUNTIME_CONTEXT) + Context->RelocDirSize * (sizeof (UINT64) / sizeof (UINT16)));
+  //
+  // Initialise the Image runtime context header.
+  //
+  if (RuntimeContext != NULL) {
+    RuntimeContext->RelocDirRva  = Context->RelocDirRva;
+    RuntimeContext->RelocDirSize = Context->RelocDirSize;
+  }
+  //
+  // Verify the Relocation Directory is not empty.
+  //
+  if (Context->RelocDirSize == 0) {
+    return RETURN_SUCCESS;
+  }
+  //
+  // Calculate the Image displacement from its prefered load address.
+  //
+  Adjust = BaseAddress - Context->ImageBase;
+  //
+  // Runtime drivers should unconditionally go through the full Relocation
+  // procedure early to eliminate the possibility of errors later at runtime.
+  // Runtime drivers don't have their Base Relocations stripped, this is
+  // verified during context creation.
+  // Skip explicit Relocation when the Image is already loaded at its
+  // prefered location.
+  //
+  if (RuntimeContext == NULL && Adjust == 0) {
+    return RETURN_SUCCESS;
+  }
+
+  RelocBlockOffset    = Context->RelocDirRva;
+  TopOfRelocDir       = Context->RelocDirRva + Context->RelocDirSize;
+  RelocBlockOffsetMax = TopOfRelocDir - sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK);
+  FixupDataIndex      = 0;
+  //
+  // Align TopOfRelocDir because, if the policy does not demand Relocation Block
+  // sizes to be aligned, the code below will manually align them. Thus, the
+  // end offset of the last Relocation Block must be compared to a manually
+  // aligned Relocation Directoriy end offset.
+  //
+  if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_RELOCATION_BLOCK_SIZES) != 0) {
+    Overflow = BaseOverflowAlignUpU32 (
+                 TopOfRelocDir,
+                 ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK),
+                 &TopOfRelocDir
+                 );
+    if (Overflow) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+  }
+  //
+  // Apply all Base Relocations of the Image.
+  //
+  while (RelocBlockOffset <= RelocBlockOffsetMax) {
+    RelocBlock = (CONST EFI_IMAGE_BASE_RELOCATION_BLOCK *) (CONST VOID *) (
+                   (CONST CHAR8 *) Context->ImageBuffer + RelocBlockOffset
+                   );
+    //
+    // Verify the Base Relocation Block size is well-formed.
+    //
+    Overflow = BaseOverflowSubU32 (
+                 RelocBlock->SizeOfBlock,
+                 sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK),
+                 &SizeOfRelocs
+                 );
+    if (Overflow) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+    //
+    // Verify the Base Relocation Block is in bounds of the Relocation
+    // Directory.
+    //
+    if (SizeOfRelocs > RelocBlockOffsetMax - RelocBlockOffset) {
+      DEBUG_RAISE ();
+      return RETURN_VOLUME_CORRUPTED;
+    }
+    //
+    // Advance to the next Base Relocation Block offset based on the alignment
+    // policy.
+    //
+    if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_RELOCATION_BLOCK_SIZES) == 0) {
+      RelocBlockSize = RelocBlock->SizeOfBlock;
+      //
+      // Verify the next Base Relocation Block offset is sufficiently aligned.
+      //
+      if (!IS_ALIGNED (RelocBlockSize, ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK))) {
+        DEBUG_RAISE ();
+        return RETURN_VOLUME_CORRUPTED;
+      }
+    } else {
+      //
+      // This arithmetic cannot overflow because we know
+      //   1) RelocBlock->SizeOfBlock <= RelocMax <= TopOfRelocDir
+      //   2) IS_ALIGNED (TopOfRelocDir, ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK)).
+      //
+      RelocBlockSize = ALIGN_VALUE (
+                         RelocBlock->SizeOfBlock,
+                         ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK)
+                         );
+    }
+    //
+    // This division is safe due to the guarantee made above.
+    //
+    NumRelocs = SizeOfRelocs / sizeof (*RelocBlock->Relocations);
+
+    if (RuntimeContext != NULL) {
+      CurrentFixupData = &RuntimeContext->FixupData[FixupDataIndex];
+      //
+      // This arithmetic cannot overflow because The number of Image Base
+      // Relocations cannot exceed the size of their Image Relocation Block, and
+      // latter has been verified to be in bounds of the Image buffer. The Image
+      // buffer size and RelocDataIndex are both bound by MAX_UINT32.
+      //
+      FixupDataIndex += NumRelocs;
+    } else {
+      CurrentFixupData = NULL;
+    }
+    //
+    // Process all Base Relocations of the current Block.
+    //
+    for (RelocIndex = 0; RelocIndex < NumRelocs; ++RelocIndex) {
+      //
+      // Apply the Image Base Relocation fixup.
+      // If RuntimeContext is not NULL, store the current value of the fixup
+      // target to determine whether it has been changed during runtime
+      // execution.
+      //
+      // It is not clear how EFI_IMAGE_REL_BASED_HIGH and
+      // EFI_IMAGE_REL_BASED_LOW are supposed to be handled. While PE reference
+      // suggests to just add the high or low part of the displacement, there
+      // are concerns about how it's supposed to deal with wraparounds.
+      // As no known linker emits them, omit support.
+      //
+      Status = InternalApplyRelocation (
+                 Context,
+                 RelocBlock,
+                 RelocIndex,
+                 Adjust,
+                 CurrentFixupData
+                 );
+      if (Status != RETURN_SUCCESS) {
+        DEBUG_RAISE ();
+        return Status;
+      }
+    }
+    //
+    // This arithmetic cannot overflow because it has been checked that the
+    // Image Base Relocation Block is in bounds of the Image buffer.
+    //
+    RelocBlockOffset += RelocBlockSize;
+  }
+  //
+  // Verify the Relocation Directory size matches the contained data.
+  //
+  if (RelocBlockOffset != TopOfRelocDir) {
+    DEBUG_RAISE ();
+    return RETURN_VOLUME_CORRUPTED;
+  }
+  //
+  // Initialise the remaining uninitialised portion of the Image runtime
+  // context.
+  //
+  if (RuntimeContext != NULL) {
+    //
+    // This arithmetic cannot overflow due to the guarantee given by
+    // PeCoffLoaderGetRuntimeContextSize().
+    //
+    ZeroMem (
+      &RuntimeContext->FixupData[FixupDataIndex],
+      RuntimeContextSize - sizeof (PE_COFF_LOADER_RUNTIME_CONTEXT) - FixupDataIndex * sizeof (UINT64)
+      );
+  }
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  Apply an Image Base Relocation for Image runtime relocation.
+
+  Well-formedness has been verified by PeCoffRelocateImage() previously.
+  Fails if the Relocation target value has changed since PeCoffRelocateImage().
+
+  @param[in]  Image       The Image destination memory. Must have been relocated
+                          by PeCoffRelocateImage().
+  @param[in]  RelocBlock  The Base Relocation Block to apply from.
+  @param[in]  RelocIndex  The index of the Base Relocation to apply.
+  @param[in]  Adjust      The delta to add to the addresses.
+  @param[out] FixupData   The bookkeeping value.
+
+  @retval RETURN_SUCCESS  The Base Relocation has been applied successfully.
+  @retval other           The Base Relocation could not be applied successfully.
+**/
+STATIC
+RETURN_STATUS
+InternalApplyRelocationRuntime (
+  IN OUT VOID    *Fixup,
+  IN     UINT16  RelocType,
+  IN     UINT64  Adjust,
+  IN     UINT64  FixupData
+  )
+{
+  UINT32 Fixup32;
+  UINT64 Fixup64;
+
+  ASSERT (Fixup != NULL);
+  ASSERT (IMAGE_RELOC_TYPE_SUPPORTED (RelocType)
+       && RelocType != EFI_IMAGE_REL_BASED_ABSOLUTE);
+  //
+  // Apply the Image Base Relocation fixup per type.
+  //
+  // If the Image relocation target value has changes since the initial
+  // Image relocation, skip or abort based on the policy. The fixup cannot
+  // be applies safely as the value might not reference an address within
+  // the Image memory space, e.g. when a global variable pointer to another
+  // variable is changed during runtime.
+  //
+  switch (RelocType) {
+    case EFI_IMAGE_REL_BASED_HIGHLOW:
+      Fixup32 = ReadUnaligned32 ((CONST VOID *) Fixup);
+      //
+      // If the Image relocation target value mismatches, skip or abort.
+      //
+      if (FixupData != Fixup32) {
+        if (PcdGetBool (PcdImageLoaderRtRelocAllowTargetMismatch)) {
+          return RETURN_SUCCESS;
+        }
+
+        return RETURN_VOLUME_CORRUPTED;
+      }
+
+      Fixup32 += (UINT32) Adjust;
+      WriteUnaligned32 (Fixup, Fixup32);
+
+      break;
+
+    case EFI_IMAGE_REL_BASED_DIR64:
+      Fixup64 = ReadUnaligned64 (Fixup);
+      //
+      // If the Image relocation target value mismatches, skip or abort.
+      //
+      if (FixupData != Fixup64) {
+        if (PcdGetBool (PcdImageLoaderRtRelocAllowTargetMismatch)) {
+          return RETURN_SUCCESS;
+        }
+
+        return RETURN_VOLUME_CORRUPTED;
+      }
+
+      Fixup64 += Adjust;
+      WriteUnaligned64 (Fixup, Fixup64);
+
+      break;
+
+    case EFI_IMAGE_REL_BASED_ARM_MOV32T:
+      ASSERT ((PcdGet32 (PcdImageLoaderRelocTypePolicy) & PCD_RELOC_TYPE_POLICY_ARM) != 0);
+
+      Fixup64 = ReadUnaligned64 (Fixup);
+      //
+      // If the Image relocation target value mismatches, skip or abort.
+      //
+      if (FixupData != Fixup64) {
+        if (PcdGetBool (PcdImageLoaderRtRelocAllowTargetMismatch)) {
+          return RETURN_SUCCESS;
+        }
+
+        return RETURN_VOLUME_CORRUPTED;
+      }
+
+      PeCoffThumbMovwMovtImmediateFixup (Fixup, Adjust);
+
+      break;
+
+    default:
+      //
+      // Invalid Base Relocation types would have caused the Image to not be
+      // loaded relocated successfully earlier.
+      //
+      ASSERT (FALSE);
+  }
+
+  return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+PeCoffLoaderGetRuntimeContextSize (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    UINT32                        *Size
+  )
+{
+  BOOLEAN Overflow;
+  UINT32  FixupDataSize;
+
+  ASSERT (Context != NULL);
+  ASSERT (!Context->RelocsStripped);
+  ASSERT (Size != NULL);
+
+  //
+  // Because the ImageBase Relocations have not been stripped,
+  // PeCoffInitializeContext() has verified the Relocation Directory exists and
+  // is valid.
+  //
+
+  //
+  // Request 64-bit of source value per 16-bit Base Relocation.
+  // This allocates too many Bytes because it assumes that every Base Relocation
+  // refers to a 64-bit target and does not account for Base Relocation Block
+  // headers.
+  //
+  Overflow = BaseOverflowMulU32 (
+               Context->RelocDirSize,
+               sizeof (UINT64) / sizeof (UINT16),
+               &FixupDataSize
+               );
+  if (Overflow) {
+    return RETURN_UNSUPPORTED;
+  }
+
+  Overflow = BaseOverflowAddU32 (
+               FixupDataSize,
+               sizeof (PE_COFF_LOADER_RUNTIME_CONTEXT),
+               Size
+               );
+  if (Overflow) {
+    return RETURN_UNSUPPORTED;
+  }
+
+  return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+PeCoffRuntimeRelocateImage (
+  IN OUT VOID                                  *Image,
+  IN     UINT32                                ImageSize,
+  IN     UINT64                                BaseAddress,
+  IN     CONST PE_COFF_LOADER_RUNTIME_CONTEXT  *RuntimeContext
+  )
+{
+  RETURN_STATUS                         Status;
+
+  UINTN                                 ImageAddress;
+  UINT32                                FixupDataIndex;
+  CONST EFI_IMAGE_BASE_RELOCATION_BLOCK *RelocBlock;
+  UINT64                                Adjust;
+
+  UINT32                                TopOfRelocDir;
+  UINT32                                RelocBlockOffset;
+  UINT32                                SizeOfRelocs;
+  UINT32                                NumRelocs;
+  UINT32                                RelocIndex;
+  UINT32                                RelocTarget;
+  UINT32                                RelocOffset;
+  UINT32                                RelocBlockSize;
+
+  (VOID) ImageSize;
+
+  ASSERT (Image != NULL);
+  ASSERT (BaseAddress != 0);
+  ASSERT (RuntimeContext != NULL);
+  //
+  // If the relocation directory is empty, skip relocation.
+  //
+  if (RuntimeContext->RelocDirSize == 0) {
+    return RETURN_SUCCESS;
+  }
+
+  //
+  // The arithmetics in this function generally cannot overflow due to the
+  // guarantees given by PeCoffRelocateImage().
+  //
+
+  ImageAddress = (UINTN) Image;
+  Adjust       = BaseAddress - ImageAddress;
+  //
+  // If the Image remains at the current address, skip relocation.
+  //
+  if (Adjust == 0) {
+    return RETURN_SUCCESS;
+  }
+  //
+  // Apply all Base Relocations of the Image.
+  //
+  RelocBlockOffset = RuntimeContext->RelocDirRva;
+  TopOfRelocDir    = RuntimeContext->RelocDirRva + RuntimeContext->RelocDirSize;
+  FixupDataIndex   = 0;
+  while (RelocBlockOffset < TopOfRelocDir) {
+    ASSERT (IS_ALIGNED (RelocBlockOffset, ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK)));
+
+    RelocBlock = (CONST EFI_IMAGE_BASE_RELOCATION_BLOCK *) (CONST VOID *) (
+                   (CONST CHAR8 *) Image + RelocBlockOffset
+                   );
+
+    STATIC_ASSERT (
+      (sizeof (UINT32) % ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK)) == 0,
+      "The following accesses must be performed unaligned."
+      );
+
+    ASSERT (sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK) <= RelocBlock->SizeOfBlock);
+    //
+    // Determine the number of Image Base Relocations in this Block.
+    //
+    SizeOfRelocs = RelocBlock->SizeOfBlock - sizeof (EFI_IMAGE_BASE_RELOCATION_BLOCK);
+    NumRelocs    = SizeOfRelocs / sizeof (*RelocBlock->Relocations);
+    //
+    // Apply all Image Base Relocation fixups of the current Image Base
+    // Relocation Block.
+    //
+    for (RelocIndex = 0; RelocIndex < NumRelocs; ++RelocIndex) {
+      //
+      // Skip Absolute Image Base Relocations.
+      //
+      if (IMAGE_RELOC_TYPE (RelocBlock->Relocations[RelocIndex]) == EFI_IMAGE_REL_BASED_ABSOLUTE) {
+        ++FixupDataIndex;
+        continue;
+      }
+      //
+      // Determine the Image Base Relocation target address.
+      //
+      RelocOffset = IMAGE_RELOC_OFFSET (RelocBlock->Relocations[RelocIndex]);
+      ASSERT (RelocOffset <= RelocBlock->VirtualAddress + RelocOffset);
+      //
+      // Apply the Image Base Relocation fixup.
+      //
+      RelocTarget = RelocBlock->VirtualAddress + RelocOffset;
+      Status = InternalApplyRelocationRuntime (
+                 (CHAR8 *) Image + RelocTarget,
+                 IMAGE_RELOC_TYPE (RelocBlock->Relocations[RelocIndex]),
+                 Adjust,
+                 RuntimeContext->FixupData[FixupDataIndex]
+                 );
+      //
+      // If the original Image Relocation target value mismatches the expected
+      // value, and the policy demands it, report an error.
+      //
+      if (!PcdGetBool (PcdImageLoaderRtRelocAllowTargetMismatch)) {
+        if (Status != RETURN_SUCCESS) {
+          return Status;
+        }
+      } else {
+        ASSERT (Status == RETURN_SUCCESS);
+      }
+
+      ++FixupDataIndex;
+    }
+    //
+    // Advance to the next Base Relocation Block based on the alignment policy.
+    //
+    if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_RELOCATION_BLOCK_SIZES) == 0) {
+      RelocBlockSize = RelocBlock->SizeOfBlock;
+      ASSERT (IS_ALIGNED (RelocBlockSize, ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK)));
+    } else {
+      RelocBlockSize = ALIGN_VALUE (
+                         RelocBlock->SizeOfBlock,
+                         ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK)
+                         );
+    }
+
+    RelocBlockOffset += RelocBlockSize;
+  }
+  //
+  // Align TopOfRelocDir because, if the policy does not demand Relocation Block
+  // sizes to be aligned, the code below will manually align them. Thus, the
+  // end offset of the last Relocation Block must be compared to a manually
+  // aligned Relocation Directoriy end offset.
+  //
+  if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_RELOCATION_BLOCK_SIZES) != 0) {
+    TopOfRelocDir = ALIGN_VALUE (TopOfRelocDir, ALIGNOF (EFI_IMAGE_BASE_RELOCATION_BLOCK));
+  }
+  //
+  // This condition is verified by PeCoffRelocateImage().
+  //
+  ASSERT (RelocBlockOffset == TopOfRelocDir);
+
+  return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+PeCoffRelocateImageInplace (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  RETURN_STATUS Status;
+  UINTN         NewBase;
+
+  Status = PeCoffLoadImageInplaceNoBase (Context);
+  if (RETURN_ERROR (Status)) {
+    DEBUG_RAISE ();
+    return Status;
+  }
+
+  NewBase = PeCoffLoaderGetImageAddress (Context);
+
+  Status = PeCoffRelocateImage (Context, NewBase, NULL, 0);
+  if (RETURN_ERROR (Status)) {
+    DEBUG_RAISE ();
+  }
+
+  return Status;
+}
diff --git a/MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf b/MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
new file mode 100644
index 0000000000..125733a234
--- /dev/null
+++ b/MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
@@ -0,0 +1,33 @@
+## @file
+#  Null PE/Coff Extra Action library instances with empty functions.
+#
+#  Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = UefiImageExtraActionLibNull
+  MODULE_UNI_FILE                = UefiImageExtraActionLibNull.uni
+  FILE_GUID                      = 0EB84DA1-267A-40b4-8347-1F48694C8B47
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = UefiImageExtraActionLib
+
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  UefiImageExtraActionLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  DebugLib
+
diff --git a/MdePkg/Library/BaseUefiImageExtraActionLibNull/UefiImageExtraActionLib.c b/MdePkg/Library/BaseUefiImageExtraActionLibNull/UefiImageExtraActionLib.c
new file mode 100644
index 0000000000..d134a48810
--- /dev/null
+++ b/MdePkg/Library/BaseUefiImageExtraActionLibNull/UefiImageExtraActionLib.c
@@ -0,0 +1,48 @@
+/** @file
+  Null PE/Coff Extra Action library instances with empty functions.
+
+  Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/UefiImageExtraActionLib.h>
+#include <Library/DebugLib.h>
+
+/**
+  Performs additional actions after a PE/COFF image has been loaded and relocated.
+
+  If ImageContext is NULL, then ASSERT().
+
+  @param  ImageContext  The pointer to the image context structure that describes the
+                        PE/COFF image that has already been loaded and relocated.
+
+**/
+VOID
+EFIAPI
+UefiImageLoaderRelocateImageExtraAction (
+  IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
+  )
+{
+  ASSERT (ImageContext != NULL);
+}
+
+/**
+  Performs additional actions just before a PE/COFF image is unloaded.  Any resources
+  that were allocated by UefiImageLoaderRelocateImageExtraAction() must be freed.
+
+  If ImageContext is NULL, then ASSERT().
+
+  @param  ImageContext  The pointer to the image context structure that describes the
+                        PE/COFF image that is being unloaded.
+
+**/
+VOID
+EFIAPI
+UefiImageLoaderUnloadImageExtraAction (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
+  )
+{
+  ASSERT (ImageContext != NULL);
+}
diff --git a/MdePkg/Library/BaseUefiImageExtraActionLibNull/UefiImageExtraActionLibNull.uni b/MdePkg/Library/BaseUefiImageExtraActionLibNull/UefiImageExtraActionLibNull.uni
new file mode 100644
index 0000000000..2ed84d48b8
--- /dev/null
+++ b/MdePkg/Library/BaseUefiImageExtraActionLibNull/UefiImageExtraActionLibNull.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Null PE/Coff Extra Action library instances with empty functions.
+//
+// Null PE/Coff Extra Action library instances with empty functions.
+//
+// Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Null PE/Coff Extra Action library instances with empty functions"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Null PE/Coff Extra Action library instances with empty functions."
+
diff --git a/MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf b/MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
new file mode 100644
index 0000000000..bfe7296e0d
--- /dev/null
+++ b/MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
@@ -0,0 +1,40 @@
+## @file
+#  UEFI Image Loader library implementation for PE/COFF and TE Images.
+#
+#  Copyright (c) 2021, Marvin Häuser. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-3-Clause
+##
+
+[Defines]
+  INF_VERSION    = 0x00010005
+  BASE_NAME      = BaseUefiImageLibPeCoff
+  FILE_GUID      = 357AD87E-8D6B-468A-B3FA-0D9CC4C725CD
+  MODULE_TYPE    = BASE
+  VERSION_STRING = 1.0
+  LIBRARY_CLASS  = UefiImageLib
+
+[Sources]
+  CommonSupport.c
+  ExecutionSupport.c
+  PeCoffSupport.h
+  PeCoffSupport.c
+  UefiImageLibPeCoff.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseOverflowLib
+  BaseMemoryLib
+  CacheMaintenanceLib
+  DebugLib
+  MemoryAllocationLib
+  PeCoffLib2
+  UefiImageExtraActionLib
+
+[FixedPcd]
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAlignmentPolicy
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderLoadHeader
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderProhibitTe
diff --git a/MdePkg/Library/BaseUefiImageLib/CommonSupport.c b/MdePkg/Library/BaseUefiImageLib/CommonSupport.c
new file mode 100644
index 0000000000..70a191c2af
--- /dev/null
+++ b/MdePkg/Library/BaseUefiImageLib/CommonSupport.c
@@ -0,0 +1,152 @@
+/** @file
+  Support for functions common to all Image formats.
+
+  Copyright (c) 2021, Marvin Häuser. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-3-Clause
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiSpec.h>
+
+#include <Library/BaseOverflowLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiImageLib.h>
+
+RETURN_STATUS
+UefiImageInitializeContext (
+  OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  IN  CONST VOID                       *FileBuffer,
+  IN  UINT32                           FileSize
+  )
+{
+  RETURN_STATUS Status;
+
+  Status = UefiImageInitializeContextPreHash (Context, FileBuffer, FileSize);
+  if (RETURN_ERROR (Status)) {
+    return Status;
+  }
+
+  return UefiImageInitializeContextPostHash (Context);
+}
+
+UINTN
+UefiImageLoaderGetImageEntryPoint (
+  IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  UINTN  ImageAddress;
+  UINT32 EntryPointAddress;
+
+  ASSERT (Context != NULL);
+
+  ImageAddress      = UefiImageLoaderGetImageAddress (Context);
+  EntryPointAddress = UefiImageGetEntryPointAddress (Context);
+
+  return ImageAddress + EntryPointAddress;
+}
+
+// FIXME: Some image prints use this and some don't. Is this really needed?
+RETURN_STATUS
+UefiImageGetModuleNameFromSymbolsPath (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    CHAR8                            *ModuleName,
+  IN     UINT32                           ModuleNameSize
+  )
+{
+  RETURN_STATUS Status;
+  CONST CHAR8   *SymbolsPath;
+  UINT32        SymbolsPathSize;
+  UINTN         Index;
+  UINTN         StartIndex;
+
+  ASSERT (Context != NULL);
+  ASSERT (ModuleName != NULL);
+  ASSERT (3 <= ModuleNameSize);
+
+  Status = UefiImageGetSymbolsPath (
+             Context,
+             &SymbolsPath,
+             &SymbolsPathSize
+             );
+  if (RETURN_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Find the last component of the symbols path, which is the file containing
+  // the debug symbols for the Image.
+  //
+  StartIndex = 0;
+  for (
+    Index = 0;
+    Index < SymbolsPathSize && SymbolsPath[Index] != '\0';
+    ++Index
+    ) {
+    if (SymbolsPath[Index] == '\\' || SymbolsPath[Index] == '/') {
+      StartIndex = Index + 1;
+    }
+  }
+  //
+  // Extract the module name from the debug symbols file and ensure the correct
+  // file extensions.
+  //
+  for (
+    Index = 0;
+    Index < MIN (ModuleNameSize, SymbolsPathSize);
+    ++Index
+    ) {
+    ModuleName[Index] = SymbolsPath[Index + StartIndex];
+    if (ModuleName[Index] == '\0') {
+      ModuleName[Index] = '.';
+    }
+    if (ModuleName[Index] == '.') {
+      if (Index > ModuleNameSize - 3) {
+        break;
+      }
+
+      ModuleName[Index + 1] = 'e';
+      ModuleName[Index + 2] = 'f';
+      ModuleName[Index + 3] = 'i';
+      Index += 4;
+      break;
+    }
+  }
+  //
+  // Terminate the newly created module name string.
+  //
+  ModuleName[Index] = '\0';
+
+  return RETURN_SUCCESS;
+}
+
+VOID
+UefiImageDebugPrintImageRecord (
+  IN CONST UEFI_IMAGE_RECORD  *ImageRecord
+  )
+{
+  UINT16 SegmentIndex;
+  UINTN  SegmentAddress;
+
+  ASSERT (ImageRecord != NULL);
+
+  SegmentAddress = ImageRecord->StartAddress;
+  for (
+    SegmentIndex = 0;
+    SegmentIndex < ImageRecord->NumSegments;
+    ++SegmentIndex
+    ) {
+    DEBUG ((
+      DEBUG_VERBOSE,
+      "  RecordSegment\n"
+      "  Address    - 0x%016llx\n"
+      "  Size       - 0x%08x\n"
+      "  Attributes - 0x%08x\n",
+      (UINT64) SegmentAddress,
+      ImageRecord->Segments[SegmentIndex].Size,
+      ImageRecord->Segments[SegmentIndex].Attributes
+      ));
+
+    SegmentAddress += ImageRecord->Segments[SegmentIndex].Size;
+  }
+}
diff --git a/MdePkg/Library/BaseUefiImageLib/ExecutionSupport.c b/MdePkg/Library/BaseUefiImageLib/ExecutionSupport.c
new file mode 100644
index 0000000000..63f5b00466
--- /dev/null
+++ b/MdePkg/Library/BaseUefiImageLib/ExecutionSupport.c
@@ -0,0 +1,113 @@
+/** @file
+  Support for functions common to all Image formats.
+
+  Copyright (c) 2021, Marvin Häuser. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-3-Clause
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiSpec.h>
+
+#include <Library/BaseOverflowLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiImageLib.h>
+
+RETURN_STATUS
+UefiImageRelocateImageInplaceForExecution (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  RETURN_STATUS Status;
+  UINTN         ImageAddress;
+  UINTN         ImageSize;
+
+  Status = UefiImageRelocateImageInplace (Context);
+  if (RETURN_ERROR (Status)) {
+    return Status;
+  }
+
+  ImageAddress = UefiImageLoaderGetImageAddress (Context);
+  ImageSize    = UefiImageGetImageSizeInplace (Context);
+  //
+  // Flush the instruction cache so the image data is written before
+  // execution.
+  //
+  InvalidateInstructionCacheRange ((VOID *) ImageAddress, ImageSize);
+
+  return RETURN_SUCCESS;
+}
+
+// FIXME: Check Subsystem here
+RETURN_STATUS
+UefiImageLoadImageForExecution (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT    *Context,
+  OUT    VOID                               *Destination,
+  IN     UINT32                             DestinationSize,
+  OUT    UEFI_IMAGE_LOADER_RUNTIME_CONTEXT  *RuntimeContext OPTIONAL,
+  IN     UINT32                             RuntimeContextSize
+  )
+{
+  RETURN_STATUS Status;
+  UINTN         BaseAddress;
+  UINTN         SizeOfImage;
+  //
+  // Load the Image into the memory space.
+  //
+  Status = UefiImageLoadImage (Context, Destination, DestinationSize);
+  if (RETURN_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Relocate the Image to the address it has been loaded to.
+  //
+  BaseAddress = UefiImageLoaderGetImageAddress (Context);
+  Status = UefiImageRelocateImage (
+             Context,
+             BaseAddress,
+             RuntimeContext,
+             RuntimeContextSize
+             );
+  if (RETURN_ERROR (Status)) {
+    return Status;
+  }
+
+  SizeOfImage = UefiImageGetImageSize (Context);
+  //
+  // Flush the instruction cache so the image data is written before execution.
+  //
+  InvalidateInstructionCacheRange ((VOID *) BaseAddress, SizeOfImage);
+
+  return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+UefiImageRuntimeRelocateImageForExecution (
+  IN OUT VOID                                     *Image,
+  IN     UINT32                                   ImageSize,
+  IN     UINT64                                   BaseAddress,
+  IN     CONST UEFI_IMAGE_LOADER_RUNTIME_CONTEXT  *RuntimeContext
+  )
+{
+  RETURN_STATUS Status;
+  //
+  // Relocate the Image to the new address.
+  //
+  Status = UefiImageRuntimeRelocateImage (
+             Image,
+             ImageSize,
+             BaseAddress,
+             RuntimeContext
+             );
+  if (RETURN_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Flush the instruction cache so the image data is written before execution.
+  //
+  InvalidateInstructionCacheRange (Image, ImageSize);
+
+  return RETURN_SUCCESS;
+}
diff --git a/MdePkg/Library/BaseUefiImageLib/PeCoffSupport.c b/MdePkg/Library/BaseUefiImageLib/PeCoffSupport.c
new file mode 100644
index 0000000000..678c6b2b5a
--- /dev/null
+++ b/MdePkg/Library/BaseUefiImageLib/PeCoffSupport.c
@@ -0,0 +1,511 @@
+/** @file
+  UEFI Image Loader library implementation for PE/COFF and TE Images.
+
+  Copyright (c) 2021, Marvin Häuser. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-3-Clause
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiSpec.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseOverflowLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffLib2.h>
+#include <Library/UefiImageLib.h>
+
+/**
+  Retrieves the memory protection attributes corresponding to PE/COFF Image
+  section permissions.
+
+  @param[in] Characteristics  The PE/COFF Image section permissions
+
+  @returns  The memory protection attributes corresponding to the PE/COFF Image
+            section permissions.
+**/
+STATIC
+UINT32
+InternalCharacteristicsToAttributes (
+  IN UINT32  Characteristics
+  )
+{
+  UINT32 Attributes;
+
+  Attributes = 0;
+  if ((Characteristics & EFI_IMAGE_SCN_MEM_READ) == 0) {
+    Attributes |= EFI_MEMORY_RP;
+  }
+  if ((Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) {
+    Attributes |= EFI_MEMORY_XP;
+  }
+  if ((Characteristics & EFI_IMAGE_SCN_MEM_WRITE) == 0) {
+    Attributes |= EFI_MEMORY_RO;
+  }
+
+  return Attributes;
+}
+
+/**
+  Index the read-only padding following an Image record section, if existent.
+
+  @param[in,out] RecordSegment  The Image record section for the current memory
+                                protection range. May be extended if it is of
+                                the same type as the adjacent padding. At least
+                                one more record section must be reserved after
+                                it in order to index the read-only padding.
+  @param[in]     NextAddress    The start address of the next memory permission
+                                range. This may be the end address of the Image
+                                in order to cover the Image trailer.
+  @param[in]     EndAddress     The end address of the current memory permission
+                                range. This also denotes the start of the added
+                                read-only padding.
+  @param[in]     Attributes     The memory protection attributes of the current
+                                memory permission range.
+
+  @returns  The amount of Image record sections that have been appended.
+**/
+STATIC
+UINT8
+InternalInsertImageRecordSegmentPadding (
+  IN OUT UEFI_IMAGE_RECORD_SEGMENT  *RecordSegment,
+  IN     UINT32                     EndAddress,
+  IN     UINT32                     NextAddress,
+  IN     UINT32                     Attributes
+  )
+{
+  ASSERT (RecordSegment != NULL);
+  ASSERT (EndAddress <= NextAddress);
+
+  if (NextAddress == EndAddress) {
+    return 0;
+  }
+  //
+  // Add a new Image record section or expand the previous one depending on
+  // the the permissions of the previous Image record section.
+  //
+  if (Attributes == (EFI_MEMORY_XP | EFI_MEMORY_RO)) {
+    RecordSegment->Size += NextAddress - EndAddress;
+
+    return 0;
+  }
+
+  ++RecordSegment;
+  RecordSegment->Size       = NextAddress - EndAddress;
+  RecordSegment->Attributes = EFI_MEMORY_XP | EFI_MEMORY_RO;
+
+  return 1;
+}
+
+UEFI_IMAGE_RECORD *
+UefiImageLoaderGetImageRecordPeCoff (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  UEFI_IMAGE_RECORD              *ImageRecord;
+  UINT32                         MaxNumRecordSegments;
+  UINT32                         NumRecordSegments;
+  UEFI_IMAGE_RECORD_SEGMENT      *RecordSegment;
+  UINTN                          ImageAddress;
+  UINT32                         SizeOfImage;
+  UINT32                         SectionAlignment;
+  CONST EFI_IMAGE_SECTION_HEADER *Sections;
+  UINT16                         NumberOfSections;
+  UINT16                         SectionIndex;
+  CONST EFI_IMAGE_SECTION_HEADER *Section;
+  UINT32                         SectionAddress;
+  UINT32                         SectionSize;
+  UINT32                         SectionCharacteristics;
+  UINT32                         StartAddress;
+  UINT32                         EndAddress;
+  UINT32                         Characteristics;
+  UINT32                         Attributes;
+
+  ASSERT (Context != NULL);
+  //
+  // Determine the maximum amount of Image record sections and allocate the
+  // Image record.
+  //
+  NumberOfSections = PeCoffGetSectionTable (Context, &Sections);
+
+  STATIC_ASSERT (
+    MAX_UINT16 <= MAX_UINT32 / 2 - 1,
+    "The following arithmetic may overflow."
+    );
+
+  if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_CONTIGUOUS_SECTIONS) == 0) {
+    //
+    // In case of contiguous Image sections, there can be two additional record
+    // sections (Image Headers and trailer, e.g. debug information).
+    //
+    MaxNumRecordSegments = (UINT32) NumberOfSections + 2;
+  } else {
+    //
+    // In case of possibly non-contiguous Image sections, there can be a trailer
+    // per Image section (the last Image section's trailer is the same as the
+    // Image trailer), as well as additionally the Image Headers.
+    //
+    MaxNumRecordSegments = (UINT32) NumberOfSections * 2 + 1;
+  }
+
+  ImageRecord = AllocatePool (
+                  sizeof (*ImageRecord)
+                    + MaxNumRecordSegments * sizeof (*ImageRecord->Segments)
+                  );
+  if (ImageRecord == NULL) {
+    DEBUG_RAISE ();
+    return NULL;
+  }
+
+  ImageRecord->Signature = UEFI_IMAGE_RECORD_SIGNATURE;
+  InitializeListHead (&ImageRecord->Link);
+
+  SectionAlignment = PeCoffGetSectionAlignment (Context);
+  //
+  // Map the Image Headers as read-only data. If the first Image section is
+  // loaded at the start of the Image memory space, the condition
+  // SectionAddress != StartAddress does not hold and these definitions will be
+  // ignored.
+  //
+  StartAddress    = 0;
+  EndAddress      = PeCoffGetSizeOfHeaders (Context);
+  Characteristics = EFI_IMAGE_SCN_MEM_READ;
+  Attributes      = EFI_MEMORY_XP | EFI_MEMORY_RO;
+  ASSERT (Attributes == InternalCharacteristicsToAttributes (Characteristics));
+  //
+  // Create an Image record section for every permission-distinct range of the
+  // Image. The current range [StartAddress, EndAddress) shares the memory
+  // permissions Charactersitics/Attributes and is extended till a new
+  // memory permission configuration is required. Headers and trailers treated
+  // as read-only data.
+  //
+  NumRecordSegments = 0;
+  for (SectionIndex = 0; SectionIndex < NumberOfSections; ++SectionIndex) {
+    Section = Sections + SectionIndex;
+    //
+    // Skip empty Image sections to avoid unnecessary splitting.
+    //
+    if (Section->VirtualSize == 0) {
+      continue;
+    }
+    //
+    // These arithmetics are safe as guaranteed by PeCoffInitializeContext().
+    //
+    SectionAddress = Section->VirtualAddress;
+    SectionSize    = ALIGN_VALUE (Section->VirtualSize, SectionAlignment);
+    SectionCharacteristics = Section->Characteristics & (EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_MEM_WRITE);
+    //
+    // Skip Image sections with the same memory permissions as the current range
+    // as they can be merged. For this, the Image sections must be adjacent, or
+    // the range must have the same memory permissions as the padding inbetween
+    // (read-only).
+    //
+    if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_CONTIGUOUS_SECTIONS) == 0
+     || SectionAddress == EndAddress
+     || Characteristics == EFI_IMAGE_SCN_MEM_READ) {
+      if (SectionCharacteristics == Characteristics) {
+        EndAddress = SectionAddress + SectionSize;
+        continue;
+      }
+    }
+    //
+    // Only create an entry if the range is not empty, otherwise discard it and
+    // start a new one. Even with skipping empty Image sections, this can still
+    // happen for the Image Headers when the first Image section starts at 0.
+    //
+    if (SectionAddress != StartAddress) {
+      //
+      // Create an Image record section for the current memory permission range.
+      //
+      RecordSegment = &ImageRecord->Segments[NumRecordSegments];
+      RecordSegment->Size       = EndAddress - StartAddress;
+      RecordSegment->Attributes = Attributes;
+      ++NumRecordSegments;
+      //
+      // If the previous range is not adjacent to the current Image section,
+      // report the padding as read-only data.
+      //
+      if ((PcdGet32 (PcdImageLoaderAlignmentPolicy) & PCD_ALIGNMENT_POLICY_CONTIGUOUS_SECTIONS) != 0) {
+        NumRecordSegments += InternalInsertImageRecordSegmentPadding (
+                               RecordSegment,
+                               EndAddress,
+                               SectionAddress,
+                               Attributes
+                               );
+      }
+
+      StartAddress = SectionAddress;
+    }
+    //
+    // Start a Image record section with the current Image section.
+    //
+    EndAddress      = SectionAddress + SectionSize;
+    Characteristics = SectionCharacteristics;
+    Attributes      = InternalCharacteristicsToAttributes (Characteristics);
+  }
+  //
+  // Image Record sections are only created once a non-empty Image section is
+  // encountered that requests a different memory permission configuration.
+  // As such, the last memory permission range is never converted in the loop.
+  // If the loop never produced such, this is true for the Image Headers, which
+  // cannot be empty.
+  //
+  ASSERT (StartAddress < EndAddress);
+  //
+  // Create an Image record section for the last Image memory permission range.
+  //
+  RecordSegment = &ImageRecord->Segments[NumRecordSegments];
+  RecordSegment->Size       = EndAddress - StartAddress;
+  RecordSegment->Attributes = Attributes;
+  ++NumRecordSegments;
+
+  ImageAddress = PeCoffLoaderGetImageAddress (Context);
+  SizeOfImage  = PeCoffGetSizeOfImage (Context);
+  //
+  // The Image trailer, if existent, is treated as padding and as such is
+  // reported as read-only data, as intended. Because it is not part of the
+  // original Image memory space, this needs to happen whether Image sections
+  // are guaranteed to be contiguously form the entire Image memory space or
+  // not.
+  //
+  NumRecordSegments += InternalInsertImageRecordSegmentPadding (
+                         RecordSegment,
+                         EndAddress,
+                         SizeOfImage,
+                         Attributes
+                         );
+
+  ImageRecord->NumSegments  = NumRecordSegments;
+  ImageRecord->StartAddress = ImageAddress;
+  ImageRecord->EndAddress   = ImageAddress + SizeOfImage;
+  //
+  // Zero the remaining array entries to avoid uninitialised data.
+  //
+  ZeroMem (
+    ImageRecord->Segments + NumRecordSegments,
+    (MaxNumRecordSegments - NumRecordSegments) * sizeof (*ImageRecord->Segments)
+    );
+
+  return ImageRecord;
+}
+
+// FIXME: Docs
+STATIC
+RETURN_STATUS
+InternalDebugLocateImage (
+  OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  IN  CHAR8                         *Buffer,
+  IN  UINTN                         Address,
+  IN  BOOLEAN                       Recurse
+  )
+{
+  RETURN_STATUS                Status;
+  RETURN_STATUS                DosStatus;
+  PE_COFF_LOADER_IMAGE_CONTEXT DosContext;
+
+  ASSERT (((UINTN) Buffer & 3U) == 0);
+  //
+  // Align the search buffer to a 4 Byte boundary.
+  //
+  // Search for the Image Header in 4 Byte steps. All dynamically loaded
+  // Images start at a page boundary to allow for Image section protection,
+  // but XIP Images may not. As all Image Headers are at least 4 Byte aligned
+  // due to natural alignment, even XIP TE Image Headers should start at a
+  // 4 Byte boundary.
+  //
+  // Do not attempt to access memory of the first page as it may be protected as
+  // part of NULL dereference detection.
+  //
+  for (; EFI_PAGE_SIZE <= (UINTN) Buffer; Buffer -= 4) {
+    //
+    // Try to parse the current memory as PE/COFF or TE Image. Pass MAX_UINT32
+    // as the file size as there isn't any more information available. Only the
+    // Image Header memory will be accessed as part of initialisation.
+    //
+    Status = PeCoffInitializeContext (
+               Context,
+               Buffer,
+               MAX_UINT32
+               );
+    if (RETURN_ERROR (Status)) {
+      continue;
+    }
+
+    if (!Recurse) {
+      //
+      // For PE/COFF Images, the PE/COFF Image Header may be discovered while
+      // there may still be a preceeding DOS Image Header. All RVAs are relatvie
+      // to the start of the Image memory space, of which the DOS Image Header
+      // is a part of, if existent. Allow one level of recursion to find a lower
+      // Image Base including the DOS Image Header.
+      //
+      if ((PcdGetBool (PcdImageLoaderProhibitTe)
+        || Context->ImageType != PeCoffLoaderTypeTe)
+       && Context->ExeHdrOffset == 0) {
+        ASSERT (Context->ImageType != PeCoffLoaderTypeTe);
+
+        DosStatus = InternalDebugLocateImage (
+                      &DosContext,
+                      Buffer - 4,
+                      Address,
+                      TRUE
+                      );
+        if (!RETURN_ERROR (DosStatus)) {
+          Buffer = DosContext.ImageBuffer;
+          CopyMem (Context, &DosContext, sizeof (*Context));
+        }
+      }
+    }
+    //
+    // We know that (UINTN) Buffer <= Address from the initialisation.
+    //
+    // FIXME: Set to non-stripped base for XIP TE Images.
+    if (Address < (UINTN) Buffer + PeCoffGetSizeOfImage (Context)) {
+      Context->ImageBuffer = Buffer;
+      //
+      // Zero the raw file information as we are initialising from a potentially
+      // non-XIP in-memory Image.
+      //
+      Context->FileBuffer  = NULL;
+      Context->FileSize    = 0;
+
+      return RETURN_SUCCESS;
+    }
+    //
+    // Continue for the unlikely case that a PE/COFF or TE Image embeds another
+    // one within its data, the outer Image may still follow.
+    //
+  }
+
+  return RETURN_NOT_FOUND;
+}
+
+RETURN_STATUS
+UefiImageDebugLocateImagePeCoff (
+  OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  IN  UINTN                         Address
+  )
+{
+  RETURN_STATUS Status;
+
+  Status = RETURN_NOT_FOUND;
+  //
+  // As this function is intrinsically unsafe, do not allow its usage outside of
+  // DEBUG-enabled code.
+  //
+  DEBUG_CODE_BEGIN ();
+
+  //
+  // If the Image Headers are not loaded explicitly, only XIP Images and Images
+  // that embed the Image Header in the first Image section can be located. As
+  // this is not the case for the majority of Images, don't attempt to locate
+  // the Image base to not access too much (potentially protected) memory.
+  //
+  if (!PcdGetBool (PcdImageLoaderLoadHeader)) {
+    DEBUG_RAISE ();
+    return RETURN_NOT_FOUND;
+  }
+  //
+  // Align the search buffer to a 4 Byte boundary.
+  //
+  Status = InternalDebugLocateImage (
+             Context,
+             (CHAR8 *) (Address & ~(UINTN) 3U),
+             Address,
+             FALSE
+             );
+
+  DEBUG_CODE_END ();
+
+  return Status;
+}
+
+RETURN_STATUS
+UefiImageGetFixedAddressPeCoff (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    UINT64                        *Address
+  )
+{
+  CONST EFI_IMAGE_SECTION_HEADER *Sections;
+  UINT16                         NumberOfSections;
+  UINT16                         SectionIndex;
+  UINT64                         FixedAddress;
+
+  ASSERT (Address != NULL);
+  //
+  // If this feature is enabled, the build tool will save the address in the
+  // PointerToRelocations and PointerToLineNumbers fields of the first Image
+  // section header that doesn't hold code. The 64-bit value across those fields
+  // will be non-zero if and only if the module has been assigned an address.
+  //
+  NumberOfSections = PeCoffGetSectionTable (Context, &Sections);
+  for (SectionIndex = 0; SectionIndex < NumberOfSections; ++SectionIndex) {
+    if ((Sections[SectionIndex].Characteristics & EFI_IMAGE_SCN_CNT_CODE) != 0) {
+      continue;
+    }
+
+    FixedAddress = ReadUnaligned64 (
+                     (CONST VOID *) &Sections[SectionIndex].PointerToRelocations
+                     );
+    if (FixedAddress != 0) {
+      if (!IS_ALIGNED (FixedAddress, Context->SectionAlignment)) {
+        return RETURN_UNSUPPORTED;
+      }
+
+      *Address = FixedAddress;
+      return RETURN_SUCCESS;
+    }
+
+    break;
+  }
+
+  return RETURN_NOT_FOUND;
+}
+
+VOID
+UefiImageDebugPrintSegmentsPeCoff (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  CONST EFI_IMAGE_SECTION_HEADER *Sections;
+  UINT16                         NumberOfSections;
+  UINT16                         SectionIndex;
+  CONST UINT8                    *Name;
+
+  NumberOfSections = PeCoffGetSectionTable (Context, &Sections);
+
+  for (SectionIndex = 0; SectionIndex < NumberOfSections; ++SectionIndex) {
+    Name = Sections[SectionIndex].Name;
+    DEBUG ((
+      DEBUG_VERBOSE,
+      "  Section - '%c%c%c%c%c%c%c%c'\n"
+      "  VirtualSize          - 0x%08x\n"
+      "  VirtualAddress       - 0x%08x\n"
+      "  SizeOfRawData        - 0x%08x\n"
+      "  PointerToRawData     - 0x%08x\n",
+      Name[0], Name[1], Name[2], Name[3], Name[4], Name[5], Name[6], Name[7],
+      Sections[SectionIndex].VirtualSize,
+      Sections[SectionIndex].VirtualAddress,
+      Sections[SectionIndex].SizeOfRawData,
+      Sections[SectionIndex].PointerToRawData
+      ));
+    DEBUG ((
+      DEBUG_VERBOSE,
+      "  PointerToRelocations - 0x%08x\n"
+      "  PointerToLinenumbers - 0x%08x\n"
+      "  NumberOfRelocations  - 0x%08x\n"
+      "  NumberOfLinenumbers  - 0x%08x\n"
+      "  Characteristics      - 0x%08x\n",
+      Sections[SectionIndex].PointerToRelocations,
+      Sections[SectionIndex].PointerToLinenumbers,
+      Sections[SectionIndex].NumberOfRelocations,
+      Sections[SectionIndex].NumberOfLinenumbers,
+      Sections[SectionIndex].Characteristics
+      ));
+  }
+}
diff --git a/MdePkg/Library/BaseUefiImageLib/PeCoffSupport.h b/MdePkg/Library/BaseUefiImageLib/PeCoffSupport.h
new file mode 100644
index 0000000000..102e09375f
--- /dev/null
+++ b/MdePkg/Library/BaseUefiImageLib/PeCoffSupport.h
@@ -0,0 +1,37 @@
+/** @file
+  UEFI Image Loader library implementation for PE/COFF and TE Images.
+
+  Copyright (c) 2021, Marvin Häuser. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-3-Clause
+**/
+
+#ifndef PE_COFF_SUPPORT_H_
+#define PE_COFF_SUPPORT_H_
+
+#include <Library/PeCoffLib2.h>
+#include <Library/UefiImageLib.h>
+
+UEFI_IMAGE_RECORD *
+UefiImageLoaderGetImageRecordPeCoff (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+RETURN_STATUS
+UefiImageDebugLocateImagePeCoff (
+  OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  IN  UINTN                         Address
+  );
+
+RETURN_STATUS
+UefiImageGetFixedAddressPeCoff (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    UINT64                        *Address
+  );
+
+VOID
+UefiImageDebugPrintSegmentsPeCoff (
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *Context
+  );
+
+#endif // PE_COFF_SUPPORT_H_
diff --git a/MdePkg/Library/BaseUefiImageLib/UefiImageLibPeCoff.c b/MdePkg/Library/BaseUefiImageLib/UefiImageLibPeCoff.c
new file mode 100644
index 0000000000..76b43f228a
--- /dev/null
+++ b/MdePkg/Library/BaseUefiImageLib/UefiImageLibPeCoff.c
@@ -0,0 +1,299 @@
+/** @file
+  UEFI Image Loader library implementation for PE/COFF and TE Images.
+
+  Copyright (c) 2021, Marvin Häuser. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-3-Clause
+**/
+
+#define UEFI_IMAGE_LOADER_IMAGE_CONTEXT    PE_COFF_LOADER_IMAGE_CONTEXT
+#define UEFI_IMAGE_LOADER_RUNTIME_CONTEXT  PE_COFF_LOADER_RUNTIME_CONTEXT
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiSpec.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseOverflowLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffLib2.h>
+#include <Library/UefiImageLib.h>
+#include <Library/UefiImageExtraActionLib.h>
+
+#include "PeCoffSupport.h"
+
+RETURN_STATUS
+UefiImageInitializeContextPreHash (
+  OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  IN  CONST VOID                       *FileBuffer,
+  IN  UINT32                           FileSize
+  )
+{
+  return PeCoffInitializeContext (Context, FileBuffer, FileSize);
+}
+
+RETURN_STATUS
+UefiImageInitializeContextPostHash (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  ASSERT (Context != NULL);
+
+  return RETURN_SUCCESS;
+}
+
+UINT8
+UefiImageGetFormat (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  return UefiImageFormatPe;
+}
+
+BOOLEAN
+UefiImageHashImageDefault (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  IN OUT VOID                             *HashContext,
+  IN     UEFI_IMAGE_LOADER_HASH_UPDATE    HashUpdate
+  )
+{
+  return PeCoffHashImageAuthenticode (Context, HashContext, HashUpdate);
+}
+
+RETURN_STATUS
+UefiImageLoadImage (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    VOID                             *Destination,
+  IN     UINT32                           DestinationSize
+  )
+{
+  return PeCoffLoadImage (Context, Destination, DestinationSize);
+}
+
+BOOLEAN
+UefiImageImageIsInplace (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  return PeCoffImageIsInplace (Context);
+}
+
+RETURN_STATUS
+UefiImageLoadImageInplace (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  return PeCoffLoadImageInplace (Context);
+}
+
+RETURN_STATUS
+UefiImageRelocateImageInplace (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  return PeCoffRelocateImageInplace (Context);
+}
+
+RETURN_STATUS
+UefiImageLoaderGetRuntimeContextSize (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    UINT32                           *Size
+  )
+{
+  return PeCoffLoaderGetRuntimeContextSize (Context, Size);
+}
+
+RETURN_STATUS
+UefiImageRelocateImage (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT    *Context,
+  IN     UINT64                             BaseAddress,
+  OUT    UEFI_IMAGE_LOADER_RUNTIME_CONTEXT  *RuntimeContext OPTIONAL,
+  IN     UINT32                             RuntimeContextSize
+  )
+{
+  RETURN_STATUS Status;
+
+  Status = PeCoffRelocateImage (
+             Context,
+             BaseAddress,
+             RuntimeContext,
+             RuntimeContextSize
+             );
+  if (!RETURN_ERROR (Status)) {
+    UefiImageLoaderRelocateImageExtraAction (Context);
+  }
+
+  return Status;
+}
+
+RETURN_STATUS
+UefiImageRuntimeRelocateImage (
+  IN OUT VOID                                     *Image,
+  IN     UINT32                                   ImageSize,
+  IN     UINT64                                   BaseAddress,
+  IN     CONST UEFI_IMAGE_LOADER_RUNTIME_CONTEXT  *RuntimeContext
+  )
+{
+  return PeCoffRuntimeRelocateImage (
+           Image,
+           ImageSize,
+           BaseAddress,
+           RuntimeContext
+           );
+}
+
+VOID
+UefiImageDiscardSegments (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  PeCoffDiscardSections (Context);
+}
+
+RETURN_STATUS
+UefiImageGetSymbolsPath (
+  IN  CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  OUT CONST CHAR8                            **SymbolsPath,
+  OUT UINT32                                 *SymbolsPathSize
+  )
+{
+  return PeCoffGetPdbPath (Context, SymbolsPath, SymbolsPathSize);
+}
+
+RETURN_STATUS
+UefiImageGetFirstCertificate (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    CONST WIN_CERTIFICATE            **Certificate
+  )
+{
+  return PeCoffGetFirstCertificate (Context, Certificate);
+}
+
+RETURN_STATUS
+UefiImageGetNextCertificate (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  IN OUT CONST WIN_CERTIFICATE            **Certificate
+  )
+{
+  return PeCoffGetNextCertificate (Context, Certificate);
+}
+
+RETURN_STATUS
+UefiImageGetHiiDataRva (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    UINT32                           *HiiRva,
+  OUT    UINT32                           *HiiSize
+  )
+{
+  return PeCoffGetHiiDataRva (Context, HiiRva, HiiSize);
+}
+
+UINT32
+UefiImageGetEntryPointAddress (
+  IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  return PeCoffGetAddressOfEntryPoint (Context);
+}
+
+UINT16
+UefiImageGetMachine (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  return PeCoffGetMachine (Context);
+}
+
+UINT16
+UefiImageGetSubsystem (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  return PeCoffGetSubsystem (Context);
+}
+
+UINT32
+UefiImageGetSegmentAlignment (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  return PeCoffGetSectionAlignment (Context);
+}
+
+UINT32
+UefiImageGetImageSize (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  return PeCoffGetSizeOfImage (Context);
+}
+
+UINT32
+UefiImageGetImageSizeInplace (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  return PeCoffGetSizeOfImageInplace (Context);
+}
+
+UINT64
+UefiImageGetPreferredAddress (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  return PeCoffGetImageBase (Context);
+}
+
+BOOLEAN
+UefiImageGetRelocsStripped (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  return PeCoffGetRelocsStripped (Context);
+}
+
+UINTN
+UefiImageLoaderGetImageAddress (
+  IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  return PeCoffLoaderGetImageAddress (Context);
+}
+
+UEFI_IMAGE_RECORD *
+UefiImageLoaderGetImageRecord (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  return UefiImageLoaderGetImageRecordPeCoff (Context);
+}
+
+RETURN_STATUS
+UefiImageDebugLocateImage (
+  OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  IN  UINTN                            Address
+  )
+{
+  return UefiImageDebugLocateImagePeCoff (Context, Address);
+}
+
+RETURN_STATUS
+UefiImageGetFixedAddress (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context,
+  OUT    UINT64                           *Address
+  )
+{
+  return UefiImageGetFixedAddressPeCoff (Context, Address);
+}
+
+VOID
+UefiImageDebugPrintSegments (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *Context
+  )
+{
+  UefiImageDebugPrintSegmentsPeCoff (Context);
+}
diff --git a/MdePkg/Library/PeiServicesLib/PeiServicesLib.c b/MdePkg/Library/PeiServicesLib/PeiServicesLib.c
index 16d5134981..5521e1690f 100644
--- a/MdePkg/Library/PeiServicesLib/PeiServicesLib.c
+++ b/MdePkg/Library/PeiServicesLib/PeiServicesLib.c
@@ -324,6 +324,38 @@ PeiServicesFfsFindSectionData3 (
   return (*PeiServices)->FindSectionData3 (PeiServices, SectionType, SectionInstance, FileHandle, SectionData, AuthenticationStatus);
 }
 
+/**
+  This service enables PEIMs to discover sections of a given instance and type within a valid FFS file.
+
+  @param  SectionType           The value of the section type to find.
+  @param  SectionInstance       Section instance to find.
+  @param  FileHandle            A pointer to the file header that contains the set
+                                of sections to be searched.
+  @param  SectionData           A pointer to the discovered section, if successful.
+  @param  SectionDataSize       The size of the discovered section, if successful.
+  @param  AuthenticationStatus  A pointer to the authentication status for this section.
+
+  @retval EFI_SUCCESS           The section was found.
+  @retval EFI_NOT_FOUND         The section was not found.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiServicesFfsFindSectionData4 (
+  IN EFI_SECTION_TYPE           SectionType,
+  IN UINTN                      SectionInstance,
+  IN EFI_PEI_FILE_HANDLE        FileHandle,
+  OUT VOID                      **SectionData,
+  OUT UINT32                    *SectionDataSize,
+  OUT UINT32                    *AuthenticationStatus
+  )
+{
+  CONST EFI_PEI_SERVICES **PeiServices;
+
+  PeiServices = GetPeiServicesTablePointer ();
+  return (*PeiServices)->FindSectionData4 (PeiServices, SectionType, SectionInstance, FileHandle, SectionData, SectionDataSize, AuthenticationStatus);
+}
+
 /**
   This service enables PEIMs to register the permanent memory configuration
   that has been initialized with the PEI Foundation.
diff --git a/MdePkg/MdeLibs.dsc.inc b/MdePkg/MdeLibs.dsc.inc
index 57818e2499..ae645164c8 100644
--- a/MdePkg/MdeLibs.dsc.inc
+++ b/MdePkg/MdeLibs.dsc.inc
@@ -28,6 +28,7 @@
   SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   MmUnblockMemoryLib|MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf
+  BaseOverflowLib|MdePkg/Library/BaseOverflowLib/BaseOverflowLib.inf
   StackCheckFailureHookLib|MdePkg/Library/StackCheckFailureHookLibNull/StackCheckFailureHookLibNull.inf
 
 !if $(CUSTOM_STACK_CHECK_LIB) == STATIC
diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
index 37a2b461d4..f4df56d209 100644
--- a/MdePkg/MdePkg.dec
+++ b/MdePkg/MdePkg.dec
@@ -132,9 +132,15 @@
   ##  @libraryclass  Provides extra action services for unloading and relocating a PE/COFF image on some specific platform such
   ## as NT32 emulator.
   PeCoffExtraActionLib|Include/Library/PeCoffExtraActionLib.h
+  # FIXME: Docs
+  ##  @libraryclass  Provides services to load and relocate a PE/COFF image.
+  PeCoffLib2|Include/Library/PeCoffLib2.h
+  ##  @libraryclass  Provides extra action services for unloading and relocating a PE/COFF image on some specific platform such
+  ## as NT32 emulator.
+  UefiImageExtraActionLib|Include/Library/UefiImageExtraActionLib.h
 
   ##  @libraryclass  Provides a service to retrieve the PE/COFF entry point from a PE/COFF image.
-  PeCoffGetEntryPointLib|Include/Library/PeCoffGetEntryPointLib.h
+  UefiImageGetEntryPointLib|Include/Library/UefiImageGetEntryPointLib.h
 
   ##  @libraryclass  Provides services to return the PCI segment information.
   PciSegmentInfoLib|Include/Library/PciSegmentInfoLib.h
@@ -2275,7 +2281,7 @@
   #   BIT0 - SMM CET Shadow Stack is enabled.<BR>
   #   Other - reserved
   # @Prompt Enable control flow enforcement.
-  gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask|0x0|UINT32|0x30001017
+  gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask|0|UINT32|0x30001017
 
   ## Indicates the type of instruction sequence to use for a speculation
   #  barrier.  The default instruction sequence is LFENCE.<BR><BR>
@@ -2294,6 +2300,63 @@
   # FALSE - Do not enforce and depend on the default implementation of RNG algorithm from the provider.
   # @Prompt Enforce the use of Secure UEFI spec defined RNG algorithms.
   gEfiMdePkgTokenSpaceGuid.PcdEnforceSecureRngAlgorithms|TRUE|BOOLEAN|0x1000000D
+  
+  ## Indicates whether Image Relocation target values at Runtime may mismatch
+  #  the values assigned during initial load.<BR><BR>
+  #   TRUE  - Image relocation target values may mismatch the expected values.<BR>
+  #   FALSE - Image relocation target values must match the expected values.<BR>
+  # @Prompt Allow Runtime Relocation Target Mismatch.
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderRtRelocAllowTargetMismatch|FALSE|BOOLEAN|0x40001018
+
+  ## Indicates whether Image section may overlap with the previous one.
+  #  Overlapping Sections could dramatically increase the hashing time.<BR><BR>
+  #   TRUE  - Image section must not overlap with the previous one.<BR>
+  #   FALSE - Image section may overlap with the previous one.<BR>
+  # @Prompt Prohibit Overlapping Sections.
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderHashProhibitOverlap|TRUE|BOOLEAN|0x40001019
+
+  ## Indicates whether Image Headers must be loaded into the memory space.<BR><BR>
+  #   TRUE  - Image Headers will be loaded into the memory space.<BR>
+  #   FALSE - Image Headers will not be loaded into the memory space.<BR>
+  # @Prompt Load Image Headers.
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderLoadHeader|TRUE|BOOLEAN|0x4000101A
+
+  ## This flag is used to control the set of supported relocations' types.<BR><BR>
+  #  BIT0  - If set, ARM Thumb Image relocations are supported.<BR>
+  # @Prompt Image Relocations Policy.
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderRelocTypePolicy|0xFFFFFFFF|UINT32|0x4000101B
+
+  ## Indicates whether Image sections must adhere to the W^X principle.<BR><BR>
+  #   TRUE  - Image sections must adhere to the W^X principle.<BR>
+  #   FALSE - Image sections may not adhere to the W^X principle.<BR>
+  # @Prompt Enforce W^X principle.
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderWXorX|TRUE|BOOLEAN|0x4000101C
+
+  ## Indicates whether Debug information can be retrieved
+  #  from the Debug Directory of the Image.<BR><BR>
+  #   TRUE  - Debug Directory will be scaned for Debug Information.<BR>
+  #   FALSE - Debug Directory will not be scaned.<BR>
+  # @Prompt Support Debug Information.
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderDebugSupport|TRUE|BOOLEAN|0x4000101D
+
+  ## This flag is used to control Image Loader alignment policy.<BR><BR>
+  #  BIT0  - If set, unaligned Image sections are permitted.<BR>
+  #  BIT1  - If set, unaligned Image Relocation Block sizes are permitted.<BR>
+  #  BIT2  - If set, unaligned Image certificate sizes are permitted.<BR>
+  # @Prompt Image Loader Alignment Policy.
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAlignmentPolicy|0xFFFFFFFF|UINT32|0x4000101E
+
+  ## Indicates whether TE Images are allowed.<BR><BR>
+  #   TRUE  - TE Images are forbidden.<BR>
+  #   FALSE - TE Images are allowed.<BR>
+  # @Prompt Prohibit TE Images Loading.
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderProhibitTe|FALSE|BOOLEAN|0x4000101F
+
+  ## Indicates whether PE32+ header offset is sufficiently aligned.<BR><BR>
+  #   TRUE  - Execution Header offset may be not aligned.<BR>
+  #   FALSE - Execution Header offset must be sufficiently aligned.<BR>
+  # @Prompt Allow Misaligned Offset.
+  gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAllowMisalignedOffset|FALSE|BOOLEAN|0x40001020
 
 [PcdsFixedAtBuild,PcdsPatchableInModule]
   ## Indicates the maximum length of unicode string used in the following
diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc
index 84730b09d4..acf7be2aa7 100644
--- a/MdePkg/MdePkg.dsc
+++ b/MdePkg/MdePkg.dsc
@@ -58,9 +58,9 @@
   MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.inf
   MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.inf
   MdePkg/Library/BaseArmTrngLibNull/BaseArmTrngLibNull.inf
-  MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
-  MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
-  MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
+  MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
   MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
   MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.inf
   MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.inf
diff --git a/NetworkPkg/NetworkPkg.dsc b/NetworkPkg/NetworkPkg.dsc
index b3710bf07a..f69df9d4c2 100644
--- a/NetworkPkg/NetworkPkg.dsc
+++ b/NetworkPkg/NetworkPkg.dsc
@@ -41,12 +41,15 @@
   UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
   TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
   DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
   SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
   RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
   VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
+  CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
 
 !ifdef CONTINUOUS_INTEGRATION
   BaseCryptLib|CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
@@ -118,7 +121,7 @@
   NetworkPkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf
   NetworkPkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf
 
-  !include NetworkPkg/Network.dsc.inc
+!include NetworkPkg/Network.dsc.inc
 
 [BuildOptions]
   *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc
index e0eaa3c574..0c3ddaf445 100644
--- a/OvmfPkg/AmdSev/AmdSevX64.dsc
+++ b/OvmfPkg/AmdSev/AmdSevX64.dsc
@@ -122,7 +122,8 @@
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
   UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
   UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
@@ -134,7 +135,6 @@
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
   DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
   DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
   PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
   PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
@@ -175,10 +175,10 @@
   ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
-  PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
+  UefiImageExtraActionLib|SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLibDebug.inf
   DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
 !else
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
 !endif
 
@@ -242,14 +242,14 @@
   PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
   ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
 !ifdef $(DEBUG_ON_SERIAL_PORT)
   DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
 !else
   DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformRomDebugLibIoPort.inf
 !endif
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
   CcProbeLib|OvmfPkg/Library/CcProbeLib/SecPeiCcProbeLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
 
 [LibraryClasses.common.PEIM]
   HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
@@ -259,13 +259,13 @@
   PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
   ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
 !ifdef $(DEBUG_ON_SERIAL_PORT)
   DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
 !else
   DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformRomDebugLibIoPort.inf
 !endif
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   ResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf
   ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
diff --git a/OvmfPkg/Bhyve/BhyveX64.dsc b/OvmfPkg/Bhyve/BhyveX64.dsc
index 5aab790316..d1e3616dc3 100644
--- a/OvmfPkg/Bhyve/BhyveX64.dsc
+++ b/OvmfPkg/Bhyve/BhyveX64.dsc
@@ -133,7 +133,8 @@
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
   UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
   UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
@@ -145,7 +146,6 @@
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
   DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
   DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
   PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
   PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
@@ -185,10 +185,10 @@
   FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
 
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
-  PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
+  UefiImageExtraActionLib|SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLibDebug.inf
   DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
 !else
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
 !endif
 
@@ -270,13 +270,13 @@
   PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
   ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
 !ifdef $(DEBUG_ON_SERIAL_PORT)
   DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
 !else
   DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformRomDebugLibIoPort.inf
 !endif
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
 
 [LibraryClasses.common.PEIM]
   HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
@@ -286,13 +286,13 @@
   PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
   ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
 !ifdef $(DEBUG_ON_SERIAL_PORT)
   DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
 !else
   DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformRomDebugLibIoPort.inf
 !endif
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   ResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf
   ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
diff --git a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
index c4416494a9..c4ae25fe2e 100644
--- a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
+++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
@@ -12,7 +12,6 @@
 
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
-#include <Library/PeCoffLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 
 #include <Protocol/PeCoffImageEmulator.h>
diff --git a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
index 74f06c64bf..c9fbbe0591 100644
--- a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
+++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
@@ -26,7 +26,6 @@
 [LibraryClasses]
   BaseMemoryLib
   DebugLib
-  PeCoffLib
   UefiBootServicesTableLib
   UefiDriverEntryPoint
 
diff --git a/OvmfPkg/IntelTdx/IntelTdxX64.dsc b/OvmfPkg/IntelTdx/IntelTdxX64.dsc
index 6d3e0a5f1c..840159d118 100644
--- a/OvmfPkg/IntelTdx/IntelTdxX64.dsc
+++ b/OvmfPkg/IntelTdx/IntelTdxX64.dsc
@@ -36,6 +36,9 @@
   #
   DEFINE BUILD_SHELL             = TRUE
 
+  DEFINE LEGACY_WINDOWS_LOADER   = FALSE
+  DEFINE LINUX_LOADER            = FALSE
+
   #
   # Device drivers
   #
@@ -90,12 +93,6 @@
   INTEL:*_*_*_CC_FLAGS = /D TDX_PEI_LESS_BOOT
   GCC:*_*_*_CC_FLAGS = -D TDX_PEI_LESS_BOOT
 
-[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
-  GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
-  XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
-  XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
-  CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096
-
 ################################################################################
 #
 # SKU Identification section - list of all SKU IDs supported by this Platform.
@@ -125,7 +122,8 @@
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
   UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
   UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
@@ -137,7 +135,6 @@
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
   DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
   DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
   PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
   PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
@@ -177,9 +174,14 @@
   CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
   FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
 
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
 
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+  UefiImageExtraActionLib|SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLibDebug.inf
+!else
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
+!endif
+
   LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
   DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
 
@@ -468,6 +470,21 @@
   #
   gUefiCpuPkgTokenSpaceGuid.PcdFirstTimeWakeUpAPsBySipi|FALSE
 
+  #
+  # Security measures for memory protection.
+  #
+  !if $(LEGACY_WINDOWS_LOADER) == TRUE
+    # Allow execution of EfiLoaderData memory regions.
+    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFFD1
+  !elseif $(LINUX_LOADER) == TRUE
+    # Allow execution of EfiReservedMemoryType, EfiConventionalMemory, EfiBootServicesData and EfiLoaderData memory regions.
+    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFF40
+    gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAllowMisalignedOffset|TRUE
+  !else
+    # Allow execution of EfiConventionalMemory and EfiBootServicesData memory regions.
+    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0xFFFFFFFFFFFFFF45
+  !endif
+
 ################################################################################
 #
 # Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform
diff --git a/OvmfPkg/IntelTdx/Sec/SecMain.c b/OvmfPkg/IntelTdx/Sec/SecMain.c
index 7f2d28af95..d9c26535eb 100644
--- a/OvmfPkg/IntelTdx/Sec/SecMain.c
+++ b/OvmfPkg/IntelTdx/Sec/SecMain.c
@@ -18,8 +18,6 @@
 #include <Library/CpuLib.h>
 #include <Library/DebugAgentLib.h>
 #include <Library/IoLib.h>
-#include <Library/PeCoffLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
 #include <Library/LocalApicLib.h>
 #include <Library/CpuExceptionHandlerLib.h>
 #include <IndustryStandard/Tdx.h>
diff --git a/OvmfPkg/IntelTdx/Sec/SecMain.inf b/OvmfPkg/IntelTdx/Sec/SecMain.inf
index a9ba5c8f78..5c281dbd6d 100644
--- a/OvmfPkg/IntelTdx/Sec/SecMain.inf
+++ b/OvmfPkg/IntelTdx/Sec/SecMain.inf
@@ -40,9 +40,6 @@
   CpuLib
   DebugAgentLib
   IoLib
-  PeCoffLib
-  PeCoffGetEntryPointLib
-  PeCoffExtraActionLib
   ExtractGuidedSectionLib
   LocalApicLib
   MemEncryptSevLib
diff --git a/OvmfPkg/Library/PeilessStartupLib/DxeLoad.c b/OvmfPkg/Library/PeilessStartupLib/DxeLoad.c
index d34690eb8a..f2f0acff3a 100644
--- a/OvmfPkg/Library/PeilessStartupLib/DxeLoad.c
+++ b/OvmfPkg/Library/PeilessStartupLib/DxeLoad.c
@@ -194,6 +194,7 @@ FindDxeNonCc (
   EFI_FV_INFO          FvImageInfo;
   UINT32               FvAlignment;
   VOID                 *FvBuffer;
+  UINT32               FvImageSize;
 
   FileHandle = NULL;
 
@@ -209,7 +210,7 @@ FindDxeNonCc (
   //
   // Find FvImage in FvFile
   //
-  Status = FfsFindSectionDataWithHook (EFI_SECTION_FIRMWARE_VOLUME_IMAGE, CheckSectionHookForDxeNonCc, FileHandle, (VOID **)&FvImageHandle);
+  Status = FfsFindSectionDataWithHook (EFI_SECTION_FIRMWARE_VOLUME_IMAGE, CheckSectionHookForDxeNonCc, FileHandle, (VOID **)&FvImageHandle, &FvImageSize);
   if (EFI_ERROR (Status)) {
     return Status;
   }
@@ -281,10 +282,11 @@ DxeLoadCore (
   EFI_STATUS            Status;
   EFI_FV_FILE_INFO      DxeCoreFileInfo;
   EFI_PHYSICAL_ADDRESS  DxeCoreAddress;
-  UINT64                DxeCoreSize;
+  UINT32                DxeCoreSize;
   EFI_PHYSICAL_ADDRESS  DxeCoreEntryPoint;
   EFI_PEI_FILE_HANDLE   FileHandle;
-  VOID                  *PeCoffImage;
+  VOID                  *UefiImage;
+  UINT32                UefiImageSize;
 
   //
   // Look in all the FVs present and find the DXE Core FileHandle
@@ -303,12 +305,12 @@ DxeLoadCore (
   //
   // Load the DXE Core from a Firmware Volume.
   //
-  Status = FfsFindSectionDataWithHook (EFI_SECTION_PE32, NULL, FileHandle, &PeCoffImage);
+  Status = FfsFindSectionDataWithHook (EFI_SECTION_PE32, NULL, FileHandle, &UefiImage, &UefiImageSize);
   if (EFI_ERROR (Status)) {
     return Status;
   }
 
-  Status = LoadPeCoffImage (PeCoffImage, &DxeCoreAddress, &DxeCoreSize, &DxeCoreEntryPoint);
+  Status = LoadUefiImage (UefiImage, UefiImageSize, &DxeCoreAddress, &DxeCoreSize, &DxeCoreEntryPoint);
   ASSERT_EFI_ERROR (Status);
 
   //
diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.h b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.h
index 18b3deb9db..9c172d56a7 100644
--- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.h
+++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.h
@@ -22,7 +22,7 @@ Abstract:
 #include <IndustryStandard/Pci.h>
 #include <IndustryStandard/Acpi.h>
 #include <IndustryStandard/SmBios.h>
-#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/PeImage2.h>
 #include <IndustryStandard/Virtio095.h>
 
 #include <Library/DebugLib.h>
diff --git a/OvmfPkg/Library/PlatformBootManagerLibBhyve/BdsPlatform.h b/OvmfPkg/Library/PlatformBootManagerLibBhyve/BdsPlatform.h
index 9be184cb64..af26b3bac7 100644
--- a/OvmfPkg/Library/PlatformBootManagerLibBhyve/BdsPlatform.h
+++ b/OvmfPkg/Library/PlatformBootManagerLibBhyve/BdsPlatform.h
@@ -23,7 +23,7 @@ Abstract:
 #include <IndustryStandard/Pci.h>
 #include <IndustryStandard/Acpi.h>
 #include <IndustryStandard/SmBios.h>
-#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/PeImage2.h>
 #include <IndustryStandard/Virtio095.h>
 
 #include <Library/DebugLib.h>
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 09c196feb3..6d75ebdb24 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -53,6 +53,10 @@
 
 !include NetworkPkg/NetworkDefines.dsc.inc
 
+  DEFINE LEGACY_WINDOWS_LOADER   = FALSE
+  DEFINE LINUX_LOADER            = FALSE
+  DEFINE WINDOWS_10_IA32         = FALSE
+
   #
   # Device drivers
   #
@@ -143,7 +147,8 @@
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
   UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
   UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
@@ -155,7 +160,6 @@
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
   DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
   DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
   PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
   PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
@@ -198,10 +202,10 @@
   FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
 
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
-  PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
+  UefiImageExtraActionLib|SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLibDebug.inf
   DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
 !else
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
 !endif
 
@@ -284,13 +288,13 @@
   PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
   ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
 !ifdef $(DEBUG_ON_SERIAL_PORT)
   DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
 !else
   DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformRomDebugLibIoPort.inf
 !endif
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
 
 [LibraryClasses.common.PEIM]
   HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
@@ -300,13 +304,13 @@
   PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
   ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
 !ifdef $(DEBUG_ON_SERIAL_PORT)
   DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
 !else
   DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformRomDebugLibIoPort.inf
 !endif
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   ResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf
   ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
@@ -591,6 +595,21 @@
   #
   gUefiCpuPkgTokenSpaceGuid.PcdFirstTimeWakeUpAPsBySipi|FALSE
 
+  #
+  # Security measures for memory protection.
+  #
+  !if $(LEGACY_WINDOWS_LOADER) == TRUE
+    # Allow execution of EfiLoaderData memory regions.
+    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7FD1
+  !elseif $(LINUX_LOADER) == TRUE
+    # Allow execution of EfiConventionalMemory, EfiBootServicesData and EfiLoaderData memory regions.
+    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7F41
+    gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAllowMisalignedOffset|TRUE
+  !elseif $(WINDOWS_10_IA32) == TRUE
+    # Allow execution of EfiReservedMemoryType, EfiConventionalMemory, EfiBootServicesData and EfiRuntimeServicesData memory regions.
+    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7F04
+  !endif
+
 ################################################################################
 #
 # Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index a9383a6b9b..b11a4523f8 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -53,6 +53,10 @@
 
 !include NetworkPkg/NetworkDefines.dsc.inc
 
+  DEFINE LEGACY_WINDOWS_LOADER   = FALSE
+  DEFINE LINUX_LOADER            = FALSE
+  DEFINE WINDOWS_10_IA32         = FALSE
+
   #
   # Device drivers
   #
@@ -106,19 +110,10 @@
 
 !include NetworkPkg/NetworkBuildOptions.dsc.inc
 
-[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
   GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
   XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
   XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
-  CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096
-
-# Force PE/COFF sections to be aligned at 4KB boundaries to support page level
-# protection of DXE_SMM_DRIVER/SMM_CORE modules
-[BuildOptions.common.EDKII.DXE_SMM_DRIVER, BuildOptions.common.EDKII.SMM_CORE]
-  GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
-  XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
-  XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
-  CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096
+  CLANGPDB:*_*_*_DLINK_FLAGS = /FILEALIGN:4096 /ALIGN:4096
 
 ################################################################################
 #
@@ -150,7 +145,8 @@
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
   UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
   UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
@@ -162,7 +158,6 @@
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
   DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
   DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
   PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
   PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
@@ -203,10 +198,10 @@
   FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
 
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
-  PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
+  UefiImageExtraActionLib|SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLibDebug.inf
   DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
 !else
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
 !endif
 
@@ -289,13 +284,13 @@
   PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
   ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
 !ifdef $(DEBUG_ON_SERIAL_PORT)
   DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
 !else
   DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformRomDebugLibIoPort.inf
 !endif
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
 
 [LibraryClasses.common.PEIM]
   HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
@@ -305,13 +300,13 @@
   PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
   ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
 !ifdef $(DEBUG_ON_SERIAL_PORT)
   DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
 !else
   DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformRomDebugLibIoPort.inf
 !endif
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   ResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf
   ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
@@ -544,7 +539,7 @@
   # DEBUG_VERBOSE   0x00400000  // Detailed debug messages that may
   #                             // significantly impact boot performance
   # DEBUG_ERROR     0x80000000  // Error
-  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
+  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x800000CF
 
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
   gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
@@ -574,6 +569,9 @@
   #
   gUefiCpuPkgTokenSpaceGuid.PcdFirstTimeWakeUpAPsBySipi|FALSE
 
+  gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask|0x1
+  gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy|0x00000003
+
 [PcdsFixedAtBuild.IA32]
   #
   # The NumberOfPages values below are ad-hoc. They are updated sporadically at
@@ -596,12 +594,27 @@
   gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize|0x20000
 
 !if $(SMM_REQUIRE) == TRUE
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackSize|0x4000
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackSize|0x8000
 !endif
 
   # Point to the MdeModulePkg/Application/UiApp/UiApp.inf
   gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
 
+  #
+  # Security measures for memory protection.
+  #
+  !if $(LEGACY_WINDOWS_LOADER) == TRUE
+    # Allow execution of EfiLoaderData memory regions.
+    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7FD1
+  !elseif $(LINUX_LOADER) == TRUE
+    # Allow execution of EfiConventionalMemory, EfiBootServicesData and EfiLoaderData memory regions.
+    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7F41
+    gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAllowMisalignedOffset|TRUE
+  !elseif $(WINDOWS_10_IA32) == TRUE
+    # Allow execution of EfiReservedMemoryType, EfiConventionalMemory, EfiBootServicesData and EfiRuntimeServicesData memory regions.
+    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7F04
+  !endif
+
 ################################################################################
 #
 # Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index 605d9cd47a..0a9a31df75 100644
--- a/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -408,7 +408,7 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
 
 [Rule.Common.SEC]
   FILE SEC = $(NAMED_GUID) {
-    PE32     PE32           $(INF_OUTPUT)/$(MODULE_NAME).efi
+    PE32     PE32   Align=Auto    $(INF_OUTPUT)/$(MODULE_NAME).efi
     UI       STRING ="$(MODULE_NAME)" Optional
     VERSION  STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
   }
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index eb5df0d74c..d562e47dae 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -53,6 +53,9 @@
 
 !include NetworkPkg/NetworkDefines.dsc.inc
 
+  DEFINE LEGACY_WINDOWS_LOADER   = FALSE
+  DEFINE LINUX_LOADER            = FALSE
+
   #
   # Device drivers
   #
@@ -161,7 +164,8 @@
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
   UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
   UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
@@ -173,7 +177,6 @@
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
   DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
   DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
   PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
   PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
@@ -219,10 +222,10 @@
   FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
 
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
-  PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
+  UefiImageExtraActionLib|SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLibDebug.inf
   DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
 !else
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
 !endif
 
@@ -307,13 +310,13 @@
   PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
   ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
 !ifdef $(DEBUG_ON_SERIAL_PORT)
   DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
 !else
   DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformRomDebugLibIoPort.inf
 !endif
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   CcProbeLib|OvmfPkg/Library/CcProbeLib/SecPeiCcProbeLib.inf
 
 [LibraryClasses.common.PEIM]
@@ -324,13 +327,13 @@
   PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
   ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
 !ifdef $(DEBUG_ON_SERIAL_PORT)
   DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
 !else
   DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformRomDebugLibIoPort.inf
 !endif
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   ResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf
   ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
@@ -567,7 +570,7 @@
   # DEBUG_VERBOSE   0x00400000  // Detailed debug messages that may
   #                             // significantly impact boot performance
   # DEBUG_ERROR     0x80000000  // Error
-  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
+  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x800000CF
 
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
   gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
@@ -624,6 +627,18 @@
   #
   gUefiCpuPkgTokenSpaceGuid.PcdFirstTimeWakeUpAPsBySipi|FALSE
 
+  #
+  # Security measures for memory protection.
+  #
+  !if $(LEGACY_WINDOWS_LOADER) == TRUE
+    # Allow execution of EfiLoaderData memory regions.
+    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7FD1
+  !elseif $(LINUX_LOADER) == TRUE
+    # Allow execution of EfiConventionalMemory, EfiBootServicesData and EfiLoaderData memory regions.
+    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x7F41
+    gEfiMdePkgTokenSpaceGuid.PcdImageLoaderAllowMisalignedOffset|TRUE
+  !endif
+
 ################################################################################
 #
 # Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform
diff --git a/OvmfPkg/OvmfXen.dsc b/OvmfPkg/OvmfXen.dsc
index a4fb92f7cf..10f2992ceb 100644
--- a/OvmfPkg/OvmfXen.dsc
+++ b/OvmfPkg/OvmfXen.dsc
@@ -134,7 +134,8 @@
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
   UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
   UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
@@ -146,7 +147,6 @@
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
   DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
   DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
   PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
   PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
@@ -185,10 +185,10 @@
   ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
-  PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
+  UefiImageExtraActionLib|SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLibDebug.inf
   DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
 !else
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
 !endif
 
@@ -270,9 +270,9 @@
   PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
   ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
   PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
 
 [LibraryClasses.common.PEIM]
   HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
@@ -282,8 +282,8 @@
   PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
   ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   ResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf
   ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c
index d13a948509..ccd1e8e060 100644
--- a/OvmfPkg/Sec/SecMain.c
+++ b/OvmfPkg/Sec/SecMain.c
@@ -9,6 +9,7 @@
 
 **/
 
+#include "ProcessorBind.h"
 #include <PiPei.h>
 
 #include <Library/BaseLib.h>
@@ -19,9 +20,9 @@
 #include <Library/CpuLib.h>
 #include <Library/DebugAgentLib.h>
 #include <Library/IoLib.h>
-#include <Library/PeCoffLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
-#include <Library/PeCoffExtraActionLib.h>
+#include <Library/UefiImageLib.h>
+
+#include <Library/UefiImageExtraActionLib.h>
 #include <Library/ExtractGuidedSectionLib.h>
 #include <Library/LocalApicLib.h>
 #include <Library/CpuExceptionHandlerLib.h>
@@ -488,7 +489,8 @@ DecompressMemFvs (
 EFI_STATUS
 FindPeiCoreImageBaseInFv (
   IN  EFI_FIRMWARE_VOLUME_HEADER  *Fv,
-  OUT  EFI_PHYSICAL_ADDRESS       *PeiCoreImageBase
+  OUT  EFI_PHYSICAL_ADDRESS             *PeiCoreImageBase,
+  OUT  UINT32                           *PeiCoreImageSize
   )
 {
   EFI_STATUS                 Status;
@@ -514,6 +516,8 @@ FindPeiCoreImageBaseInFv (
   }
 
   *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);
+  // FIXME: Size check, common API?
+  *PeiCoreImageSize = SECTION_SIZE (Section) - sizeof (*Section);
   return EFI_SUCCESS;
 }
 
@@ -571,7 +575,8 @@ GetS3ResumePeiFv (
 VOID
 FindPeiCoreImageBase (
   IN OUT  EFI_FIRMWARE_VOLUME_HEADER  **BootFv,
-  OUT  EFI_PHYSICAL_ADDRESS           *PeiCoreImageBase
+     OUT  EFI_PHYSICAL_ADDRESS             *PeiCoreImageBase,
+  OUT     UINT32                           *PeiCoreImageSize
   )
 {
   BOOLEAN  S3Resume;
@@ -601,7 +606,7 @@ FindPeiCoreImageBase (
     DecompressMemFvs (BootFv);
   }
 
-  FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);
+  FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase, PeiCoreImageSize);
 }
 
 /**
@@ -611,7 +616,8 @@ FindPeiCoreImageBase (
 EFI_STATUS
 FindImageBase (
   IN  EFI_FIRMWARE_VOLUME_HEADER  *BootFirmwareVolumePtr,
-  OUT EFI_PHYSICAL_ADDRESS        *SecCoreImageBase
+  OUT EFI_PHYSICAL_ADDRESS             *SecCoreImageBase,
+  OUT UINT32                           *SecCoreImageSize
   )
 {
   EFI_PHYSICAL_ADDRESS       CurrentAddress;
@@ -623,6 +629,7 @@ FindImageBase (
   EFI_PHYSICAL_ADDRESS       EndOfSection;
 
   *SecCoreImageBase = 0;
+  *SecCoreImageSize = 0;
 
   CurrentAddress      = (EFI_PHYSICAL_ADDRESS)(UINTN)BootFirmwareVolumePtr;
   EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;
@@ -678,6 +685,7 @@ FindImageBase (
       if ((Section->Type == EFI_SECTION_PE32) || (Section->Type == EFI_SECTION_TE)) {
         if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {
           *SecCoreImageBase = (PHYSICAL_ADDRESS)(UINTN)(Section + 1);
+          *SecCoreImageSize = Size - sizeof (*Section);
         }
 
         break;
@@ -708,39 +716,45 @@ FindAndReportEntryPoints (
 {
   EFI_STATUS                    Status;
   EFI_PHYSICAL_ADDRESS          SecCoreImageBase;
+  UINT32                           SecCoreImageSize;
   EFI_PHYSICAL_ADDRESS          PeiCoreImageBase;
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
+  UINT32                           PeiCoreImageSize;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT  ImageContext;
 
   //
   // Find SEC Core and PEI Core image base
   //
-  Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);
+  Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase, &SecCoreImageSize);
   ASSERT_EFI_ERROR (Status);
 
-  FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);
+  FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase, &PeiCoreImageSize);
 
-  ZeroMem ((VOID *)&ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
   //
   // Report SEC Core debug information when remote debug is enabled
   //
-  ImageContext.ImageAddress = SecCoreImageBase;
-  ImageContext.PdbPointer   = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress);
-  PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+  Status = UefiImageInitializeContext (&ImageContext, (VOID *) (UINTN) SecCoreImageBase, SecCoreImageSize);
+  ASSERT_EFI_ERROR (Status);
 
-  //
-  // Report PEI Core debug information when remote debug is enabled
-  //
-  ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;
-  ImageContext.PdbPointer   = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress);
-  PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+  Status = UefiImageLoadImageInplace (&ImageContext);
+  ASSERT_EFI_ERROR (Status);
+
+  UefiImageLoaderRelocateImageExtraAction (&ImageContext);
 
   //
   // Find PEI Core entry point
   //
-  Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)PeiCoreImageBase, (VOID **)PeiCoreEntryPoint);
-  if (EFI_ERROR (Status)) {
-    *PeiCoreEntryPoint = 0;
-  }
+  Status = UefiImageInitializeContext (&ImageContext, (VOID *) (UINTN) PeiCoreImageBase, PeiCoreImageSize);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = UefiImageLoadImageInplace (&ImageContext);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Report PEI Core debug information when remote debug is enabled
+  //
+  UefiImageLoaderRelocateImageExtraAction (&ImageContext);
+
+  *PeiCoreEntryPoint = (EFI_PEI_CORE_ENTRY_POINT)(UINTN)(UefiImageLoaderGetImageEntryPoint (&ImageContext));
 
   return;
 }
diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf
index 4a91fb2bbb..0383c4f999 100644
--- a/OvmfPkg/Sec/SecMain.inf
+++ b/OvmfPkg/Sec/SecMain.inf
@@ -47,9 +47,8 @@
   CpuLib
   DebugAgentLib
   IoLib
-  PeCoffLib
-  PeCoffGetEntryPointLib
-  PeCoffExtraActionLib
+  UefiImageLib
+  UefiImageExtraActionLib
   ExtractGuidedSectionLib
   LocalApicLib
   MemEncryptSevLib
diff --git a/OvmfPkg/Tcg/TdTcg2Dxe/MeasureBootPeCoff.c b/OvmfPkg/Tcg/TdTcg2Dxe/MeasureBootPeCoff.c
index 4d542156ba..e6e372b6b6 100644
--- a/OvmfPkg/Tcg/TdTcg2Dxe/MeasureBootPeCoff.c
+++ b/OvmfPkg/Tcg/TdTcg2Dxe/MeasureBootPeCoff.c
@@ -19,11 +19,17 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/MemoryAllocationLib.h>
 #include <Library/DevicePathLib.h>
 #include <Library/UefiBootServicesTableLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/HashLib.h>
 
 UINTN  mTcg2DxeImageSize = 0;
 
+typedef union {
+  EFI_IMAGE_NT_HEADERS32            *Pe32;
+  EFI_IMAGE_NT_HEADERS64            *Pe32Plus;
+  EFI_IMAGE_OPTIONAL_HEADER_UNION   *Union;
+} EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION;
+
 /**
   Reads contents of a PE/COFF image in memory buffer.
 
@@ -113,25 +119,19 @@ MeasurePeImageAndExtend (
   UINT32                               NumberOfRvaAndSizes;
   UINT32                               CertSize;
   HASH_HANDLE                          HashHandle;
-  PE_COFF_LOADER_IMAGE_CONTEXT         ImageContext;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT      ImageContext;
 
   HashHandle = 0xFFFFFFFF; // Know bad value
 
   Status        = EFI_UNSUPPORTED;
   SectionHeader = NULL;
 
-  //
-  // Check PE/COFF image
-  //
-  ZeroMem (&ImageContext, sizeof (ImageContext));
-  ImageContext.Handle    = (VOID *)(UINTN)ImageAddress;
-  mTcg2DxeImageSize      = ImageSize;
-  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)Tcg2DxeImageRead;
+  mTcg2DxeImageSize = ImageSize;
 
   //
   // Get information about the image being loaded
   //
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);
+  Status = UefiImageInitializeContext (&ImageContext, (VOID *) (UINTN) ImageAddress, ImageSize);
   if (EFI_ERROR (Status)) {
     //
     // The information can't be got from the invalid PeImage
@@ -147,7 +147,7 @@ MeasurePeImageAndExtend (
   }
 
   Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *)(UINTN)ImageAddress + PeCoffHeaderOffset);
-  if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
+  if (Hdr.Pe32->CommonHeader.Signature != EFI_IMAGE_NT_SIGNATURE) {
     Status = EFI_UNSUPPORTED;
     goto Finish;
   }
@@ -179,18 +179,18 @@ MeasurePeImageAndExtend (
   // 4.  Hash the image header from its base to beginning of the image checksum.
   //
   HashBase = (UINT8 *)(UINTN)ImageAddress;
-  if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+  if (Hdr.Pe32->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
     //
     // Use PE32 offset
     //
-    NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
-    HashSize            = (UINTN)(&Hdr.Pe32->OptionalHeader.CheckSum) - (UINTN)HashBase;
+    NumberOfRvaAndSizes = Hdr.Pe32->NumberOfRvaAndSizes;
+    HashSize            = (UINTN)(&Hdr.Pe32->CheckSum) - (UINTN)HashBase;
   } else {
     //
     // Use PE32+ offset
     //
-    NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
-    HashSize            = (UINTN)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - (UINTN)HashBase;
+    NumberOfRvaAndSizes = Hdr.Pe32Plus->NumberOfRvaAndSizes;
+    HashSize            = (UINTN)(&Hdr.Pe32Plus->CheckSum) - (UINTN)HashBase;
   }
 
   Status = HashUpdate (HashHandle, HashBase, HashSize);
@@ -206,18 +206,18 @@ MeasurePeImageAndExtend (
     // 6.  Since there is no Cert Directory in optional header, hash everything
     //     from the end of the checksum to the end of image header.
     //
-    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+    if (Hdr.Pe32->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
       //
       // Use PE32 offset.
       //
-      HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
-      HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
+      HashBase = (UINT8 *)&Hdr.Pe32->CheckSum + sizeof (UINT32);
+      HashSize = Hdr.Pe32->SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
     } else {
       //
       // Use PE32+ offset.
       //
-      HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
-      HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
+      HashBase = (UINT8 *)&Hdr.Pe32Plus->CheckSum + sizeof (UINT32);
+      HashSize = Hdr.Pe32Plus->SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
     }
 
     if (HashSize != 0) {
@@ -230,18 +230,18 @@ MeasurePeImageAndExtend (
     //
     // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.
     //
-    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+    if (Hdr.Pe32->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
       //
       // Use PE32 offset
       //
-      HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
-      HashSize = (UINTN)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
+      HashBase = (UINT8 *)&Hdr.Pe32->CheckSum + sizeof (UINT32);
+      HashSize = (UINTN)(&Hdr.Pe32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
     } else {
       //
       // Use PE32+ offset
       //
-      HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
-      HashSize = (UINTN)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
+      HashBase = (UINT8 *)&Hdr.Pe32Plus->CheckSum + sizeof (UINT32);
+      HashSize = (UINTN)(&Hdr.Pe32Plus->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
     }
 
     if (HashSize != 0) {
@@ -255,18 +255,18 @@ MeasurePeImageAndExtend (
     // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
     // 9.  Hash everything from the end of the Cert Directory to the end of image header.
     //
-    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+    if (Hdr.Pe32->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
       //
       // Use PE32 offset
       //
-      HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
-      HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
+      HashBase = (UINT8 *)&Hdr.Pe32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
+      HashSize = Hdr.Pe32->SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
     } else {
       //
       // Use PE32+ offset
       //
-      HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
-      HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
+      HashBase = (UINT8 *)&Hdr.Pe32Plus->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
+      HashSize = Hdr.Pe32Plus->SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
     }
 
     if (HashSize != 0) {
@@ -280,16 +280,16 @@ MeasurePeImageAndExtend (
   //
   // 10. Set the SUM_OF_BYTES_HASHED to the size of the header
   //
-  if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+  if (Hdr.Pe32->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
     //
     // Use PE32 offset
     //
-    SumOfBytesHashed = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
+    SumOfBytesHashed = Hdr.Pe32->SizeOfHeaders;
   } else {
     //
     // Use PE32+ offset
     //
-    SumOfBytesHashed = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders;
+    SumOfBytesHashed = Hdr.Pe32Plus->SizeOfHeaders;
   }
 
   //
@@ -298,7 +298,7 @@ MeasurePeImageAndExtend (
   //     header indicates how big the table should be. Do not include any
   //     IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
   //
-  SectionHeader = (EFI_IMAGE_SECTION_HEADER *)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections);
+  SectionHeader = (EFI_IMAGE_SECTION_HEADER *)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->CommonHeader.FileHeader.NumberOfSections);
   if (SectionHeader == NULL) {
     Status = EFI_OUT_OF_RESOURCES;
     goto Finish;
@@ -315,9 +315,9 @@ MeasurePeImageAndExtend (
                                          PeCoffHeaderOffset +
                                          sizeof (UINT32) +
                                          sizeof (EFI_IMAGE_FILE_HEADER) +
-                                         Hdr.Pe32->FileHeader.SizeOfOptionalHeader
+                                         Hdr.Pe32->CommonHeader.FileHeader.SizeOfOptionalHeader
                                          );
-  for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
+  for (Index = 0; Index < Hdr.Pe32->CommonHeader.FileHeader.NumberOfSections; Index++) {
     Pos = Index;
     while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
       CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
@@ -335,7 +335,7 @@ MeasurePeImageAndExtend (
   // 14.  Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
   // 15.  Repeat steps 13 and 14 for all the sections in the sorted table.
   //
-  for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
+  for (Index = 0; Index < Hdr.Pe32->CommonHeader.FileHeader.NumberOfSections; Index++) {
     Section = (EFI_IMAGE_SECTION_HEADER *)&SectionHeader[Index];
     if (Section->SizeOfRawData == 0) {
       continue;
@@ -364,16 +364,16 @@ MeasurePeImageAndExtend (
     if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
       CertSize = 0;
     } else {
-      if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+      if (Hdr.Pe32->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
         //
         // Use PE32 offset.
         //
-        CertSize = Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
+        CertSize = Hdr.Pe32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
       } else {
         //
         // Use PE32+ offset.
         //
-        CertSize = Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
+        CertSize = Hdr.Pe32Plus->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
       }
     }
 
diff --git a/OvmfPkg/Tcg/TdTcg2Dxe/TdTcg2Dxe.inf b/OvmfPkg/Tcg/TdTcg2Dxe/TdTcg2Dxe.inf
index 0c2d116cc7..9c019fdb1d 100644
--- a/OvmfPkg/Tcg/TdTcg2Dxe/TdTcg2Dxe.inf
+++ b/OvmfPkg/Tcg/TdTcg2Dxe/TdTcg2Dxe.inf
@@ -47,7 +47,7 @@
   HashLib
   PerformanceLib
   ReportStatusCodeLib
-  PeCoffLib
+  UefiImageLib
   TpmMeasurementLib
   TdxLib
   TdxMeasurementLib
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000..efa9528d4d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,71 @@
+# PE/COFF loader designed with formal methods
+
+This branch demonstrates the integration of a new PE/COFF loader designed with the help of formal methods into the EDK II infrastructure.
+
+## Introduction
+
+The PE/COFF loader is one of the central components of the firmware core and its trust base. Every Image which is part of a UEFI system, including platform drivers from the primary firmware storage, Option ROMs from external hardware, and OS loaders from arbitrary storage, is verified and loaded by this library. Clearly it is a key component to ensure platform reliability and software compatibility, and can only be modified with great care. It also is an essential component for security technologies such as Secure Boot and Measured Boot.
+
+![image](LoaderFlow.png)
+
+Unfortunately, over the years, the current solution has been subject to bug reports affecting platform reliability, some of which have been unresolved to date. Please refer to the TianoCore BugZilla and especially discussions on the edk2-devel mailing list for further reading. Due to the incremental changes to the existing solution over the years, the state of a sound solution has been lost, and it has become a maintenance burden that is hard to fix and further advance incrementally. At the same time, the demand on not only tested but proven security has become more important in the recent times.
+
+The usage of formal methods to design the new solution greatly helped restore the state of a truly sound solution, resolving many issues regarding inter-API guarantees and Image format validation. Many new abstractions have been introduced, external code has been centralized, and the overall flexibility has been improved, to hopefully aid developers to extend the codebase more easily in the future. Beyond that, the formal model ensures a high level of confidence that security-wise there have been no regressions, and there might even be potential improvements.
+
+Please also refer to the new work-in-progress documentation available at [MdePkg/Library/BasePeCoffLib2/Documentation.md](MdePkg/Library/BasePeCoffLib2/Documentation.md)
+
+## Further abstraction
+
+The new solution has been implemented as a new library class in MdePkg. ``PeCoffLib2`` features a new API that allows for a more resilient and a more flexible caller design. Most notably, all Image operations have been integrated into the API design rather than the callers accessing the library context and duplicating certain work. ``PeCoffLib`` remains intact as deprecated API to support legacy code during the transition period.
+
+To increase platform flexibility, a new layer of abstraction is introduced in the form of the library class ``UefiImageLib``, which can be found at [MdePkg/Include/Library/UefiImageLib.h](MdePkg/Include/Library/UefiImageLib.h). Currently, it is a subset of the APIs provided by ``PeCoffLib2`` that is expected to be compatible with most other common executable formats, plus a few convenience functions. As part of the proposal, the instance ``UefiImageLibPeCoff`` is provided, which is basically a shim for ``PeCoffLib2``. In the future, instances to support other file formats can be introduced without having to integrate them across the entire EDK II tree.
+
+## Issues of the current solution
+* High level of maintenance cost due to convoluted function contracts
+* Error-prone design promoting the introduction of code bugs
+* Multiple real-world bugs affecting reliability, some unaddressed for years
+* A lot of duplicate caller-side code that decreases the flexibility of porting and integration (e.g. Image permissions in PEI)
+* Dependency on Image re-parsing for production code
+
+## Benefits of the new solution
+* Fixes all known reported BugZilla tickets on PE/COFF loader reliability
+* Formal methods increase confidence in a high level of reliability and security
+* Improved design eases future maintenance and extension
+* Architecture-independent Image processing (e.g. for emulation)
+* Support for more granular Image section permissions (e.g. read-only)
+
+## Benefits of the formal methods involved
+* Complete proof arithmetic cannot overflow (excluding intentional modulo arithmetic)
+* Mostly complete proof memory accesses are safe (requires axioms)
+* Complete proof of Image format compliance verification
+* Complete proof of Image loading
+* Mostly complete proof of Image relocation (final memory state cannot be easily described)
+
+## Further notes about the formal approach
+* A snapshot of the new PE/COFF loader code will be provided with annotations and proving results
+* The snapshot will not be current and updating the old code is out of the scope of this project, however the functional changes should be manageable to review
+* We are currently investigating whether deploying the proving environment as a Docker container is feasible
+* There may be aids to compare the updates over the last fully verified state (e.g. stripped versions of the code with diffs)
+* If accepted, the new PE/COFF loader code should be developed further without updating the formal annotations, but with thorough review of important invariants and sufficient documentation
+
+## Current progress, future goals, and further notes
+* OVMF boots to Shell with SMM and Secure Boot enabled
+* Linux EmulatorPkg boots
+* Extended support for Image protection has been implemented
+* FFS and DebugTable enhancements have been implemented
+* Not all features have been implemented, e.g. RISC-V support
+* There are unrelated changes present to help testing and validation
+* Specified interfaces need adjustments (e.g. security architectural protocol)
+* Some validation is still absent
+
+## BZs fixed by integrating the new PE/COFF loader
+* https://bugzilla.tianocore.org/show_bug.cgi?id=1860
+* https://bugzilla.tianocore.org/show_bug.cgi?id=1999
+* https://bugzilla.tianocore.org/show_bug.cgi?id=2120
+* https://bugzilla.tianocore.org/show_bug.cgi?id=3329
+* More to be added shortly...
+
+## BZs easier to address by integrating the new PE/COFF loader
+* https://bugzilla.tianocore.org/show_bug.cgi?id=3326
+* https://bugzilla.tianocore.org/show_bug.cgi?id=3331
+* More to be added shortly...
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf
index 5e91968576..11e65bc739 100644
--- a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf
@@ -43,3 +43,8 @@
   BaseCryptLib
   RngLib
   MemLibWrapper
+
+[BuildOptions]
+  CLANGPDB:*_*_*_CC_FLAGS = -Wno-non-literal-null-conversion
+  GCC:*_*_*_CC_FLAGS      = -Wno-non-literal-null-conversion
+  XCODE:*_*_*_CC_FLAGS    = -Wno-non-literal-null-conversion
diff --git a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmAuthentication.c b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmAuthentication.c
index 86cf9b225c..3852025ec4 100644
--- a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmAuthentication.c
+++ b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmAuthentication.c
@@ -136,9 +136,9 @@ ExtendCertificate (
 
   EventLog = NULL;
   ZeroMem (&Parameter, sizeof (Parameter));
-  Parameter.location = SpdmDataLocationConnection;
+  Parameter.location = (libspdm_data_location_t)SpdmDataLocationConnection;
   DataSize           = sizeof (BaseHashAlgo);
-  Status             = SpdmGetData (SpdmContext, SpdmDataBaseHashAlgo, &Parameter, &BaseHashAlgo, &DataSize);
+  Status             = SpdmGetData (SpdmContext, (libspdm_data_type_t)SpdmDataBaseHashAlgo, &Parameter, &BaseHashAlgo, &DataSize);
   ASSERT_EFI_ERROR (Status);
 
   DeviceContextSize = GetDeviceMeasurementContextSize (SpdmDeviceContext);
@@ -520,9 +520,9 @@ DoDeviceCertificate (
   SpdmContext = SpdmDeviceContext->SpdmContext;
 
   ZeroMem (&Parameter, sizeof (Parameter));
-  Parameter.location = SpdmDataLocationConnection;
+  Parameter.location = (libspdm_data_location_t)SpdmDataLocationConnection;
   DataSize           = sizeof (CapabilityFlags);
-  SpdmReturn         = SpdmGetData (SpdmContext, SpdmDataCapabilityFlags, &Parameter, &CapabilityFlags, &DataSize);
+  SpdmReturn         = SpdmGetData (SpdmContext, (libspdm_data_type_t)SpdmDataCapabilityFlags, &Parameter, &CapabilityFlags, &DataSize);
   if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
     SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
     return EFI_DEVICE_ERROR;
@@ -641,9 +641,9 @@ DoDeviceAuthentication (
   SpdmContext = SpdmDeviceContext->SpdmContext;
 
   ZeroMem (&Parameter, sizeof (Parameter));
-  Parameter.location = SpdmDataLocationConnection;
+  Parameter.location = (libspdm_data_location_t)SpdmDataLocationConnection;
   DataSize           = sizeof (CapabilityFlags);
-  SpdmReturn         = SpdmGetData (SpdmContext, SpdmDataCapabilityFlags, &Parameter, &CapabilityFlags, &DataSize);
+  SpdmReturn         = SpdmGetData (SpdmContext, (libspdm_data_type_t)SpdmDataCapabilityFlags, &Parameter, &CapabilityFlags, &DataSize);
   if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
     SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
     return EFI_DEVICE_ERROR;
diff --git a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmConnectionInit.c b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmConnectionInit.c
index d61aa01698..962e906e4e 100644
--- a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmConnectionInit.c
+++ b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmConnectionInit.c
@@ -338,8 +338,8 @@ CreateSpdmDeviceContext (
         DataSize = DbList->SignatureSize - sizeof (EFI_GUID);
 
         ZeroMem (&Parameter, sizeof (Parameter));
-        Parameter.location = SpdmDataLocationLocal;
-        SpdmReturn         = SpdmSetData (SpdmContext, SpdmDataPeerPublicRootCert, &Parameter, Data, DataSize);
+        Parameter.location = (libspdm_data_location_t)SpdmDataLocationLocal;
+        SpdmReturn         = SpdmSetData (SpdmContext, (libspdm_data_type_t)SpdmDataPeerPublicRootCert, &Parameter, Data, DataSize);
         if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
           if (SpdmReturn == LIBSPDM_STATUS_BUFFER_FULL) {
             Status = RecordConnectionFailureStatus (
@@ -366,22 +366,22 @@ CreateSpdmDeviceContext (
 
   Data8 = 0;
   ZeroMem (&Parameter, sizeof (Parameter));
-  Parameter.location = SpdmDataLocationLocal;
-  SpdmReturn         = SpdmSetData (SpdmContext, SpdmDataCapabilityCTExponent, &Parameter, &Data8, sizeof (Data8));
+  Parameter.location = (libspdm_data_location_t)SpdmDataLocationLocal;
+  SpdmReturn         = SpdmSetData (SpdmContext, (libspdm_data_type_t)SpdmDataCapabilityCTExponent, &Parameter, &Data8, sizeof (Data8));
   if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
     ASSERT (FALSE);
     goto Error;
   }
 
   Data32     = 0;
-  SpdmReturn = SpdmSetData (SpdmContext, SpdmDataCapabilityFlags, &Parameter, &Data32, sizeof (Data32));
+  SpdmReturn = SpdmSetData (SpdmContext, (libspdm_data_type_t)SpdmDataCapabilityFlags, &Parameter, &Data32, sizeof (Data32));
   if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
     ASSERT (FALSE);
     goto Error;
   }
 
   Data8      = SPDM_MEASUREMENT_SPECIFICATION_DMTF;
-  SpdmReturn = SpdmSetData (SpdmContext, SpdmDataMeasurementSpec, &Parameter, &Data8, sizeof (Data8));
+  SpdmReturn = SpdmSetData (SpdmContext, (libspdm_data_type_t)SpdmDataMeasurementSpec, &Parameter, &Data8, sizeof (Data8));
   if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
     ASSERT (FALSE);
     goto Error;
@@ -398,7 +398,7 @@ CreateSpdmDeviceContext (
              SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521;
   }
 
-  SpdmReturn = SpdmSetData (SpdmContext, SpdmDataBaseAsymAlgo, &Parameter, &Data32, sizeof (Data32));
+  SpdmReturn = SpdmSetData (SpdmContext, (libspdm_data_type_t)SpdmDataBaseAsymAlgo, &Parameter, &Data32, sizeof (Data32));
   if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
     ASSERT (FALSE);
     goto Error;
@@ -412,7 +412,7 @@ CreateSpdmDeviceContext (
              SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_512;
   }
 
-  SpdmReturn = SpdmSetData (SpdmContext, SpdmDataBaseHashAlgo, &Parameter, &Data32, sizeof (Data32));
+  SpdmReturn = SpdmSetData (SpdmContext, (libspdm_data_type_t)SpdmDataBaseHashAlgo, &Parameter, &Data32, sizeof (Data32));
   if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
     ASSERT (FALSE);
     goto Error;
@@ -433,9 +433,9 @@ CreateSpdmDeviceContext (
   }
 
   ZeroMem (&Parameter, sizeof (Parameter));
-  Parameter.location = SpdmDataLocationConnection;
+  Parameter.location = (libspdm_data_location_t)SpdmDataLocationConnection;
   DataSize           = sizeof (Data16);
-  SpdmReturn         = SpdmGetData (SpdmContext, SpdmDataSpdmVersion, &Parameter, &Data16, &DataSize);
+  SpdmReturn         = SpdmGetData (SpdmContext, (libspdm_data_type_t)SpdmDataSpdmVersion, &Parameter, &Data16, &DataSize);
   if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
     DEBUG ((DEBUG_ERROR, "SpdmGetData - %p\n", SpdmReturn));
     goto Error;
diff --git a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmMeasurement.c b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmMeasurement.c
index f94ec1e7bf..3eb33292bd 100644
--- a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmMeasurement.c
+++ b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmMeasurement.c
@@ -209,9 +209,9 @@ ExtendMeasurement (
 
   EventLog = NULL;
   ZeroMem (&Parameter, sizeof (Parameter));
-  Parameter.location = SpdmDataLocationConnection;
+  Parameter.location = (libspdm_data_location_t)SpdmDataLocationConnection;
   DataSize           = sizeof (MeasurementHashAlgo);
-  Status             = SpdmGetData (SpdmContext, SpdmDataMeasurementHashAlgo, &Parameter, &MeasurementHashAlgo, &DataSize);
+  Status             = SpdmGetData (SpdmContext, (libspdm_data_type_t)SpdmDataMeasurementHashAlgo, &Parameter, &MeasurementHashAlgo, &DataSize);
   ASSERT_EFI_ERROR (Status);
 
   if (MeasurementRecord != NULL) {
@@ -531,9 +531,9 @@ DoDeviceMeasurement (
   SpdmContext = SpdmDeviceContext->SpdmContext;
 
   ZeroMem (&Parameter, sizeof (Parameter));
-  Parameter.location = SpdmDataLocationConnection;
+  Parameter.location = (libspdm_data_location_t)SpdmDataLocationConnection;
   DataSize           = sizeof (CapabilityFlags);
-  SpdmGetData (SpdmContext, SpdmDataCapabilityFlags, &Parameter, &CapabilityFlags, &DataSize);
+  SpdmGetData (SpdmContext, (libspdm_data_type_t)SpdmDataCapabilityFlags, &Parameter, &CapabilityFlags, &DataSize);
 
   if ((CapabilityFlags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP_SIG) == 0) {
     AuthState                       = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_NO_SIG;
diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
index b05da19c2b..3ac202a32b 100644
--- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
+++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
@@ -19,22 +19,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 **/
 
 #include "DxeImageVerificationLib.h"
-
-//
-// Caution: This is used by a function which may receive untrusted input.
-// These global variables hold PE/COFF image data, and they should be validated before use.
-//
-EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  mNtHeader;
-UINT32                               mPeCoffHeaderOffset;
-EFI_GUID                             mCertType;
-
-//
-// Information on current PE/COFF image
-//
-UINTN  mImageSize;
-UINT8  *mImageBase = NULL;
-UINT8  mImageDigest[MAX_DIGEST_SIZE];
-UINTN  mImageDigestSize;
+#include "Library/BaseCryptLib.h"
+#include "Library/UefiImageLib.h"
 
 //
 // Notify string for authorization UI.
@@ -57,19 +43,23 @@ UINT8  mHashOidValue[] = {
   0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
 };
 
-HASH_TABLE  mHash[] = {
- #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
-  { L"SHA1",   20, &mHashOidValue[0],  5, Sha1GetContextSize,   Sha1Init,   Sha1Update,   Sha1Final   },
- #else
-  { L"SHA1",   20, &mHashOidValue[0],  5, NULL,                 NULL,       NULL,         NULL        },
- #endif
-  { L"SHA224", 28, &mHashOidValue[5],  9, NULL,                 NULL,       NULL,         NULL        },
-  { L"SHA256", 32, &mHashOidValue[14], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final },
-  { L"SHA384", 48, &mHashOidValue[23], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final },
-  { L"SHA512", 64, &mHashOidValue[32], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final }
-};
+//
+//  Support hash types
+//
+#define HASHALG_SHA256  0x00000000
+#define HASHALG_SHA384  0x00000001
+#define HASHALG_SHA512  0x00000002
+#define HASHALG_SHA1    0x00000003
+#define HASHALG_MAX     0x00000004
 
-EFI_STRING  mHashTypeStr;
+HASH_TABLE mHash[] = {
+  { L"SHA256", 32, &mHashOidValue[14], 9, &gEfiCertSha256Guid, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final },
+  { L"SHA384", 48, &mHashOidValue[23], 9, &gEfiCertSha384Guid, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final },
+  { L"SHA512", 64, &mHashOidValue[32], 9, &gEfiCertSha512Guid, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final },
+#ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
+  { L"SHA1",   20, &mHashOidValue[0],  5, &gEfiCertSha1Guid, Sha1GetContextSize,   Sha1Init,   Sha1Update,   Sha1Final  },
+#endif
+};
 
 /**
   SecureBoot Hook for processing image verification.
@@ -90,54 +80,6 @@ SecureBootHook (
   IN VOID      *Data
   );
 
-/**
-  Reads contents of a PE/COFF image in memory buffer.
-
-  Caution: This function may receive untrusted input.
-  PE/COFF image is external input, so this function will make sure the PE/COFF image content
-  read is within the image buffer.
-
-  @param  FileHandle      Pointer to the file handle to read the PE/COFF image.
-  @param  FileOffset      Offset into the PE/COFF image to begin the read operation.
-  @param  ReadSize        On input, the size in bytes of the requested read operation.
-                          On output, the number of bytes actually read.
-  @param  Buffer          Output buffer that contains the data read from the PE/COFF image.
-
-  @retval EFI_SUCCESS     The specified portion of the PE/COFF image was read and the size
-**/
-EFI_STATUS
-EFIAPI
-DxeImageVerificationLibImageRead (
-  IN     VOID   *FileHandle,
-  IN     UINTN  FileOffset,
-  IN OUT UINTN  *ReadSize,
-  OUT    VOID   *Buffer
-  )
-{
-  UINTN  EndPosition;
-
-  if ((FileHandle == NULL) || (ReadSize == NULL) || (Buffer == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (MAX_ADDRESS - FileOffset < *ReadSize) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  EndPosition = FileOffset + *ReadSize;
-  if (EndPosition > mImageSize) {
-    *ReadSize = (UINT32)(mImageSize - FileOffset);
-  }
-
-  if (FileOffset >= mImageSize) {
-    *ReadSize = 0;
-  }
-
-  CopyMem (Buffer, (UINT8 *)((UINTN)FileHandle + FileOffset), *ReadSize);
-
-  return EFI_SUCCESS;
-}
-
 /**
   Get the image type.
 
@@ -279,7 +221,7 @@ GetImageType (
   PE/COFF image is external input, so this function will validate its data structure
   within this image buffer before use.
 
-  Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
+  Notes: PE/COFF image has been checked by UefiImageLibLib UefiImageInitializeContext() in
   its caller function DxeImageVerificationHandler().
 
   @param[in]    HashAlg   Hash algorithm type.
@@ -290,318 +232,54 @@ GetImageType (
 **/
 BOOLEAN
 HashPeImage (
-  IN  UINT32  HashAlg
+  IN  UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext,
+  IN  HASH_TABLE                       *HashAlg,
+  OUT UINT8                            ImageDigest[MAX_DIGEST_SIZE],
+  OUT UINTN                            *ImageDigestSize
   )
 {
-  BOOLEAN                   Status;
-  EFI_IMAGE_SECTION_HEADER  *Section;
-  VOID                      *HashCtx;
-  UINTN                     CtxSize;
-  UINT8                     *HashBase;
-  UINTN                     HashSize;
-  UINTN                     SumOfBytesHashed;
-  EFI_IMAGE_SECTION_HEADER  *SectionHeader;
-  UINTN                     Index;
-  UINTN                     Pos;
-  UINT32                    CertSize;
-  UINT32                    NumberOfRvaAndSizes;
+  BOOLEAN  Status;
+  VOID     *HashCtx;
+  UINTN    CtxSize;
 
-  HashCtx       = NULL;
-  SectionHeader = NULL;
-  Status        = FALSE;
-
-  if ((HashAlg >= HASHALG_MAX)) {
-    return FALSE;
-  }
+  HashCtx = NULL;
+  Status  = FALSE;
 
   //
   // Initialize context of hash.
   //
-  ZeroMem (mImageDigest, MAX_DIGEST_SIZE);
+  ZeroMem (ImageDigest, MAX_DIGEST_SIZE);
 
-  switch (HashAlg) {
- #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
-    case HASHALG_SHA1:
-      mImageDigestSize = SHA1_DIGEST_SIZE;
-      mCertType        = gEfiCertSha1Guid;
-      break;
- #endif
-
-    case HASHALG_SHA256:
-      mImageDigestSize = SHA256_DIGEST_SIZE;
-      mCertType        = gEfiCertSha256Guid;
-      break;
-
-    case HASHALG_SHA384:
-      mImageDigestSize = SHA384_DIGEST_SIZE;
-      mCertType        = gEfiCertSha384Guid;
-      break;
-
-    case HASHALG_SHA512:
-      mImageDigestSize = SHA512_DIGEST_SIZE;
-      mCertType        = gEfiCertSha512Guid;
-      break;
-
-    default:
-      return FALSE;
-  }
-
-  mHashTypeStr = mHash[HashAlg].Name;
-  CtxSize      = mHash[HashAlg].GetContextSize ();
+  CtxSize = HashAlg->GetContextSize ();
 
   HashCtx = AllocatePool (CtxSize);
   if (HashCtx == NULL) {
     return FALSE;
   }
 
-  // 1.  Load the image header into memory.
-
-  // 2.  Initialize a SHA hash context.
-  Status = mHash[HashAlg].HashInit (HashCtx);
+  Status = HashAlg->HashInit (HashCtx);
 
   if (!Status) {
     goto Done;
   }
 
-  //
-  // Measuring PE/COFF Image Header;
-  // But CheckSum field and SECURITY data directory (certificate) are excluded
-  //
+  Status = UefiImageHashImageDefault (ImageContext, HashCtx, HashAlg->HashUpdate);
 
-  //
-  // 3.  Calculate the distance from the base of the image header to the image checksum address.
-  // 4.  Hash the image header from its base to beginning of the image checksum.
-  //
-  HashBase = mImageBase;
-  if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-    //
-    // Use PE32 offset.
-    //
-    HashSize            = (UINTN)(&mNtHeader.Pe32->OptionalHeader.CheckSum) - (UINTN)HashBase;
-    NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;
-  } else if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
-    //
-    // Use PE32+ offset.
-    //
-    HashSize            = (UINTN)(&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - (UINTN)HashBase;
-    NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
-  } else {
-    //
-    // Invalid header magic number.
-    //
-    Status = FALSE;
-    goto Done;
-  }
-
-  Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
   if (!Status) {
+    DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Failed to hash this image using %s.\n", HashAlg->Name));
     goto Done;
   }
 
-  //
-  // 5.  Skip over the image checksum (it occupies a single ULONG).
-  //
-  if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
-    //
-    // 6.  Since there is no Cert Directory in optional header, hash everything
-    //     from the end of the checksum to the end of image header.
-    //
-    if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-      //
-      // Use PE32 offset.
-      //
-      HashBase = (UINT8 *)&mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
-      HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - ((UINTN)HashBase - (UINTN)mImageBase);
-    } else {
-      //
-      // Use PE32+ offset.
-      //
-      HashBase = (UINT8 *)&mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
-      HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - ((UINTN)HashBase - (UINTN)mImageBase);
-    }
+  ASSERT (HashAlg->DigestLength <= MAX_DIGEST_SIZE);
+  Status = HashAlg->HashFinal(HashCtx, ImageDigest);
 
-    if (HashSize != 0) {
-      Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
-      if (!Status) {
-        goto Done;
-      }
-    }
-  } else {
-    //
-    // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.
-    //
-    if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-      //
-      // Use PE32 offset.
-      //
-      HashBase = (UINT8 *)&mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
-      HashSize = (UINTN)(&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
-    } else {
-      //
-      // Use PE32+ offset.
-      //
-      HashBase = (UINT8 *)&mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
-      HashSize = (UINTN)(&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
-    }
-
-    if (HashSize != 0) {
-      Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
-      if (!Status) {
-        goto Done;
-      }
-    }
-
-    //
-    // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
-    // 9.  Hash everything from the end of the Cert Directory to the end of image header.
-    //
-    if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-      //
-      // Use PE32 offset
-      //
-      HashBase = (UINT8 *)&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
-      HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - ((UINTN)HashBase - (UINTN)mImageBase);
-    } else {
-      //
-      // Use PE32+ offset.
-      //
-      HashBase = (UINT8 *)&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
-      HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - ((UINTN)HashBase - (UINTN)mImageBase);
-    }
-
-    if (HashSize != 0) {
-      Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
-      if (!Status) {
-        goto Done;
-      }
-    }
-  }
-
-  //
-  // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
-  //
-  if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-    //
-    // Use PE32 offset.
-    //
-    SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;
-  } else {
-    //
-    // Use PE32+ offset
-    //
-    SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;
-  }
-
-  Section = (EFI_IMAGE_SECTION_HEADER *)(
-                                         mImageBase +
-                                         mPeCoffHeaderOffset +
-                                         sizeof (UINT32) +
-                                         sizeof (EFI_IMAGE_FILE_HEADER) +
-                                         mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader
-                                         );
-
-  //
-  // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
-  //     structures in the image. The 'NumberOfSections' field of the image
-  //     header indicates how big the table should be. Do not include any
-  //     IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
-  //
-  SectionHeader = (EFI_IMAGE_SECTION_HEADER *)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);
-  if (SectionHeader == NULL) {
-    Status = FALSE;
-    goto Done;
-  }
-
-  //
-  // 12.  Using the 'PointerToRawData' in the referenced section headers as
-  //      a key, arrange the elements in the table in ascending order. In other
-  //      words, sort the section headers according to the disk-file offset of
-  //      the section.
-  //
-  for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
-    Pos = Index;
-    while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
-      CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
-      Pos--;
-    }
-
-    CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
-    Section += 1;
-  }
-
-  //
-  // 13.  Walk through the sorted table, bring the corresponding section
-  //      into memory, and hash the entire section (using the 'SizeOfRawData'
-  //      field in the section header to determine the amount of data to hash).
-  // 14.  Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
-  // 15.  Repeat steps 13 and 14 for all the sections in the sorted table.
-  //
-  for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
-    Section = &SectionHeader[Index];
-    if (Section->SizeOfRawData == 0) {
-      continue;
-    }
-
-    HashBase = mImageBase + Section->PointerToRawData;
-    HashSize = (UINTN)Section->SizeOfRawData;
-
-    Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
-    if (!Status) {
-      goto Done;
-    }
-
-    SumOfBytesHashed += HashSize;
-  }
-
-  //
-  // 16.  If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
-  //      data in the file that needs to be added to the hash. This data begins
-  //      at file offset SUM_OF_BYTES_HASHED and its length is:
-  //             FileSize  -  (CertDirectory->Size)
-  //
-  if (mImageSize > SumOfBytesHashed) {
-    HashBase = mImageBase + SumOfBytesHashed;
-
-    if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
-      CertSize = 0;
-    } else {
-      if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-        //
-        // Use PE32 offset.
-        //
-        CertSize = mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
-      } else {
-        //
-        // Use PE32+ offset.
-        //
-        CertSize = mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
-      }
-    }
-
-    if (mImageSize > CertSize + SumOfBytesHashed) {
-      HashSize = (UINTN)(mImageSize - CertSize - SumOfBytesHashed);
-
-      Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
-      if (!Status) {
-        goto Done;
-      }
-    } else if (mImageSize < CertSize + SumOfBytesHashed) {
-      Status = FALSE;
-      goto Done;
-    }
-  }
-
-  Status = mHash[HashAlg].HashFinal (HashCtx, mImageDigest);
+  *ImageDigestSize = HashAlg->DigestLength;
 
 Done:
   if (HashCtx != NULL) {
     FreePool (HashCtx);
   }
 
-  if (SectionHeader != NULL) {
-    FreePool (SectionHeader);
-  }
-
   return Status;
 }
 
@@ -623,34 +301,38 @@ Done:
 **/
 EFI_STATUS
 HashPeImageByType (
-  IN UINT8  *AuthData,
-  IN UINTN  AuthDataSize
+  IN  UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext,
+  IN  CONST UINT8                      *AuthData,
+  IN  UINTN                            AuthDataSize,
+  OUT UINT8                            ImageDigest[MAX_DIGEST_SIZE],
+  OUT UINTN                            *ImageDigestSize,
+  OUT CONST EFI_GUID                   **CertType
   )
 {
   UINT8  Index;
 
-  for (Index = 0; Index < HASHALG_MAX; Index++) {
+  //
+  // Check the Hash algorithm in PE/COFF Authenticode.
+  //    According to PKCS#7 Definition:
+  //        SignedData ::= SEQUENCE {
+  //            version Version,
+  //            digestAlgorithms DigestAlgorithmIdentifiers,
+  //            contentInfo ContentInfo,
+  //            .... }
+  //    The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
+  //    This field has the fixed offset (+32) in final Authenticode ASN.1 data.
+  //    Fixed offset (+32) is calculated based on two bytes of length encoding.
+  //
+  if ((*(AuthData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
     //
-    // Check the Hash algorithm in PE/COFF Authenticode.
-    //    According to PKCS#7 Definition:
-    //        SignedData ::= SEQUENCE {
-    //            version Version,
-    //            digestAlgorithms DigestAlgorithmIdentifiers,
-    //            contentInfo ContentInfo,
-    //            .... }
-    //    The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
-    //    This field has the fixed offset (+32) in final Authenticode ASN.1 data.
-    //    Fixed offset (+32) is calculated based on two bytes of length encoding.
+    // Only support two bytes of Long Form of Length Encoding.
     //
-    if ((*(AuthData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
-      //
-      // Only support two bytes of Long Form of Length Encoding.
-      //
-      continue;
-    }
+    return EFI_UNSUPPORTED;
+  }
 
+  for (Index = 0; Index < HASHALG_MAX; Index++) {
     if (AuthDataSize < 32 + mHash[Index].OidLength) {
-      return EFI_UNSUPPORTED;
+      continue;
     }
 
     if (CompareMem (AuthData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {
@@ -665,10 +347,12 @@ HashPeImageByType (
   //
   // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
   //
-  if (!HashPeImage (Index)) {
+  if (!HashPeImage (ImageContext, &mHash[Index], ImageDigest, ImageDigestSize)) {
     return EFI_UNSUPPORTED;
   }
 
+  *CertType = mHash[Index].CertType;
+
   return EFI_SUCCESS;
 }
 
@@ -911,15 +595,15 @@ IsCertHashFoundInDbx (
       goto Done;
     }
 
-    if (!mHash[HashAlg].HashInit (HashCtx)) {
+    if (EFI_ERROR(mHash[HashAlg].HashInit (HashCtx))) {
       goto Done;
     }
 
-    if (!mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize)) {
+    if (EFI_ERROR(mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize))) {
       goto Done;
     }
 
-    if (!mHash[HashAlg].HashFinal (HashCtx, CertDigest)) {
+    if (EFI_ERROR(mHash[HashAlg].HashFinal (HashCtx, CertDigest))) {
       goto Done;
     }
 
@@ -980,11 +664,11 @@ Done:
 **/
 EFI_STATUS
 IsSignatureFoundInDatabase (
-  IN  CHAR16    *VariableName,
-  IN  UINT8     *Signature,
-  IN  EFI_GUID  *CertType,
-  IN  UINTN     SignatureSize,
-  OUT BOOLEAN   *IsFound
+  IN  CHAR16          *VariableName,
+  IN  UINT8           *Signature,
+  IN  CONST EFI_GUID  *CertType,
+  IN  UINTN           SignatureSize,
+  OUT BOOLEAN         *IsFound
   )
 {
   EFI_STATUS          Status;
@@ -1137,9 +821,9 @@ IsTimeZero (
 **/
 BOOLEAN
 PassTimestampCheck (
-  IN UINT8     *AuthData,
-  IN UINTN     AuthDataSize,
-  IN EFI_TIME  *RevocationTime
+  IN CONST UINT8  *AuthData,
+  IN UINTN        AuthDataSize,
+  IN EFI_TIME     *RevocationTime
   )
 {
   EFI_STATUS          Status;
@@ -1244,8 +928,10 @@ Done:
 **/
 BOOLEAN
 IsForbiddenByDbx (
-  IN UINT8  *AuthData,
-  IN UINTN  AuthDataSize
+  IN CONST UINT8            *AuthData,
+  IN UINTN                  AuthDataSize,
+  UINT8                         ImageDigest[MAX_DIGEST_SIZE],
+  UINTN                         ImageDigestSize
   )
 {
   EFI_STATUS          Status;
@@ -1338,8 +1024,8 @@ IsForbiddenByDbx (
                         AuthDataSize,
                         RootCert,
                         RootCertSize,
-                        mImageDigest,
-                        mImageDigestSize
+                        ImageDigest,
+                        ImageDigestSize
                         );
         if (IsForbidden) {
           DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature is forbidden by DBX.\n"));
@@ -1440,8 +1126,10 @@ Done:
 **/
 BOOLEAN
 IsAllowedByDb (
-  IN UINT8  *AuthData,
-  IN UINTN  AuthDataSize
+  IN  CONST UINT8  *AuthData,
+  IN  UINTN        AuthDataSize,
+  OUT UINT8        ImageDigest[MAX_DIGEST_SIZE],
+  OUT UINTN        ImageDigestSize
   )
 {
   EFI_STATUS          Status;
@@ -1543,8 +1231,8 @@ IsAllowedByDb (
                          AuthDataSize,
                          RootCert,
                          RootCertSize,
-                         mImageDigest,
-                         mImageDigestSize
+                         ImageDigest,
+                         ImageDigestSize
                          );
         if (VerifyStatus) {
           //
@@ -1663,28 +1351,16 @@ DxeImageVerificationHandler (
   IN  BOOLEAN                         BootPolicy
   )
 {
-  EFI_IMAGE_DOS_HEADER          *DosHdr;
   BOOLEAN                       IsVerified;
   EFI_SIGNATURE_LIST            *SignatureList;
   UINTN                         SignatureListSize;
   EFI_SIGNATURE_DATA            *Signature;
   EFI_IMAGE_EXECUTION_ACTION    Action;
-  WIN_CERTIFICATE               *WinCertificate;
   UINT32                        Policy;
   UINT8                         SecureBoot;
   UINTN                         SecureBootSize;
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
-  UINT32                        NumberOfRvaAndSizes;
-  WIN_CERTIFICATE_EFI_PKCS      *PkcsCertData;
-  WIN_CERTIFICATE_UEFI_GUID     *WinCertUefiGuid;
-  UINT8                         *AuthData;
   UINTN                         AuthDataSize;
-  EFI_IMAGE_DATA_DIRECTORY      *SecDataDir;
-  UINT32                        SecDataDirEnd;
-  UINT32                        SecDataDirLeft;
-  UINT32                        OffSet;
   CHAR16                        *NameStr;
-  RETURN_STATUS                 PeCoffStatus;
   EFI_STATUS                    HashStatus;
   EFI_STATUS                    DbStatus;
   EFI_STATUS                    VarStatus;
@@ -1693,16 +1369,29 @@ DxeImageVerificationHandler (
   UINT8                         HashAlg;
   BOOLEAN                       IsFoundInDatabase;
 
+  CONST WIN_CERTIFICATE            *WinCertificate;
+  CONST WIN_CERTIFICATE_EFI_PKCS   *PkcsCertData;
+  CONST WIN_CERTIFICATE_UEFI_GUID  *WinCertUefiGuid;
+  CONST UINT8                      *AuthData;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext;
+
+  UINT8                            ImageDigest[MAX_DIGEST_SIZE];
+  UINTN                            ImageDigestSize;
+  CONST EFI_GUID                   *CertType;
+
   SignatureList     = NULL;
   SignatureListSize = 0;
   WinCertificate    = NULL;
-  SecDataDir        = NULL;
   PkcsCertData      = NULL;
   Action            = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
   IsVerified        = FALSE;
   IsFound           = FALSE;
   IsFoundInDatabase = FALSE;
 
+  // FIXME:
+  ASSERT (FileSize == sizeof (UEFI_IMAGE_LOADER_IMAGE_CONTEXT));
+  ImageContext = FileBuffer;
+
   //
   // Check the image type and get policy setting.
   //
@@ -1775,70 +1464,12 @@ DxeImageVerificationHandler (
     return EFI_ACCESS_DENIED;
   }
 
-  mImageBase = (UINT8 *)FileBuffer;
-  mImageSize = FileSize;
-
-  ZeroMem (&ImageContext, sizeof (ImageContext));
-  ImageContext.Handle    = (VOID *)FileBuffer;
-  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)DxeImageVerificationLibImageRead;
-
-  //
-  // Get information about the image being loaded
-  //
-  PeCoffStatus = PeCoffLoaderGetImageInfo (&ImageContext);
-  if (RETURN_ERROR (PeCoffStatus)) {
-    //
-    // The information can't be got from the invalid PeImage
-    //
-    DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: PeImage invalid. Cannot retrieve image information.\n"));
-    goto Failed;
-  }
-
-  DosHdr = (EFI_IMAGE_DOS_HEADER *)mImageBase;
-  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
-    //
-    // DOS image header is present,
-    // so read the PE header after the DOS image header.
-    //
-    mPeCoffHeaderOffset = DosHdr->e_lfanew;
-  } else {
-    mPeCoffHeaderOffset = 0;
-  }
-
-  //
-  // Check PE/COFF image.
-  //
-  mNtHeader.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(mImageBase + mPeCoffHeaderOffset);
-  if (mNtHeader.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
-    //
-    // It is not a valid Pe/Coff file.
-    //
-    DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Not a valid PE/COFF image.\n"));
-    goto Failed;
-  }
-
-  if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-    //
-    // Use PE32 offset.
-    //
-    NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;
-    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
-      SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *)&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
-    }
-  } else {
-    //
-    // Use PE32+ offset.
-    //
-    NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
-    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
-      SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *)&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
-    }
-  }
+  HashStatus = UefiImageGetFirstCertificate (ImageContext, &WinCertificate);
 
   //
   // Start Image Validation.
   //
-  if ((SecDataDir == NULL) || (SecDataDir->Size == 0)) {
+  if (HashStatus == RETURN_NOT_FOUND) {
     //
     // This image is not signed. The hash value of the image must match a record in the security database "db",
     // and not be reflected in the security data base "dbx".
@@ -1850,30 +1481,32 @@ DxeImageVerificationHandler (
         continue;
       }
 
-      if (!HashPeImage (HashAlg)) {
+      if (!HashPeImage (ImageContext, &mHash[HashAlg], ImageDigest, &ImageDigestSize)) {
         continue;
       }
 
+      CertType = mHash[HashAlg].CertType;
+
       DbStatus = IsSignatureFoundInDatabase (
                    EFI_IMAGE_SECURITY_DATABASE1,
-                   mImageDigest,
-                   &mCertType,
-                   mImageDigestSize,
+                   ImageDigest,
+                   CertType,
+                   ImageDigestSize,
                    &IsFound
                    );
       if (EFI_ERROR (DbStatus) || IsFound) {
         //
         // Image Hash is in forbidden database (DBX).
         //
-        DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is not signed and %s hash of image is forbidden by DBX.\n", mHashTypeStr));
+        DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is not signed and hash of image is forbidden by DBX.\n"));
         goto Failed;
       }
 
       DbStatus = IsSignatureFoundInDatabase (
                    EFI_IMAGE_SECURITY_DATABASE,
-                   mImageDigest,
-                   &mCertType,
-                   mImageDigestSize,
+                   ImageDigest,
+                   CertType,
+                   ImageDigestSize,
                    &IsFound
                    );
       if (!EFI_ERROR (DbStatus) && IsFound) {
@@ -1891,7 +1524,7 @@ DxeImageVerificationHandler (
     //
     // Image Hash is not found in both forbidden and allowed database.
     //
-    DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is not signed and %s hash of image is not found in DB/DBX.\n", mHashTypeStr));
+    DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is not signed and hash of image is not found in DB/DBX.\n"));
     goto Failed;
   }
 
@@ -1900,24 +1533,12 @@ DxeImageVerificationHandler (
   // "Attribute Certificate Table".
   // The first certificate starts at offset (SecDataDir->VirtualAddress) from the start of the file.
   //
-  SecDataDirEnd = SecDataDir->VirtualAddress + SecDataDir->Size;
-  for (OffSet = SecDataDir->VirtualAddress;
-       OffSet < SecDataDirEnd;
-       OffSet += (WinCertificate->dwLength + ALIGN_SIZE (WinCertificate->dwLength)))
+  for (
+    ;
+    !RETURN_ERROR (HashStatus);
+    HashStatus = UefiImageGetNextCertificate (ImageContext, &WinCertificate)
+    )
   {
-    SecDataDirLeft = SecDataDirEnd - OffSet;
-    if (SecDataDirLeft <= sizeof (WIN_CERTIFICATE)) {
-      break;
-    }
-
-    WinCertificate = (WIN_CERTIFICATE *)(mImageBase + OffSet);
-    if ((SecDataDirLeft < WinCertificate->dwLength) ||
-        (SecDataDirLeft - WinCertificate->dwLength <
-         ALIGN_SIZE (WinCertificate->dwLength)))
-    {
-      break;
-    }
-
     //
     // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.
     //
@@ -1926,7 +1547,7 @@ DxeImageVerificationHandler (
       // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the
       // Authenticode specification.
       //
-      PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *)WinCertificate;
+      PkcsCertData = (CONST WIN_CERTIFICATE_EFI_PKCS *)WinCertificate;
       if (PkcsCertData->Hdr.dwLength <= sizeof (PkcsCertData->Hdr)) {
         break;
       }
@@ -1937,26 +1558,23 @@ DxeImageVerificationHandler (
       //
       // The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec.
       //
-      WinCertUefiGuid = (WIN_CERTIFICATE_UEFI_GUID *)WinCertificate;
-      if (WinCertUefiGuid->Hdr.dwLength <= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)) {
-        break;
-      }
+      WinCertUefiGuid = (CONST WIN_CERTIFICATE_UEFI_GUID *)WinCertificate;
 
       if (!CompareGuid (&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid)) {
         continue;
       }
 
+      if (WinCertUefiGuid->Hdr.dwLength <= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)) {
+        break;
+      }
       AuthData     = WinCertUefiGuid->CertData;
       AuthDataSize = WinCertUefiGuid->Hdr.dwLength - OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
     } else {
-      if (WinCertificate->dwLength < sizeof (WIN_CERTIFICATE)) {
-        break;
-      }
 
       continue;
     }
 
-    HashStatus = HashPeImageByType (AuthData, AuthDataSize);
+    HashStatus = HashPeImageByType (ImageContext, AuthData, AuthDataSize, ImageDigest, &ImageDigestSize, &CertType);
     if (EFI_ERROR (HashStatus)) {
       continue;
     }
@@ -1964,17 +1582,16 @@ DxeImageVerificationHandler (
     //
     // Check the digital signature against the revoked certificate in forbidden database (dbx).
     //
-    if (IsForbiddenByDbx (AuthData, AuthDataSize)) {
+    if (IsForbiddenByDbx (AuthData, AuthDataSize, ImageDigest, ImageDigestSize)) {
       Action     = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;
       IsVerified = FALSE;
-      break;
     }
 
     //
     // Check the digital signature against the valid certificate in allowed database (db).
     //
     if (!IsVerified) {
-      if (IsAllowedByDb (AuthData, AuthDataSize)) {
+      if (IsAllowedByDb (AuthData, AuthDataSize, ImageDigest, ImageDigestSize)) {
         IsVerified = TRUE;
       }
     }
@@ -1984,14 +1601,14 @@ DxeImageVerificationHandler (
     //
     DbStatus = IsSignatureFoundInDatabase (
                  EFI_IMAGE_SECURITY_DATABASE1,
-                 mImageDigest,
-                 &mCertType,
-                 mImageDigestSize,
+                 ImageDigest,
+                 CertType,
+                 ImageDigestSize,
                  &IsFound
                  );
     if (EFI_ERROR (DbStatus) || IsFound) {
       Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;
-      DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but %s hash of image is found in DBX.\n", mHashTypeStr));
+      DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but hash of image is found in DBX.\n"));
       IsVerified = FALSE;
       break;
     }
@@ -1999,36 +1616,28 @@ DxeImageVerificationHandler (
     if (!IsVerified) {
       DbStatus = IsSignatureFoundInDatabase (
                    EFI_IMAGE_SECURITY_DATABASE,
-                   mImageDigest,
-                   &mCertType,
-                   mImageDigestSize,
+                   ImageDigest,
+                   CertType,
+                   ImageDigestSize,
                    &IsFound
                    );
       if (!EFI_ERROR (DbStatus) && IsFound) {
         IsVerified = TRUE;
       } else {
         Action = EFI_IMAGE_EXECUTION_AUTH_SIG_NOT_FOUND;
-        DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature is not allowed by DB and %s hash of image is not found in DB/DBX.\n", mHashTypeStr));
+        DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature is not allowed by DB and hash of image is not found in DB/DBX.\n"));
       }
     }
   }
 
-  if (OffSet != SecDataDirEnd) {
-    //
-    // The Size in Certificate Table or the attribute certificate table is corrupted.
-    //
-    IsVerified = FALSE;
-  }
-
   if (IsVerified) {
     return EFI_SUCCESS;
   }
-
   if ((Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED) || (Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND)) {
     //
     // Get image hash value as signature of executable.
     //
-    SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize;
+    SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + ImageDigestSize;
     SignatureList     = (EFI_SIGNATURE_LIST *)AllocateZeroPool (SignatureListSize);
     if (SignatureList == NULL) {
       SignatureListSize = 0;
@@ -2037,10 +1646,10 @@ DxeImageVerificationHandler (
 
     SignatureList->SignatureHeaderSize = 0;
     SignatureList->SignatureListSize   = (UINT32)SignatureListSize;
-    SignatureList->SignatureSize       = (UINT32)(sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize);
-    CopyMem (&SignatureList->SignatureType, &mCertType, sizeof (EFI_GUID));
+    SignatureList->SignatureSize       = (UINT32)(sizeof (EFI_SIGNATURE_DATA) - 1 + ImageDigestSize);
+    CopyMem (&SignatureList->SignatureType, CertType, sizeof (EFI_GUID));
     Signature = (EFI_SIGNATURE_DATA *)((UINT8 *)SignatureList + sizeof (EFI_SIGNATURE_LIST));
-    CopyMem (Signature->SignatureData, mImageDigest, mImageDigestSize);
+    CopyMem (Signature->SignatureData, ImageDigest, ImageDigestSize);
   }
 
 Failed:
@@ -2078,8 +1687,8 @@ Failed:
 VOID
 EFIAPI
 OnReadyToBoot (
-  IN      EFI_EVENT  Event,
-  IN      VOID       *Context
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
   )
 {
   EFI_IMAGE_EXECUTION_INFO_TABLE  *ImageExeInfoTable;
diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.h b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.h
index 53fe34358c..903ffd3f29 100644
--- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.h
+++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.h
@@ -22,7 +22,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/PcdLib.h>
 #include <Library/DevicePathLib.h>
 #include <Library/SecurityManagementLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 #include <Protocol/FirmwareVolume2.h>
 #include <Protocol/DevicePath.h>
 #include <Protocol/BlockIo.h>
@@ -30,7 +30,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Protocol/VariableWrite.h>
 #include <Guid/ImageAuthentication.h>
 #include <Guid/AuthenticatedVariableFormat.h>
-#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/PeImage2.h>
 
 #define EFI_CERT_TYPE_RSA2048_SHA256_SIZE  256
 #define EFI_CERT_TYPE_RSA2048_SIZE         256
@@ -59,16 +59,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #define DENY_EXECUTE_ON_SECURITY_VIOLATION   0x00000004
 #define QUERY_USER_ON_SECURITY_VIOLATION     0x00000005
 
-//
-// Support hash types
-//
-#define HASHALG_SHA1    0x00000000
-#define HASHALG_SHA224  0x00000001
-#define HASHALG_SHA256  0x00000002
-#define HASHALG_SHA384  0x00000003
-#define HASHALG_SHA512  0x00000004
-#define HASHALG_MAX     0x00000005
-
 //
 // Set max digest size as SHA512 Output (64 bytes) by far
 //
@@ -178,6 +168,10 @@ typedef struct {
   //
   UINTN                    OidLength;
   //
+  // GUID of the certificate type
+  //
+  CONST GUID               *CertType;
+  //
   // Pointer to Hash GetContentSize function
   //
   HASH_GET_CONTEXT_SIZE    GetContextSize;
diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
index 1e1a639857..3b944cddf9 100644
--- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
+++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
@@ -51,7 +51,7 @@
   DevicePathLib
   BaseCryptLib
   SecurityManagementLib
-  PeCoffLib
+  UefiImageLib
   TpmMeasurementLib
 
 [Protocols]
@@ -75,6 +75,10 @@
   ## SOMETIMES_PRODUCES   ## GUID       # Unique ID for the type of the signature.
   gEfiCertSha256Guid
 
+  ## SOMETIMES_CONSUMES   ## GUID       # Unique ID for the type of the signature.
+  ## SOMETIMES_PRODUCES   ## GUID       # Unique ID for the type of the signature.
+  gEfiCertSha224Guid
+
   ## SOMETIMES_CONSUMES   ## GUID       # Unique ID for the type of the signature.
   ## SOMETIMES_PRODUCES   ## GUID       # Unique ID for the type of the signature.
   gEfiCertSha384Guid
diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
index 73719f3b96..c963739c17 100644
--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
+++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c
@@ -7,9 +7,6 @@
   This external input must be validated carefully to avoid security issue like
   buffer overflow, integer overflow.
 
-  DxeTpm2MeasureBootLibImageRead() function will make sure the PE/COFF image content
-  read is within the image buffer.
-
   Tcg2MeasurePeImage() function will accept untrusted PE/COFF image and validate its
   data structure within this image buffer before use.
 
@@ -41,7 +38,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/DevicePathLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/BaseCryptLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/SecurityManagementLib.h>
 #include <Library/HobLib.h>
 #include <Protocol/CcMeasurement.h>
@@ -58,62 +55,12 @@ typedef struct {
 //
 BOOLEAN  mTcg2MeasureGptTableFlag = FALSE;
 UINTN    mTcg2MeasureGptCount     = 0;
-VOID     *mTcg2FileBuffer;
-UINTN    mTcg2ImageSize;
 //
 // Measured FV handle cache
 //
 EFI_HANDLE         mTcg2CacheMeasuredHandle = NULL;
 MEASURED_HOB_DATA  *mTcg2MeasuredHobData    = NULL;
 
-/**
-  Reads contents of a PE/COFF image in memory buffer.
-
-  Caution: This function may receive untrusted input.
-  PE/COFF image is external input, so this function will make sure the PE/COFF image content
-  read is within the image buffer.
-
-  @param  FileHandle      Pointer to the file handle to read the PE/COFF image.
-  @param  FileOffset      Offset into the PE/COFF image to begin the read operation.
-  @param  ReadSize        On input, the size in bytes of the requested read operation.
-                          On output, the number of bytes actually read.
-  @param  Buffer          Output buffer that contains the data read from the PE/COFF image.
-
-  @retval EFI_SUCCESS     The specified portion of the PE/COFF image was read and the size
-**/
-EFI_STATUS
-EFIAPI
-DxeTpm2MeasureBootLibImageRead (
-  IN     VOID   *FileHandle,
-  IN     UINTN  FileOffset,
-  IN OUT UINTN  *ReadSize,
-  OUT    VOID   *Buffer
-  )
-{
-  UINTN  EndPosition;
-
-  if ((FileHandle == NULL) || (ReadSize == NULL) || (Buffer == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (MAX_ADDRESS - FileOffset < *ReadSize) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  EndPosition = FileOffset + *ReadSize;
-  if (EndPosition > mTcg2ImageSize) {
-    *ReadSize = (UINT32)(mTcg2ImageSize - FileOffset);
-  }
-
-  if (FileOffset >= mTcg2ImageSize) {
-    *ReadSize = 0;
-  }
-
-  CopyMem (Buffer, (UINT8 *)((UINTN)FileHandle + FileOffset), *ReadSize);
-
-  return EFI_SUCCESS;
-}
-
 /**
   Measure GPT table data into TPM log.
 
@@ -640,11 +587,15 @@ DxeTpm2MeasureBootHandler (
   EFI_HANDLE                          Handle;
   EFI_HANDLE                          TempHandle;
   BOOLEAN                             ApplicationRequired;
-  PE_COFF_LOADER_IMAGE_CONTEXT        ImageContext;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT     *ImageContext;
   EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *FvbProtocol;
   EFI_PHYSICAL_ADDRESS                FvAddress;
   UINT32                              Index;
 
+  // FIXME:
+  ASSERT (FileSize == sizeof (UEFI_IMAGE_LOADER_IMAGE_CONTEXT));
+  ImageContext = FileBuffer;
+
   MeasureBootProtocols.Tcg2Protocol = NULL;
   MeasureBootProtocols.CcProtocol   = NULL;
 
@@ -806,42 +757,17 @@ DxeTpm2MeasureBootHandler (
     goto Finish;
   }
 
-  mTcg2ImageSize  = FileSize;
-  mTcg2FileBuffer = FileBuffer;
-
   //
   // Measure PE Image
   //
   DevicePathNode = OrigDevicePathNode;
-  ZeroMem (&ImageContext, sizeof (ImageContext));
-  ImageContext.Handle    = (VOID *)FileBuffer;
-  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)DxeTpm2MeasureBootLibImageRead;
-
-  //
-  // Get information about the image being loaded
-  //
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);
-  if (EFI_ERROR (Status)) {
-    //
-    // Check for invalid parameters.
-    //
-    if (File == NULL) {
-      Status = EFI_ACCESS_DENIED;
-    }
-
-    //
-    // The information can't be got from the invalid PeImage
-    //
-    goto Finish;
-  }
 
   //
   // Measure only application if Application flag is set
   // Measure drivers and applications if Application flag is not set
   //
   if ((!ApplicationRequired) ||
-      (ApplicationRequired && (ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)))
-  {
+        (ApplicationRequired && UefiImageGetSubsystem (ImageContext) == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)) {
     //
     // Print the image path to be measured.
     //
@@ -862,12 +788,13 @@ DxeTpm2MeasureBootHandler (
     //
     // Measure PE image into TPM log.
     //
+    // FIXME: Pass context?
     Status = Tcg2MeasurePeImage (
                &MeasureBootProtocols,
                (EFI_PHYSICAL_ADDRESS)(UINTN)FileBuffer,
                FileSize,
-               (UINTN)ImageContext.ImageAddress,
-               ImageContext.ImageType,
+               UefiImageLoaderGetImageAddress (ImageContext),
+               UefiImageGetSubsystem (ImageContext),
                DevicePathNode
                );
   }
diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
index 28995f438d..713c56b1ab 100644
--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
+++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
@@ -54,7 +54,7 @@
   DevicePathLib
   UefiBootServicesTableLib
   BaseCryptLib
-  PeCoffLib
+  UefiImageLib
   BaseLib
   SecurityManagementLib
   HobLib
diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
index ac855b8fbb..fb06a8112b 100644
--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
+++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
@@ -6,9 +6,6 @@
   This external input must be validated carefully to avoid security issue like
   buffer overflow, integer overflow.
 
-  DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF image content
-  read is within the image buffer.
-
   TcgMeasurePeImage() function will accept untrusted PE/COFF image and validate its
   data structure within this image buffer before use.
 
@@ -39,7 +36,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/DevicePathLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/BaseCryptLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/SecurityManagementLib.h>
 #include <Library/HobLib.h>
 
@@ -50,62 +47,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 //
 BOOLEAN  mMeasureGptTableFlag = FALSE;
 UINTN    mMeasureGptCount     = 0;
-VOID     *mFileBuffer;
-UINTN    mTpmImageSize;
 //
 // Measured FV handle cache
 //
 EFI_HANDLE         mCacheMeasuredHandle = NULL;
 MEASURED_HOB_DATA  *mMeasuredHobData    = NULL;
 
-/**
-  Reads contents of a PE/COFF image in memory buffer.
-
-  Caution: This function may receive untrusted input.
-  PE/COFF image is external input, so this function will make sure the PE/COFF image content
-  read is within the image buffer.
-
-  @param  FileHandle      Pointer to the file handle to read the PE/COFF image.
-  @param  FileOffset      Offset into the PE/COFF image to begin the read operation.
-  @param  ReadSize        On input, the size in bytes of the requested read operation.
-                          On output, the number of bytes actually read.
-  @param  Buffer          Output buffer that contains the data read from the PE/COFF image.
-
-  @retval EFI_SUCCESS     The specified portion of the PE/COFF image was read and the size
-**/
-EFI_STATUS
-EFIAPI
-DxeTpmMeasureBootLibImageRead (
-  IN     VOID   *FileHandle,
-  IN     UINTN  FileOffset,
-  IN OUT UINTN  *ReadSize,
-  OUT    VOID   *Buffer
-  )
-{
-  UINTN  EndPosition;
-
-  if ((FileHandle == NULL) || (ReadSize == NULL) || (Buffer == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (MAX_ADDRESS - FileOffset < *ReadSize) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  EndPosition = FileOffset + *ReadSize;
-  if (EndPosition > mTpmImageSize) {
-    *ReadSize = (UINT32)(mTpmImageSize - FileOffset);
-  }
-
-  if (FileOffset >= mTpmImageSize) {
-    *ReadSize = 0;
-  }
-
-  CopyMem (Buffer, (UINT8 *)((UINTN)FileHandle + FileOffset), *ReadSize);
-
-  return EFI_SUCCESS;
-}
-
 /**
   Measure GPT table data into TPM log.
 
@@ -292,7 +239,7 @@ TcgMeasureGptTable (
   PE/COFF image is external input, so this function will validate its data structure
   within this image buffer before use.
 
-  Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
+  Notes: PE/COFF image has been checked by UefiImageLibLib UefiImageInitializeContext() in
   its caller function DxeTpmMeasureBootHandler().
 
   @param[in] TcgProtocol    Pointer to the located TCG protocol instance.
@@ -311,12 +258,11 @@ TcgMeasureGptTable (
 EFI_STATUS
 EFIAPI
 TcgMeasurePeImage (
-  IN  EFI_TCG_PROTOCOL          *TcgProtocol,
-  IN  EFI_PHYSICAL_ADDRESS      ImageAddress,
-  IN  UINTN                     ImageSize,
-  IN  UINTN                     LinkTimeBase,
-  IN  UINT16                    ImageType,
-  IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath
+  IN  EFI_TCG_PROTOCOL              *TcgProtocol,
+  IN  EFI_PHYSICAL_ADDRESS          ImageAddress,
+  IN  UINTN                         ImageSize,
+  IN  UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext,
+  IN  EFI_DEVICE_PATH_PROTOCOL      *FilePath
   )
 {
   EFI_STATUS                           Status;
@@ -325,22 +271,12 @@ TcgMeasurePeImage (
   UINT32                               FilePathSize;
   VOID                                 *Sha1Ctx;
   UINTN                                CtxSize;
-  EFI_IMAGE_DOS_HEADER                 *DosHdr;
-  UINT32                               PeCoffHeaderOffset;
-  EFI_IMAGE_SECTION_HEADER             *Section;
-  UINT8                                *HashBase;
-  UINTN                                HashSize;
-  UINTN                                SumOfBytesHashed;
   EFI_IMAGE_SECTION_HEADER             *SectionHeader;
-  UINTN                                Index;
-  UINTN                                Pos;
   UINT32                               EventSize;
   UINT32                               EventNumber;
   EFI_PHYSICAL_ADDRESS                 EventLogLastEntry;
-  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;
-  UINT32                               NumberOfRvaAndSizes;
   BOOLEAN                              HashStatus;
-  UINT32                               CertSize;
+  UINT16                               ImageType;
 
   Status        = EFI_UNSUPPORTED;
   ImageLoad     = NULL;
@@ -364,6 +300,8 @@ TcgMeasurePeImage (
   TcgEvent->EventSize = EventSize - sizeof (TCG_PCR_EVENT_HDR);
   ImageLoad           = (EFI_IMAGE_LOAD_EVENT *)TcgEvent->Event;
 
+  ImageType = UefiImageGetSubsystem (ImageContext);
+
   switch (ImageType) {
     case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:
       TcgEvent->EventType = EV_EFI_BOOT_SERVICES_APPLICATION;
@@ -390,26 +328,12 @@ TcgMeasurePeImage (
 
   ImageLoad->ImageLocationInMemory = ImageAddress;
   ImageLoad->ImageLengthInMemory   = ImageSize;
-  ImageLoad->ImageLinkTimeAddress  = LinkTimeBase;
+  ImageLoad->ImageLinkTimeAddress  = UefiImageLoaderGetImageAddress (ImageContext);
   ImageLoad->LengthOfDevicePath    = FilePathSize;
   if ((FilePath != NULL) && (FilePathSize != 0)) {
     CopyMem (ImageLoad->DevicePath, FilePath, FilePathSize);
   }
 
-  //
-  // Check PE/COFF image
-  //
-  DosHdr             = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageAddress;
-  PeCoffHeaderOffset = 0;
-  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
-    PeCoffHeaderOffset = DosHdr->e_lfanew;
-  }
-
-  Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *)(UINTN)ImageAddress + PeCoffHeaderOffset);
-  if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
-    goto Finish;
-  }
-
   //
   // PE/COFF Image Measurement
   //
@@ -418,9 +342,7 @@ TcgMeasurePeImage (
   //
   //
 
-  // 1.  Load the image header into memory.
-
-  // 2.  Initialize a SHA hash context.
+  // Initialize a SHA hash context.
   CtxSize = Sha1GetContextSize ();
   Sha1Ctx = AllocatePool (CtxSize);
   if (Sha1Ctx == NULL) {
@@ -438,220 +360,7 @@ TcgMeasurePeImage (
   // But CheckSum field and SECURITY data directory (certificate) are excluded
   //
 
-  //
-  // 3.  Calculate the distance from the base of the image header to the image checksum address.
-  // 4.  Hash the image header from its base to beginning of the image checksum.
-  //
-  HashBase = (UINT8 *)(UINTN)ImageAddress;
-  if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-    //
-    // Use PE32 offset
-    //
-    NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
-    HashSize            = (UINTN)(&Hdr.Pe32->OptionalHeader.CheckSum) - (UINTN)HashBase;
-  } else {
-    //
-    // Use PE32+ offset
-    //
-    NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
-    HashSize            = (UINTN)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - (UINTN)HashBase;
-  }
-
-  HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);
-  if (!HashStatus) {
-    goto Finish;
-  }
-
-  //
-  // 5.  Skip over the image checksum (it occupies a single ULONG).
-  //
-  if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
-    //
-    // 6.  Since there is no Cert Directory in optional header, hash everything
-    //     from the end of the checksum to the end of image header.
-    //
-    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-      //
-      // Use PE32 offset.
-      //
-      HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
-      HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
-    } else {
-      //
-      // Use PE32+ offset.
-      //
-      HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
-      HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
-    }
-
-    if (HashSize != 0) {
-      HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);
-      if (!HashStatus) {
-        goto Finish;
-      }
-    }
-  } else {
-    //
-    // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.
-    //
-    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-      //
-      // Use PE32 offset
-      //
-      HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
-      HashSize = (UINTN)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
-    } else {
-      //
-      // Use PE32+ offset
-      //
-      HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
-      HashSize = (UINTN)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
-    }
-
-    if (HashSize != 0) {
-      HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);
-      if (!HashStatus) {
-        goto Finish;
-      }
-    }
-
-    //
-    // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
-    // 9.  Hash everything from the end of the Cert Directory to the end of image header.
-    //
-    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-      //
-      // Use PE32 offset
-      //
-      HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
-      HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
-    } else {
-      //
-      // Use PE32+ offset
-      //
-      HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
-      HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
-    }
-
-    if (HashSize != 0) {
-      HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);
-      if (!HashStatus) {
-        goto Finish;
-      }
-    }
-  }
-
-  //
-  // 10. Set the SUM_OF_BYTES_HASHED to the size of the header
-  //
-  if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-    //
-    // Use PE32 offset
-    //
-    SumOfBytesHashed = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
-  } else {
-    //
-    // Use PE32+ offset
-    //
-    SumOfBytesHashed = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders;
-  }
-
-  //
-  // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
-  //     structures in the image. The 'NumberOfSections' field of the image
-  //     header indicates how big the table should be. Do not include any
-  //     IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
-  //
-  SectionHeader = (EFI_IMAGE_SECTION_HEADER *)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections);
-  if (SectionHeader == NULL) {
-    Status = EFI_OUT_OF_RESOURCES;
-    goto Finish;
-  }
-
-  //
-  // 12.  Using the 'PointerToRawData' in the referenced section headers as
-  //      a key, arrange the elements in the table in ascending order. In other
-  //      words, sort the section headers according to the disk-file offset of
-  //      the section.
-  //
-  Section = (EFI_IMAGE_SECTION_HEADER *)(
-                                         (UINT8 *)(UINTN)ImageAddress +
-                                         PeCoffHeaderOffset +
-                                         sizeof (UINT32) +
-                                         sizeof (EFI_IMAGE_FILE_HEADER) +
-                                         Hdr.Pe32->FileHeader.SizeOfOptionalHeader
-                                         );
-  for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
-    Pos = Index;
-    while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
-      CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
-      Pos--;
-    }
-
-    CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
-    Section += 1;
-  }
-
-  //
-  // 13.  Walk through the sorted table, bring the corresponding section
-  //      into memory, and hash the entire section (using the 'SizeOfRawData'
-  //      field in the section header to determine the amount of data to hash).
-  // 14.  Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
-  // 15.  Repeat steps 13 and 14 for all the sections in the sorted table.
-  //
-  for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
-    Section = (EFI_IMAGE_SECTION_HEADER *)&SectionHeader[Index];
-    if (Section->SizeOfRawData == 0) {
-      continue;
-    }
-
-    HashBase = (UINT8 *)(UINTN)ImageAddress + Section->PointerToRawData;
-    HashSize = (UINTN)Section->SizeOfRawData;
-
-    HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);
-    if (!HashStatus) {
-      goto Finish;
-    }
-
-    SumOfBytesHashed += HashSize;
-  }
-
-  //
-  // 16.  If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
-  //      data in the file that needs to be added to the hash. This data begins
-  //      at file offset SUM_OF_BYTES_HASHED and its length is:
-  //             FileSize  -  (CertDirectory->Size)
-  //
-  if (ImageSize > SumOfBytesHashed) {
-    HashBase = (UINT8 *)(UINTN)ImageAddress + SumOfBytesHashed;
-
-    if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
-      CertSize = 0;
-    } else {
-      if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-        //
-        // Use PE32 offset.
-        //
-        CertSize = Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
-      } else {
-        //
-        // Use PE32+ offset.
-        //
-        CertSize = Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
-      }
-    }
-
-    if (ImageSize > CertSize + SumOfBytesHashed) {
-      HashSize = (UINTN)(ImageSize - CertSize - SumOfBytesHashed);
-
-      HashStatus = Sha1Update (Sha1Ctx, HashBase, HashSize);
-      if (!HashStatus) {
-        goto Finish;
-      }
-    } else if (ImageSize < CertSize + SumOfBytesHashed) {
-      goto Finish;
-    }
-  }
+  UefiImageHashImageDefault (ImageContext, Sha1Ctx, Sha1Update);
 
   //
   // 17.  Finalize the SHA hash.
@@ -756,11 +465,15 @@ DxeTpmMeasureBootHandler (
   EFI_HANDLE                          Handle;
   EFI_HANDLE                          TempHandle;
   BOOLEAN                             ApplicationRequired;
-  PE_COFF_LOADER_IMAGE_CONTEXT        ImageContext;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT     *ImageContext;
   EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *FvbProtocol;
   EFI_PHYSICAL_ADDRESS                FvAddress;
   UINT32                              Index;
 
+  // FIXME:
+  ASSERT (FileSize == sizeof (UEFI_IMAGE_LOADER_IMAGE_CONTEXT));
+  ImageContext = FileBuffer;
+
   Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol);
   if (EFI_ERROR (Status)) {
     //
@@ -922,42 +635,17 @@ DxeTpmMeasureBootHandler (
     goto Finish;
   }
 
-  mTpmImageSize = FileSize;
-  mFileBuffer   = FileBuffer;
-
   //
   // Measure PE Image
   //
   DevicePathNode = OrigDevicePathNode;
-  ZeroMem (&ImageContext, sizeof (ImageContext));
-  ImageContext.Handle    = (VOID *)FileBuffer;
-  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)DxeTpmMeasureBootLibImageRead;
-
-  //
-  // Get information about the image being loaded
-  //
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);
-  if (EFI_ERROR (Status)) {
-    //
-    // Check for invalid parameters.
-    //
-    if (File == NULL) {
-      return EFI_ACCESS_DENIED;
-    }
-
-    //
-    // The information can't be got from the invalid PeImage
-    //
-    goto Finish;
-  }
 
   //
   // Measure only application if Application flag is set
   // Measure drivers and applications if Application flag is not set
   //
   if ((!ApplicationRequired) ||
-      (ApplicationRequired && (ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)))
-  {
+        (ApplicationRequired && UefiImageGetSubsystem (ImageContext) == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)) {
     //
     // Print the image path to be measured.
     //
@@ -982,8 +670,7 @@ DxeTpmMeasureBootHandler (
                TcgProtocol,
                (EFI_PHYSICAL_ADDRESS)(UINTN)FileBuffer,
                FileSize,
-               (UINTN)ImageContext.ImageAddress,
-               ImageContext.ImageType,
+               ImageContext,
                DevicePathNode
                );
   }
diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf
index 414c654d15..ffe925af25 100644
--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf
+++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf
@@ -49,7 +49,7 @@
   DevicePathLib
   UefiBootServicesTableLib
   BaseCryptLib
-  PeCoffLib
+  UefiImageLib
   BaseLib
   SecurityManagementLib
   HobLib
diff --git a/SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.c b/SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.c
index c786c2189c..5de9ac1762 100644
--- a/SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.c
+++ b/SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.c
@@ -56,7 +56,9 @@ Sha1HashInit (
 
   CtxSize = Sha1GetContextSize ();
   Sha1Ctx = AllocatePool (CtxSize);
-  ASSERT (Sha1Ctx != NULL);
+  if (Sha1Ctx == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
 
   Sha1Init (Sha1Ctx);
 
@@ -82,10 +84,7 @@ Sha1HashUpdate (
   IN UINTN        DataToHashLen
   )
 {
-  VOID  *Sha1Ctx;
-
-  Sha1Ctx = (VOID *)HashHandle;
-  Sha1Update (Sha1Ctx, DataToHash, DataToHashLen);
+  Sha1Update ((VOID *)HashHandle, DataToHash, DataToHashLen);
 
   return EFI_SUCCESS;
 }
@@ -101,17 +100,15 @@ Sha1HashUpdate (
 EFI_STATUS
 EFIAPI
 Sha1HashFinal (
-  IN HASH_HANDLE          HashHandle,
+  IN  HASH_HANDLE         HashHandle,
   OUT TPML_DIGEST_VALUES  *DigestList
   )
 {
   UINT8  Digest[SHA1_DIGEST_SIZE];
-  VOID   *Sha1Ctx;
 
-  Sha1Ctx = (VOID *)HashHandle;
-  Sha1Final (Sha1Ctx, Digest);
+  Sha1Final ((VOID *)HashHandle, Digest);
 
-  FreePool (Sha1Ctx);
+  FreePool ((VOID *)HashHandle);
 
   Tpm2SetSha1ToDigestList (DigestList, Digest);
 
diff --git a/SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.c b/SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.c
index 4387740001..57c8c9590a 100644
--- a/SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.c
+++ b/SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.c
@@ -56,7 +56,9 @@ Sha256HashInit (
 
   CtxSize   = Sha256GetContextSize ();
   Sha256Ctx = AllocatePool (CtxSize);
-  ASSERT (Sha256Ctx != NULL);
+  if (Sha256Ctx == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
 
   Sha256Init (Sha256Ctx);
 
@@ -82,10 +84,7 @@ Sha256HashUpdate (
   IN UINTN        DataToHashLen
   )
 {
-  VOID  *Sha256Ctx;
-
-  Sha256Ctx = (VOID *)HashHandle;
-  Sha256Update (Sha256Ctx, DataToHash, DataToHashLen);
+  Sha256Update ((VOID *)HashHandle, DataToHash, DataToHashLen);
 
   return EFI_SUCCESS;
 }
@@ -106,12 +105,10 @@ Sha256HashFinal (
   )
 {
   UINT8  Digest[SHA256_DIGEST_SIZE];
-  VOID   *Sha256Ctx;
 
-  Sha256Ctx = (VOID *)HashHandle;
-  Sha256Final (Sha256Ctx, Digest);
+  Sha256Final ((VOID *)HashHandle, Digest);
 
-  FreePool (Sha256Ctx);
+  FreePool ((VOID *)HashHandle);
 
   Tpm2SetSha256ToDigestList (DigestList, Digest);
 
diff --git a/SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.c b/SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.c
index 1f21483e16..4997874eb0 100644
--- a/SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.c
+++ b/SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.c
@@ -56,7 +56,9 @@ Sha384HashInit (
 
   CtxSize   = Sha384GetContextSize ();
   Sha384Ctx = AllocatePool (CtxSize);
-  ASSERT (Sha384Ctx != NULL);
+  if (Sha384Ctx == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
 
   Sha384Init (Sha384Ctx);
 
@@ -106,12 +108,10 @@ Sha384HashFinal (
   )
 {
   UINT8  Digest[SHA384_DIGEST_SIZE];
-  VOID   *Sha384Ctx;
 
-  Sha384Ctx = (VOID *)HashHandle;
-  Sha384Final (Sha384Ctx, Digest);
+  Sha384Final ((VOID *)HashHandle, Digest);
 
-  FreePool (Sha384Ctx);
+  FreePool ((VOID *)HashHandle);
 
   Tpm2SetSha384ToDigestList (DigestList, Digest);
 
diff --git a/SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.c b/SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.c
index e25ecb9ed6..f426f31e28 100644
--- a/SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.c
+++ b/SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.c
@@ -55,7 +55,9 @@ Sha512HashInit (
 
   CtxSize   = Sha512GetContextSize ();
   Sha512Ctx = AllocatePool (CtxSize);
-  ASSERT (Sha512Ctx != NULL);
+  if (Sha512Ctx == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
 
   Sha512Init (Sha512Ctx);
 
@@ -81,10 +83,7 @@ Sha512HashUpdate (
   IN UINTN        DataToHashLen
   )
 {
-  VOID  *Sha512Ctx;
-
-  Sha512Ctx = (VOID *)HashHandle;
-  Sha512Update (Sha512Ctx, DataToHash, DataToHashLen);
+  Sha512Update ((VOID *)HashHandle, DataToHash, DataToHashLen);
 
   return EFI_SUCCESS;
 }
@@ -100,17 +99,15 @@ Sha512HashUpdate (
 EFI_STATUS
 EFIAPI
 Sha512HashFinal (
-  IN HASH_HANDLE          HashHandle,
+  IN  HASH_HANDLE         HashHandle,
   OUT TPML_DIGEST_VALUES  *DigestList
   )
 {
   UINT8  Digest[SHA512_DIGEST_SIZE];
-  VOID   *Sha512Ctx;
 
-  Sha512Ctx = (VOID *)HashHandle;
-  Sha512Final (Sha512Ctx, Digest);
+  Sha512Final ((VOID *)HashHandle, Digest);
 
-  FreePool (Sha512Ctx);
+  FreePool ((VOID *)HashHandle);
 
   Tpm2SetSha512ToDigestList (DigestList, Digest);
 
diff --git a/SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.c b/SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.c
index 635ca1ebfb..88eee675ca 100644
--- a/SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.c
+++ b/SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.c
@@ -83,10 +83,7 @@ Sm3HashUpdate (
   IN UINTN        DataToHashLen
   )
 {
-  VOID  *Sm3Ctx;
-
-  Sm3Ctx = (VOID *)HashHandle;
-  Sm3Update (Sm3Ctx, DataToHash, DataToHashLen);
+  Sm3Update ((VOID *)HashHandle, DataToHash, DataToHashLen);
 
   return EFI_SUCCESS;
 }
@@ -102,17 +99,15 @@ Sm3HashUpdate (
 EFI_STATUS
 EFIAPI
 Sm3HashFinal (
-  IN HASH_HANDLE          HashHandle,
+  IN  HASH_HANDLE         HashHandle,
   OUT TPML_DIGEST_VALUES  *DigestList
   )
 {
   UINT8  Digest[SM3_256_DIGEST_SIZE];
-  VOID   *Sm3Ctx;
 
-  Sm3Ctx = (VOID *)HashHandle;
-  Sm3Final (Sm3Ctx, Digest);
+  Sm3Final ((VOID *)HashHandle, Digest);
 
-  FreePool (Sm3Ctx);
+  FreePool ((VOID *)HashHandle);
 
   Tpm2SetSm3ToDigestList (DigestList, Digest);
 
diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c
index 2169c5e185..ac6fb8f9f6 100644
--- a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c
+++ b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c
@@ -76,7 +76,9 @@ HashStart (
   CheckSupportedHashMaskMismatch ();
 
   HashCtx = AllocatePool (sizeof (*HashCtx) * mHashInterfaceCount);
-  ASSERT (HashCtx != NULL);
+  if (HashCtx == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
 
   for (Index = 0; Index < mHashInterfaceCount; Index++) {
     HashMask = Tpm2GetHashMaskFromAlgo (&mHashInterface[Index].HashGuid);
diff --git a/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c b/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c
index 00ba80b884..6c82dac66b 100644
--- a/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c
+++ b/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c
@@ -72,11 +72,13 @@ HashStart (
   AlgoId = Tpm2GetAlgoFromHashMask ();
 
   Status = Tpm2HashSequenceStart (AlgoId, &SequenceHandle);
-  if (!EFI_ERROR (Status)) {
-    *HashHandle = (HASH_HANDLE)SequenceHandle;
+  if (EFI_ERROR (Status)) {
+    return Status;
   }
 
-  return Status;
+  *HashHandle = (HASH_HANDLE)SequenceHandle;
+
+  return EFI_SUCCESS;
 }
 
 /**
@@ -109,7 +111,7 @@ HashUpdate (
 
     Status = Tpm2SequenceUpdate ((TPMI_DH_OBJECT)HashHandle, &HashBuffer);
     if (EFI_ERROR (Status)) {
-      return EFI_DEVICE_ERROR;
+      return Status;
     }
   }
 
@@ -120,7 +122,7 @@ HashUpdate (
   CopyMem (HashBuffer.buffer, Buffer, (UINTN)HashLen);
   Status = Tpm2SequenceUpdate ((TPMI_DH_OBJECT)HashHandle, &HashBuffer);
   if (EFI_ERROR (Status)) {
-    return EFI_DEVICE_ERROR;
+    return Status;
   }
 
   return EFI_SUCCESS;
diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index ea6a14c328..5000e05b7c 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -32,8 +32,12 @@
   PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
   UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
+  # FIXME: ARM?
+  CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+
 
   DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
   UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
diff --git a/SecurityPkg/Tcg/Tcg2Dxe/MeasureBootPeCoff.c b/SecurityPkg/Tcg/Tcg2Dxe/MeasureBootPeCoff.c
deleted file mode 100644
index b6c6faf2d2..0000000000
--- a/SecurityPkg/Tcg/Tcg2Dxe/MeasureBootPeCoff.c
+++ /dev/null
@@ -1,408 +0,0 @@
-/** @file
-  This module implements measuring PeCoff image for Tcg2 Protocol.
-
-  Caution: This file requires additional review when modified.
-  This driver will have external input - PE/COFF image.
-  This external input must be validated carefully to avoid security issue like
-  buffer overflow, integer overflow.
-
-Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <PiDxe.h>
-
-#include <Library/BaseLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/DevicePathLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/PeCoffLib.h>
-#include <Library/Tpm2CommandLib.h>
-#include <Library/HashLib.h>
-
-UINTN  mTcg2DxeImageSize = 0;
-
-/**
-  Reads contents of a PE/COFF image in memory buffer.
-
-  Caution: This function may receive untrusted input.
-  PE/COFF image is external input, so this function will make sure the PE/COFF image content
-  read is within the image buffer.
-
-  @param  FileHandle      Pointer to the file handle to read the PE/COFF image.
-  @param  FileOffset      Offset into the PE/COFF image to begin the read operation.
-  @param  ReadSize        On input, the size in bytes of the requested read operation.
-                          On output, the number of bytes actually read.
-  @param  Buffer          Output buffer that contains the data read from the PE/COFF image.
-
-  @retval EFI_SUCCESS     The specified portion of the PE/COFF image was read and the size
-**/
-EFI_STATUS
-EFIAPI
-Tcg2DxeImageRead (
-  IN     VOID   *FileHandle,
-  IN     UINTN  FileOffset,
-  IN OUT UINTN  *ReadSize,
-  OUT    VOID   *Buffer
-  )
-{
-  UINTN  EndPosition;
-
-  if ((FileHandle == NULL) || (ReadSize == NULL) || (Buffer == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (MAX_ADDRESS - FileOffset < *ReadSize) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  EndPosition = FileOffset + *ReadSize;
-  if (EndPosition > mTcg2DxeImageSize) {
-    *ReadSize = (UINT32)(mTcg2DxeImageSize - FileOffset);
-  }
-
-  if (FileOffset >= mTcg2DxeImageSize) {
-    *ReadSize = 0;
-  }
-
-  CopyMem (Buffer, (UINT8 *)((UINTN)FileHandle + FileOffset), *ReadSize);
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Measure PE image into TPM log based on the authenticode image hashing in
-  PE/COFF Specification 8.0 Appendix A.
-
-  Caution: This function may receive untrusted input.
-  PE/COFF image is external input, so this function will validate its data structure
-  within this image buffer before use.
-
-  Notes: PE/COFF image is checked by BasePeCoffLib PeCoffLoaderGetImageInfo().
-
-  @param[in]  PCRIndex       TPM PCR index
-  @param[in]  ImageAddress   Start address of image buffer.
-  @param[in]  ImageSize      Image size
-  @param[out] DigestList     Digest list of this image.
-
-  @retval EFI_SUCCESS            Successfully measure image.
-  @retval EFI_OUT_OF_RESOURCES   No enough resource to measure image.
-  @retval other error value
-**/
-EFI_STATUS
-MeasurePeImageAndExtend (
-  IN  UINT32                PCRIndex,
-  IN  EFI_PHYSICAL_ADDRESS  ImageAddress,
-  IN  UINTN                 ImageSize,
-  OUT TPML_DIGEST_VALUES    *DigestList
-  )
-{
-  EFI_STATUS                           Status;
-  EFI_IMAGE_DOS_HEADER                 *DosHdr;
-  UINT32                               PeCoffHeaderOffset;
-  EFI_IMAGE_SECTION_HEADER             *Section;
-  UINT8                                *HashBase;
-  UINTN                                HashSize;
-  UINTN                                SumOfBytesHashed;
-  EFI_IMAGE_SECTION_HEADER             *SectionHeader;
-  UINTN                                Index;
-  UINTN                                Pos;
-  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;
-  UINT32                               NumberOfRvaAndSizes;
-  UINT32                               CertSize;
-  HASH_HANDLE                          HashHandle;
-  PE_COFF_LOADER_IMAGE_CONTEXT         ImageContext;
-
-  HashHandle = 0xFFFFFFFF; // Know bad value
-
-  Status        = EFI_UNSUPPORTED;
-  SectionHeader = NULL;
-
-  //
-  // Check PE/COFF image
-  //
-  ZeroMem (&ImageContext, sizeof (ImageContext));
-  ImageContext.Handle    = (VOID *)(UINTN)ImageAddress;
-  mTcg2DxeImageSize      = ImageSize;
-  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)Tcg2DxeImageRead;
-
-  //
-  // Get information about the image being loaded
-  //
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);
-  if (EFI_ERROR (Status)) {
-    //
-    // The information can't be got from the invalid PeImage
-    //
-    DEBUG ((DEBUG_INFO, "Tcg2Dxe: PeImage invalid. Cannot retrieve image information.\n"));
-    goto Finish;
-  }
-
-  DosHdr             = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageAddress;
-  PeCoffHeaderOffset = 0;
-  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
-    PeCoffHeaderOffset = DosHdr->e_lfanew;
-  }
-
-  Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *)(UINTN)ImageAddress + PeCoffHeaderOffset);
-  if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
-    Status = EFI_UNSUPPORTED;
-    goto Finish;
-  }
-
-  //
-  // PE/COFF Image Measurement
-  //
-  //    NOTE: The following codes/steps are based upon the authenticode image hashing in
-  //      PE/COFF Specification 8.0 Appendix A.
-  //
-  //
-
-  // 1.  Load the image header into memory.
-
-  // 2.  Initialize a SHA hash context.
-
-  Status = HashStart (&HashHandle);
-  if (EFI_ERROR (Status)) {
-    goto Finish;
-  }
-
-  //
-  // Measuring PE/COFF Image Header;
-  // But CheckSum field and SECURITY data directory (certificate) are excluded
-  //
-
-  //
-  // 3.  Calculate the distance from the base of the image header to the image checksum address.
-  // 4.  Hash the image header from its base to beginning of the image checksum.
-  //
-  HashBase = (UINT8 *)(UINTN)ImageAddress;
-  if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-    //
-    // Use PE32 offset
-    //
-    NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
-    HashSize            = (UINTN)(&Hdr.Pe32->OptionalHeader.CheckSum) - (UINTN)HashBase;
-  } else {
-    //
-    // Use PE32+ offset
-    //
-    NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
-    HashSize            = (UINTN)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - (UINTN)HashBase;
-  }
-
-  Status = HashUpdate (HashHandle, HashBase, HashSize);
-  if (EFI_ERROR (Status)) {
-    goto Finish;
-  }
-
-  //
-  // 5.  Skip over the image checksum (it occupies a single ULONG).
-  //
-  if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
-    //
-    // 6.  Since there is no Cert Directory in optional header, hash everything
-    //     from the end of the checksum to the end of image header.
-    //
-    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-      //
-      // Use PE32 offset.
-      //
-      HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
-      HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
-    } else {
-      //
-      // Use PE32+ offset.
-      //
-      HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
-      HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
-    }
-
-    if (HashSize != 0) {
-      Status = HashUpdate (HashHandle, HashBase, HashSize);
-      if (EFI_ERROR (Status)) {
-        goto Finish;
-      }
-    }
-  } else {
-    //
-    // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.
-    //
-    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-      //
-      // Use PE32 offset
-      //
-      HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
-      HashSize = (UINTN)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
-    } else {
-      //
-      // Use PE32+ offset
-      //
-      HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
-      HashSize = (UINTN)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
-    }
-
-    if (HashSize != 0) {
-      Status = HashUpdate (HashHandle, HashBase, HashSize);
-      if (EFI_ERROR (Status)) {
-        goto Finish;
-      }
-    }
-
-    //
-    // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
-    // 9.  Hash everything from the end of the Cert Directory to the end of image header.
-    //
-    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-      //
-      // Use PE32 offset
-      //
-      HashBase = (UINT8 *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
-      HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
-    } else {
-      //
-      // Use PE32+ offset
-      //
-      HashBase = (UINT8 *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
-      HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN)(HashBase - ImageAddress);
-    }
-
-    if (HashSize != 0) {
-      Status = HashUpdate (HashHandle, HashBase, HashSize);
-      if (EFI_ERROR (Status)) {
-        goto Finish;
-      }
-    }
-  }
-
-  //
-  // 10. Set the SUM_OF_BYTES_HASHED to the size of the header
-  //
-  if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-    //
-    // Use PE32 offset
-    //
-    SumOfBytesHashed = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
-  } else {
-    //
-    // Use PE32+ offset
-    //
-    SumOfBytesHashed = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders;
-  }
-
-  //
-  // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
-  //     structures in the image. The 'NumberOfSections' field of the image
-  //     header indicates how big the table should be. Do not include any
-  //     IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
-  //
-  SectionHeader = (EFI_IMAGE_SECTION_HEADER *)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections);
-  if (SectionHeader == NULL) {
-    Status = EFI_OUT_OF_RESOURCES;
-    goto Finish;
-  }
-
-  //
-  // 12.  Using the 'PointerToRawData' in the referenced section headers as
-  //      a key, arrange the elements in the table in ascending order. In other
-  //      words, sort the section headers according to the disk-file offset of
-  //      the section.
-  //
-  Section = (EFI_IMAGE_SECTION_HEADER *)(
-                                         (UINT8 *)(UINTN)ImageAddress +
-                                         PeCoffHeaderOffset +
-                                         sizeof (UINT32) +
-                                         sizeof (EFI_IMAGE_FILE_HEADER) +
-                                         Hdr.Pe32->FileHeader.SizeOfOptionalHeader
-                                         );
-  for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
-    Pos = Index;
-    while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
-      CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
-      Pos--;
-    }
-
-    CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
-    Section += 1;
-  }
-
-  //
-  // 13.  Walk through the sorted table, bring the corresponding section
-  //      into memory, and hash the entire section (using the 'SizeOfRawData'
-  //      field in the section header to determine the amount of data to hash).
-  // 14.  Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
-  // 15.  Repeat steps 13 and 14 for all the sections in the sorted table.
-  //
-  for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
-    Section = (EFI_IMAGE_SECTION_HEADER *)&SectionHeader[Index];
-    if (Section->SizeOfRawData == 0) {
-      continue;
-    }
-
-    HashBase = (UINT8 *)(UINTN)ImageAddress + Section->PointerToRawData;
-    HashSize = (UINTN)Section->SizeOfRawData;
-
-    Status = HashUpdate (HashHandle, HashBase, HashSize);
-    if (EFI_ERROR (Status)) {
-      goto Finish;
-    }
-
-    SumOfBytesHashed += HashSize;
-  }
-
-  //
-  // 16.  If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
-  //      data in the file that needs to be added to the hash. This data begins
-  //      at file offset SUM_OF_BYTES_HASHED and its length is:
-  //             FileSize  -  (CertDirectory->Size)
-  //
-  if (ImageSize > SumOfBytesHashed) {
-    HashBase = (UINT8 *)(UINTN)ImageAddress + SumOfBytesHashed;
-
-    if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
-      CertSize = 0;
-    } else {
-      if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-        //
-        // Use PE32 offset.
-        //
-        CertSize = Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
-      } else {
-        //
-        // Use PE32+ offset.
-        //
-        CertSize = Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
-      }
-    }
-
-    if (ImageSize > CertSize + SumOfBytesHashed) {
-      HashSize = (UINTN)(ImageSize - CertSize - SumOfBytesHashed);
-
-      Status = HashUpdate (HashHandle, HashBase, HashSize);
-      if (EFI_ERROR (Status)) {
-        goto Finish;
-      }
-    } else if (ImageSize < CertSize + SumOfBytesHashed) {
-      Status = EFI_UNSUPPORTED;
-      goto Finish;
-    }
-  }
-
-  //
-  // 17.  Finalize the SHA hash.
-  //
-  Status = HashCompleteAndExtend (HashHandle, PCRIndex, NULL, 0, DigestList);
-  if (EFI_ERROR (Status)) {
-    goto Finish;
-  }
-
-Finish:
-  if (SectionHeader != NULL) {
-    FreePool (SectionHeader);
-  }
-
-  return Status;
-}
diff --git a/SecurityPkg/Tcg/Tcg2Dxe/MeasureBootUefiImage.c b/SecurityPkg/Tcg/Tcg2Dxe/MeasureBootUefiImage.c
new file mode 100644
index 0000000000..51956c5e6d
--- /dev/null
+++ b/SecurityPkg/Tcg/Tcg2Dxe/MeasureBootUefiImage.c
@@ -0,0 +1,111 @@
+/** @file
+  This module implements measuring UEFI Image for Tcg2 Protocol.
+
+  Caution: This file requires additional review when modified.
+  This driver will have external input - PE/COFF image.
+  This external input must be validated carefully to avoid security issue like
+  buffer overflow, integer overflow.
+
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiImageLib.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/HashLib.h>
+
+STATIC
+EFI_STATUS
+EFIAPI
+UifiImageHashUpdate (
+  IN UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext,
+  IN HASH_HANDLE                      HashHandle
+  )
+{
+  return UefiImageHashImageDefault (
+           ImageContext,
+           (VOID *)HashHandle,
+           (UEFI_IMAGE_LOADER_HASH_UPDATE)HashUpdate
+           ) ? EFI_SUCCESS : EFI_ABORTED;
+}
+
+/**
+  Measure UEFI image into TPM log based on its default image hashing.
+
+  Caution: This function may receive untrusted input.
+  UEFI image is external input, so this function will validate its data structure
+  within this image buffer before use.
+
+  Notes: UEFI image is checked by UefiImageLibLib UefiImageInitializeContext().
+
+  @param[in]  PCRIndex       TPM PCR index
+  @param[in]  ImageAddress   Start address of image buffer.
+  @param[in]  ImageSize      Image size
+  @param[out] DigestList     Digest list of this image.
+
+  @retval EFI_SUCCESS            Successfully measure image.
+  @retval EFI_OUT_OF_RESOURCES   No enough resource to measure image.
+  @retval other error value
+**/
+EFI_STATUS
+MeasureUefiImageAndExtend (
+  IN  UINT32                PCRIndex,
+  IN  EFI_PHYSICAL_ADDRESS  ImageAddress,
+  IN  UINTN                 ImageSize,
+  OUT TPML_DIGEST_VALUES    *DigestList
+  )
+{
+  EFI_STATUS                       Status;
+  HASH_HANDLE                      HashHandle;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT  ImageContext;
+
+  Status = EFI_UNSUPPORTED;
+
+  // FIXME: Can this somehow be abstracted away?
+  //
+  // Get information about the image being loaded
+  //
+  Status = UefiImageInitializeContextPreHash (
+             &ImageContext,
+             (VOID *) (UINTN) ImageAddress,
+             (UINT32) ImageSize
+             );
+  if (EFI_ERROR (Status)) {
+    //
+    // The information can't be got from the invalid PeImage
+    //
+    DEBUG ((DEBUG_INFO, "Tcg2Dxe: PeImage invalid. Cannot retrieve image information.\n"));
+    return Status;
+  }
+
+  //
+  // UEFI Image Measurement
+  //
+
+  // Initialize a SHA hash context.
+
+  Status = HashStart (&HashHandle);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // FIXME: This is just an ugly wrapper, the types should match (UINTN <-> VOID *), fix the libs
+  Status = UifiImageHashUpdate (&ImageContext, HashHandle);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // 17.  Finalize the SHA hash.
+  //
+  return HashCompleteAndExtend (HashHandle, PCRIndex, NULL, 0, DigestList);
+}
diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c
index 4d0c241f4d..2637df578d 100644
--- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c
+++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c
@@ -9,7 +9,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 
 #include <PiDxe.h>
 #include <IndustryStandard/Acpi.h>
-#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/PeImage2.h>
 #include <IndustryStandard/TcpaAcpi.h>
 
 #include <Guid/GlobalVariable.h>
@@ -124,7 +124,7 @@ EFI_HANDLE  mImageHandle;
   PE/COFF image is external input, so this function will validate its data structure
   within this image buffer before use.
 
-  Notes: PE/COFF image is checked by BasePeCoffLib PeCoffLoaderGetImageInfo().
+  Notes: PE/COFF image is checked by UefiImageLibLib UefiImageInitializeContext().
 
   @param[in]  PCRIndex       TPM PCR index
   @param[in]  ImageAddress   Start address of image buffer.
@@ -136,7 +136,7 @@ EFI_HANDLE  mImageHandle;
   @retval other error value
 **/
 EFI_STATUS
-MeasurePeImageAndExtend (
+MeasureUefiImageAndExtend (
   IN  UINT32                PCRIndex,
   IN  EFI_PHYSICAL_ADDRESS  ImageAddress,
   IN  UINTN                 ImageSize,
@@ -1346,7 +1346,7 @@ Tcg2HashLogExtendEvent (
   NewEventHdr.EventType = Event->Header.EventType;
   NewEventHdr.EventSize = Event->Size - sizeof (UINT32) - Event->Header.HeaderSize;
   if ((Flags & PE_COFF_IMAGE) != 0) {
-    Status = MeasurePeImageAndExtend (
+    Status = MeasureUefiImageAndExtend (
                NewEventHdr.PCRIndex,
                DataToHash,
                (UINTN)DataToHashLen,
@@ -1359,7 +1359,7 @@ Tcg2HashLogExtendEvent (
     }
 
     if (Status == EFI_DEVICE_ERROR) {
-      DEBUG ((DEBUG_ERROR, "MeasurePeImageAndExtend - %r. Disable TPM.\n", Status));
+      DEBUG ((DEBUG_ERROR, "MeasureUefiImageAndExtend - %r. Disable TPM.\n", Status));
       mTcgDxeData.BsCap.TPMPresentFlag = FALSE;
       REPORT_STATUS_CODE (
         EFI_ERROR_CODE | EFI_ERROR_MINOR,
diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf
index a645474bf3..3e86b6c999 100644
--- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf
+++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf
@@ -38,7 +38,7 @@
 
 [Sources]
   Tcg2Dxe.c
-  MeasureBootPeCoff.c
+  MeasureBootUefiImage.c
 
 [Packages]
   MdePkg/MdePkg.dec
@@ -63,7 +63,7 @@
   PerformanceLib
   ReportStatusCodeLib
   Tcg2PhysicalPresenceLib
-  PeCoffLib
+  UefiImageLib
 
 [Guids]
   ## SOMETIMES_CONSUMES     ## Variable:L"SecureBoot"
diff --git a/SecurityPkg/Tcg/TcgDxe/TcgDxe.c b/SecurityPkg/Tcg/TcgDxe/TcgDxe.c
index ee6c627303..95458a2c4c 100644
--- a/SecurityPkg/Tcg/TcgDxe/TcgDxe.c
+++ b/SecurityPkg/Tcg/TcgDxe/TcgDxe.c
@@ -17,7 +17,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <PiDxe.h>
 #include <IndustryStandard/Tpm12.h>
 #include <IndustryStandard/Acpi.h>
-#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/PeImage2.h>
 #include <IndustryStandard/TcpaAcpi.h>
 
 #include <Guid/GlobalVariable.h>
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
index 0602acf702..ba5775198f 100644
--- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
+++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
@@ -53,7 +53,7 @@
   PlatformSecureLib
   DevicePathLib
   FileExplorerLib
-  PeCoffLib
+  UefiImageLib
   SecureBootVariableLib
   SecureBootVariableProvisionLib
 
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
index d4dc4e1402..dd953e63ac 100644
--- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
+++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
@@ -12,6 +12,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <UefiSecureBoot.h>
 #include <Protocol/HiiPopup.h>
 #include <Protocol/RealTimeClock.h>
+#include "Library/UefiImageLib.h"
 #include <Library/BaseCryptLib.h>
 #include <Library/SecureBootVariableLib.h>
 #include <Library/SecureBootVariableProvisionLib.h>
@@ -71,26 +72,25 @@ UINT8  mHashOidValue[] = {
   0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
 };
 
+//
+//  Support hash types
+//
+#define HASHALG_SHA256  0x00000001
+#define HASHALG_SHA384  0x00000002
+#define HASHALG_SHA512  0x00000003
+#define HASHALG_RAW     0x00000004
+#define HASHALG_MAX     0x00000004
+
 HASH_TABLE  mHash[] = {
-  { L"SHA224", 28, &mHashOidValue[13], 9, NULL,                 NULL,       NULL,         NULL        },
-  { L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final },
-  { L"SHA384", 48, &mHashOidValue[31], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final },
-  { L"SHA512", 64, &mHashOidValue[40], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final }
+  { L"SHA256", 32, &mHashOidValue[14], 9, &gEfiCertSha256Guid, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final },
+  { L"SHA384", 48, &mHashOidValue[23], 9, &gEfiCertSha384Guid, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final },
+  { L"SHA512", 64, &mHashOidValue[32], 9, &gEfiCertSha512Guid, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final }
 };
 
 //
 // Variable Definitions
 //
-UINT32                               mPeCoffHeaderOffset = 0;
-WIN_CERTIFICATE                      *mCertificate       = NULL;
-IMAGE_TYPE                           mImageType;
-UINT8                                *mImageBase = NULL;
-UINTN                                mImageSize  = 0;
-UINT8                                mImageDigest[MAX_DIGEST_SIZE];
-UINTN                                mImageDigestSize;
-EFI_GUID                             mCertType;
-EFI_IMAGE_SECURITY_DATA_DIRECTORY    *mSecDataDir = NULL;
-EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  mNtHeader;
+EFI_IMAGE_SECURITY_DATA_DIRECTORY  *mSecDataDir = NULL;
 
 //
 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
@@ -234,6 +234,8 @@ IsAuthentication2Format (
   EFI_STATUS                     Status;
   EFI_VARIABLE_AUTHENTICATION_2  *Auth2;
   BOOLEAN                        IsAuth2Format;
+  UINT8                          *ImageBase;
+  UINTN                          ImageSize;
 
   IsAuth2Format = FALSE;
 
@@ -242,15 +244,15 @@ IsAuthentication2Format (
   //
   Status = ReadFileContent (
              FileHandle,
-             (VOID **)&mImageBase,
-             &mImageSize,
+             (VOID **)&ImageBase,
+             &ImageSize,
              0
              );
   if (EFI_ERROR (Status)) {
     goto ON_EXIT;
   }
 
-  Auth2 = (EFI_VARIABLE_AUTHENTICATION_2 *)mImageBase;
+  Auth2 = (EFI_VARIABLE_AUTHENTICATION_2 *)ImageBase;
   if (Auth2->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) {
     goto ON_EXIT;
   }
@@ -263,9 +265,8 @@ ON_EXIT:
   //
   // Do not close File. simply check file content
   //
-  if (mImageBase != NULL) {
-    FreePool (mImageBase);
-    mImageBase = NULL;
+  if (ImageBase != NULL) {
+    FreePool (ImageBase);
   }
 
   return IsAuth2Format;
@@ -1683,151 +1684,11 @@ ON_EXIT:
   return IsFound;
 }
 
-/**
-  Reads contents of a PE/COFF image in memory buffer.
-
-  Caution: This function may receive untrusted input.
-  PE/COFF image is external input, so this function will make sure the PE/COFF image content
-  read is within the image buffer.
-
-  @param  FileHandle      Pointer to the file handle to read the PE/COFF image.
-  @param  FileOffset      Offset into the PE/COFF image to begin the read operation.
-  @param  ReadSize        On input, the size in bytes of the requested read operation.
-                          On output, the number of bytes actually read.
-  @param  Buffer          Output buffer that contains the data read from the PE/COFF image.
-
-  @retval EFI_SUCCESS     The specified portion of the PE/COFF image was read and the size
-**/
-EFI_STATUS
-EFIAPI
-SecureBootConfigImageRead (
-  IN     VOID   *FileHandle,
-  IN     UINTN  FileOffset,
-  IN OUT UINTN  *ReadSize,
-  OUT    VOID   *Buffer
-  )
-{
-  UINTN  EndPosition;
-
-  if ((FileHandle == NULL) || (ReadSize == NULL) || (Buffer == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (MAX_ADDRESS - FileOffset < *ReadSize) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  EndPosition = FileOffset + *ReadSize;
-  if (EndPosition > mImageSize) {
-    *ReadSize = (UINT32)(mImageSize - FileOffset);
-  }
-
-  if (FileOffset >= mImageSize) {
-    *ReadSize = 0;
-  }
-
-  CopyMem (Buffer, (UINT8 *)((UINTN)FileHandle + FileOffset), *ReadSize);
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Load PE/COFF image information into internal buffer and check its validity.
-
-  @retval   EFI_SUCCESS         Successful
-  @retval   EFI_UNSUPPORTED     Invalid PE/COFF file
-  @retval   EFI_ABORTED         Serious error occurs, like file I/O error etc.
-
-**/
-EFI_STATUS
-LoadPeImage (
-  VOID
-  )
-{
-  EFI_IMAGE_DOS_HEADER          *DosHdr;
-  EFI_IMAGE_NT_HEADERS32        *NtHeader32;
-  EFI_IMAGE_NT_HEADERS64        *NtHeader64;
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
-  EFI_STATUS                    Status;
-
-  NtHeader32 = NULL;
-  NtHeader64 = NULL;
-
-  ZeroMem (&ImageContext, sizeof (ImageContext));
-  ImageContext.Handle    = (VOID *)mImageBase;
-  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)SecureBootConfigImageRead;
-
-  //
-  // Get information about the image being loaded
-  //
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);
-  if (EFI_ERROR (Status)) {
-    //
-    // The information can't be got from the invalid PeImage
-    //
-    DEBUG ((DEBUG_INFO, "SecureBootConfigDxe: PeImage invalid. \n"));
-    return Status;
-  }
-
-  //
-  // Read the Dos header
-  //
-  DosHdr = (EFI_IMAGE_DOS_HEADER *)(mImageBase);
-  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
-    //
-    // DOS image header is present,
-    // So read the PE header after the DOS image header
-    //
-    mPeCoffHeaderOffset = DosHdr->e_lfanew;
-  } else {
-    mPeCoffHeaderOffset = 0;
-  }
-
-  //
-  // Read PE header and check the signature validity and machine compatibility
-  //
-  NtHeader32 = (EFI_IMAGE_NT_HEADERS32 *)(mImageBase + mPeCoffHeaderOffset);
-  if (NtHeader32->Signature != EFI_IMAGE_NT_SIGNATURE) {
-    return EFI_UNSUPPORTED;
-  }
-
-  mNtHeader.Pe32 = NtHeader32;
-
-  //
-  // Check the architecture field of PE header and get the Certificate Data Directory data
-  // Note the size of FileHeader field is constant for both IA32 and X64 arch
-  //
-  if (  (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32)
-     || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_EBC)
-     || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED))
-  {
-    //
-    // 32-bits Architecture
-    //
-    mImageType  = ImageType_IA32;
-    mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY *)&(NtHeader32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);
-  } else if (  (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64)
-            || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64)
-            || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_AARCH64))
-  {
-    //
-    // 64-bits Architecture
-    //
-    mImageType  = ImageType_X64;
-    NtHeader64  = (EFI_IMAGE_NT_HEADERS64 *)(mImageBase + mPeCoffHeaderOffset);
-    mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY *)&(NtHeader64->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);
-  } else {
-    return EFI_UNSUPPORTED;
-  }
-
-  return EFI_SUCCESS;
-}
-
 /**
   Calculate hash of Pe/Coff image based on the authenticode image hashing in
   PE/COFF Specification 8.0 Appendix A
 
-  Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in
+  Notes: PE/COFF image has been checked by UefiImageLibLib UefiImageInitializeContext() in
   the function LoadPeImage ().
 
   @param[in]    HashAlg   Hash algorithm type.
@@ -1838,254 +1699,56 @@ LoadPeImage (
 **/
 BOOLEAN
 HashPeImage (
-  IN  UINT32  HashAlg
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext,
+  IN  UINT32                       HashAlg,
+  UINT8                            ImageDigest[MAX_DIGEST_SIZE],
+  UINTN                            *ImageDigestSize
   )
 {
-  BOOLEAN                   Status;
-  EFI_IMAGE_SECTION_HEADER  *Section;
-  VOID                      *HashCtx;
-  UINTN                     CtxSize;
-  UINT8                     *HashBase;
-  UINTN                     HashSize;
-  UINTN                     SumOfBytesHashed;
-  EFI_IMAGE_SECTION_HEADER  *SectionHeader;
-  UINTN                     Index;
-  UINTN                     Pos;
+  BOOLEAN  Status;
+  VOID     *HashCtx;
+  UINTN    CtxSize;
 
-  HashCtx       = NULL;
-  SectionHeader = NULL;
-  Status        = FALSE;
+  ASSERT (HashAlg < HASHALG_MAX);
 
-  if ((HashAlg >= HASHALG_MAX)) {
-    return FALSE;
-  }
+  HashCtx = NULL;
+  Status  = FALSE;
 
   //
   // Initialize context of hash.
   //
-  ZeroMem (mImageDigest, MAX_DIGEST_SIZE);
-
-  switch (HashAlg) {
-    case HASHALG_SHA256:
-      mImageDigestSize = SHA256_DIGEST_SIZE;
-      mCertType        = gEfiCertSha256Guid;
-      break;
-
-    case HASHALG_SHA384:
-      mImageDigestSize = SHA384_DIGEST_SIZE;
-      mCertType        = gEfiCertSha384Guid;
-      break;
-
-    case HASHALG_SHA512:
-      mImageDigestSize = SHA512_DIGEST_SIZE;
-      mCertType        = gEfiCertSha512Guid;
-      break;
-
-    default:
-      return FALSE;
-  }
+  ZeroMem (ImageDigest, MAX_DIGEST_SIZE);
 
   CtxSize = mHash[HashAlg].GetContextSize ();
 
   HashCtx = AllocatePool (CtxSize);
-  ASSERT (HashCtx != NULL);
+  if (HashCtx == NULL) {
+    return FALSE;
+  }
 
-  // 1.  Load the image header into memory.
-
-  // 2.  Initialize a SHA hash context.
   Status = mHash[HashAlg].HashInit (HashCtx);
+
   if (!Status) {
     goto Done;
   }
 
-  //
-  // Measuring PE/COFF Image Header;
-  // But CheckSum field and SECURITY data directory (certificate) are excluded
-  //
+  Status = UefiImageHashImageDefault (ImageContext, HashCtx, mHash[HashAlg].HashUpdate);
 
-  //
-  // 3.  Calculate the distance from the base of the image header to the image checksum address.
-  // 4.  Hash the image header from its base to beginning of the image checksum.
-  //
-  HashBase = mImageBase;
-  if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-    //
-    // Use PE32 offset.
-    //
-    HashSize = (UINTN)(&mNtHeader.Pe32->OptionalHeader.CheckSum) - (UINTN)HashBase;
-  } else {
-    //
-    // Use PE32+ offset.
-    //
-    HashSize = (UINTN)(&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - (UINTN)HashBase;
-  }
-
-  Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
   if (!Status) {
+    DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Failed to hash this image using %s.\n", mHash[HashAlg].Name));
     goto Done;
   }
 
-  //
-  // 5.  Skip over the image checksum (it occupies a single ULONG).
-  // 6.  Get the address of the beginning of the Cert Directory.
-  // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.
-  //
-  if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-    //
-    // Use PE32 offset.
-    //
-    HashBase = (UINT8 *)&mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
-    HashSize = (UINTN)(&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
-  } else {
-    //
-    // Use PE32+ offset.
-    //
-    HashBase = (UINT8 *)&mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
-    HashSize = (UINTN)(&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN)HashBase;
-  }
+  ASSERT (mHash[HashAlg].DigestLength <= MAX_DIGEST_SIZE);
+  Status = mHash[HashAlg].HashFinal (HashCtx, ImageDigest);
 
-  Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
-  if (!Status) {
-    goto Done;
-  }
-
-  //
-  // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
-  // 9.  Hash everything from the end of the Cert Directory to the end of image header.
-  //
-  if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-    //
-    // Use PE32 offset
-    //
-    HashBase = (UINT8 *)&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
-    HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - ((UINTN)(&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINTN)mImageBase);
-  } else {
-    //
-    // Use PE32+ offset.
-    //
-    HashBase = (UINT8 *)&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
-    HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - ((UINTN)(&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINTN)mImageBase);
-  }
-
-  Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
-  if (!Status) {
-    goto Done;
-  }
-
-  //
-  // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
-  //
-  if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-    //
-    // Use PE32 offset.
-    //
-    SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;
-  } else {
-    //
-    // Use PE32+ offset
-    //
-    SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;
-  }
-
-  //
-  // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
-  //     structures in the image. The 'NumberOfSections' field of the image
-  //     header indicates how big the table should be. Do not include any
-  //     IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
-  //
-  SectionHeader = (EFI_IMAGE_SECTION_HEADER *)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);
-  ASSERT (SectionHeader != NULL);
-  //
-  // 12.  Using the 'PointerToRawData' in the referenced section headers as
-  //      a key, arrange the elements in the table in ascending order. In other
-  //      words, sort the section headers according to the disk-file offset of
-  //      the section.
-  //
-  Section = (EFI_IMAGE_SECTION_HEADER *)(
-                                         mImageBase +
-                                         mPeCoffHeaderOffset +
-                                         sizeof (UINT32) +
-                                         sizeof (EFI_IMAGE_FILE_HEADER) +
-                                         mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader
-                                         );
-  for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
-    Pos = Index;
-    while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
-      CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));
-      Pos--;
-    }
-
-    CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));
-    Section += 1;
-  }
-
-  //
-  // 13.  Walk through the sorted table, bring the corresponding section
-  //      into memory, and hash the entire section (using the 'SizeOfRawData'
-  //      field in the section header to determine the amount of data to hash).
-  // 14.  Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
-  // 15.  Repeat steps 13 and 14 for all the sections in the sorted table.
-  //
-  for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
-    Section = &SectionHeader[Index];
-    if (Section->SizeOfRawData == 0) {
-      continue;
-    }
-
-    HashBase = mImageBase + Section->PointerToRawData;
-    HashSize = (UINTN)Section->SizeOfRawData;
-
-    Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
-    if (!Status) {
-      goto Done;
-    }
-
-    SumOfBytesHashed += HashSize;
-  }
-
-  //
-  // 16.  If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
-  //      data in the file that needs to be added to the hash. This data begins
-  //      at file offset SUM_OF_BYTES_HASHED and its length is:
-  //             FileSize  -  (CertDirectory->Size)
-  //
-  if (mImageSize > SumOfBytesHashed) {
-    HashBase = mImageBase + SumOfBytesHashed;
-    if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-      //
-      // Use PE32 offset.
-      //
-      HashSize = (UINTN)(
-                         mImageSize -
-                         mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
-                         SumOfBytesHashed);
-    } else {
-      //
-      // Use PE32+ offset.
-      //
-      HashSize = (UINTN)(
-                         mImageSize -
-                         mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
-                         SumOfBytesHashed);
-    }
-
-    Status = mHash[HashAlg].HashUpdate (HashCtx, HashBase, HashSize);
-    if (!Status) {
-      goto Done;
-    }
-  }
-
-  Status = mHash[HashAlg].HashFinal (HashCtx, mImageDigest);
+  *ImageDigestSize = mHash[HashAlg].DigestLength;
 
 Done:
   if (HashCtx != NULL) {
     FreePool (HashCtx);
   }
 
-  if (SectionHeader != NULL) {
-    FreePool (SectionHeader);
-  }
-
   return Status;
 }
 
@@ -2100,36 +1763,41 @@ Done:
 **/
 EFI_STATUS
 HashPeImageByType (
-  VOID
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext,
+  IN CONST UINT8                   *AuthData,
+  IN UINTN                         AuthDataSize,
+  UINT8                            ImageDigest[MAX_DIGEST_SIZE],
+  UINTN                            *ImageDigestSize,
+  OUT CONST EFI_GUID               **CertType
   )
 {
-  UINT8                     Index;
-  WIN_CERTIFICATE_EFI_PKCS  *PkcsCertData;
+  UINT8  Index;
 
-  PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *)(mImageBase + mSecDataDir->Offset);
+  //
+  // Check the Hash algorithm in PE/COFF Authenticode.
+  //    According to PKCS#7 Definition:
+  //        SignedData ::= SEQUENCE {
+  //            version Version,
+  //            digestAlgorithms DigestAlgorithmIdentifiers,
+  //            contentInfo ContentInfo,
+  //            .... }
+  //    The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
+  //    This field has the fixed offset (+32) in final Authenticode ASN.1 data.
+  //    Fixed offset (+32) is calculated based on two bytes of length encoding.
+  //
+  if ((*(AuthData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
+    //
+    // Only support two bytes of Long Form of Length Encoding.
+    //
+    return EFI_UNSUPPORTED;
+  }
 
   for (Index = 0; Index < HASHALG_MAX; Index++) {
-    //
-    // Check the Hash algorithm in PE/COFF Authenticode.
-    //    According to PKCS#7 Definition:
-    //        SignedData ::= SEQUENCE {
-    //            version Version,
-    //            digestAlgorithms DigestAlgorithmIdentifiers,
-    //            contentInfo ContentInfo,
-    //            .... }
-    //    The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
-    //    This field has the fixed offset (+32) in final Authenticode ASN.1 data.
-    //    Fixed offset (+32) is calculated based on two bytes of length encoding.
-    //
-    if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
-      //
-      // Only support two bytes of Long Form of Length Encoding.
-      //
+    if (AuthDataSize < 32 + mHash[Index].OidLength) {
       continue;
     }
 
-    //
-    if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {
+    if (CompareMem (AuthData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {
       break;
     }
   }
@@ -2141,10 +1809,12 @@ HashPeImageByType (
   //
   // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
   //
-  if (!HashPeImage (Index)) {
+  if (!HashPeImage (ImageContext, Index, ImageDigest, ImageDigestSize)) {
     return EFI_UNSUPPORTED;
   }
 
+  *CertType = mHash[Index].CertType;
+
   return EFI_SUCCESS;
 }
 
@@ -2172,6 +1842,8 @@ EnrollAuthentication2Descriptor (
   VOID        *Data;
   UINTN       DataSize;
   UINT32      Attr;
+  UINT8       *ImageBase;
+  UINTN       ImageSize;
 
   Data = NULL;
 
@@ -2187,16 +1859,14 @@ EnrollAuthentication2Descriptor (
   //
   Status = ReadFileContent (
              Private->FileContext->FHandle,
-             (VOID **)&mImageBase,
-             &mImageSize,
+             (VOID **)&ImageBase,
+             &ImageSize,
              0
              );
   if (EFI_ERROR (Status)) {
     goto ON_EXIT;
   }
 
-  ASSERT (mImageBase != NULL);
-
   Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
          | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
 
@@ -2226,8 +1896,8 @@ EnrollAuthentication2Descriptor (
                   VariableName,
                   &gEfiImageSecurityDatabaseGuid,
                   Attr,
-                  mImageSize,
-                  mImageBase
+                  ImageSize,
+                  ImageBase
                   );
 
   DEBUG ((DEBUG_INFO, "Enroll AUTH_2 data to Var:%s Status: %x\n", VariableName, Status));
@@ -2240,9 +1910,8 @@ ON_EXIT:
     FreePool (Data);
   }
 
-  if (mImageBase != NULL) {
-    FreePool (mImageBase);
-    mImageBase = NULL;
+  if (ImageBase != NULL) {
+    FreePool (ImageBase);
   }
 
   return Status;
@@ -2268,16 +1937,24 @@ EnrollImageSignatureToSigDB (
   IN CHAR16                          *VariableName
   )
 {
-  EFI_STATUS                 Status;
-  EFI_SIGNATURE_LIST         *SigDBCert;
-  EFI_SIGNATURE_DATA         *SigDBCertData;
-  VOID                       *Data;
-  UINTN                      DataSize;
-  UINTN                      SigDBSize;
-  UINT32                     Attr;
-  WIN_CERTIFICATE_UEFI_GUID  *GuidCertData;
-  EFI_TIME                   Time;
-  UINT32                     HashAlg;
+  EFI_STATUS                       Status;
+  EFI_SIGNATURE_LIST               *SigDBCert;
+  EFI_SIGNATURE_DATA               *SigDBCertData;
+  VOID                             *Data;
+  UINTN                            DataSize;
+  UINTN                            SigDBSize;
+  UINT32                           Attr;
+  EFI_TIME                         Time;
+  UINT32                           HashAlg;
+  CONST WIN_CERTIFICATE_UEFI_GUID  *GuidCertData;
+  CONST WIN_CERTIFICATE            *Certificate;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT  ImageContext;
+  UINT8                            *ImageBase;
+  UINTN                            ImageSize;
+  UINT8                            ImageDigest[MAX_DIGEST_SIZE];
+  UINTN                            ImageDigestSize;
+  CONST EFI_GUID                   *CertType;
+  CONST WIN_CERTIFICATE_EFI_PKCS   *PkcsCertData;
 
   Data         = NULL;
   GuidCertData = NULL;
@@ -2300,22 +1977,22 @@ EnrollImageSignatureToSigDB (
   //
   Status = ReadFileContent (
              Private->FileContext->FHandle,
-             (VOID **)&mImageBase,
-             &mImageSize,
+             (VOID **)&ImageBase,
+             &ImageSize,
              0
              );
   if (EFI_ERROR (Status)) {
     goto ON_EXIT;
   }
 
-  ASSERT (mImageBase != NULL);
-
-  Status = LoadPeImage ();
+  Status = UefiImageInitializeContextPreHash (&ImageContext, ImageBase, (UINT32)ImageSize);
   if (EFI_ERROR (Status)) {
     goto ON_EXIT;
   }
 
-  if (mSecDataDir->SizeOfCert == 0) {
+  Status = UefiImageGetFirstCertificate (&ImageContext, &Certificate);
+
+  if (Status == RETURN_NOT_FOUND) {
     Status  = EFI_SECURITY_VIOLATION;
     HashAlg = sizeof (mHash) / sizeof (HASH_TABLE);
     while (HashAlg > 0) {
@@ -2324,7 +2001,7 @@ EnrollImageSignatureToSigDB (
         continue;
       }
 
-      if (HashPeImage (HashAlg)) {
+      if (HashPeImage (&ImageContext, HashAlg, ImageDigest, &ImageDigestSize)) {
         Status = EFI_SUCCESS;
         break;
       }
@@ -2335,24 +2012,21 @@ EnrollImageSignatureToSigDB (
       goto ON_EXIT;
     }
   } else {
-    //
-    // Read the certificate data
-    //
-    mCertificate = (WIN_CERTIFICATE *)(mImageBase + mSecDataDir->Offset);
-
-    if (mCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
-      GuidCertData = (WIN_CERTIFICATE_UEFI_GUID *)mCertificate;
+    if (Certificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
+      GuidCertData = (CONST WIN_CERTIFICATE_UEFI_GUID *)Certificate;
       if (CompareMem (&GuidCertData->CertType, &gEfiCertTypeRsa2048Sha256Guid, sizeof (EFI_GUID)) != 0) {
         Status = EFI_ABORTED;
         goto ON_EXIT;
       }
 
-      if (!HashPeImage (HASHALG_SHA256)) {
+      if (!HashPeImage (&ImageContext, HASHALG_SHA256, ImageDigest, &ImageDigestSize)) {
         Status = EFI_ABORTED;
         goto ON_EXIT;
       }
-    } else if (mCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
-      Status = HashPeImageByType ();
+    } else if (Certificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
+      PkcsCertData = (CONST WIN_CERTIFICATE_EFI_PKCS *)Certificate;
+
+      Status = HashPeImageByType (&ImageContext, PkcsCertData->CertData, PkcsCertData->Hdr.dwLength - sizeof (PkcsCertData->Hdr), ImageDigest, &ImageDigestSize, &CertType);
       if (EFI_ERROR (Status)) {
         goto ON_EXIT;
       }
@@ -2367,7 +2041,7 @@ EnrollImageSignatureToSigDB (
   //
   SigDBSize = sizeof (EFI_SIGNATURE_LIST)
               + sizeof (EFI_SIGNATURE_DATA) - 1
-              + (UINT32)mImageDigestSize;
+              + (UINT32)ImageDigestSize;
 
   Data = (UINT8 *)AllocateZeroPool (SigDBSize);
   if (Data == NULL) {
@@ -2381,12 +2055,12 @@ EnrollImageSignatureToSigDB (
   SigDBCert                      = (EFI_SIGNATURE_LIST *)Data;
   SigDBCert->SignatureListSize   = (UINT32)SigDBSize;
   SigDBCert->SignatureHeaderSize = 0;
-  SigDBCert->SignatureSize       = sizeof (EFI_SIGNATURE_DATA) - 1 + (UINT32)mImageDigestSize;
-  CopyGuid (&SigDBCert->SignatureType, &mCertType);
+  SigDBCert->SignatureSize       = sizeof (EFI_SIGNATURE_DATA) - 1 + (UINT32)ImageDigestSize;
+  CopyGuid (&SigDBCert->SignatureType, CertType);
 
   SigDBCertData = (EFI_SIGNATURE_DATA *)((UINT8 *)SigDBCert + sizeof (EFI_SIGNATURE_LIST));
   CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);
-  CopyMem (SigDBCertData->SignatureData, mImageDigest, mImageDigestSize);
+  CopyMem (SigDBCertData->SignatureData, ImageDigest, ImageDigestSize);
 
   Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS
          | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
@@ -2448,9 +2122,9 @@ ON_EXIT:
     FreePool (Data);
   }
 
-  if (mImageBase != NULL) {
-    FreePool (mImageBase);
-    mImageBase = NULL;
+  if (ImageBase != NULL) {
+    FreePool (ImageBase);
+    ImageBase = NULL;
   }
 
   return Status;
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h
index ff6e7301af..7ad3052a6a 100644
--- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h
+++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h
@@ -34,7 +34,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/PlatformSecureLib.h>
 #include <Library/BaseCryptLib.h>
 #include <Library/FileExplorerLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 
 #include <Guid/MdeModuleHii.h>
 #include <Guid/AuthenticatedVariableFormat.h>
@@ -85,16 +85,6 @@ extern  EFI_IFR_GUID_LABEL  *mEndLabel;
 #define WIN_CERT_UEFI_RSA3072_SIZE  384
 #define WIN_CERT_UEFI_RSA4096_SIZE  512
 
-//
-// Support hash types
-//
-#define HASHALG_SHA224  0x00000000
-#define HASHALG_SHA256  0x00000001
-#define HASHALG_SHA384  0x00000002
-#define HASHALG_SHA512  0x00000003
-#define HASHALG_RAW     0x00000004
-#define HASHALG_MAX     0x00000004
-
 //
 // Certificate public key minimum size (bytes)
 //
@@ -306,6 +296,7 @@ typedef struct {
   UINTN                    DigestLength;    ///< Digest Length
   UINT8                    *OidValue;       ///< Hash Algorithm OID ASN.1 Value
   UINTN                    OidLength;       ///< Length of Hash OID Value
+  CONST GUID               *CertType;       ///< GUID of the certificate type
   HASH_GET_CONTEXT_SIZE    GetContextSize;  ///< Pointer to Hash GetContentSize function
   HASH_INIT                HashInit;        ///< Pointer to Hash Init function
   HASH_UPDATE              HashUpdate;      ///< Pointer to Hash Update function
diff --git a/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.inf b/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.inf
index d9e1c23a1e..abe15b3f42 100644
--- a/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.inf
+++ b/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.inf
@@ -50,7 +50,6 @@
   DevicePathLib
   PerformanceLib
   DxeServicesLib
-  PeCoffGetEntryPointLib
 
 [Guids]
   gPerformanceProtocolGuid                                ## CONSUMES ## SystemTable
diff --git a/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf b/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf
index 2723fee706..290d1adebd 100644
--- a/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf
+++ b/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf
@@ -51,11 +51,11 @@
   DevicePathLib
   PerformanceLib
   DxeServicesLib
-  PeCoffGetEntryPointLib
 
 [Guids]
   gPerformanceProtocolGuid                                ## CONSUMES ## SystemTable
   gEdkiiFpdtExtendedFirmwarePerformanceGuid               ## CONSUMES ## SystemTable
+  gEfiDebugImageInfoTableGuid                             ## CONSUMES ## SystemTable
 
 [Protocols]
   gEfiLoadedImageProtocolGuid                             ## CONSUMES
diff --git a/ShellPkg/DynamicCommand/DpDynamicCommand/DpInternal.h b/ShellPkg/DynamicCommand/DpDynamicCommand/DpInternal.h
index 97f47f2960..3ce8d05d49 100644
--- a/ShellPkg/DynamicCommand/DpDynamicCommand/DpInternal.h
+++ b/ShellPkg/DynamicCommand/DpDynamicCommand/DpInternal.h
@@ -109,8 +109,8 @@ IsCorePerf (
 **/
 VOID
 DpGetShortPdbFileName (
-  IN  CHAR8   *PdbFileName,
-  OUT CHAR16  *UnicodeBuffer
+  IN  CONST CHAR8 *PdbFileName,
+  OUT CHAR16      *UnicodeBuffer
   );
 
 /**
diff --git a/ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c b/ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c
index 9c0a9a06a1..5cd28ff919 100644
--- a/ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c
+++ b/ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c
@@ -11,7 +11,7 @@
 #include <Library/MemoryAllocationLib.h>
 #include <Library/DebugLib.h>
 #include <Library/UefiBootServicesTableLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
+
 #include <Library/PerformanceLib.h>
 #include <Library/PrintLib.h>
 #include <Library/HiiLib.h>
diff --git a/ShellPkg/DynamicCommand/DpDynamicCommand/DpUtilities.c b/ShellPkg/DynamicCommand/DpDynamicCommand/DpUtilities.c
index 60c886c11d..240093dc26 100644
--- a/ShellPkg/DynamicCommand/DpDynamicCommand/DpUtilities.c
+++ b/ShellPkg/DynamicCommand/DpDynamicCommand/DpUtilities.c
@@ -11,7 +11,7 @@
 #include <Library/MemoryAllocationLib.h>
 #include <Library/DebugLib.h>
 #include <Library/UefiBootServicesTableLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
+
 #include <Library/PrintLib.h>
 #include <Library/HiiLib.h>
 #include <Library/PcdLib.h>
@@ -28,6 +28,7 @@
 #include <Protocol/DevicePath.h>
 
 #include <Guid/Performance.h>
+#include <Guid/DebugImageInfoTable.h>
 
 #include "Dp.h"
 #include "Literals.h"
@@ -148,8 +149,8 @@ IsCorePerf (
 **/
 VOID
 DpGetShortPdbFileName (
-  IN  CHAR8   *PdbFileName,
-  OUT CHAR16  *UnicodeBuffer
+  IN  CONST CHAR8 *PdbFileName,
+  OUT CHAR16      *UnicodeBuffer
   )
 {
   UINTN  IndexA;    // Current work location within an ASCII string.
@@ -188,6 +189,41 @@ DpGetShortPdbFileName (
   }
 }
 
+// FIXME: Duplicate (GetImageName), create API
+CONST CHAR8 *
+GetImagePdb (
+  IN CONST VOID  *ImageBase
+  )
+{
+  EFI_STATUS                          Status;
+  EFI_DEBUG_IMAGE_INFO_TABLE_HEADER   *DebugTableHeader;
+  EFI_DEBUG_IMAGE_INFO                *DebugTable;
+  UINTN                               Entry;
+
+  Status = EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid, (VOID **)&DebugTableHeader);
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  DebugTable = DebugTableHeader->EfiDebugImageInfoTable;
+  if (DebugTable == NULL) {
+    return NULL;
+  }
+
+  for (Entry = 0; Entry < DebugTableHeader->TableSize; Entry++, DebugTable++) {
+    if (DebugTable->NormalImage != NULL) {
+      if ((DebugTable->NormalImage->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) &&
+          (DebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) {
+        if (ImageBase == DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase) {
+          return DebugTable->NormalImage->PdbPath;
+        }
+      }
+    }
+  }
+
+  return NULL;
+}
+
 /**
   Get a human readable name for an image handle.
   The following methods will be tried orderly:
@@ -211,7 +247,7 @@ DpGetNameFromHandle (
 {
   EFI_STATUS                    Status;
   EFI_LOADED_IMAGE_PROTOCOL     *Image;
-  CHAR8                         *PdbFileName;
+  CONST CHAR8                  *PdbFileName;
   EFI_DRIVER_BINDING_PROTOCOL   *DriverBinding;
   EFI_STRING                    StringPtr;
   EFI_DEVICE_PATH_PROTOCOL      *LoadedImageDevicePath;
@@ -255,7 +291,7 @@ DpGetNameFromHandle (
   }
 
   if (!EFI_ERROR (Status)) {
-    PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);
+    PdbFileName = GetImagePdb (Image->ImageBase);
 
     if (PdbFileName != NULL) {
       DpGetShortPdbFileName (PdbFileName, mGaugeString);
diff --git a/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c b/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c
index 1e3ba1b0a9..13168a9872 100644
--- a/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c
+++ b/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c
@@ -309,7 +309,9 @@ LoadedImageProtocolDumpInformation (
     return NULL;
   }
 
-  PdbFileName = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);
+  // FIXME:
+  //PdbFileName = UefiImageLoaderGetPdbPointer (LoadedImage->ImageBase);
+  PdbFileName = NULL;
   DataType    = ConvertMemoryType (LoadedImage->ImageDataType);
   CodeType    = ConvertMemoryType (LoadedImage->ImageCodeType);
   if ((PdbFileName != NULL) && (DataType != NULL) && (CodeType != NULL) && (FilePath != NULL)) {
diff --git a/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h b/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h
index 6be0d78c4c..74aa3c88f6 100644
--- a/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h
+++ b/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h
@@ -148,7 +148,7 @@
 #include <Library/ShellLib.h>
 #include <Library/SortLib.h>
 #include <Library/ShellCommandLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
+
 
 #define   EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION_V1  1
 #define   EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION_V2  2
diff --git a/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf b/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
index 0d483805e7..f51b22516b 100644
--- a/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
+++ b/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
@@ -45,7 +45,6 @@
   UefiLib
   HiiLib
   SortLib
-  PeCoffGetEntryPointLib
 
 [Protocols]
   gEfiSimpleFileSystemProtocolGuid                        ## SOMETIMES_CONSUMES
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/LoadPciRom.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/LoadPciRom.c
index 40260ea3dc..1244668bbe 100644
--- a/ShellPkg/Library/UefiShellDebug1CommandsLib/LoadPciRom.c
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/LoadPciRom.c
@@ -10,7 +10,7 @@
 #include "UefiShellDebug1CommandsLib.h"
 #include <IndustryStandard/Pci22.h>
 #include <IndustryStandard/Pci23.h>
-#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/PeImage2.h>
 #include <Protocol/Decompress.h>
 
 /**
diff --git a/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h b/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h
index 1c002361de..6273491aee 100644
--- a/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h
+++ b/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h
@@ -54,7 +54,7 @@
 #include <Library/DevicePathLib.h>
 #include <Library/PrintLib.h>
 #include <Library/HandleParsingLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
+
 #include <Library/HandleParsingLib.h>
 
 extern        EFI_HII_HANDLE  gShellDriver1HiiHandle;
diff --git a/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf b/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
index e7661c3fce..518eb1a09e 100644
--- a/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
+++ b/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
@@ -50,7 +50,6 @@
   UefiBootServicesTableLib
   SortLib
   PrintLib
-  PeCoffGetEntryPointLib
 
 [Pcd]
   gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask  ## CONSUMES
diff --git a/ShellPkg/ShellPkg.dsc b/ShellPkg/ShellPkg.dsc
index 7e985f8280..9f22cdb4a3 100644
--- a/ShellPkg/ShellPkg.dsc
+++ b/ShellPkg/ShellPkg.dsc
@@ -53,7 +53,6 @@
   HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
   OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf
 
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
   AcpiViewCommandLib|ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
   IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
diff --git a/SignedCapsulePkg/SignedCapsulePkg.dsc b/SignedCapsulePkg/SignedCapsulePkg.dsc
index b38fd2da15..c840a1acb2 100644
--- a/SignedCapsulePkg/SignedCapsulePkg.dsc
+++ b/SignedCapsulePkg/SignedCapsulePkg.dsc
@@ -40,8 +40,8 @@
   PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
   PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
   CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
   #
   # UEFI & PI
@@ -75,7 +75,7 @@
   DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
   DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
   ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
   PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
index b553a2a9aa..8fc4c6d79b 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
@@ -183,30 +183,7 @@ IsDebugAgentInitialzed (
   }
 }
 
-/**
-  Find and report module image info to HOST.
-
-  @param[in] AlignSize      Image aligned size.
-
-**/
-VOID
-FindAndReportModuleImageInfo (
-  IN UINTN  AlignSize
-  )
-{
-  UINTN                         Pe32Data;
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
-
-  //
-  // Find Image Base
-  //
-  Pe32Data = PeCoffSearchImageBase ((UINTN)mErrorMsgVersionAlert);
-  if (Pe32Data != 0) {
-    ImageContext.ImageAddress = Pe32Data;
-    ImageContext.PdbPointer   = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress);
-    PeCoffLoaderRelocateImageExtraAction (&ImageContext);
-  }
-}
+// FIXME: UefiImageRelocExtra functio removed, done by *Core?
 
 /**
   Trigger one software interrupt to debug agent to handle it.
@@ -1315,7 +1292,7 @@ GetBreakCause (
           // triggered by the single step execution mode.
           // The single-step mode is the highest priority debug exception.
           // This is single step, no need to check DR0, to ensure single step
-          // work in PeCoffExtraActionLib (right after triggering a breakpoint
+        // work in UefiImageExtraActionLib (right after triggering a breakpoint
           // to report image load/unload).
           //
           return Cause;
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.h b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.h
index 4c72f8f3a9..fdbef964bd 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.h
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.h
@@ -26,8 +26,7 @@
 #include <Library/DebugLib.h>
 #include <Library/TimerLib.h>
 #include <Library/PrintLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
-#include <Library/PeCoffExtraActionLib.h>
+#include <Library/UefiImageExtraActionLib.h>
 #include <Register/ArchitecturalMsr.h>
 
 #include <TransferProtocol.h>
@@ -313,17 +312,6 @@ MultiProcessorDebugSupport (
   VOID
   );
 
-/**
-  Find and report module image info to HOST.
-
-  @param[in] AlignSize      Image aligned size.
-
-**/
-VOID
-FindAndReportModuleImageInfo (
-  IN UINTN  AlignSize
-  );
-
 /**
   Read IDT entry to check if IDT entries are setup by Debug Agent.
 
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.c b/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.c
index fcb1b631c1..c957e7558e 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.c
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.c
@@ -446,7 +446,6 @@ InitializeDebugAgent (
       EnableInterrupts ();
 
       mDebugAgentInitialized = TRUE;
-      FindAndReportModuleImageInfo (SIZE_4KB);
 
       *(EFI_STATUS *)Context = EFI_SUCCESS;
 
@@ -528,7 +527,6 @@ InitializeDebugAgent (
       // Disable interrupt
       //
       DisableInterrupts ();
-      FindAndReportModuleImageInfo (SIZE_4KB);
       if (GetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT) == 1) {
         //
         // If Boot Script entry break is set, code will be break at here.
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf b/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
index aa50048780..ba670014c6 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
+++ b/SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
@@ -69,8 +69,7 @@
   LocalApicLib
   TimerLib
   PrintLib
-  PeCoffGetEntryPointLib
-  PeCoffExtraActionLib
+  UefiImageExtraActionLib
   MemoryAllocationLib
 
 [Guids]
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c b/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c
index b32754fc2a..64e66b3d29 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c
+++ b/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c
@@ -575,10 +575,7 @@ InitializeDebugAgent (
       Phase2Context.InitFlag = InitFlag;
       Phase2Context.Context  = Context;
       Phase2Context.Function = Function;
-      DebugPortInitialize ((VOID *)&Phase2Context, InitializeDebugAgentPhase2);
-
-      FindAndReportModuleImageInfo (4);
-
+      DebugPortInitialize ((VOID *) &Phase2Context, InitializeDebugAgentPhase2);
       break;
 
     case DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64:
@@ -606,10 +603,7 @@ InitializeDebugAgent (
         // Update IDT entry to save location pointer saved the mailbox pointer
         //
         SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationPointer);
-
-        FindAndReportModuleImageInfo (4);
       }
-
       break;
 
     default:
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf b/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
index f91e2d01ad..da030e9bc7 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
+++ b/SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
@@ -66,8 +66,7 @@
   PrintLib
   PeiServicesLib
   MemoryAllocationLib
-  PeCoffGetEntryPointLib
-  PeCoffExtraActionLib
+  UefiImageExtraActionLib
 
 [Ppis]
   gEfiPeiMemoryDiscoveredPpiGuid                ## NOTIFY
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c b/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c
index cc5bb957f7..633d009ceb 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c
+++ b/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c
@@ -278,11 +278,6 @@ InitializeDebugAgent (
         //
         TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);
       }
-
-      //
-      // Find and report PE/COFF image info to HOST
-      //
-      FindAndReportModuleImageInfo (SIZE_4KB);
       //
       // Restore saved IDT entries
       //
@@ -396,10 +391,7 @@ InitializeDebugAgent (
         //
         SaveAndSetDebugTimerInterrupt (TRUE);
         EnableInterrupts ();
-
-        FindAndReportModuleImageInfo (SIZE_4KB);
       }
-
       break;
 
     default:
diff --git a/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf b/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf
index 2084b34a85..e4abdd50cd 100644
--- a/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf
+++ b/SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf
@@ -63,8 +63,7 @@
   LocalApicLib
   TimerLib
   PrintLib
-  PeCoffExtraActionLib
-  PeCoffGetEntryPointLib
+  UefiImageExtraActionLib
   SmmServicesTableLib
 
 [Guids]
diff --git a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/Ia32/IntHandler.nasm b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/Ia32/IntHandler.nasm
index 9442d3adc5..fc08898254 100644
--- a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/Ia32/IntHandler.nasm
+++ b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/Ia32/IntHandler.nasm
@@ -1,3 +1,5 @@
+#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
+
 ;------------------------------------------------------------------------------
 ;
 ; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
@@ -20,3 +22,5 @@ ASM_PFX(AsmInterruptHandle):
     cli
     mov   al, 1
     iretd
+
+#endif // DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c
index 2c80f7e22d..80ab235376 100644
--- a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c
+++ b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c
@@ -1,3 +1,5 @@
+#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
+
 /** @file
   PE/Coff Extra Action library instances.
 
@@ -27,7 +29,7 @@ IsDrxEnabled (
   IN  UINTN  Dr7
   )
 {
-  return (BOOLEAN)(((Dr7 >> (RegisterIndex * 2)) & (BIT0 | BIT1)) == (BIT0 | BIT1));
+  return (BOOLEAN) (((Dr7 >> (RegisterIndex * 2)) & (BIT0 | BIT1)) == (BIT0 | BIT1));
 }
 
 /**
@@ -46,25 +48,25 @@ PeCoffLoaderExtraActionCommon (
   IN     UINTN                         Signature
   )
 {
-  BOOLEAN                   InterruptState;
-  UINTN                     Dr0;
-  UINTN                     Dr1;
-  UINTN                     Dr2;
-  UINTN                     Dr3;
-  UINTN                     Dr7;
-  UINTN                     Cr4;
-  UINTN                     NewDr7;
-  UINT8                     LoadImageMethod;
-  UINT8                     DebugAgentStatus;
-  IA32_DESCRIPTOR           IdtDescriptor;
-  IA32_IDT_GATE_DESCRIPTOR  OriginalIdtEntry;
-  BOOLEAN                   IdtEntryHooked;
-  UINT32                    RegEdx;
+  BOOLEAN                    InterruptState;
+  UINTN                      Dr0;
+  UINTN                      Dr1;
+  UINTN                      Dr2;
+  UINTN                      Dr3;
+  UINTN                      Dr7;
+  UINTN                      Cr4;
+  UINTN                      NewDr7;
+  UINT8                      LoadImageMethod;
+  UINT8                      DebugAgentStatus;
+  IA32_DESCRIPTOR            IdtDescriptor;
+  IA32_IDT_GATE_DESCRIPTOR   OriginalIdtEntry;
+  BOOLEAN                    IdtEntryHooked;
+  UINT32                     RegEdx;
 
   ASSERT (ImageContext != NULL);
 
   if (ImageContext->PdbPointer != NULL) {
-    DEBUG ((DEBUG_ERROR, "    PDB = %a\n", ImageContext->PdbPointer));
+    DEBUG((EFI_D_ERROR, "    PDB = %a\n", ImageContext->PdbPointer));
   }
 
   //
@@ -84,7 +86,6 @@ PeCoffLoaderExtraActionCommon (
       LoadImageMethod = DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3;
     }
   }
-
   AsmReadIdtr (&IdtDescriptor);
   if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
     if (!CheckDebugAgentHandler (&IdtDescriptor, SOFT_INT_VECTOR_NUM)) {
@@ -123,8 +124,8 @@ PeCoffLoaderExtraActionCommon (
   //
   AsmWriteDr7 (BIT10);
   AsmWriteDr0 (Signature);
-  AsmWriteDr1 ((UINTN)ImageContext->PdbPointer);
-  AsmWriteDr2 ((UINTN)ImageContext);
+  AsmWriteDr1 ((UINTN) ImageContext->PdbPointer);
+  AsmWriteDr2 ((UINTN) ImageContext);
   AsmWriteDr3 (IO_PORT_BREAKPOINT_ADDRESS);
 
   if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
@@ -137,6 +138,7 @@ PeCoffLoaderExtraActionCommon (
     do {
       DebugAgentStatus = IoRead8 (IO_PORT_BREAKPOINT_ADDRESS);
     } while (DebugAgentStatus == DEBUG_AGENT_IMAGE_WAIT);
+
   } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
     //
     // Generate a software break point.
@@ -150,31 +152,26 @@ PeCoffLoaderExtraActionCommon (
   //       in the above exception handler
   //
   NewDr7 = AsmReadDr7 () | BIT10; // H/w sets bit 10, some simulators don't
-  if (!IsDrxEnabled (0, NewDr7) && ((AsmReadDr0 () == 0) || (AsmReadDr0 () == Signature))) {
+  if (!IsDrxEnabled (0, NewDr7) && (AsmReadDr0 () == 0 || AsmReadDr0 () == Signature)) {
     //
     // If user changed Dr3 (by setting HW bp in the above exception handler,
     // we will not set Dr0 to 0 in GO/STEP handler because the break cause is not IMAGE_LOAD/_UNLOAD.
     //
     AsmWriteDr0 (Dr0);
   }
-
-  if (!IsDrxEnabled (1, NewDr7) && (AsmReadDr1 () == (UINTN)ImageContext->PdbPointer)) {
+  if (!IsDrxEnabled (1, NewDr7) && (AsmReadDr1 () == (UINTN) ImageContext->PdbPointer)) {
     AsmWriteDr1 (Dr1);
   }
-
-  if (!IsDrxEnabled (2, NewDr7) && (AsmReadDr2 () == (UINTN)ImageContext)) {
+  if (!IsDrxEnabled (2, NewDr7) && (AsmReadDr2 () == (UINTN) ImageContext)) {
     AsmWriteDr2 (Dr2);
   }
-
   if (!IsDrxEnabled (3, NewDr7) && (AsmReadDr3 () == IO_PORT_BREAKPOINT_ADDRESS)) {
     AsmWriteDr3 (Dr3);
   }
-
   if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
     if (AsmReadCr4 () == (Cr4 | BIT3)) {
       AsmWriteCr4 (Cr4);
     }
-
     if (NewDr7 == 0x20000480) {
       AsmWriteDr7 (Dr7);
     }
@@ -183,14 +180,12 @@ PeCoffLoaderExtraActionCommon (
       AsmWriteDr7 (Dr7);
     }
   }
-
   //
   // Restore original IDT entry for INT1 if it was hooked.
   //
   if (IdtEntryHooked) {
     RestoreIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry);
   }
-
   //
   // Restore the interrupt state
   //
@@ -229,3 +224,5 @@ PeCoffLoaderUnloadImageExtraAction (
 {
   PeCoffLoaderExtraActionCommon (ImageContext, IMAGE_UNLOAD_SIGNATURE);
 }
+
+#endif // DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/X64/IntHandler.nasm b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/X64/IntHandler.nasm
index 6b3a7a526f..2aa9280797 100644
--- a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/X64/IntHandler.nasm
+++ b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/X64/IntHandler.nasm
@@ -1,3 +1,5 @@
+#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
+
 ;------------------------------------------------------------------------------
 ;
 ; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
@@ -21,3 +23,5 @@ ASM_PFX(AsmInterruptHandle):
     cli
     mov   al, 1
     iretq
+
+#endif // DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/Ia32/IntHandler.nasm b/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/Ia32/IntHandler.nasm
new file mode 100644
index 0000000000..9442d3adc5
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/Ia32/IntHandler.nasm
@@ -0,0 +1,22 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+;   IntHandler.nasm
+;
+; Abstract:
+;
+;   Assembly interrupt handler function.
+;
+;------------------------------------------------------------------------------
+
+global ASM_PFX(AsmInterruptHandle)
+
+SECTION .text
+ASM_PFX(AsmInterruptHandle):
+    cli
+    mov   al, 1
+    iretd
diff --git a/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/Ia32/IntHandlerFuncs.c b/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/Ia32/IntHandlerFuncs.c
new file mode 100644
index 0000000000..9e2934fda5
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/Ia32/IntHandlerFuncs.c
@@ -0,0 +1,93 @@
+/** @file
+  Ia32 arch functions to access IDT vector.
+
+  Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <UefiImageExtraActionLib.h>
+
+/**
+  Read IDT entry to check if IDT entries are setup by Debug Agent.
+
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.
+  @param[in]  InterruptType      Interrupt type.
+
+  @retval  TRUE     IDT entries were setup by Debug Agent.
+  @retval  FALSE    IDT entries were not setuo by Debug Agent.
+
+**/
+BOOLEAN
+CheckDebugAgentHandler (
+  IN  IA32_DESCRIPTOR  *IdtDescriptor,
+  IN  UINTN            InterruptType
+  )
+{
+  IA32_IDT_GATE_DESCRIPTOR  *IdtEntry;
+  UINTN                     InterruptHandler;
+
+  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)IdtDescriptor->Base;
+  if (IdtEntry == NULL) {
+    return FALSE;
+  }
+
+  InterruptHandler = IdtEntry[InterruptType].Bits.OffsetLow +
+                     (IdtEntry[InterruptType].Bits.OffsetHigh << 16);
+  if ((InterruptHandler >= sizeof (UINT32)) &&  (*(UINT32 *)(InterruptHandler - sizeof (UINT32)) == AGENT_HANDLER_SIGNATURE)) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Save IDT entry for INT1 and update it.
+
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.
+  @param[out] SavedIdtEntry      Original IDT entry returned.
+
+**/
+VOID
+SaveAndUpdateIdtEntry1 (
+  IN  IA32_DESCRIPTOR           *IdtDescriptor,
+  OUT IA32_IDT_GATE_DESCRIPTOR  *SavedIdtEntry
+  )
+{
+  IA32_IDT_GATE_DESCRIPTOR  *IdtEntry;
+  UINT16                    CodeSegment;
+  UINTN                     InterruptHandler;
+
+  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)IdtDescriptor->Base;
+  CopyMem (SavedIdtEntry, &IdtEntry[1], sizeof (IA32_IDT_GATE_DESCRIPTOR));
+
+  //
+  // Use current CS as the segment selector of interrupt gate in IDT
+  //
+  CodeSegment = AsmReadCs ();
+
+  InterruptHandler            = (UINTN)&AsmInterruptHandle;
+  IdtEntry[1].Bits.OffsetLow  = (UINT16)(UINTN)InterruptHandler;
+  IdtEntry[1].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
+  IdtEntry[1].Bits.Selector   = CodeSegment;
+  IdtEntry[1].Bits.GateType   = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+}
+
+/**
+  Restore IDT entry for INT1.
+
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.
+  @param[in]  RestoredIdtEntry   IDT entry to be restored.
+
+**/
+VOID
+RestoreIdtEntry1 (
+  IN  IA32_DESCRIPTOR           *IdtDescriptor,
+  IN  IA32_IDT_GATE_DESCRIPTOR  *RestoredIdtEntry
+  )
+{
+  IA32_IDT_GATE_DESCRIPTOR  *IdtEntry;
+
+  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)IdtDescriptor->Base;
+  CopyMem (&IdtEntry[1], RestoredIdtEntry, sizeof (IA32_IDT_GATE_DESCRIPTOR));
+}
diff --git a/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLib.c b/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLib.c
new file mode 100644
index 0000000000..35f7db1258
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLib.c
@@ -0,0 +1,241 @@
+/** @file
+  PE/Coff Extra Action library instances.
+
+  Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Library/UefiImageLib.h"
+#include "ProcessorBind.h"
+#include "Uefi/UefiBaseType.h"
+#include <UefiImageExtraActionLib.h>
+
+/**
+  Check if the hardware breakpoint in Drx is enabled by checking the Lx and Gx bit in Dr7.
+
+  It assumes that DebugAgent will set both Lx and Gx bit when setting up the hardware breakpoint.
+
+
+  @param  RegisterIndex  Index of Dr register. The value range is from 0 to 3.
+  @param  Dr7            Value of Dr7 register.
+
+  @return TRUE   The hardware breakpoint specified in the Drx is enabled.
+  @return FALSE  The hardware breakpoint specified in the Drx is disabled.
+
+**/
+BOOLEAN
+IsDrxEnabled (
+  IN  UINT8  RegisterIndex,
+  IN  UINTN  Dr7
+  )
+{
+  return (BOOLEAN)(((Dr7 >> (RegisterIndex * 2)) & (BIT0 | BIT1)) == (BIT0 | BIT1));
+}
+
+/**
+  Common routine to report the PE/COFF image loading/relocating or unloading event.
+
+  If ImageContext is NULL, then ASSERT().
+
+  @param  ImageContext  Pointer to the image context structure that describes the
+                        PE/COFF image.
+  @param  Signature     IMAGE_LOAD_SIGNATURE or IMAGE_UNLOAD_SIGNATURE.
+
+**/
+VOID
+UefiImageLoaderExtraActionCommon (
+  IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext,
+  IN UINTN                                  Signature
+  )
+{
+  BOOLEAN                   InterruptState;
+  UINTN                     Dr0;
+  UINTN                     Dr1;
+  UINTN                     Dr2;
+  UINTN                     Dr3;
+  UINTN                     Dr7;
+  UINTN                     Cr4;
+  UINTN                     NewDr7;
+  UINT8                     LoadImageMethod;
+  UINT8                     DebugAgentStatus;
+  IA32_DESCRIPTOR           IdtDescriptor;
+  IA32_IDT_GATE_DESCRIPTOR  OriginalIdtEntry;
+  BOOLEAN                   IdtEntryHooked;
+  UINT32                    RegEdx;
+  RETURN_STATUS              Status;
+  CONST CHAR8                *PdbPath;
+  UINT32                     PdbPathSize;
+  EFI_PHYSICAL_ADDRESS       ImageBase;
+
+  ASSERT (ImageContext != NULL);
+
+  Status = UefiImageGetSymbolsPath (ImageContext, &PdbPath, &PdbPathSize);
+  if (!RETURN_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "    PDB = %a\n", PdbPath));
+  }
+
+  //
+  // Disable interrupts and save the current interrupt state
+  //
+  InterruptState = SaveAndDisableInterrupts ();
+
+  IdtEntryHooked  = FALSE;
+  LoadImageMethod = PcdGet8 (PcdDebugLoadImageMethod);
+  if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
+    //
+    // If the CPU does not support Debug Extensions(CPUID:01 EDX:BIT2)
+    // then force use of DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3
+    //
+    AsmCpuid (1, NULL, NULL, NULL, &RegEdx);
+    if ((RegEdx & BIT2) == 0) {
+      LoadImageMethod = DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3;
+    }
+  }
+
+  AsmReadIdtr (&IdtDescriptor);
+  if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
+    if (!CheckDebugAgentHandler (&IdtDescriptor, SOFT_INT_VECTOR_NUM)) {
+      //
+      // Do not trigger INT3 if Debug Agent did not setup IDT entries.
+      //
+      return;
+    }
+  } else {
+    if (!CheckDebugAgentHandler (&IdtDescriptor, IO_HW_BREAKPOINT_VECTOR_NUM)) {
+      //
+      // Save and update IDT entry for INT1
+      //
+      SaveAndUpdateIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry);
+      IdtEntryHooked = TRUE;
+    }
+  }
+
+  ImageBase = UefiImageLoaderGetImageAddress (ImageContext);
+
+  //
+  // Save Debug Register State
+  //
+  Dr0 = AsmReadDr0 ();
+  Dr1 = AsmReadDr1 ();
+  Dr2 = AsmReadDr2 ();
+  Dr3 = AsmReadDr3 ();
+  Dr7 = AsmReadDr7 () | BIT10; // H/w sets bit 10, some simulators don't
+  Cr4 = AsmReadCr4 ();
+
+  //
+  // DR0 = Signature
+  // DR1 = The address of the Null-terminated ASCII string for the PE/COFF image's PDB file name
+  // DR2 = The pointer to the ImageBase address
+  // DR3 = IO_PORT_BREAKPOINT_ADDRESS
+  // DR7 = Disables all HW breakpoints except for DR3 I/O port access of length 1 byte
+  // CR4 = Make sure DE(BIT3) is set
+  //
+  AsmWriteDr7 (BIT10);
+  AsmWriteDr0 (Signature);
+  AsmWriteDr1 ((UINTN)PdbPath);
+  AsmWriteDr2 ((UINTN)&ImageBase);
+  AsmWriteDr3 (IO_PORT_BREAKPOINT_ADDRESS);
+
+  if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
+    AsmWriteDr7 (0x20000480);
+    AsmWriteCr4 (Cr4 | BIT3);
+    //
+    // Do an IN from IO_PORT_BREAKPOINT_ADDRESS to generate a HW breakpoint until the port
+    // returns a read value other than DEBUG_AGENT_IMAGE_WAIT
+    //
+    do {
+      DebugAgentStatus = IoRead8 (IO_PORT_BREAKPOINT_ADDRESS);
+    } while (DebugAgentStatus == DEBUG_AGENT_IMAGE_WAIT);
+  } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
+    //
+    // Generate a software break point.
+    //
+    CpuBreakpoint ();
+  }
+
+  //
+  // Restore Debug Register State only when Host didn't change it inside exception handler.
+  // E.g.: User halts the target and sets the HW breakpoint while target is
+  //       in the above exception handler
+  //
+  NewDr7 = AsmReadDr7 () | BIT10; // H/w sets bit 10, some simulators don't
+  if (!IsDrxEnabled (0, NewDr7) && ((AsmReadDr0 () == 0) || (AsmReadDr0 () == Signature))) {
+    //
+    // If user changed Dr3 (by setting HW bp in the above exception handler,
+    // we will not set Dr0 to 0 in GO/STEP handler because the break cause is not IMAGE_LOAD/_UNLOAD.
+    //
+    AsmWriteDr0 (Dr0);
+  }
+
+  if (!IsDrxEnabled (1, NewDr7) && (AsmReadDr1 () == (UINTN)PdbPath)) {
+    AsmWriteDr1 (Dr1);
+  }
+
+  if (!IsDrxEnabled (2, NewDr7) && (AsmReadDr2 () == (UINTN)&ImageBase)) {
+    AsmWriteDr2 (Dr2);
+  }
+
+  if (!IsDrxEnabled (3, NewDr7) && (AsmReadDr3 () == IO_PORT_BREAKPOINT_ADDRESS)) {
+    AsmWriteDr3 (Dr3);
+  }
+
+  if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
+    if (AsmReadCr4 () == (Cr4 | BIT3)) {
+      AsmWriteCr4 (Cr4);
+    }
+
+    if (NewDr7 == 0x20000480) {
+      AsmWriteDr7 (Dr7);
+    }
+  } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
+    if (NewDr7 == BIT10) {
+      AsmWriteDr7 (Dr7);
+    }
+  }
+
+  //
+  // Restore original IDT entry for INT1 if it was hooked.
+  //
+  if (IdtEntryHooked) {
+    RestoreIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry);
+  }
+
+  //
+  // Restore the interrupt state
+  //
+  SetInterruptState (InterruptState);
+}
+
+/**
+  Performs additional actions after a PE/COFF image has been loaded and relocated.
+
+  @param  ImageContext  Pointer to the image context structure that describes the
+                        PE/COFF image that has already been loaded and relocated.
+
+**/
+VOID
+EFIAPI
+UefiImageLoaderRelocateImageExtraAction (
+  IN CONST UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
+  )
+{
+  UefiImageLoaderExtraActionCommon (ImageContext, IMAGE_LOAD_SIGNATURE);
+}
+
+/**
+  Performs additional actions just before a PE/COFF image is unloaded.  Any resources
+  that were allocated by UefiImageLoaderRelocateImageExtraAction() must be freed.
+
+  @param  ImageContext  Pointer to the image context structure that describes the
+                        PE/COFF image that is being unloaded.
+
+**/
+VOID
+EFIAPI
+UefiImageLoaderUnloadImageExtraAction (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
+  )
+{
+  UefiImageLoaderExtraActionCommon (ImageContext, IMAGE_UNLOAD_SIGNATURE);
+}
diff --git a/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLib.h b/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLib.h
new file mode 100644
index 0000000000..594ad394aa
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLib.h
@@ -0,0 +1,72 @@
+/** @file
+  PE/Coff Extra Action library instances, it will report image debug info.
+
+  Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _UEFI_IMAGE_EXTRA_ACTION_LIB_H_
+#define _UEFI_IMAGE_EXTRA_ACTION_LIB_H_
+
+#include <Base.h>
+#include <Library/UefiImageExtraActionLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#include <ImageDebugSupport.h>
+
+#define DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT  1
+#define DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3         2
+
+#define IO_HW_BREAKPOINT_VECTOR_NUM  1
+#define SOFT_INT_VECTOR_NUM          3
+
+extern UINTN  AsmInterruptHandle;
+
+/**
+  Read IDT entry to check if IDT entries are setup by Debug Agent.
+
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.
+  @param[in]  InterruptType      Interrupt type.
+
+  @retval  TRUE     IDT entries were setup by Debug Agent.
+  @retval  FALSE    IDT entries were not setuo by Debug Agent.
+
+**/
+BOOLEAN
+CheckDebugAgentHandler (
+  IN  IA32_DESCRIPTOR  *IdtDescriptor,
+  IN  UINTN            InterruptType
+  );
+
+/**
+  Save IDT entry for INT1 and update it.
+
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.
+  @param[out] SavedIdtEntry      Original IDT entry returned.
+
+**/
+VOID
+SaveAndUpdateIdtEntry1 (
+  IN  IA32_DESCRIPTOR           *IdtDescriptor,
+  OUT IA32_IDT_GATE_DESCRIPTOR  *SavedIdtEntry
+  );
+
+/**
+  Restore IDT entry for INT1.
+
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.
+  @param[in]  RestoredIdtEntry   IDT entry to be restored.
+
+**/
+VOID
+RestoreIdtEntry1 (
+  IN  IA32_DESCRIPTOR           *IdtDescriptor,
+  IN  IA32_IDT_GATE_DESCRIPTOR  *RestoredIdtEntry
+  );
+
+#endif
diff --git a/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLib.uni b/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLib.uni
new file mode 100644
index 0000000000..f2ba4aa32d
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLib.uni
@@ -0,0 +1,15 @@
+// /** @file
+// UefiImageExtraAction Library to support source level debug.
+//
+// UefiImageExtraAction Library to support source level debug.
+//
+// Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "UefiImageExtraAction Library to support source level debug"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "UefiImageExtraAction Library to support source level debug."
diff --git a/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLibDebug.inf b/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLibDebug.inf
new file mode 100644
index 0000000000..82a3dc7971
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLibDebug.inf
@@ -0,0 +1,50 @@
+## @file
+#  UefiImageExtraAction Library to support source level debug.
+#
+#  Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = UefiImageExtraActionLib
+  MODULE_UNI_FILE                = UefiImageExtraActionLib.uni
+  FILE_GUID                      = 8F01CBD5-E069-44d7-90C9-35F0318603AD
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 0.8
+  LIBRARY_CLASS                  = UefiImageExtraActionLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources.common]
+  UefiImageExtraActionLib.h
+  UefiImageExtraActionLib.c
+
+[Sources.IA32]
+  Ia32/IntHandlerFuncs.c
+  Ia32/IntHandler.nasm
+
+[Sources.X64]
+  X64/IntHandlerFuncs.c
+  X64/IntHandler.nasm
+
+[Packages]
+  MdePkg/MdePkg.dec
+  SourceLevelDebugPkg/SourceLevelDebugPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  IoLib
+  PcdLib
+
+[Pcd]
+  gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod    ## CONSUMES
+
diff --git a/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/X64/IntHandler.nasm b/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/X64/IntHandler.nasm
new file mode 100644
index 0000000000..6b3a7a526f
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/X64/IntHandler.nasm
@@ -0,0 +1,23 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+;   IntHandler.nasm
+;
+; Abstract:
+;
+;   Assembly interrupt handler function.
+;
+;------------------------------------------------------------------------------
+
+global ASM_PFX(AsmInterruptHandle)
+
+DEFAULT REL
+SECTION .text
+ASM_PFX(AsmInterruptHandle):
+    cli
+    mov   al, 1
+    iretq
diff --git a/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/X64/IntHandlerFuncs.c b/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/X64/IntHandlerFuncs.c
new file mode 100644
index 0000000000..a518892d2c
--- /dev/null
+++ b/SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/X64/IntHandlerFuncs.c
@@ -0,0 +1,95 @@
+/** @file
+  X64 arch function to access IDT vector.
+
+  Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <UefiImageExtraActionLib.h>
+
+/**
+  Read IDT entry to check if IDT entries are setup by Debug Agent.
+
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.
+  @param[in]  InterruptType      Interrupt type.
+
+  @retval  TRUE     IDT entries were setup by Debug Agent.
+  @retval  FALSE    IDT entries were not setuo by Debug Agent.
+
+**/
+BOOLEAN
+CheckDebugAgentHandler (
+  IN  IA32_DESCRIPTOR  *IdtDescriptor,
+  IN  UINTN            InterruptType
+  )
+{
+  IA32_IDT_GATE_DESCRIPTOR  *IdtEntry;
+  UINTN                     InterruptHandler;
+
+  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)IdtDescriptor->Base;
+  if (IdtEntry == NULL) {
+    return FALSE;
+  }
+
+  InterruptHandler = IdtEntry[InterruptType].Bits.OffsetLow +
+                     (((UINTN)IdtEntry[InterruptType].Bits.OffsetHigh) << 16) +
+                     (((UINTN)IdtEntry[InterruptType].Bits.OffsetUpper) << 32);
+  if ((InterruptHandler >= sizeof (UINT32)) &&  (*(UINT32 *)(InterruptHandler - sizeof (UINT32)) == AGENT_HANDLER_SIGNATURE)) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Save IDT entry for INT1 and update it.
+
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.
+  @param[out] SavedIdtEntry      Original IDT entry returned.
+
+**/
+VOID
+SaveAndUpdateIdtEntry1 (
+  IN  IA32_DESCRIPTOR           *IdtDescriptor,
+  OUT IA32_IDT_GATE_DESCRIPTOR  *SavedIdtEntry
+  )
+{
+  IA32_IDT_GATE_DESCRIPTOR  *IdtEntry;
+  UINT16                    CodeSegment;
+  UINTN                     InterruptHandler;
+
+  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)IdtDescriptor->Base;
+  CopyMem (SavedIdtEntry, &IdtEntry[1], sizeof (IA32_IDT_GATE_DESCRIPTOR));
+
+  //
+  // Use current CS as the segment selector of interrupt gate in IDT
+  //
+  CodeSegment = AsmReadCs ();
+
+  InterruptHandler             = (UINTN)&AsmInterruptHandle;
+  IdtEntry[1].Bits.OffsetLow   = (UINT16)(UINTN)InterruptHandler;
+  IdtEntry[1].Bits.OffsetHigh  = (UINT16)((UINTN)InterruptHandler >> 16);
+  IdtEntry[1].Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32);
+  IdtEntry[1].Bits.Selector    = CodeSegment;
+  IdtEntry[1].Bits.GateType    = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+}
+
+/**
+  Restore IDT entry for INT1.
+
+  @param[in]  IdtDescriptor      Pointer to IDT Descriptor.
+  @param[in]  RestoredIdtEntry   IDT entry to be restored.
+
+**/
+VOID
+RestoreIdtEntry1 (
+  IN  IA32_DESCRIPTOR           *IdtDescriptor,
+  IN  IA32_IDT_GATE_DESCRIPTOR  *RestoredIdtEntry
+  )
+{
+  IA32_IDT_GATE_DESCRIPTOR  *IdtEntry;
+
+  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)IdtDescriptor->Base;
+  CopyMem (&IdtEntry[1], RestoredIdtEntry, sizeof (IA32_IDT_GATE_DESCRIPTOR));
+}
diff --git a/SourceLevelDebugPkg/SourceLevelDebugPkg.dec b/SourceLevelDebugPkg/SourceLevelDebugPkg.dec
index 564aca6e7c..a743a69bfe 100644
--- a/SourceLevelDebugPkg/SourceLevelDebugPkg.dec
+++ b/SourceLevelDebugPkg/SourceLevelDebugPkg.dec
@@ -3,7 +3,7 @@
 # The target side components includes the Debug Agent Library instance
 # to communicate with host side modules, Debug Communication Library and
 # instances to provide the communication I/O functions between Debug Agent
-# and host, PeCoffExtraActionLib instance to report symbol path information,
+# and host, UefiImageExtraActionLib instance to report symbol path information,
 # etc.
 #
 # Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
diff --git a/SourceLevelDebugPkg/SourceLevelDebugPkg.dsc b/SourceLevelDebugPkg/SourceLevelDebugPkg.dsc
index 986dd5a769..744b9527b4 100644
--- a/SourceLevelDebugPkg/SourceLevelDebugPkg.dsc
+++ b/SourceLevelDebugPkg/SourceLevelDebugPkg.dsc
@@ -35,9 +35,9 @@
   IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
   LocalApicLib|UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+  UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
   SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
-  PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
+  UefiImageExtraActionLib|SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLibDebug.inf
   TimerLib|UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.inf
   ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
   PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
@@ -100,7 +100,7 @@
   SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Pei.inf
   SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
   SourceLevelDebugPkg/Library/DebugCommunicationLibUsb/DebugCommunicationLibUsb.inf
-  SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
+  SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLibDebug.inf
   SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
   SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
   SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf
diff --git a/SourceLevelDebugPkg/SourceLevelDebugPkg.uni b/SourceLevelDebugPkg/SourceLevelDebugPkg.uni
index 8d2f06eb4e..2613c5fd2e 100644
--- a/SourceLevelDebugPkg/SourceLevelDebugPkg.uni
+++ b/SourceLevelDebugPkg/SourceLevelDebugPkg.uni
@@ -5,7 +5,7 @@
 // The target side components includes the Debug Agent Library instance
 // to communicate with host side modules, Debug Communication Library and
 // instances to provide the communication I/O functions between Debug Agent
-// and host, PeCoffExtraActionLib instance to report symbol path information,
+// and host, UefiImageExtraActionLib instance to report symbol path information,
 // etc.
 //
 // Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
@@ -20,7 +20,7 @@
 #string STR_PACKAGE_DESCRIPTION         #language en-US "The target side components includes the Debug Agent Library instance\n"
                                                         "to communicate with host side modules, Debug Communication Library and\n"
                                                         "instances to provide the communication I/O functions between Debug Agent\n"
-                                                        "and host, PeCoffExtraActionLib instance to report symbol path information,\n"
+                                                        "and host, UefiImageExtraActionLib instance to report symbol path information,\n"
                                                         "etc."
 
 
diff --git a/StandaloneMmPkg/Core/Dispatcher.c b/StandaloneMmPkg/Core/Dispatcher.c
index b686c31aaf..eeed408eb6 100644
--- a/StandaloneMmPkg/Core/Dispatcher.c
+++ b/StandaloneMmPkg/Core/Dispatcher.c
@@ -36,6 +36,7 @@
 
 **/
 
+#include "ProcessorBind.h"
 #include "StandaloneMmCore.h"
 
 //
@@ -97,6 +98,76 @@ BOOLEAN  gDispatcherRunning = FALSE;
 //
 BOOLEAN  gRequestDispatch = FALSE;
 
+STATIC
+RETURN_STATUS
+InternalProtectMmImage (
+  IN OUT UEFI_IMAGE_LOADER_IMAGE_CONTEXT  *ImageContext
+  )
+{
+  UEFI_IMAGE_RECORD       *ImageRecord;
+  UINTN                   SectionAddress;
+  UINT32                  SectionIndex;
+
+  if (UefiImageGetSegmentAlignment (ImageContext) < EFI_PAGE_SIZE) {
+    // FIXME: PCD to abort loading?
+    //
+    // The sections need to be at least 4 KB aligned, since that is the
+    // granularity at which we can tighten permissions. So just clear the
+    // noexec permissions on the entire region.
+    //
+    DEBUG ((DEBUG_WARN,
+      "%a: Image at 0x%lx has SectionAlignment < 4 KB (%lu)\n",
+      __FUNCTION__, UefiImageLoaderGetImageAddress (ImageContext), UefiImageGetSegmentAlignment (ImageContext)));
+
+    ASSERT ((UefiImageLoaderGetImageAddress (ImageContext) & (EFI_PAGE_SIZE - 1)) == 0);
+
+    ClearMemoryRegionNoExec (
+      UefiImageLoaderGetImageAddress (ImageContext),
+      ALIGN_VALUE (UefiImageGetImageSize (ImageContext), EFI_PAGE_SIZE)
+      );
+
+    return RETURN_SUCCESS;
+  }
+
+  ImageRecord = UefiImageLoaderGetImageRecord (ImageContext);
+  if (ImageRecord == NULL) {
+    return RETURN_OUT_OF_RESOURCES;
+  }
+  //
+  // Images are loaded into RW memory, thus only +X and -W need to be handled.
+  //
+  SectionAddress = ImageRecord->StartAddress;
+  for (SectionIndex = 0; SectionIndex < ImageRecord->NumSegments; ++ SectionIndex) {
+    DEBUG ((DEBUG_INFO,
+      "%a: Mapping segment of image at 0x%lx with %s-%s permissions and size 0x%x\n",
+      __FUNCTION__, SectionAddress,
+      (ImageRecord->Segments[SectionIndex].Attributes & EFI_MEMORY_RO) != 0 ? "RO" : "RW",
+      (ImageRecord->Segments[SectionIndex].Attributes & EFI_MEMORY_XP) != 0 ? "XN" : "X",
+      ImageRecord->Segments[SectionIndex].Size));
+
+    // FIXME: What about their return values?
+    if ((ImageRecord->Segments[SectionIndex].Attributes & EFI_MEMORY_RO) != 0) {
+      SetMemoryRegionReadOnly (
+        SectionAddress,
+        ImageRecord->Segments[SectionIndex].Size
+        );
+    }
+
+    if ((ImageRecord->Segments[SectionIndex].Attributes & EFI_MEMORY_XP) == 0) {
+      ClearMemoryRegionNoExec (
+        SectionAddress,
+        ImageRecord->Segments[SectionIndex].Size
+        );
+    }
+
+    SectionAddress += ImageRecord->Segments[SectionIndex].Size;
+  }
+
+  FreePool (ImageRecord);
+
+  return RETURN_SUCCESS;
+}
+
 /**
   Loads an EFI image into SMRAM.
 
@@ -113,9 +184,12 @@ MmLoadImage (
   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
   )
 {
-  UINTN                 PageCount;
-  EFI_STATUS            Status;
-  EFI_PHYSICAL_ADDRESS  DstBuffer;
+  UINT32      ImageSize;
+  UINT32      ImageAlignment;
+  EFI_STATUS  Status;
+  VOID        *DstBuffer;
+  UINT32      DstBufferPages;
+  UINT32      DstBufferSize;
 
   DEBUG ((DEBUG_INFO, "MmLoadImage - %g\n", &DriverEntry->FileName));
 
@@ -125,73 +199,39 @@ MmLoadImage (
 
   Status = EFI_SUCCESS;
 
-  //
-  // Initialize ImageContext
-  //
-  ImageContext->Handle    = DriverEntry->Pe32Data;
-  ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory;
-
   //
   // Get information about the image being loaded
   //
-  Status = PeCoffLoaderGetImageInfo (ImageContext);
+  Status = UefiImageInitializeContext (ImageContext, DriverEntry->Pe32Data, DriverEntry->Pe32DataSize);
   if (EFI_ERROR (Status)) {
     return Status;
   }
 
-  PageCount = (UINTN)EFI_SIZE_TO_PAGES ((UINTN)ImageContext->ImageSize + ImageContext->SectionAlignment);
-  DstBuffer = (UINTN)(-1);
+  ImageSize      = UefiImageGetImageSize (ImageContext);
+  DstBufferPages = EFI_SIZE_TO_PAGES (ImageSize);
+  DstBufferSize  = EFI_PAGES_TO_SIZE (DstBufferPages);
+  ImageAlignment = UefiImageGetSegmentAlignment (ImageContext);
 
-  Status = MmAllocatePages (
-             AllocateMaxAddress,
-             EfiRuntimeServicesCode,
-             PageCount,
-             &DstBuffer
-             );
-  if (EFI_ERROR (Status)) {
-    ASSERT_EFI_ERROR (Status);
-    return Status;
+  DstBuffer = AllocateAlignedCodePages (DstBufferPages, ImageAlignment);
+  if (DstBuffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
   }
 
-  ImageContext->ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;
-
-  //
-  // Align buffer on section boundary
-  //
-  ImageContext->ImageAddress += ImageContext->SectionAlignment - 1;
-  ImageContext->ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)(ImageContext->SectionAlignment - 1));
-
   //
   // Load the image to our new buffer
   //
-  Status = PeCoffLoaderLoadImage (ImageContext);
+  Status = UefiImageLoadImageForExecution (ImageContext, DstBuffer, DstBufferSize, NULL, 0);
   if (EFI_ERROR (Status)) {
-    MmFreePages (DstBuffer, PageCount);
+    FreeAlignedPages (DstBuffer, DstBufferPages);
     return Status;
   }
 
-  //
-  // Relocate the image in our new buffer
-  //
-  Status = PeCoffLoaderRelocateImage (ImageContext);
-  if (EFI_ERROR (Status)) {
-    // if relocate fails, we don't need to call unload image here, as the extra action that may change page attributes
-    // only is called on a successful return
-    MmFreePages (DstBuffer, PageCount);
-    return Status;
-  }
-
-  //
-  // Flush the instruction cache so the image data are written before we execute it
-  //
-  InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext->ImageAddress, (UINTN)ImageContext->ImageSize);
-
   //
   // Save Image EntryPoint in DriverEntry
   //
-  DriverEntry->ImageEntryPoint = ImageContext->EntryPoint;
-  DriverEntry->ImageBuffer     = DstBuffer;
-  DriverEntry->NumberOfPage    = PageCount;
+  DriverEntry->ImageEntryPoint = UefiImageLoaderGetImageEntryPoint (ImageContext);
+  DriverEntry->ImageBuffer     = (UINTN)DstBuffer;
+  DriverEntry->NumberOfPage    = DstBufferPages;
 
   //
   // Fill in the remaining fields of the Loaded Image Protocol instance.
@@ -203,8 +243,8 @@ MmLoadImage (
   DriverEntry->LoadedImage.DeviceHandle = NULL;
   DriverEntry->LoadedImage.FilePath     = NULL;
 
-  DriverEntry->LoadedImage.ImageBase     = (VOID *)(UINTN)DriverEntry->ImageBuffer;
-  DriverEntry->LoadedImage.ImageSize     = ImageContext->ImageSize;
+  DriverEntry->LoadedImage.ImageBase     = DstBuffer;
+  DriverEntry->LoadedImage.ImageSize     = ImageSize;
   DriverEntry->LoadedImage.ImageCodeType = EfiRuntimeServicesCode;
   DriverEntry->LoadedImage.ImageDataType = EfiRuntimeServicesData;
 
@@ -218,58 +258,32 @@ MmLoadImage (
     &DriverEntry->LoadedImage
     );
 
+  InternalProtectMmImage (ImageContext);
+
   //
   // Print the load address and the PDB file name if it is available
   //
   DEBUG_CODE_BEGIN ();
 
-  UINTN  Index;
-  UINTN  StartIndex;
   CHAR8  EfiFileName[256];
 
   DEBUG ((
     DEBUG_INFO | DEBUG_LOAD,
     "Loading MM driver at 0x%11p EntryPoint=0x%11p ",
-    (VOID *)(UINTN)ImageContext->ImageAddress,
-    FUNCTION_ENTRY_POINT (ImageContext->EntryPoint)
+    DstBuffer,
+    FUNCTION_ENTRY_POINT (UefiImageLoaderGetImageEntryPoint (ImageContext))
     ));
 
+  Status = UefiImageGetModuleNameFromSymbolsPath (
+             ImageContext,
+             EfiFileName,
+             sizeof (EfiFileName)
+             );
+
   //
   // Print Module Name by Pdb file path.
-  // Windows and Unix style file path are all trimmed correctly.
   //
-  if (ImageContext->PdbPointer != NULL) {
-    StartIndex = 0;
-    for (Index = 0; ImageContext->PdbPointer[Index] != 0; Index++) {
-      if ((ImageContext->PdbPointer[Index] == '\\') || (ImageContext->PdbPointer[Index] == '/')) {
-        StartIndex = Index + 1;
-      }
-    }
-
-    //
-    // Copy the PDB file name to our temporary string, and replace .pdb with .efi
-    // The PDB file name is limited in the range of 0~255.
-    // If the length is bigger than 255, trim the redundant characters to avoid overflow in array boundary.
-    //
-    for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {
-      EfiFileName[Index] = ImageContext->PdbPointer[Index + StartIndex];
-      if (EfiFileName[Index] == 0) {
-        EfiFileName[Index] = '.';
-      }
-
-      if (EfiFileName[Index] == '.') {
-        EfiFileName[Index + 1] = 'e';
-        EfiFileName[Index + 2] = 'f';
-        EfiFileName[Index + 3] = 'i';
-        EfiFileName[Index + 4] = 0;
-        break;
-      }
-    }
-
-    if (Index == sizeof (EfiFileName) - 4) {
-      EfiFileName[Index] = 0;
-    }
-
+  if (!EFI_ERROR (Status)) {
     DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName));
   }
 
@@ -699,7 +713,7 @@ EFI_STATUS
 MmAddToDriverList (
   IN EFI_FIRMWARE_VOLUME_HEADER  *FwVolHeader,
   IN VOID                        *Pe32Data,
-  IN UINTN                       Pe32DataSize,
+  IN UINT32                      Pe32DataSize,
   IN VOID                        *Depex,
   IN UINTN                       DepexSize,
   IN EFI_GUID                    *DriverName
diff --git a/StandaloneMmPkg/Core/FwVol.c b/StandaloneMmPkg/Core/FwVol.c
index d5dfdacbf0..d059329204 100644
--- a/StandaloneMmPkg/Core/FwVol.c
+++ b/StandaloneMmPkg/Core/FwVol.c
@@ -19,7 +19,7 @@ EFI_STATUS
 MmAddToDriverList (
   IN EFI_FIRMWARE_VOLUME_HEADER  *FwVolHeader,
   IN VOID                        *Pe32Data,
-  IN UINTN                       Pe32DataSize,
+  IN UINT32                      Pe32DataSize,
   IN VOID                        *Depex,
   IN UINTN                       DepexSize,
   IN EFI_GUID                    *DriverName
@@ -65,12 +65,12 @@ MmCoreFfsFindMmDriver (
   EFI_STATUS                  DepexStatus;
   EFI_FFS_FILE_HEADER         *FileHeader;
   VOID                        *Pe32Data;
-  UINTN                       Pe32DataSize;
+  UINT32                      Pe32DataSize;
   VOID                        *Depex;
-  UINTN                       DepexSize;
+  UINT32                      DepexSize;
   EFI_COMMON_SECTION_HEADER   *Section;
   VOID                        *SectionData;
-  UINTN                       SectionDataSize;
+  UINT32                      SectionDataSize;
   UINT32                      DstBufferSize;
   VOID                        *ScratchBuffer;
   UINT32                      ScratchBufferSize;
diff --git a/StandaloneMmPkg/Core/StandaloneMmCore.h b/StandaloneMmPkg/Core/StandaloneMmCore.h
index 24574b254c..de7cdf50ab 100644
--- a/StandaloneMmPkg/Core/StandaloneMmCore.h
+++ b/StandaloneMmPkg/Core/StandaloneMmCore.h
@@ -34,9 +34,10 @@
 #include <Guid/PiSmmMemoryAttributesTable.h>
 
 #include <Library/StandaloneMmCoreEntryPoint.h>
+#include <Library/StandaloneMmProtectionLib.h>
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/CacheMaintenanceLib.h>
 #include <Library/DebugLib.h>
 #include <Library/ReportStatusCodeLib.h>
@@ -74,7 +75,7 @@ typedef struct {
   EFI_FIRMWARE_VOLUME_HEADER    *FwVolHeader;
   EFI_GUID                      FileName;
   VOID                          *Pe32Data;
-  UINTN                         Pe32DataSize;
+  UINT32                          Pe32DataSize;
 
   VOID                          *Depex;
   UINTN                         DepexSize;
diff --git a/StandaloneMmPkg/Core/StandaloneMmCore.inf b/StandaloneMmPkg/Core/StandaloneMmCore.inf
index aca21a7e20..ec9283df7a 100644
--- a/StandaloneMmPkg/Core/StandaloneMmCore.inf
+++ b/StandaloneMmPkg/Core/StandaloneMmCore.inf
@@ -50,8 +50,9 @@
   HobLib
   MemoryAllocationLib
   MemLib
-  PeCoffLib
+  UefiImageLib
   ReportStatusCodeLib
+  StandaloneMmProtectionLib
   StandaloneMmCoreEntryPoint
   HobPrintLib
   ImagePropertiesRecordLib
@@ -88,13 +89,10 @@
   gStandaloneMmPkgTokenSpaceGuid.PcdShadowBfv    ##CONSUMES
 
 #
-# This configuration fails for CLANGPDB, which does not support PIE in the GCC
-# sense. Such however is required for ARM family StandaloneMmCore
-# self-relocation, and thus the CLANGPDB toolchain is unsupported for ARM and
-# AARCH64 for this module.
+# This configuration fails for CLANGDPB, which does not support PIE in the GCC
+# sense. Such however is required for AArch64 StandaloneMmCore self-relocation,
+# and thus the CLANGPDB toolchain is unsupported for AArch64 for this module.
 #
 [BuildOptions]
-  GCC:*_*_ARM_CC_FLAGS = -fpie
-  GCC:*_*_ARM_DLINK_FLAGS = -Wl,-z,text,-Bsymbolic,-pie
   GCC:*_*_AARCH64_CC_FLAGS = -fpie
   GCC:*_*_AARCH64_DLINK_FLAGS = -Wl,-z,text,-Bsymbolic,-pie
diff --git a/StandaloneMmPkg/Include/Library/FvLib.h b/StandaloneMmPkg/Include/Library/FvLib.h
index 3b603e473d..2c951b4691 100644
--- a/StandaloneMmPkg/Include/Library/FvLib.h
+++ b/StandaloneMmPkg/Include/Library/FvLib.h
@@ -98,7 +98,7 @@ FfsFindSectionData (
   IN EFI_SECTION_TYPE     SectionType,
   IN EFI_FFS_FILE_HEADER  *FfsFileHeader,
   OUT VOID                **SectionData,
-  OUT UINTN               *SectionDataSize
+  OUT UINT32                       *SectionDataSize
   );
 
 #endif
diff --git a/StandaloneMmPkg/Include/Library/StandaloneMmProtectionLib.h b/StandaloneMmPkg/Include/Library/StandaloneMmProtectionLib.h
new file mode 100644
index 0000000000..395aaff910
--- /dev/null
+++ b/StandaloneMmPkg/Include/Library/StandaloneMmProtectionLib.h
@@ -0,0 +1,30 @@
+// FIXME: docs
+
+#ifndef STANDALONE_MM_PROTECTION_LIB_H_
+#define STANDALONE_MM_PROTECTION_LIB_H_
+
+EFI_STATUS
+SetMemoryRegionNoExec (
+  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN UINT64                Length
+  );
+
+EFI_STATUS
+ClearMemoryRegionNoExec (
+  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN UINT64                Length
+  );
+
+EFI_STATUS
+SetMemoryRegionReadOnly (
+  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN UINT64                Length
+  );
+
+EFI_STATUS
+ClearMemoryRegionReadOnly (
+  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN UINT64                Length
+  );
+
+#endif // STANDALONE_MM_PROTECTION_LIB_H_
diff --git a/StandaloneMmPkg/Library/FvLib/FvLib.c b/StandaloneMmPkg/Library/FvLib/FvLib.c
index 2faa7cd054..5693031758 100644
--- a/StandaloneMmPkg/Library/FvLib/FvLib.c
+++ b/StandaloneMmPkg/Library/FvLib/FvLib.c
@@ -353,7 +353,7 @@ FfsFindSectionData (
   IN EFI_SECTION_TYPE     SectionType,
   IN EFI_FFS_FILE_HEADER  *FfsFileHeader,
   IN OUT VOID             **SectionData,
-  IN OUT UINTN            *SectionDataSize
+  IN OUT UINT32            *SectionDataSize
   )
 {
   UINT32                     FileSize;
diff --git a/StandaloneMmPkg/Library/StandaloneMmProtectionLib/ProtectionAarch64.c b/StandaloneMmPkg/Library/StandaloneMmProtectionLib/ProtectionAarch64.c
new file mode 100644
index 0000000000..b1258fb373
--- /dev/null
+++ b/StandaloneMmPkg/Library/StandaloneMmProtectionLib/ProtectionAarch64.c
@@ -0,0 +1,41 @@
+// FIXME: Docs, more general libclass for DXE?
+
+#include <Base.h>
+
+#include <Library/StandaloneMmMmuLib.h>
+
+EFI_STATUS
+SetMemoryRegionNoExec (
+  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN UINT64                Length
+  )
+{
+  return ArmSetMemoryRegionNoExec (BaseAddress, Length);
+}
+
+EFI_STATUS
+ClearMemoryRegionNoExec (
+  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN UINT64                Length
+  )
+{
+  return ArmClearMemoryRegionNoExec (BaseAddress, Length);
+}
+
+EFI_STATUS
+SetMemoryRegionReadOnly (
+  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN UINT64                Length
+  )
+{
+  return ArmSetMemoryRegionReadOnly (BaseAddress, Length);
+}
+
+EFI_STATUS
+ClearMemoryRegionReadOnly (
+  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN UINT64                Length
+  )
+{
+  return ArmClearMemoryRegionReadOnly (BaseAddress, Length);
+}
diff --git a/StandaloneMmPkg/Library/StandaloneMmProtectionLib/ProtectionNull.c b/StandaloneMmPkg/Library/StandaloneMmProtectionLib/ProtectionNull.c
new file mode 100644
index 0000000000..706762d8c8
--- /dev/null
+++ b/StandaloneMmPkg/Library/StandaloneMmProtectionLib/ProtectionNull.c
@@ -0,0 +1,49 @@
+#include <Base.h>
+
+EFI_STATUS
+SetMemoryRegionNoExec (
+  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN UINT64                Length
+  )
+{
+  (VOID) BaseAddress;
+  (VOID) Length;
+
+  return RETURN_SUCCESS;
+}
+
+EFI_STATUS
+ClearMemoryRegionNoExec (
+  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN UINT64                Length
+  )
+{
+  (VOID) BaseAddress;
+  (VOID) Length;
+
+  return RETURN_SUCCESS;
+}
+
+EFI_STATUS
+SetMemoryRegionReadOnly (
+  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN UINT64                Length
+  )
+{
+  (VOID) BaseAddress;
+  (VOID) Length;
+
+  return RETURN_SUCCESS;
+}
+
+EFI_STATUS
+ClearMemoryRegionReadOnly (
+  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN UINT64                Length
+  )
+{
+  (VOID) BaseAddress;
+  (VOID) Length;
+
+  return RETURN_SUCCESS;
+}
diff --git a/StandaloneMmPkg/Library/StandaloneMmProtectionLib/StandaloneMmProtectionLib.inf b/StandaloneMmPkg/Library/StandaloneMmProtectionLib/StandaloneMmProtectionLib.inf
new file mode 100644
index 0000000000..fe817c6f8e
--- /dev/null
+++ b/StandaloneMmPkg/Library/StandaloneMmProtectionLib/StandaloneMmProtectionLib.inf
@@ -0,0 +1,29 @@
+# FIXME: Docs
+[Defines]
+  INF_VERSION                    = 0x0001001A
+  BASE_NAME                      = StandaloneMmProtectionLib
+  FILE_GUID                      = 4FCCC091-D240-4FE3-A922-5153D1DB1649
+  MODULE_TYPE                    = MM_CORE_STANDALONE
+  VERSION_STRING                 = 1.0
+  PI_SPECIFICATION_VERSION       = 0x00010032
+  LIBRARY_CLASS                  = StandaloneMmProtectionLib|MM_CORE_STANDALONE
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC (EBC is for build only)
+#
+
+[Sources.AARCH64]
+  ProtectionAarch64.c
+
+[Sources.X64, Sources.ARM]
+  ProtectionNull.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  StandaloneMmPkg/StandaloneMmPkg.dec
+
+[Packages.AARCH64]
+  ArmPkg/ArmPkg.dec
+
+[LibraryClasses.AARCH64]
+  StandaloneMmMmuLib
diff --git a/StandaloneMmPkg/StandaloneMmPkg.dec b/StandaloneMmPkg/StandaloneMmPkg.dec
index 00ec8c076e..903aac7022 100644
--- a/StandaloneMmPkg/StandaloneMmPkg.dec
+++ b/StandaloneMmPkg/StandaloneMmPkg.dec
@@ -30,6 +30,9 @@
 [LibraryClasses.X64.PEIM]
   MmPlatformHobProducerLib|Include/Library/MmPlatformHobProducerLib.h
 
+  ## FIXME: docs
+  StandaloneMmProtectionLib|Include/Library/StandaloneMmProtectionLib.h
+
 [Guids]
   gStandaloneMmPkgTokenSpaceGuid           = { 0x18fe7632, 0xf5c8, 0x4e63, { 0x8d, 0xe8, 0x17, 0xa5, 0x5c, 0x59, 0x13, 0xbd }}
   gMpInformationHobGuid                    = { 0xba33f15d, 0x4000, 0x45c1, { 0x8e, 0x88, 0xf9, 0x16, 0x92, 0xd4, 0x57, 0xe3 }}
diff --git a/StandaloneMmPkg/StandaloneMmPkg.dsc b/StandaloneMmPkg/StandaloneMmPkg.dsc
index 08b80c9360..dfe51ad519 100644
--- a/StandaloneMmPkg/StandaloneMmPkg.dsc
+++ b/StandaloneMmPkg/StandaloneMmPkg.dsc
@@ -52,11 +52,13 @@
   MemoryAllocationLib|StandaloneMmPkg/Library/StandaloneMmCoreMemoryAllocationLib/StandaloneMmCoreMemoryAllocationLib.inf
   MmServicesTableLib|MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
   ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
   StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
+  StandaloneMmProtectionLib|StandaloneMmPkg/Library/StandaloneMmProtectionLib/StandaloneMmProtectionLib.inf
   VariableMmDependency|StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.inf
   HobPrintLib|MdeModulePkg/Library/HobPrintLib/HobPrintLib.inf
   MmPlatformHobProducerLib|StandaloneMmPkg/Library/MmPlatformHobProducerLibNull/MmPlatformHobProducerLibNull.inf
@@ -81,7 +83,6 @@
   ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf
   ArmSvcLib|ArmPkg/Library/ArmSvcLib/ArmSvcLib.inf
   CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf
-  PeCoffExtraActionLib|StandaloneMmPkg/Library/StandaloneMmPeCoffExtraActionLib/StandaloneMmPeCoffExtraActionLib.inf
   ArmTransferListLib|ArmPkg/Library/ArmTransferListLib/ArmTransferListLib.inf
 
 [LibraryClasses.common.MM_CORE_STANDALONE]
@@ -148,6 +149,7 @@
   StandaloneMmPkg/Library/MmPlatformHobProducerLibNull/MmPlatformHobProducerLibNull.inf
   StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.inf
   StandaloneMmPkg/Library/StandaloneMmExtractGuidedSectionLib/StandaloneMmExtractGuidedSectionLib.inf
+  StandaloneMmPkg/Library/StandaloneMmProtectionLib/StandaloneMmProtectionLib.inf
 
 [Components.AARCH64, Components.ARM]
   StandaloneMmPkg/Library/StandaloneMmPeCoffExtraActionLib/StandaloneMmPeCoffExtraActionLib.inf
diff --git a/UefiCpuPkg/CpuDxe/CpuPageTable.c b/UefiCpuPkg/CpuDxe/CpuPageTable.c
index 9a519bcb7e..6a3f1f34ed 100644
--- a/UefiCpuPkg/CpuDxe/CpuPageTable.c
+++ b/UefiCpuPkg/CpuDxe/CpuPageTable.c
@@ -10,7 +10,7 @@
 
 #include <Base.h>
 #include <Uefi.h>
-#include <Library/PeCoffGetEntryPointLib.h>
+
 #include <Library/SerialPortLib.h>
 #include <Library/SynchronizationLib.h>
 #include <Library/PrintLib.h>
diff --git a/UefiCpuPkg/CpuDxe/CpuPageTable.h b/UefiCpuPkg/CpuDxe/CpuPageTable.h
index f2694452f5..3245e97bfb 100644
--- a/UefiCpuPkg/CpuDxe/CpuPageTable.h
+++ b/UefiCpuPkg/CpuDxe/CpuPageTable.h
@@ -9,7 +9,7 @@
 #ifndef _PAGE_TABLE_LIB_H_
 #define _PAGE_TABLE_LIB_H_
 
-#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/PeImage2.h>
 #include <Protocol/MemoryAttribute.h>
 
 #define PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PSE              BIT0
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c
index 903fac927e..76ea152955 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c
@@ -118,35 +118,29 @@ DumpModuleImageInfo (
   IN  UINTN  CurrentEip
   )
 {
-  EFI_STATUS  Status;
-  UINTN       Pe32Data;
-  VOID        *PdbPointer;
-  VOID        *EntryPoint;
+  BOOLEAN      Result;
+  UINTN        ImageBase;
+  CONST CHAR8  *PdbPath;
 
-  Pe32Data = PeCoffSearchImageBase (CurrentEip);
-  if (Pe32Data == 0) {
+  Result = GetImageInfoByIp (&ImageBase, &PdbPath, CurrentEip);
+
+  if (!Result) {
     InternalPrintMessage ("!!!! Can't find image information. !!!!\n");
   } else {
     //
     // Find Image Base entry point
     //
-    Status = PeCoffLoaderGetEntryPoint ((VOID *)Pe32Data, &EntryPoint);
-    if (EFI_ERROR (Status)) {
-      EntryPoint = NULL;
-    }
 
     InternalPrintMessage ("!!!! Find image based on IP(0x%x) ", CurrentEip);
-    PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)Pe32Data);
-    if (PdbPointer != NULL) {
-      InternalPrintMessage ("%a", PdbPointer);
+    if (PdbPath!= NULL) {
+      InternalPrintMessage ("%a", PdbPath);
     } else {
       InternalPrintMessage ("(No PDB) ");
     }
 
     InternalPrintMessage (
-      " (ImageBase=%016lp, EntryPoint=%016p) !!!!\n",
-      (VOID *)Pe32Data,
-      EntryPoint
+      " (ImageBase=%016lp) !!!!\n",
+      (EFI_PHYSICAL_ADDRESS) ImageBase
       );
   }
 }
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
index 4593c204a6..95877b8be0 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
@@ -15,7 +15,8 @@
 #include <Library/SerialPortLib.h>
 #include <Library/PrintLib.h>
 #include <Library/LocalApicLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/DebugLib.h>
+
 #include <Library/BaseMemoryLib.h>
 #include <Library/SynchronizationLib.h>
 #include <Library/CpuExceptionHandlerLib.h>
@@ -321,4 +322,13 @@ AsmGetTssTemplateMap (
   OUT EXCEPTION_HANDLER_TEMPLATE_MAP  *AddressMap
   );
 
+// FIXME:
+BOOLEAN
+GetImageInfoByIp (
+  OUT UINTN        *ImageBase,
+  OUT CONST CHAR8  **SymbolsPath,
+  IN  UINTN        CurrentEip
+  );
+
 #endif
+
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
index 9fcba009d6..e8b4deeddd 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
@@ -63,7 +63,6 @@
   BaseLib
   DebugLib
   MemoryAllocationLib
-  PeCoffGetEntryPointLib
   PrintLib
   SerialPortLib
   SynchronizationLib
@@ -77,3 +76,6 @@
 
 [BuildOptions]
   XCODE:*_*_X64_NASM_FLAGS = -D NO_ABSOLUTE_RELOCS_IN_TEXT
+
+[Guids]
+  gEfiDebugImageInfoTableGuid  ## CONSUMES ## SystemTable
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c
index d4e9979c92..2a4fca621a 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c
@@ -11,6 +11,8 @@
 #include <Library/DebugLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Guid/DebugImageInfoTable.h>
 
 CONST UINTN  mDoFarReturnFlag = 0;
 
@@ -26,6 +28,8 @@ EXCEPTION_HANDLER_DATA     mExceptionHandlerData = {
 UINT8  mBuffer[CPU_STACK_SWITCH_EXCEPTION_NUMBER * CPU_KNOWN_GOOD_STACK_SIZE
                + sizeof (IA32_TSS_DESCRIPTOR) + CPU_TSS_GDT_SIZE];
 
+STATIC CONST EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *mDebugImageInfoTable = NULL;
+
 /**
   Common exception handler.
 
@@ -135,3 +139,51 @@ InitializeSeparateExceptionStacks (
     return ArchSetupExceptionStack (Buffer, BufferSize);
   }
 }
+
+BOOLEAN
+GetImageInfoByIp (
+  OUT UINTN        *ImageBase,
+  OUT CONST CHAR8  **SymbolsPath,
+  IN  UINTN        CurrentEip
+  )
+{
+  EFI_STATUS                        Status;
+  UINT32                            Index;
+  CONST EFI_DEBUG_IMAGE_INFO_NORMAL *NormalImage;
+
+  if (mDebugImageInfoTable == NULL) {
+    Status = EfiGetSystemConfigurationTable (
+               &gEfiDebugImageInfoTableGuid,
+               (VOID **) &mDebugImageInfoTable
+               );
+    if (EFI_ERROR (Status)) {
+      mDebugImageInfoTable = NULL;
+      return FALSE;
+    }
+  }
+
+  ASSERT (mDebugImageInfoTable != NULL);
+
+  for (Index = 0; Index < mDebugImageInfoTable->TableSize; ++Index) {
+    if (mDebugImageInfoTable->EfiDebugImageInfoTable[Index].ImageInfoType == NULL) {
+      continue;
+    }
+
+    if (*mDebugImageInfoTable->EfiDebugImageInfoTable[Index].ImageInfoType != EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) {
+      continue;
+    }
+
+    NormalImage = mDebugImageInfoTable->EfiDebugImageInfoTable[Index].NormalImage;
+
+    ASSERT (NormalImage->LoadedImageProtocolInstance != NULL);
+
+    if (CurrentEip >= (UINTN) NormalImage->LoadedImageProtocolInstance->ImageBase &&
+        CurrentEip < (UINTN) NormalImage->LoadedImageProtocolInstance->ImageBase + NormalImage->LoadedImageProtocolInstance->ImageSize) {
+      *ImageBase   = (UINTN) NormalImage->LoadedImageProtocolInstance->ImageBase;
+      *SymbolsPath = NormalImage->PdbPath;
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuException.c
index 994e3917fb..2e49bd88b6 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuException.c
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuException.c
@@ -12,6 +12,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/HobLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/PcdLib.h>
+#include <Library/UefiImageLib.h>
 
 CONST UINTN  mDoFarReturnFlag = 0;
 
@@ -224,3 +225,26 @@ InitializeSeparateExceptionStacks (
 
   return ArchSetupExceptionStack (Buffer, BufferSize);
 }
+
+// FIXME: Expose DebugImageInfoTable as PPI?
+BOOLEAN
+GetImageInfoByIp (
+  OUT UINTN        *ImageBase,
+  OUT CONST CHAR8  **SymbolsPath,
+  IN  UINTN        CurrentEip
+  )
+{
+  RETURN_STATUS                   Status;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext;
+  UINT32                          PdbPathSize;
+
+  Status = UefiImageDebugLocateImage (&ImageContext, CurrentEip);
+  if (RETURN_ERROR (Status)) {
+    return FALSE;
+  }
+
+  *ImageBase = UefiImageLoaderGetImageAddress (&ImageContext);
+
+  Status = UefiImageGetSymbolsPath (&ImageContext, SymbolsPath, &PdbPathSize);
+  return !RETURN_ERROR (Status);
+}
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
index 3a11516e32..3db1ad47ab 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
@@ -49,7 +49,7 @@
   HobLib
   LocalApicLib
   MemoryAllocationLib
-  PeCoffGetEntryPointLib
+  UefiImageLib
   PrintLib
   SerialPortLib
   SynchronizationLib
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c
index 497cd16499..8351d29b96 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c
@@ -222,3 +222,13 @@ InitializeSeparateExceptionStacks (
 {
   return EFI_UNSUPPORTED;
 }
+
+BOOLEAN
+GetImageInfoByIp (
+  OUT UINTN        *ImageBase,
+  OUT CONST CHAR8  **SymbolsPath,
+  IN  UINTN        CurrentEip
+  )
+{
+  return FALSE;
+}
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
index 64de252dcd..55acb46ebe 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
@@ -54,7 +54,7 @@
 
 [LibraryClasses.common]
   BaseLib
-  PeCoffGetEntryPointLib
+  UefiImageLib
   PrintLib
   SerialPortLib
 
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
index cc280a6ee7..ef835ee9dc 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
@@ -48,7 +48,6 @@
   CcExitLib
   DebugLib
   LocalApicLib
-  PeCoffGetEntryPointLib
   PrintLib
   SerialPortLib
   SynchronizationLib
@@ -63,3 +62,6 @@
 
 [BuildOptions]
   XCODE:*_*_X64_NASM_FLAGS = -D NO_ABSOLUTE_RELOCS_IN_TEXT
+
+[Guids]
+  gEfiDebugImageInfoTableGuid  ## CONSUMES ## SystemTable
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmException.c
index 46a86ad2c6..d14d00aa7e 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmException.c
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmException.c
@@ -8,6 +8,8 @@
 
 #include <PiSmm.h>
 #include "CpuExceptionCommon.h"
+#include <Library/SmmServicesTableLib.h>
+#include <Guid/DebugImageInfoTable.h>
 
 CONST UINTN  mDoFarReturnFlag = 1;
 
@@ -20,6 +22,7 @@ EXCEPTION_HANDLER_DATA     mExceptionHandlerData = {
   mExternalInterruptHandlerTable
 };
 
+STATIC CONST EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *mDebugImageInfoTableHeader = NULL;
 /**
   Common exception handler.
 
@@ -118,3 +121,76 @@ InitializeSeparateExceptionStacks (
 {
   return EFI_UNSUPPORTED;
 }
+
+// FIXME: Lib?
+STATIC
+EFI_STATUS
+EFIAPI
+InternalGetSystemConfigurationTable (
+  IN  EFI_GUID  *TableGuid,
+  OUT VOID      **Table
+  )
+{
+  UINTN             Index;
+
+  ASSERT (TableGuid != NULL);
+  ASSERT (Table != NULL);
+
+  *Table = NULL;
+  for (Index = 0; Index < gSmst->NumberOfTableEntries; Index++) {
+    if (CompareGuid (TableGuid, &(gSmst->SmmConfigurationTable[Index].VendorGuid))) {
+      *Table = gSmst->SmmConfigurationTable[Index].VendorTable;
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+BOOLEAN
+GetImageInfoByIp (
+  OUT UINTN        *ImageBase,
+  OUT CONST CHAR8  **SymbolsPath,
+  IN  UINTN        CurrentEip
+  )
+{
+  EFI_STATUS                        Status;
+  UINT32                            Index;
+  CONST EFI_DEBUG_IMAGE_INFO_NORMAL *NormalImage;
+
+  if (mDebugImageInfoTableHeader == NULL) {
+    Status = InternalGetSystemConfigurationTable (
+               &gEfiDebugImageInfoTableGuid,
+               (VOID **) &mDebugImageInfoTableHeader
+               );
+    if (EFI_ERROR (Status)) {
+      mDebugImageInfoTableHeader = NULL;
+      return FALSE;
+    }
+  }
+
+  ASSERT (mDebugImageInfoTableHeader != NULL);
+
+  for (Index = 0; Index < mDebugImageInfoTableHeader->TableSize; ++Index) {
+    if (mDebugImageInfoTableHeader->EfiDebugImageInfoTable[Index].ImageInfoType == NULL) {
+      continue;
+    }
+
+    if (*mDebugImageInfoTableHeader->EfiDebugImageInfoTable[Index].ImageInfoType != EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) {
+      continue;
+    }
+
+    NormalImage = mDebugImageInfoTableHeader->EfiDebugImageInfoTable[Index].NormalImage;
+
+    ASSERT (NormalImage->LoadedImageProtocolInstance != NULL);
+
+    if (CurrentEip >= (UINTN) NormalImage->LoadedImageProtocolInstance->ImageBase &&
+        CurrentEip < (UINTN) NormalImage->LoadedImageProtocolInstance->ImageBase + NormalImage->LoadedImageProtocolInstance->ImageSize) {
+      *ImageBase   = (UINTN) NormalImage->LoadedImageProtocolInstance->ImageBase;
+      *SymbolsPath = NormalImage->PdbPath;
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.c b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.c
index c6df9358eb..5e24c12548 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.c
@@ -182,20 +182,6 @@ DumpModuleInfoByIp (
   IN  UINTN  CallerIpAddress
   )
 {
-  UINTN  Pe32Data;
-  VOID   *PdbPointer;
-
-  //
-  // Find Image Base
-  //
-  Pe32Data = PeCoffSearchImageBase (CallerIpAddress);
-  if (Pe32Data != 0) {
-    DEBUG ((DEBUG_ERROR, "It is invoked from the instruction before IP(0x%p)", (VOID *)CallerIpAddress));
-    PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)Pe32Data);
-    if (PdbPointer != NULL) {
-      DEBUG ((DEBUG_ERROR, " in module (%a)\n", PdbPointer));
-    }
-  }
 }
 
 /**
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h
index bc08f03640..d0ad3be63a 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h
@@ -51,7 +51,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/CpuExceptionHandlerLib.h>
 #include <Library/ReportStatusCodeLib.h>
 #include <Library/SmmCpuFeaturesLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
+
 #include <Library/RegisterCpuFeaturesLib.h>
 #include <Library/PerformanceLib.h>
 #include <Library/CpuPageTableLib.h>
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
index 44972bbb76..38724cddd7 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
@@ -38,6 +38,64 @@ IsSmmProfileEnabled (
   return FeaturePcdGet (PcdCpuSmmProfileEnable);
 }
 
+#include <Library/SmmServicesTableLib.h>
+#include <Guid/DebugImageInfoTable.h>
+#include <Library/DebugLib.h>
+
+EFI_STATUS
+EFIAPI
+SmmGetSystemConfigurationTable (
+  IN  EFI_GUID  *TableGuid,
+  OUT VOID      **Table
+  );
+
+CONST EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *mDebugImageInfoTableHeader = NULL;
+
+// FIXME:
+CONST EFI_DEBUG_IMAGE_INFO_NORMAL *
+InternalLocateImage (
+  IN  UINTN              CurrentEip
+  )
+{
+  EFI_STATUS                        Status;
+  UINT32                            Index;
+  CONST EFI_DEBUG_IMAGE_INFO_NORMAL *NormalImage;
+
+  if (mDebugImageInfoTableHeader == NULL) {
+    Status = SmmGetSystemConfigurationTable (
+               &gEfiDebugImageInfoTableGuid,
+               (VOID **) &mDebugImageInfoTableHeader
+               );
+    if (EFI_ERROR (Status)) {
+      mDebugImageInfoTableHeader = NULL;
+      return NULL;
+    }
+  }
+
+  ASSERT (mDebugImageInfoTableHeader != NULL);
+
+  for (Index = 0; Index < mDebugImageInfoTableHeader->TableSize; ++Index) {
+    if (mDebugImageInfoTableHeader->EfiDebugImageInfoTable[Index].ImageInfoType == NULL) {
+      continue;
+    }
+
+    if (*mDebugImageInfoTableHeader->EfiDebugImageInfoTable[Index].ImageInfoType != EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) {
+      continue;
+    }
+
+    NormalImage = mDebugImageInfoTableHeader->EfiDebugImageInfoTable[Index].NormalImage;
+
+    ASSERT (NormalImage->LoadedImageProtocolInstance != NULL);
+
+    if (CurrentEip >= (UINTN) NormalImage->LoadedImageProtocolInstance->ImageBase &&
+        CurrentEip < (UINTN) NormalImage->LoadedImageProtocolInstance->ImageBase + NormalImage->LoadedImageProtocolInstance->ImageSize) {
+      return NormalImage;
+    }
+  }
+
+  return NULL;
+}
+
 /**
   Perform the remaining tasks.
 
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
index 8c4be7e588..8b8d3b5c80 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
@@ -97,7 +97,6 @@
   CpuLib
   ReportStatusCodeLib
   SmmCpuFeaturesLib
-  PeCoffGetEntryPointLib
   PerformanceLib
   CpuPageTableLib
   MmSaveStateLib
@@ -121,6 +120,7 @@
   gSmmBaseHobGuid                          ## CONSUMES
   gMpInformation2HobGuid                   ## CONSUMES # Assume the HOB must has been created
   gEfiSmmSmramMemoryGuid
+  gEfiDebugImageInfoTableGuid              ## CONSUMES ## SystemTable
 
 [FeaturePcd]
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmDebug                         ## CONSUMES
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuStandaloneMm.inf b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuStandaloneMm.inf
index d0ae5e709d..bc13e266f9 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuStandaloneMm.inf
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuStandaloneMm.inf
@@ -79,7 +79,6 @@
   CpuLib
   ReportStatusCodeLib
   SmmCpuFeaturesLib
-  PeCoffGetEntryPointLib
   PerformanceLib
   CpuPageTableLib
   MmSaveStateLib
diff --git a/UefiCpuPkg/SecCore/FindPeiCore.c b/UefiCpuPkg/SecCore/FindPeiCore.c
index 97adb68138..3187dcf60f 100644
--- a/UefiCpuPkg/SecCore/FindPeiCore.c
+++ b/UefiCpuPkg/SecCore/FindPeiCore.c
@@ -23,7 +23,8 @@ EFIAPI
 FindImageBase (
   IN  EFI_FIRMWARE_VOLUME_HEADER  *FirmwareVolumePtr,
   IN  EFI_FV_FILETYPE             FileType,
-  OUT EFI_PHYSICAL_ADDRESS        *CoreImageBase
+  OUT EFI_PHYSICAL_ADDRESS             *CoreImageBase,
+  OUT UINT32                           *CoreImageSize
   )
 {
   EFI_PHYSICAL_ADDRESS       CurrentAddress;
@@ -110,8 +111,10 @@ FindImageBase (
         if (File->Type == FileType) {
           if (IS_SECTION2 (Section)) {
             *CoreImageBase = (PHYSICAL_ADDRESS)(UINTN)((UINT8 *)Section + sizeof (EFI_COMMON_SECTION_HEADER2));
+            *CoreImageSize = Size - sizeof (EFI_COMMON_SECTION_HEADER2);
           } else {
             *CoreImageBase = (PHYSICAL_ADDRESS)(UINTN)((UINT8 *)Section + sizeof (EFI_COMMON_SECTION_HEADER));
+            *CoreImageSize = Size - sizeof (EFI_COMMON_SECTION_HEADER);
           }
         }
 
@@ -147,45 +150,70 @@ FindAndReportEntryPoints (
   OUT EFI_PEI_CORE_ENTRY_POINT    *PeiCoreEntryPoint
   )
 {
-  EFI_STATUS                    Status;
-  EFI_PHYSICAL_ADDRESS          SecCoreImageBase;
-  EFI_PHYSICAL_ADDRESS          PeiCoreImageBase;
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
+  EFI_STATUS                       Status;
+  EFI_PHYSICAL_ADDRESS             SecCoreImageBase;
+  UINT32                           SecCoreImageSize;
+  EFI_PHYSICAL_ADDRESS             PeiCoreImageBase;
+  UINT32                           PeiCoreImageSize;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT  ImageContext;
 
   //
   // Find SEC Core image base
   //
-  Status = FindImageBase (SecCoreFirmwareVolumePtr, EFI_FV_FILETYPE_SECURITY_CORE, &SecCoreImageBase);
+  Status = FindImageBase (
+             SecCoreFirmwareVolumePtr,
+             EFI_FV_FILETYPE_SECURITY_CORE,
+             &SecCoreImageBase,
+             &SecCoreImageSize
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  // FIXME: DEBUG-only
+  Status = UefiImageInitializeContext (
+             &ImageContext,
+             (VOID*) (UINTN) SecCoreImageBase,
+             SecCoreImageSize
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = UefiImageLoadImageInplace (&ImageContext);
   ASSERT_EFI_ERROR (Status);
 
-  ZeroMem ((VOID *)&ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
   //
   // Report SEC Core debug information when remote debug is enabled
   //
-  ImageContext.ImageAddress = SecCoreImageBase;
-  ImageContext.PdbPointer   = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress);
-  PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+  UefiImageLoaderRelocateImageExtraAction (&ImageContext);
 
   //
   // Find PEI Core image base
   //
-  Status = FindImageBase (PeiCoreFirmwareVolumePtr, EFI_FV_FILETYPE_PEI_CORE, &PeiCoreImageBase);
+  Status = FindImageBase (
+             PeiCoreFirmwareVolumePtr,
+             EFI_FV_FILETYPE_PEI_CORE,
+             &PeiCoreImageBase,
+             &PeiCoreImageSize
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = UefiImageInitializeContext (
+             &ImageContext,
+             (VOID*)(UINTN)PeiCoreImageBase,
+             PeiCoreImageSize
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = UefiImageLoadImageInplace (&ImageContext);
   ASSERT_EFI_ERROR (Status);
 
   //
   // Report PEI Core debug information when remote debug is enabled
   //
-  ImageContext.ImageAddress = PeiCoreImageBase;
-  ImageContext.PdbPointer   = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress);
-  PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+  UefiImageLoaderRelocateImageExtraAction (&ImageContext);
 
   //
   // Find PEI Core entry point
   //
-  Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)PeiCoreImageBase, (VOID **)PeiCoreEntryPoint);
-  if (EFI_ERROR (Status)) {
-    *PeiCoreEntryPoint = 0;
-  }
+  *PeiCoreEntryPoint = (EFI_PEI_CORE_ENTRY_POINT) (UINTN) (UefiImageLoaderGetImageEntryPoint (&ImageContext));
 
   return;
 }
diff --git a/UefiCpuPkg/SecCore/SecCore.inf b/UefiCpuPkg/SecCore/SecCore.inf
index 94966f4edf..7d3a80cf04 100644
--- a/UefiCpuPkg/SecCore/SecCore.inf
+++ b/UefiCpuPkg/SecCore/SecCore.inf
@@ -48,8 +48,8 @@
   PcdLib
   DebugAgentLib
   CpuLib
-  PeCoffGetEntryPointLib
-  PeCoffExtraActionLib
+  UefiCpuLib
+  UefiImageExtraActionLib
   CpuExceptionHandlerLib
   ReportStatusCodeLib
   PeiServicesLib
diff --git a/UefiCpuPkg/SecCore/SecMain.h b/UefiCpuPkg/SecCore/SecMain.h
index 81c561424e..f26d337843 100644
--- a/UefiCpuPkg/SecCore/SecMain.h
+++ b/UefiCpuPkg/SecCore/SecMain.h
@@ -25,8 +25,9 @@
 #include <Library/BaseMemoryLib.h>
 #include <Library/PlatformSecLib.h>
 #include <Library/CpuLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
-#include <Library/PeCoffExtraActionLib.h>
+#include <Library/UefiCpuLib.h>
+
+#include <Library/UefiImageExtraActionLib.h>
 #include <Library/DebugAgentLib.h>
 #include <Library/CpuExceptionHandlerLib.h>
 #include <Library/ReportStatusCodeLib.h>
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 8ac7747eca..42919debdb 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -446,7 +446,7 @@
   #   TRUE  - Access to non-SMRAM memory is restricted to reserved, runtime and ACPI NVS type after SmmReadyToLock.<BR>
   #   FALSE - Access to any type of non-SMRAM memory after SmmReadyToLock is allowed.<BR>
   # @Prompt Access to non-SMRAM memory is restricted to reserved, runtime and ACPI NVS type after SmmReadyToLock.
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmRestrictedMemoryAccess|TRUE|BOOLEAN|0x3213210F
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmRestrictedMemoryAccess|FALSE|BOOLEAN|0x3213210F
 
 [PcdsFixedAtBuild.RISCV64]
   ## Indicate the maximum SATP mode allowed.
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index ec2b6cc722..dc6150ce57 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -58,8 +58,9 @@
   SmmCpuPlatformHookLib|UefiCpuPkg/Library/SmmCpuPlatformHookLibNull/SmmCpuPlatformHookLibNull.inf
   SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
   SmmCpuSyncLib|UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
   TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
   CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
   TdxMeasurementLib|UefiCpuPkg/Library/TdxMeasurementLibNull/TdxMeasurementLibNull.inf
diff --git a/UefiPayloadPkg/UefiPayloadEntry/MemoryAllocation.c b/UefiPayloadPkg/Library/UefiPayloadEntryMemoryAllocationLib/MemoryAllocation.c
similarity index 100%
rename from UefiPayloadPkg/UefiPayloadEntry/MemoryAllocation.c
rename to UefiPayloadPkg/Library/UefiPayloadEntryMemoryAllocationLib/MemoryAllocation.c
diff --git a/UefiPayloadPkg/Library/UefiPayloadEntryMemoryAllocationLib/UefiPayloadEntryMemoryAllocationLib.inf b/UefiPayloadPkg/Library/UefiPayloadEntryMemoryAllocationLib/UefiPayloadEntryMemoryAllocationLib.inf
new file mode 100644
index 0000000000..03da9b5cff
--- /dev/null
+++ b/UefiPayloadPkg/Library/UefiPayloadEntryMemoryAllocationLib/UefiPayloadEntryMemoryAllocationLib.inf
@@ -0,0 +1,27 @@
+# FIXME: Docs
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = UefiPayloadEntryMemoryAllocationLib
+  FILE_GUID                      = D3C5B8A1-B946-4D46-8251-9020A527EE40
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = UefiPayloadEntryMemoryAllocationLib|SEC
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  MemoryAllocation.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiPayloadPkg/UefiPayloadPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  HobLib
diff --git a/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c b/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c
index 3e13496147..5904d9cb51 100644
--- a/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c
+++ b/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c
@@ -48,7 +48,7 @@ AllocateCodePages (
 /**
     Loads and relocates a PE/COFF image
 
-  @param[in]  PeCoffImage     Point to a Pe/Coff image.
+  @param[in]   UefiImage      Point to a Pe/Coff image.
   @param[out]  ImageAddress   The image memory address after relocation.
   @param[out]  ImageSize      The image size.
   @param[out]  EntryPoint     The image entry point.
@@ -57,59 +57,59 @@ AllocateCodePages (
   @return Others         If the image failed to load or relocate.
 **/
 EFI_STATUS
-LoadPeCoffImage (
-  IN  VOID                  *PeCoffImage,
+LoadUefiImage (
+  IN  VOID                  *UefiImage,
+  IN  UINT32                UefiImageSize,
   OUT EFI_PHYSICAL_ADDRESS  *ImageAddress,
-  OUT UINT64                *ImageSize,
+  OUT UINT64                *DestinationSize,
   OUT EFI_PHYSICAL_ADDRESS  *EntryPoint
   )
 {
   RETURN_STATUS                 Status;
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
+  UEFI_IMAGE_LOADER_IMAGE_CONTEXT   ImageContext;
+  UINT32                            ImageSize;
+  UINT32                            ImageAlignment;
+  UINT32                        BufferPages;
+  UINT32                        BufferSize;
   VOID                          *Buffer;
 
-  ZeroMem (&ImageContext, sizeof (ImageContext));
-
-  ImageContext.Handle    = PeCoffImage;
-  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
-
-  Status = PeCoffLoaderGetImageInfo (&ImageContext);
+  Status = UefiImageInitializeContext (&ImageContext, UefiImage, UefiImageSize);
   if (EFI_ERROR (Status)) {
     ASSERT_EFI_ERROR (Status);
     return Status;
   }
 
+  ImageSize      = UefiImageGetImageSize (&ImageContext);
+  BufferPages    = EFI_SIZE_TO_PAGES (ImageSize);
+  BufferSize     = EFI_PAGES_TO_SIZE (BufferPages);
+  ImageAlignment = UefiImageGetSegmentAlignment (&ImageContext);
+
   //
   // Allocate Memory for the image
   //
-  Buffer = AllocateCodePages (EFI_SIZE_TO_PAGES ((UINT32)ImageContext.ImageSize));
+  Buffer = AllocateAlignedCodePages (BufferPages, ImageAlignment);
   if (Buffer == NULL) {
     return EFI_OUT_OF_RESOURCES;
   }
 
-  ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
-
   //
-  // Load the image to our new buffer
+  // Load and relocate the image to our new buffer
   //
-  Status = PeCoffLoaderLoadImage (&ImageContext);
+  Status = UefiImageLoadImageForExecution (
+             &ImageContext,
+             Buffer,
+             BufferSize,
+             NULL,
+             0
+             );
   if (EFI_ERROR (Status)) {
     ASSERT_EFI_ERROR (Status);
     return Status;
   }
 
-  //
-  // Relocate the image in our new buffer
-  //
-  Status = PeCoffLoaderRelocateImage (&ImageContext);
-  if (EFI_ERROR (Status)) {
-    ASSERT_EFI_ERROR (Status);
-    return Status;
-  }
-
-  *ImageAddress = ImageContext.ImageAddress;
-  *ImageSize    = ImageContext.ImageSize;
-  *EntryPoint   = ImageContext.EntryPoint;
+  *ImageAddress    = (UINTN)Buffer;
+  *DestinationSize = BufferSize;
+  *EntryPoint      = UefiImageLoaderGetImageEntryPoint (&ImageContext);
 
   return EFI_SUCCESS;
 }
@@ -201,12 +201,13 @@ EFI_STATUS
 FileFindSection (
   IN EFI_FFS_FILE_HEADER  *FileHeader,
   IN EFI_SECTION_TYPE     SectionType,
-  OUT VOID                **SectionData
+  OUT VOID                      **SectionData,
+  OUT UINT32                    *SectionSize
   )
 {
   UINT32                     FileSize;
   EFI_COMMON_SECTION_HEADER  *Section;
-  UINT32                     SectionSize;
+  UINT32                        CurSectionSize;
   UINT32                     Index;
 
   if (IS_FFS_FILE2 (FileHeader)) {
@@ -222,26 +223,29 @@ FileFindSection (
   Index = 0;
   while (Index < FileSize) {
     if (Section->Type == SectionType) {
+      // FIXME: Use general API (MdePkg?) with proper size checks
       if (IS_SECTION2 (Section)) {
         *SectionData = (VOID *)((UINT8 *)Section + sizeof (EFI_COMMON_SECTION_HEADER2));
+        *SectionSize = CurSectionSize - sizeof (EFI_COMMON_SECTION_HEADER2);
       } else {
         *SectionData = (VOID *)((UINT8 *)Section + sizeof (EFI_COMMON_SECTION_HEADER));
+        *SectionSize = CurSectionSize - sizeof (EFI_COMMON_SECTION_HEADER);
       }
 
       return EFI_SUCCESS;
     }
 
     if (IS_SECTION2 (Section)) {
-      SectionSize = SECTION2_SIZE (Section);
+      CurSectionSize = SECTION2_SIZE (Section);
     } else {
-      SectionSize = SECTION_SIZE (Section);
+      CurSectionSize = SECTION_SIZE (Section);
     }
 
-    SectionSize = GET_OCCUPIED_SIZE (SectionSize, 4);
-    ASSERT (SectionSize != 0);
-    Index += SectionSize;
+    CurSectionSize = GET_OCCUPIED_SIZE (CurSectionSize, 4);
+    ASSERT (CurSectionSize != 0);
+    Index += CurSectionSize;
 
-    Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionSize);
+    Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + CurSectionSize);
   }
 
   return EFI_NOT_FOUND;
@@ -263,10 +267,12 @@ LoadDxeCore (
   EFI_STATUS                  Status;
   EFI_FIRMWARE_VOLUME_HEADER  *PayloadFv;
   EFI_FIRMWARE_VOLUME_HEADER  *DxeCoreFv;
+  UINT32                      DxeCoreFvSize;
   EFI_FFS_FILE_HEADER         *FileHeader;
-  VOID                        *PeCoffImage;
+  VOID                        *UefiImage;
+  UINT32                      UefiImageSize;
   EFI_PHYSICAL_ADDRESS        ImageAddress;
-  UINT64                      ImageSize;
+  UINT64                      DestinationSize;
 
   PayloadFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdPayloadFdMemBase);
 
@@ -278,7 +284,7 @@ LoadDxeCore (
     return Status;
   }
 
-  Status = FileFindSection (FileHeader, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, (VOID **)&DxeCoreFv);
+  Status = FileFindSection (FileHeader, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, (VOID **)&DxeCoreFv, &DxeCoreFvSize);
   if (EFI_ERROR (Status)) {
     return Status;
   }
@@ -296,7 +302,7 @@ LoadDxeCore (
     return Status;
   }
 
-  Status = FileFindSection (FileHeader, EFI_SECTION_PE32, (VOID **)&PeCoffImage);
+  Status = FileFindSection (FileHeader, EFI_SECTION_PE32, (VOID **)&UefiImage, &UefiImageSize);
   if (EFI_ERROR (Status)) {
     return Status;
   }
@@ -304,12 +310,12 @@ LoadDxeCore (
   //
   // Get DXE core info
   //
-  Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, DxeCoreEntryPoint);
+  Status = LoadUefiImage (UefiImage, UefiImageSize, &ImageAddress, &DestinationSize, DxeCoreEntryPoint);
   if (EFI_ERROR (Status)) {
     return Status;
   }
 
-  BuildModuleHob (&FileHeader->Name, ImageAddress, EFI_SIZE_TO_PAGES ((UINT32)ImageSize) * EFI_PAGE_SIZE, *DxeCoreEntryPoint);
+  BuildModuleHob (&FileHeader->Name, ImageAddress, DestinationSize, *DxeCoreEntryPoint);
 
   return EFI_SUCCESS;
 }
@@ -331,7 +337,8 @@ UniversalLoadDxeCore (
 {
   EFI_STATUS            Status;
   EFI_FFS_FILE_HEADER   *FileHeader;
-  VOID                  *PeCoffImage;
+  VOID                        *UefiImage;
+  UINT32                      UefiImageSize;
   EFI_PHYSICAL_ADDRESS  ImageAddress;
   UINT64                ImageSize;
 
@@ -343,7 +350,7 @@ UniversalLoadDxeCore (
     return Status;
   }
 
-  Status = FileFindSection (FileHeader, EFI_SECTION_PE32, (VOID **)&PeCoffImage);
+  Status = FileFindSection (FileHeader, EFI_SECTION_PE32, (VOID **)&UefiImage, &UefiImageSize);
   if (EFI_ERROR (Status)) {
     return Status;
   }
@@ -351,7 +358,7 @@ UniversalLoadDxeCore (
   //
   // Get DXE core info
   //
-  Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, DxeCoreEntryPoint);
+  Status = LoadUefiImage (UefiImage, UefiImageSize, &ImageAddress, &ImageSize, DxeCoreEntryPoint);
   if (EFI_ERROR (Status)) {
     return Status;
   }
diff --git a/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h b/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h
index 09fce8dbcf..91095769ee 100644
--- a/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h
+++ b/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h
@@ -15,12 +15,12 @@
 #include <Library/BaseMemoryLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/DebugLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/HobLib.h>
 #include <Library/PcdLib.h>
 #include <Guid/MemoryAllocationHob.h>
 #include <Library/IoLib.h>
-#include <Library/PeCoffLib.h>
+#include <Library/UefiImageLib.h>
 #include <Library/BlParseLib.h>
 #include <Library/PlatformSupportLib.h>
 #include <Library/CpuLib.h>
@@ -196,7 +196,8 @@ EFI_STATUS
 FileFindSection (
   IN EFI_FFS_FILE_HEADER  *FileHeader,
   IN EFI_SECTION_TYPE     SectionType,
-  OUT VOID                **SectionData
+  OUT VOID                      **SectionData,
+  OUT UINT32                    *SectionSize
   );
 
 /**
diff --git a/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf b/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
index da5a58ab22..f012299f41 100644
--- a/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
+++ b/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
@@ -24,7 +24,6 @@
 [Sources]
   UefiPayloadEntry.c
   LoadDxeCore.c
-  MemoryAllocation.c
   AcpiTable.c
 
 [Sources.Ia32]
@@ -52,10 +51,11 @@
   IoLib
   BlParseLib
   HobLib
-  PeCoffLib
+  UefiImageLib
   PlatformSupportLib
   CpuLib
   StackCheckLib
+  MemoryAllocationLib
 
 [Guids]
   gEfiMemoryTypeInformationGuid
diff --git a/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c b/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c
index 5b864eeefe..b6329834c1 100644
--- a/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c
+++ b/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c
@@ -54,6 +54,7 @@ FixUpPcdDatabase (
   EFI_STATUS           Status;
   EFI_FFS_FILE_HEADER  *FileHeader;
   VOID                 *PcdRawData;
+  UINT32                      PcdRawSize;
   PEI_PCD_DATABASE     *PeiDatabase;
   PEI_PCD_DATABASE     *UplDatabase;
   EFI_HOB_GUID_TYPE    *GuidHob;
@@ -77,7 +78,7 @@ FixUpPcdDatabase (
     return Status;
   }
 
-  Status = FileFindSection (FileHeader, EFI_SECTION_RAW, &PcdRawData);
+  Status = FileFindSection (FileHeader, EFI_SECTION_RAW, &PcdRawData, &PcdRawSize);
   ASSERT_EFI_ERROR (Status);
   if (EFI_ERROR (Status)) {
     return Status;
diff --git a/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf b/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
index 8804ef6b9c..a13afd8ef3 100644
--- a/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
+++ b/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
@@ -44,10 +44,10 @@
   SerialPortLib
   IoLib
   HobLib
-  PeCoffLib
   CpuLib
   HobPrintLib
   StackCheckLib
+  UefiImageLib
 
 [Guids]
   gEfiMemoryTypeInformationGuid
diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc
index 9ff326a6cb..f0c713c8dd 100644
--- a/UefiPayloadPkg/UefiPayloadPkg.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkg.dsc
@@ -216,8 +216,8 @@
 !endif
   PciSegmentLib|MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf
   PciSegmentInfoLib|UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.inf
-  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
-  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+  PeCoffLib2|MdePkg/Library/BasePeCoffLib2/BasePeCoffLib2.inf
+  UefiImageLib|MdePkg/Library/BaseUefiImageLib/BaseUefiImageLibPeCoff.inf
   CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
   SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
   DxeHobListLib|UefiPayloadPkg/Library/DxeHobListLib/DxeHobListLib.inf
@@ -288,10 +288,10 @@
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
   ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
-  PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
+  UefiImageExtraActionLib|SourceLevelDebugPkg/Library/UefiImageExtraActionLibDebug/UefiImageExtraActionLibDebug.inf
   DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
 !else
-  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  UefiImageExtraActionLib|MdePkg/Library/BaseUefiImageExtraActionLibNull/BaseUefiImageExtraActionLibNull.inf
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
 !endif
   PlatformSupportLib|UefiPayloadPkg/Library/PlatformSupportLibNull/PlatformSupportLibNull.inf
@@ -371,6 +371,7 @@
 !if $(MULTIPLE_DEBUG_PORT_SUPPORT) == TRUE
   SerialPortLib|UefiPayloadPkg/Library/BaseSerialPortLibHob/BaseSerialPortLibHob.inf
 !endif
+  MemoryAllocationLib|UefiPayloadPkg/Library/UefiPayloadEntryMemoryAllocationLib/UefiPayloadEntryMemoryAllocationLib.inf
 
 [LibraryClasses.common.DXE_CORE]
   DxeHobListLib|UefiPayloadPkg/Library/DxeHobListLibNull/DxeHobListLibNull.inf