]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Pei/Image/Image.c
MdeModulePkg: Refine casting expression result to bigger size
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Image / Image.c
index 202936869b62eb4b2f9417f4b5dc6562d76f934c..c8bb2300a0a6681a7c58dca85fb2f1d8f22b343c 100644 (file)
-/*++\r
+/** @file\r
+  Pei Core Load Image Support\r
 \r
-Copyright (c) 2006 - 2007, Intel Corporation                                                         \r
-All rights reserved. This program and the accompanying materials                          \r
-are licensed and made available under the terms and conditions of the BSD License         \r
-which accompanies this distribution.  The full text of the license may be found at        \r
-http://opensource.org/licenses/bsd-license.php                                            \r
-                                                                                          \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
 \r
-Module Name:\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 \r
-  Image.c\r
+**/\r
 \r
-Abstract:\r
+#include "PeiMain.h"\r
 \r
-  Pei Core Load Image Support\r
 \r
---*/\r
+EFI_PEI_LOAD_FILE_PPI   mPeiLoadImagePpi = {\r
+  PeiLoadImageLoadImageWrapper\r
+};\r
+\r
+\r
+EFI_PEI_PPI_DESCRIPTOR     gPpiLoadFilePpiList = {\r
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+  &gEfiPeiLoadFilePpiGuid,\r
+  &mPeiLoadImagePpi\r
+};\r
+\r
+/**\r
 \r
-#include <PeiMain.h>\r
+  Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file.\r
+  The function is used for XIP code to have optimized memory copy.\r
 \r
+  @param FileHandle      - The handle to the PE/COFF file\r
+  @param FileOffset      - The offset, in bytes, into the file to read\r
+  @param ReadSize        - The number of bytes to read from the file starting at FileOffset\r
+  @param Buffer          - A pointer to the buffer to read the data into.\r
 \r
+  @return EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
 \r
+**/\r
 EFI_STATUS\r
-PeiLoadImage (\r
-  IN EFI_PEI_SERVICES         **PeiServices,\r
-  IN EFI_FFS_FILE_HEADER      *PeimFileHeader,\r
-  OUT VOID                    **EntryPoint\r
+EFIAPI\r
+PeiImageRead (\r
+  IN     VOID    *FileHandle,\r
+  IN     UINTN   FileOffset,\r
+  IN     UINTN   *ReadSize,\r
+  OUT    VOID    *Buffer\r
   )\r
-/*++\r
+{\r
+  CHAR8 *Destination8;\r
+  CHAR8 *Source8;\r
+  \r
+  Destination8  = Buffer;\r
+  Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
+  if (Destination8 != Source8) {\r
+    CopyMem (Destination8, Source8, *ReadSize);\r
+  }\r
 \r
-Routine Description:\r
+  return EFI_SUCCESS;\r
+}\r
 \r
-  Routine for loading file image.\r
+/**\r
 \r
-Arguments:\r
+  Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file.\r
+  The function is implemented as PIC so as to support shadowing.\r
 \r
-  PeiServices     - The PEI core services table.\r
-  PeimFileHeader  - Pointer to the FFS file header of the image.\r
-  EntryPoint      - Pointer to entry point of specified image file for output.\r
+  @param FileHandle      - The handle to the PE/COFF file\r
+  @param FileOffset      - The offset, in bytes, into the file to read\r
+  @param ReadSize        - The number of bytes to read from the file starting at FileOffset\r
+  @param Buffer          - A pointer to the buffer to read the data into.\r
 \r
-Returns:\r
+  @return EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
 \r
-  Status - EFI_SUCCESS    - Image is successfully loaded.\r
-           EFI_NOT_FOUND  - Fail to locate necessary PPI\r
-           Others         - Fail to load file.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiImageReadForShadow (\r
+  IN     VOID    *FileHandle,\r
+  IN     UINTN   FileOffset,\r
+  IN     UINTN   *ReadSize,\r
+  OUT    VOID    *Buffer\r
+  )\r
+{\r
+  volatile CHAR8  *Destination8;\r
+  CHAR8           *Source8;\r
+  UINTN           Length;\r
+\r
+  Destination8  = Buffer;\r
+  Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
+  if (Destination8 != Source8) {\r
+    Length        = *ReadSize;\r
+    while ((Length--) > 0) {\r
+      *(Destination8++) = *(Source8++);\r
+    }\r
+  }\r
 \r
---*/\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Support routine to get the Image read file function.\r
+\r
+  @param ImageContext    - The context of the image being loaded\r
+\r
+  @retval EFI_SUCCESS - If Image function location is found\r
+\r
+**/\r
+EFI_STATUS\r
+GetImageReadFunction (\r
+  IN      PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext\r
+  )\r
+{\r
+  PEI_CORE_INSTANCE     *Private;\r
+  EFI_PHYSICAL_ADDRESS  MemoryBuffer;\r
+\r
+  Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());\r
+  MemoryBuffer = 0;\r
+\r
+  if (Private->PeiMemoryInstalled  && (((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && PcdGetBool (PcdShadowPeimOnBoot)) || \r
+      ((Private->HobList.HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME) && PcdGetBool (PcdShadowPeimOnS3Boot))) &&\r
+      (EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_X64) || EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_IA32))) {\r
+    // \r
+    // Shadow algorithm makes lots of non ANSI C assumptions and only works for IA32 and X64 \r
+    //  compilers that have been tested\r
+    //\r
+    if (Private->ShadowedImageRead == NULL) {\r
+      PeiServicesAllocatePages (EfiBootServicesCode, 0x400 / EFI_PAGE_SIZE + 1, &MemoryBuffer);\r
+      ASSERT (MemoryBuffer != 0);\r
+      CopyMem ((VOID *)(UINTN)MemoryBuffer, (CONST VOID *) (UINTN) PeiImageReadForShadow, 0x400);\r
+      Private->ShadowedImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer;\r
+    }\r
+\r
+    ImageContext->ImageRead = Private->ShadowedImageRead;\r
+  } else {\r
+    ImageContext->ImageRead = PeiImageRead;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+/**\r
+  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\r
+  memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.\r
+  The function is only invoked when load modules at fixed address feature is enabled. \r
+  \r
+  @param  Private                  Pointer to the private data passed in from caller\r
+  @param  ImageBase                The base address the image will be loaded at.\r
+  @param  ImageSize                The size of the image\r
+  \r
+  @retval EFI_SUCCESS              The memory range the image will be loaded in is available\r
+  @retval EFI_NOT_FOUND            The memory range the image will be loaded in is not available\r
+**/\r
+EFI_STATUS\r
+CheckAndMarkFixLoadingMemoryUsageBitMap (\r
+  IN  PEI_CORE_INSTANCE             *Private,\r
+  IN  EFI_PHYSICAL_ADDRESS          ImageBase,\r
+  IN  UINT32                        ImageSize\r
+  )\r
+{\r
+   UINT32                             DxeCodePageNumber;\r
+   UINT64                             ReservedCodeSize;\r
+   EFI_PHYSICAL_ADDRESS               PeiCodeBase;\r
+   UINT32                             BaseOffsetPageNumber;\r
+   UINT32                             TopOffsetPageNumber;\r
+   UINT32                             Index;\r
+   UINT64                             *MemoryUsageBitMap;\r
+   \r
+\r
+   //\r
+   // The reserved code range includes RuntimeCodePage range, Boot time code range and PEI code range.\r
+   //\r
+   DxeCodePageNumber = PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
+   DxeCodePageNumber += PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
+   ReservedCodeSize  = EFI_PAGES_TO_SIZE(DxeCodePageNumber + PcdGet32(PcdLoadFixAddressPeiCodePageNumber));\r
+   PeiCodeBase       = Private->LoadModuleAtFixAddressTopAddress - ReservedCodeSize;\r
+   \r
+   //\r
+   // Test the memory range for loading the image in the PEI code range.\r
+   //\r
+   if ((Private->LoadModuleAtFixAddressTopAddress - EFI_PAGES_TO_SIZE(DxeCodePageNumber)) < (ImageBase + ImageSize) ||\r
+       (PeiCodeBase > ImageBase)) {         \r
+     return EFI_NOT_FOUND; \r
+   }\r
+   \r
+   //\r
+   // Test if the memory is avalaible or not.\r
+   //\r
+   MemoryUsageBitMap    = Private->PeiCodeMemoryRangeUsageBitMap;  \r
+   BaseOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase - PeiCodeBase));\r
+   TopOffsetPageNumber  = EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - PeiCodeBase));\r
+   for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
+     if ((MemoryUsageBitMap[Index / 64] & LShiftU64(1, (Index % 64))) != 0) {\r
+       //\r
+       // This page is already used.\r
+       //\r
+       return EFI_NOT_FOUND;  \r
+     }\r
+   }\r
+   \r
+   //\r
+   // Being here means the memory range is available.  So mark the bits for the memory range\r
+   // \r
+   for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
+     MemoryUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));\r
+   }\r
+   return  EFI_SUCCESS;   \r
+}\r
+/**\r
+\r
+  Get the fixed loading address from image header assigned by build tool. This function only be called\r
+  when Loading module at Fixed address feature enabled.\r
+\r
+  @param ImageContext              Pointer to the image context structure that describes the PE/COFF\r
+                                    image that needs to be examined by this function.\r
+  @param Private                    Pointer to the private data passed in from caller\r
+\r
+  @retval EFI_SUCCESS               An fixed loading address is assigned to this image by build tools .\r
+  @retval EFI_NOT_FOUND             The image has no assigned fixed loading address.\r
+\r
+**/\r
+EFI_STATUS\r
+GetPeCoffImageFixLoadingAssignedAddress(\r
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,\r
+  IN     PEI_CORE_INSTANCE             *Private\r
+  )\r
+{\r
+   UINTN                              SectionHeaderOffset;\r
+   EFI_STATUS                         Status;\r
+   EFI_IMAGE_SECTION_HEADER           SectionHeader;\r
+   EFI_IMAGE_OPTIONAL_HEADER_UNION    *ImgHdr;\r
+   EFI_PHYSICAL_ADDRESS               FixLoadingAddress;\r
+   UINT16                             Index;\r
+   UINTN                              Size;\r
+   UINT16                             NumberOfSections;\r
+   UINT64                             ValueInSectionHeader;\r
\r
+\r
+   FixLoadingAddress = 0;\r
+   Status = EFI_NOT_FOUND;\r
+\r
+   //\r
+   // Get PeHeader pointer\r
+   //\r
+   ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + ImageContext->PeCoffHeaderOffset);\r
+   if (ImageContext->IsTeImage) {\r
+     //\r
+     // for TE image, the fix loading address is saved in first section header that doesn't point\r
+     // to code section.\r
+     //\r
+     SectionHeaderOffset = sizeof (EFI_TE_IMAGE_HEADER);\r
+     NumberOfSections = ImgHdr->Te.NumberOfSections;\r
+   } else {\r
+     SectionHeaderOffset = ImageContext->PeCoffHeaderOffset +\r
+                           sizeof (UINT32) +\r
+                           sizeof (EFI_IMAGE_FILE_HEADER) +\r
+                           ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;\r
+      NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;\r
+   }\r
+   //\r
+   // Get base address from the first section header that doesn't point to code section.\r
+   //\r
+   for (Index = 0; Index < NumberOfSections; Index++) {\r
+     //\r
+     // Read section header from file\r
+     //\r
+     Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
+     Status = ImageContext->ImageRead (\r
+                              ImageContext->Handle,\r
+                              SectionHeaderOffset,\r
+                              &Size,\r
+                              &SectionHeader\r
+                              );\r
+     if (EFI_ERROR (Status)) {\r
+       return Status;\r
+     }\r
+\r
+     Status = EFI_NOT_FOUND;\r
+\r
+     if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
+       //\r
+       // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header\r
+       // that doesn't point to code section in image header, as well as ImageBase field of image header. A notable thing is\r
+       // that for PEIM, the value in ImageBase field may not be equal to the value in PointerToRelocations & PointerToLineNumbers because\r
+       // for XIP PEIM, ImageBase field holds the image base address running on the Flash. And PointerToRelocations & PointerToLineNumbers\r
+       // 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\r
+       // module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers fields should NOT be Zero, or\r
+       // else, these 2 fields should be set to Zero\r
+       //\r
+       ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);\r
+       if (ValueInSectionHeader != 0) {\r
+         //\r
+         // Found first section header that doesn't point to code section.\r
+         //\r
+         if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) > 0) {\r
+           //\r
+           // When LMFA feature is configured as Load Module at Fixed Absolute Address mode, PointerToRelocations & PointerToLineNumbers field\r
+           // hold the absolute address of image base running in memory\r
+           //\r
+           FixLoadingAddress = ValueInSectionHeader;\r
+         } else {\r
+           //\r
+           // When LMFA feature is configured as Load Module at Fixed offset mode, PointerToRelocations & PointerToLineNumbers field\r
+           // hold the offset relative to a platform-specific top address.\r
+           //\r
+           FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(Private->LoadModuleAtFixAddressTopAddress + (INT64)ValueInSectionHeader);\r
+         }\r
+         //\r
+         // Check if the memory range is available.\r
+         //\r
+         Status = CheckAndMarkFixLoadingMemoryUsageBitMap (Private, FixLoadingAddress, (UINT32) ImageContext->ImageSize);\r
+         if (!EFI_ERROR(Status)) {\r
+           //\r
+           // The assigned address is valid. Return the specified loading address\r
+           //\r
+           ImageContext->ImageAddress = FixLoadingAddress;\r
+         }\r
+       }\r
+       break;\r
+     }\r
+     SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
+   }\r
+   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));\r
+   return Status;\r
+}\r
+/**\r
+\r
+  Loads and relocates a PE/COFF image into memory.\r
+  If the image is not relocatable, it will not be loaded into memory and be loaded as XIP image.\r
+\r
+  @param FileHandle      - Pointer to the FFS file header of the image.\r
+  @param Pe32Data        - The base address of the PE/COFF file that is to be loaded and relocated\r
+  @param ImageAddress    - The base address of the relocated PE/COFF image\r
+  @param ImageSize       - The size of the relocated PE/COFF image\r
+  @param EntryPoint      - The entry point of the relocated PE/COFF image\r
+\r
+  @retval EFI_SUCCESS           The file was loaded and relocated\r
+  @retval EFI_OUT_OF_RESOURCES  There was not enough memory to load and relocate the PE/COFF file\r
+  @retval EFI_WARN_BUFFER_TOO_SMALL \r
+                                There is not enough heap to allocate the requested size.\r
+                                This will not prevent the XIP image from being invoked.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadAndRelocatePeCoffImage (\r
+  IN  EFI_PEI_FILE_HANDLE                       FileHandle,\r
+  IN  VOID                                      *Pe32Data,\r
+  OUT EFI_PHYSICAL_ADDRESS                      *ImageAddress,\r
+  OUT UINT64                                    *ImageSize,\r
+  OUT EFI_PHYSICAL_ADDRESS                      *EntryPoint\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;\r
+  PEI_CORE_INSTANCE                     *Private;\r
+  UINT64                                AlignImageSize;\r
+  BOOLEAN                               IsXipImage;\r
+  EFI_STATUS                            ReturnStatus;\r
+  BOOLEAN                               IsS3Boot;\r
+  BOOLEAN                               IsPeiModule;\r
+  BOOLEAN                               IsRegisterForShadow;\r
+  EFI_FV_FILE_INFO                      FileInfo;\r
+\r
+  Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());\r
+\r
+  ReturnStatus = EFI_SUCCESS;\r
+  IsXipImage   = FALSE;\r
+  ZeroMem (&ImageContext, sizeof (ImageContext));\r
+  ImageContext.Handle = Pe32Data;\r
+  Status              = GetImageReadFunction (&ImageContext);\r
+\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  \r
+  //\r
+  // Initilize local IsS3Boot and IsRegisterForShadow variable\r
+  //\r
+  IsS3Boot = FALSE;\r
+  if (Private->HobList.HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME) {\r
+    IsS3Boot = TRUE;\r
+  }\r
+  IsRegisterForShadow = FALSE;\r
+  if ((Private->CurrentFileHandle == FileHandle) \r
+    && (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW)) {\r
+    IsRegisterForShadow = TRUE;\r
+  }\r
+\r
+  //\r
+  // XIP image that ImageAddress is same to Image handle.\r
+  //\r
+  if (ImageContext.ImageAddress == (EFI_PHYSICAL_ADDRESS)(UINTN) Pe32Data) {\r
+    IsXipImage = TRUE;\r
+  }\r
+\r
+  //\r
+  // Get file type first\r
+  //\r
+  Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);\r
+  ASSERT_EFI_ERROR (Status);\r
+  \r
+  //\r
+  // Check whether the file type is PEI module.\r
+  //\r
+  IsPeiModule = FALSE;\r
+  if (FileInfo.FileType == EFI_FV_FILETYPE_PEI_CORE || \r
+      FileInfo.FileType == EFI_FV_FILETYPE_PEIM || \r
+      FileInfo.FileType == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER) {\r
+    IsPeiModule = TRUE;\r
+  }\r
+\r
+  //\r
+  // When Image has no reloc section, it can't be relocated into memory.\r
+  //\r
+  if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) && ((!IsPeiModule) ||\r
+      (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) || (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))) {\r
+    DEBUG ((EFI_D_INFO|EFI_D_LOAD, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN) Pe32Data));\r
+  }\r
+\r
+  //\r
+  // Set default base address to current image address.\r
+  //\r
+  ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Pe32Data;\r
+\r
+  //\r
+  // Allocate Memory for the image when memory is ready, and image is relocatable.\r
+  // On normal boot, PcdShadowPeimOnBoot decides whether load PEIM or PeiCore into memory.\r
+  // On S3 boot, PcdShadowPeimOnS3Boot decides whether load PEIM or PeiCore into memory.\r
+  //\r
+  if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) && ((!IsPeiModule) ||\r
+      (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) || (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))) {\r
+    //\r
+    // Allocate more buffer to avoid buffer overflow.\r
+    //\r
+    if (ImageContext.IsTeImage) {\r
+      AlignImageSize = ImageContext.ImageSize + ((EFI_TE_IMAGE_HEADER *) Pe32Data)->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);\r
+    } else {\r
+      AlignImageSize = ImageContext.ImageSize;\r
+    }\r
+\r
+    if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {\r
+      AlignImageSize += ImageContext.SectionAlignment;\r
+    }\r
+\r
+    if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
+      Status = GetPeCoffImageFixLoadingAssignedAddress(&ImageContext, Private);\r
+      if (EFI_ERROR (Status)){\r
+        DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));\r
+        //\r
+        // The PEIM is not assiged valid address, try to allocate page to load it.\r
+        //\r
+        Status = PeiServicesAllocatePages (EfiBootServicesCode,\r
+                                           EFI_SIZE_TO_PAGES ((UINT32) AlignImageSize),\r
+                                           &ImageContext.ImageAddress);\r
+      }\r
+    } else {\r
+      Status = PeiServicesAllocatePages (EfiBootServicesCode,\r
+                                         EFI_SIZE_TO_PAGES ((UINT32) AlignImageSize),\r
+                                         &ImageContext.ImageAddress);\r
+    }\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Adjust the Image Address to make sure it is section alignment.\r
+      //\r
+      if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {\r
+        ImageContext.ImageAddress =\r
+            (ImageContext.ImageAddress + ImageContext.SectionAlignment - 1) &\r
+            ~((UINTN)ImageContext.SectionAlignment - 1);\r
+      }\r
+      //\r
+      // Fix alignment requirement when Load IPF TeImage into memory.\r
+      // Skip the reserved space for the stripped PeHeader when load TeImage into memory.\r
+      //\r
+      if (ImageContext.IsTeImage) {\r
+        ImageContext.ImageAddress = ImageContext.ImageAddress +\r
+                                    ((EFI_TE_IMAGE_HEADER *) Pe32Data)->StrippedSize -\r
+                                    sizeof (EFI_TE_IMAGE_HEADER);\r
+      }\r
+    } else {\r
+      //\r
+      // No enough memory resource.\r
+      //\r
+      if (IsXipImage) {\r
+        //\r
+        // XIP image can still be invoked.\r
+        //\r
+        ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Pe32Data;\r
+        ReturnStatus = EFI_WARN_BUFFER_TOO_SMALL;\r
+      } else {\r
+        //\r
+        // Non XIP image can't be loaded because no enough memory is allocated.\r
+        //\r
+        ASSERT (FALSE);\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Load the image to our new buffer\r
+  //\r
+  Status = PeCoffLoaderLoadImage (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Relocate the image in our new buffer\r
+  //\r
+  Status = PeCoffLoaderRelocateImage (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Flush the instruction cache so the image data is written before we execute it\r
+  //\r
+  if (ImageContext.ImageAddress != (EFI_PHYSICAL_ADDRESS)(UINTN) Pe32Data) {\r
+    InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
+  }\r
+\r
+  *ImageAddress = ImageContext.ImageAddress;\r
+  *ImageSize    = ImageContext.ImageSize;\r
+  *EntryPoint   = ImageContext.EntryPoint;\r
+\r
+  return ReturnStatus;\r
+}\r
+\r
+/**\r
+  Loads a PEIM into memory for subsequent execution. If there are compressed\r
+  images or images that need to be relocated into memory for performance reasons,\r
+  this service performs that transformation.\r
+\r
+  @param PeiServices      An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
+  @param FileHandle       Pointer to the FFS file header of the image.\r
+  @param ImageAddressArg  Pointer to PE/TE image.\r
+  @param ImageSizeArg     Size of PE/TE image.\r
+  @param EntryPoint       Pointer to entry point of specified image file for output.\r
+  @param AuthenticationState - Pointer to attestation authentication state of image.\r
+\r
+  @retval EFI_SUCCESS      Image is successfully loaded.\r
+  @retval EFI_NOT_FOUND    Fail to locate necessary PPI.\r
+  @retval EFI_UNSUPPORTED  Image Machine Type is not supported.\r
+  @retval EFI_WARN_BUFFER_TOO_SMALL \r
+                           There is not enough heap to allocate the requested size.\r
+                           This will not prevent the XIP image from being invoked.\r
+\r
+**/\r
+EFI_STATUS\r
+PeiLoadImageLoadImage (\r
+  IN     CONST EFI_PEI_SERVICES       **PeiServices,\r
+  IN     EFI_PEI_FILE_HANDLE          FileHandle,\r
+  OUT    EFI_PHYSICAL_ADDRESS         *ImageAddressArg,  OPTIONAL\r
+  OUT    UINT64                       *ImageSizeArg,     OPTIONAL\r
+  OUT    EFI_PHYSICAL_ADDRESS         *EntryPoint,\r
+  OUT    UINT32                       *AuthenticationState\r
+  )\r
 {\r
   EFI_STATUS                  Status;\r
   VOID                        *Pe32Data;\r
-  EFI_PEI_FV_FILE_LOADER_PPI  *FvLoadFilePpi;\r
   EFI_PHYSICAL_ADDRESS        ImageAddress;\r
   UINT64                      ImageSize;\r
   EFI_PHYSICAL_ADDRESS        ImageEntryPoint;\r
-  EFI_TE_IMAGE_HEADER         *TEImageHeader;\r
   UINT16                      Machine;\r
+  EFI_SECTION_TYPE            SearchType1;\r
+  EFI_SECTION_TYPE            SearchType2;\r
 \r
-  *EntryPoint   = NULL;\r
-  TEImageHeader = NULL;\r
+  *EntryPoint          = 0;\r
+  ImageSize            = 0;\r
+  *AuthenticationState = 0;\r
+\r
+  if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) {\r
+    SearchType1 = EFI_SECTION_TE;\r
+    SearchType2 = EFI_SECTION_PE32;\r
+  } else {\r
+    SearchType1 = EFI_SECTION_PE32;\r
+    SearchType2 = EFI_SECTION_TE;\r
+  }\r
 \r
   //\r
-  // Try to find a PE32 section.\r
+  // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst\r
+  // is true, TE will be searched first).\r
   //\r
-  Status = PeiServicesFfsFindSectionData (\r
-             EFI_SECTION_PE32,\r
-             PeimFileHeader,\r
-             &Pe32Data\r
+  Status = PeiServicesFfsFindSectionData3 (\r
+             SearchType1,\r
+             0,\r
+             FileHandle,\r
+             &Pe32Data,\r
+             AuthenticationState\r
              );\r
   //\r
-  // If we didn't find a PE32 section, try to find a TE section.\r
+  // If we didn't find a first exe section, try to find the second exe section.\r
   //\r
   if (EFI_ERROR (Status)) {\r
-    Status = PeiServicesFfsFindSectionData (\r
-               EFI_SECTION_TE,\r
-               PeimFileHeader,\r
-               (VOID **) &TEImageHeader\r
+    Status = PeiServicesFfsFindSectionData3 (\r
+               SearchType2,\r
+               0,\r
+               FileHandle,\r
+               &Pe32Data,\r
+               AuthenticationState\r
                );\r
-    if (EFI_ERROR (Status) || TEImageHeader == NULL) {\r
+    if (EFI_ERROR (Status)) {\r
       //\r
-      // There was not a PE32 or a TE section, so assume that it's a Compressed section\r
-      // and use the LoadFile\r
+      // PEI core only carry the loader function for TE and PE32 executables\r
+      // If this two section does not exist, just return.\r
       //\r
-      Status = PeiServicesLocatePpi (\r
-                &gEfiPeiFvFileLoaderPpiGuid,\r
-                0,\r
-                NULL,\r
-                (VOID **)&FvLoadFilePpi\r
-                );\r
-      if (EFI_ERROR (Status)) {\r
-        return EFI_NOT_FOUND;\r
-      }\r
+      return Status;\r
+    }\r
+  }\r
 \r
-      Status = FvLoadFilePpi->FvLoadFile (\r
-                                FvLoadFilePpi,\r
-                                PeimFileHeader,\r
-                                &ImageAddress,\r
-                                &ImageSize,\r
-                                &ImageEntryPoint\r
-                                );\r
+  //\r
+  // If memory is installed, perform the shadow operations\r
+  //\r
+  Status = LoadAndRelocatePeCoffImage (\r
+    FileHandle,\r
+    Pe32Data,\r
+    &ImageAddress,\r
+    &ImageSize,\r
+    &ImageEntryPoint\r
+  );\r
 \r
-      if (EFI_ERROR (Status)) {\r
-        return EFI_NOT_FOUND;\r
-      }\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
+  //\r
+  // Got the entry point from the loaded Pe32Data\r
+  //\r
+  Pe32Data    = (VOID *) ((UINTN) ImageAddress);\r
+  *EntryPoint = ImageEntryPoint;\r
+\r
+  Machine = PeCoffLoaderGetMachineType (Pe32Data);\r
+\r
+  if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {\r
+    if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Machine)) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+\r
+  if (ImageAddressArg != NULL) {\r
+    *ImageAddressArg = ImageAddress;\r
+  }\r
+\r
+  if (ImageSizeArg != NULL) {\r
+    *ImageSizeArg = ImageSize;\r
+  }\r
+\r
+  DEBUG_CODE_BEGIN ();\r
+    CHAR8                              *AsciiString;\r
+    CHAR8                              EfiFileName[512];\r
+    INT32                              Index;\r
+    INT32                              StartIndex;\r
+\r
+    //\r
+    // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi\r
+    //\r
+    if (Machine != EFI_IMAGE_MACHINE_IA64) {\r
+      DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)*EntryPoint));\r
+    } else {\r
       //\r
-      // Got the entry point from ImageEntryPoint and ImageStartAddress\r
+      // For IPF Image, the real entry point should be print.\r
       //\r
-      Pe32Data    = (VOID *) ((UINTN) ImageAddress);\r
-      *EntryPoint = (VOID *) ((UINTN) ImageEntryPoint);\r
-    } else {\r
+      DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint)));\r
+    }\r
+\r
+    //\r
+    // Print Module Name by PeImage PDB file name.\r
+    //\r
+    AsciiString = PeCoffLoaderGetPdbPointer (Pe32Data);\r
+\r
+    if (AsciiString != NULL) {\r
+      StartIndex = 0;\r
+      for (Index = 0; AsciiString[Index] != 0; Index++) {\r
+        if (AsciiString[Index] == '\\' || AsciiString[Index] == '/') {\r
+          StartIndex = Index + 1;\r
+        }\r
+      }\r
+\r
       //\r
-      // Retrieve the entry point from the TE image header\r
+      // Copy the PDB file name to our temporary string, and replace .pdb with .efi\r
+      // The PDB file name is limited in the range of 0~511.\r
+      // If the length is bigger than 511, trim the redudant characters to avoid overflow in array boundary.\r
       //\r
-      ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) TEImageHeader;\r
-      *EntryPoint  = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) +\r
-                    TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize);\r
+      for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {\r
+        EfiFileName[Index] = AsciiString[Index + StartIndex];\r
+        if (EfiFileName[Index] == 0) {\r
+          EfiFileName[Index] = '.';\r
+        }\r
+        if (EfiFileName[Index] == '.') {\r
+          EfiFileName[Index + 1] = 'e';\r
+          EfiFileName[Index + 2] = 'f';\r
+          EfiFileName[Index + 3] = 'i';\r
+          EfiFileName[Index + 4] = 0;\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (Index == sizeof (EfiFileName) - 4) {\r
+        EfiFileName[Index] = 0;\r
+      }\r
+\r
+      DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a", EfiFileName));\r
     }\r
+\r
+  DEBUG_CODE_END ();\r
+\r
+  DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+  The wrapper function of PeiLoadImageLoadImage().\r
+\r
+  @param This            - Pointer to EFI_PEI_LOAD_FILE_PPI.\r
+  @param FileHandle      - Pointer to the FFS file header of the image.\r
+  @param ImageAddressArg - Pointer to PE/TE image.\r
+  @param ImageSizeArg    - Size of PE/TE image.\r
+  @param EntryPoint      - Pointer to entry point of specified image file for output.\r
+  @param AuthenticationState - Pointer to attestation authentication state of image.\r
+\r
+  @return Status of PeiLoadImageLoadImage().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiLoadImageLoadImageWrapper (\r
+  IN     CONST EFI_PEI_LOAD_FILE_PPI  *This,\r
+  IN     EFI_PEI_FILE_HANDLE          FileHandle,\r
+  OUT    EFI_PHYSICAL_ADDRESS         *ImageAddressArg,  OPTIONAL\r
+  OUT    UINT64                       *ImageSizeArg,     OPTIONAL\r
+  OUT    EFI_PHYSICAL_ADDRESS         *EntryPoint,\r
+  OUT    UINT32                       *AuthenticationState\r
+  )\r
+{\r
+  return PeiLoadImageLoadImage (\r
+           GetPeiServicesTablePointer (),\r
+           FileHandle,\r
+           ImageAddressArg,\r
+           ImageSizeArg,\r
+           EntryPoint,\r
+           AuthenticationState\r
+           );\r
+}\r
+\r
+/**\r
+  Check whether the input image has the relocation.\r
+\r
+  @param  Pe32Data   Pointer to the PE/COFF or TE image.\r
+\r
+  @retval TRUE       Relocation is stripped.\r
+  @retval FALSE      Relocation is not stripped.\r
+\r
+**/\r
+BOOLEAN\r
+RelocationIsStrip (\r
+  IN VOID  *Pe32Data\r
+  )\r
+{\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;\r
+  EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
+\r
+  ASSERT (Pe32Data != NULL);\r
+\r
+  DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
+  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+    //\r
+    // DOS image header is present, so read the PE header after the DOS image header.\r
+    //\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
   } else {\r
     //\r
-    // Retrieve the entry point from the PE/COFF image header\r
+    // DOS image header is not present, so PE header is at the image base.\r
     //\r
-    ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data;\r
-    Status = PeCoffLoaderGetEntryPoint (Pe32Data, EntryPoint);\r
-    if (EFI_ERROR (Status)) {\r
-      return EFI_NOT_FOUND;\r
-    }\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
   }\r
 \r
-  if (((EFI_TE_IMAGE_HEADER *) (UINTN) ImageAddress)->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
-    TEImageHeader = (EFI_TE_IMAGE_HEADER *) (UINTN) ImageAddress;\r
-    Machine = TEImageHeader->Machine;\r
-  } else {\r
-    Machine = PeCoffLoaderGetMachineType (Pe32Data);\r
-  } \r
-  \r
-  if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {\r
-    return EFI_UNSUPPORTED;  \r
+  //\r
+  // Three cases with regards to relocations:\r
+  // - Image has base relocs, RELOCS_STRIPPED==0    => image is relocatable\r
+  // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable\r
+  // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but\r
+  //   has no base relocs to apply\r
+  // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.\r
+  //\r
+  // Look at the file header to determine if relocations have been stripped, and\r
+  // save this info in the image context for later use.\r
+  //\r
+  if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+    if ((Hdr.Te->DataDirectory[0].Size == 0) && (Hdr.Te->DataDirectory[0].VirtualAddress == 0)) {\r
+      return TRUE;\r
+    } else {\r
+      return FALSE;\r
+    }\r
+  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE)  {\r
+    if ((Hdr.Pe32->FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0) {\r
+      return TRUE;\r
+    } else {\r
+      return FALSE;\r
+    }\r
   }\r
 \r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Routine to load image file for subsequent execution by LoadFile Ppi.\r
+  If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE\r
+  XIP image format is used.\r
+\r
+  @param PeiServices     - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
+  @param FileHandle      - Pointer to the FFS file header of the image.\r
+  @param PeimState       - The dispatch state of the input PEIM handle.\r
+  @param EntryPoint      - Pointer to entry point of specified image file for output.\r
+  @param AuthenticationState - Pointer to attestation authentication state of image.\r
+\r
+  @retval EFI_SUCCESS    - Image is successfully loaded.\r
+  @retval EFI_NOT_FOUND  - Fail to locate necessary PPI\r
+  @retval Others         - Fail to load file.\r
+\r
+**/\r
+EFI_STATUS\r
+PeiLoadImage (\r
+  IN     CONST EFI_PEI_SERVICES       **PeiServices,\r
+  IN     EFI_PEI_FILE_HANDLE          FileHandle,\r
+  IN     UINT8                        PeimState,\r
+  OUT    EFI_PHYSICAL_ADDRESS         *EntryPoint,\r
+  OUT    UINT32                       *AuthenticationState\r
+  )\r
+{\r
+  EFI_STATUS              PpiStatus;\r
+  EFI_STATUS              Status;\r
+  UINTN                   Index;\r
+  EFI_PEI_LOAD_FILE_PPI   *LoadFile;\r
+  EFI_PHYSICAL_ADDRESS    ImageAddress;\r
+  UINT64                  ImageSize;\r
+  BOOLEAN                 IsStrip;\r
+\r
+  IsStrip = FALSE;\r
   //\r
-  // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi\r
+  // If any instances of PEI_LOAD_FILE_PPI are installed, they are called.\r
+  // one at a time, until one reports EFI_SUCCESS.\r
   //\r
-  DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", (UINTN) ImageAddress, *EntryPoint));\r
-  DEBUG_CODE_BEGIN ();\r
-    EFI_IMAGE_DATA_DIRECTORY            *DirectoryEntry;\r
-    EFI_IMAGE_DEBUG_DIRECTORY_ENTRY     *DebugEntry;\r
-    UINTN                               DirCount;\r
-    UINTN                               Index;\r
-    UINTN                               Index1;\r
-    BOOLEAN                             FileNameFound;\r
-    CHAR8                               *AsciiString;\r
-    CHAR8                               AsciiBuffer[512];\r
-    VOID                                *CodeViewEntryPointer;\r
-    INTN                                TEImageAdjust;\r
-    EFI_IMAGE_DOS_HEADER                *DosHeader;\r
-    EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
-    UINT32                              NumberOfRvaAndSizes;\r
-\r
-    Hdr.Pe32 = NULL;\r
-    if (TEImageHeader == NULL) {\r
-      DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
-      if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+  Index = 0;\r
+  do {\r
+    PpiStatus = PeiServicesLocatePpi (\r
+                  &gEfiPeiLoadFilePpiGuid,\r
+                  Index,\r
+                  NULL,\r
+                  (VOID **)&LoadFile\r
+                  );\r
+    if (!EFI_ERROR (PpiStatus)) {\r
+      Status = LoadFile->LoadFile (\r
+                          LoadFile,\r
+                          FileHandle,\r
+                          &ImageAddress,\r
+                          &ImageSize,\r
+                          EntryPoint,\r
+                          AuthenticationState\r
+                          );\r
+      if (!EFI_ERROR (Status) || Status == EFI_WARN_BUFFER_TOO_SMALL) {\r
         //\r
-        // DOS image header is present, so read the PE header after the DOS image header\r
+        // The shadowed PEIM must be relocatable.\r
         //\r
-        Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHeader->e_lfanew) & 0x0ffff));\r
-      } else {\r
+        if (PeimState == PEIM_STATE_REGISITER_FOR_SHADOW) {\r
+          IsStrip = RelocationIsStrip ((VOID *) (UINTN) ImageAddress);\r
+          ASSERT (!IsStrip);\r
+          if (IsStrip) {\r
+            return EFI_UNSUPPORTED;\r
+          }\r
+        }\r
+\r
         //\r
-        // DOS image header is not present, so PE header is at the image base\r
+        // The image to be started must have the machine type supported by PeiCore.\r
         //\r
-        Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
+        ASSERT (EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCoffLoaderGetMachineType ((VOID *) (UINTN) ImageAddress)));\r
+        if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCoffLoaderGetMachineType ((VOID *) (UINTN) ImageAddress))) {\r
+          return EFI_UNSUPPORTED;\r
+        }\r
+        return EFI_SUCCESS;\r
       }\r
     }\r
+    Index++;\r
+  } while (!EFI_ERROR (PpiStatus));\r
+\r
+  return PpiStatus;\r
+}\r
+\r
+\r
+/**\r
 \r
+  Install Pei Load File PPI.\r
+\r
+\r
+  @param PrivateData     - Pointer to PEI_CORE_INSTANCE.\r
+  @param OldCoreData     - Pointer to PEI_CORE_INSTANCE.\r
+\r
+**/\r
+VOID\r
+InitializeImageServices (\r
+  IN  PEI_CORE_INSTANCE   *PrivateData,\r
+  IN  PEI_CORE_INSTANCE   *OldCoreData\r
+  )\r
+{\r
+  if (OldCoreData == NULL) {\r
     //\r
-    // Find the codeview info in the image and display the file name\r
-    // being loaded.\r
+    // The first time we are XIP (running from FLASH). We need to remember the\r
+    // FLASH address so we can reinstall the memory version that runs faster\r
     //\r
-    // Per the PE/COFF spec, you can't assume that a given data directory\r
-    // is present in the image. You have to check the NumberOfRvaAndSizes in\r
-    // the optional header to verify a desired directory entry is there.\r
+    PrivateData->XipLoadFile = &gPpiLoadFilePpiList;\r
+    PeiServicesInstallPpi (PrivateData->XipLoadFile);\r
+  } else {\r
     //\r
-    DebugEntry          = NULL;\r
-    DirectoryEntry      = NULL;\r
-    NumberOfRvaAndSizes = 0;\r
-    TEImageAdjust       = 0;\r
-    \r
-    if (TEImageHeader == NULL) {\r
-      if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-        //     \r
-        // Use PE32 offset get Debug Directory Entry\r
-        //\r
-        NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
-        DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
-        DebugEntry     = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);\r
-      } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
-        //     \r
-        // Use PE32+ offset get Debug Directory Entry\r
-        //\r
-        NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
-        DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
-        DebugEntry     = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);\r
-      }\r
+    // 2nd time we are running from memory so replace the XIP version with the\r
+    // new memory version.\r
+    //\r
+    PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList);\r
+  }\r
+}\r
 \r
-      if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
-        DirectoryEntry = NULL;\r
-        DebugEntry = NULL;\r
-      }\r
-    } else {\r
-      if (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {\r
-        DirectoryEntry  = &TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
-        TEImageAdjust   = sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize;\r
-        DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) TEImageHeader +\r
-                      TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +\r
-                      TEImageAdjust);\r
-      }\r
-    }\r
 \r
-    if (DebugEntry != NULL && DirectoryEntry != NULL) {\r
-      for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) {\r
-        if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
-          if (DebugEntry->SizeOfData > 0) {\r
-            CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageAddress + (UINTN)TEImageAdjust);\r
-            switch (* (UINT32 *) CodeViewEntryPointer) {\r
-              case CODEVIEW_SIGNATURE_NB10:\r
-                AsciiString = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);\r
-                break;\r
-\r
-              case CODEVIEW_SIGNATURE_RSDS:\r
-                AsciiString = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);\r
-                break;\r
-\r
-              default:\r
-                AsciiString = NULL;\r
-                break;\r
-            }\r
-            if (AsciiString != NULL) {\r
-              FileNameFound = FALSE;\r
-              for (Index = 0, Index1 = 0; AsciiString[Index] != '\0'; Index++) {\r
-                if (AsciiString[Index] == '\\') {\r
-                  Index1 = Index;\r
-                  FileNameFound = TRUE;\r
-                }\r
-              }\r
-\r
-              if (FileNameFound) {\r
-                for (Index = Index1 + 1; AsciiString[Index] != '.'; Index++) {\r
-                  AsciiBuffer[Index - (Index1 + 1)] = AsciiString[Index];\r
-                }\r
-                AsciiBuffer[Index - (Index1 + 1)] = 0;\r
-                DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer));\r
-                break;\r
-              }\r
-            }\r
-          }\r
-        }\r
-      }\r
-    }\r
-  DEBUG_CODE_END ();\r
 \r
-  DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));\r
 \r
-  return EFI_SUCCESS;\r
-}\r