示例#1
0
文件: Image.c 项目: B-Rich/edk2
/**

  Support routine to get the Image read file function.

  @param ImageContext    - The context of the image being loaded

  @retval EFI_SUCCESS - If Image function location is found

**/
EFI_STATUS
GetImageReadFunction (
  IN      PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
  )
{
  PEI_CORE_INSTANCE  *Private;
  VOID*  MemoryBuffer;

  Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
  
  if (Private->PeiMemoryInstalled  && ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) || PcdGetBool (PcdShadowPeimOnS3Boot))  &&
      (EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_X64) || EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_IA32))) {
    // 
    // Shadow algorithm makes lots of non ANSI C assumptions and only works for IA32 and X64 
    //  compilers that have been tested
    //
    if (Private->ShadowedImageRead == NULL) {
      MemoryBuffer = AllocatePages (0x400 / EFI_PAGE_SIZE + 1);
      ASSERT (MemoryBuffer != NULL);
      CopyMem (MemoryBuffer, (CONST VOID *) (UINTN) PeiImageReadForShadow, 0x400);
      Private->ShadowedImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer;
    }

    ImageContext->ImageRead = Private->ShadowedImageRead;
  } else {
    ImageContext->ImageRead = PeiImageRead;
  }

  return EFI_SUCCESS;
}
/**
  Return whether the PE header of the load option is valid or not.

  @param[in] Type       The load option type.
  @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) &&
          EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeHeader->Pe32.FileHeader.Machine)
          ) {
        //
        // 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 == 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)
            ) {
          return TRUE;
        }
      }
    }
  }

  return FALSE;
}
示例#3
0
/**
  Initialize all the stuff needed for on-demand paging hooks for PI<->Framework
  CpuSaveStates marshalling.

  @param[in] FrameworkSmst   Framework SMM system table pointer.

**/
VOID
InitHook (
  IN EFI_SMM_SYSTEM_TABLE  *FrameworkSmst
  )
{
  UINTN                 NumCpuStatePages;
  UINTN                 CpuStatePage;
  UINTN                 Bottom2MPage;
  UINTN                 Top2MPage;
  
  mPageTableHookEnabled = FALSE;
  NumCpuStatePages = EFI_SIZE_TO_PAGES (mNumberOfProcessors * sizeof (EFI_SMM_CPU_SAVE_STATE));
  //
  // Only hook page table for X64 image and less than 2MB needed to hold all CPU Save States
  //
  if (EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_X64) && NumCpuStatePages <= EFI_SIZE_TO_PAGES (SIZE_2MB)) {
    //
    // Allocate double page size to make sure all CPU Save States are in one 2MB page.
    //
    CpuStatePage = (UINTN)AllocatePages (NumCpuStatePages * 2);
    ASSERT (CpuStatePage != 0);
    Bottom2MPage = CpuStatePage & ~(SIZE_2MB-1);
    Top2MPage    = (CpuStatePage + EFI_PAGES_TO_SIZE (NumCpuStatePages * 2) - 1) & ~(SIZE_2MB-1);
    if (Bottom2MPage == Top2MPage ||
        CpuStatePage + EFI_PAGES_TO_SIZE (NumCpuStatePages * 2) - Top2MPage >= EFI_PAGES_TO_SIZE (NumCpuStatePages)
        ) {
      //
      // If the allocated 4KB pages are within the same 2MB page or higher portion is larger, use higher portion pages.
      //
      FrameworkSmst->CpuSaveState = (EFI_SMM_CPU_SAVE_STATE *)(CpuStatePage + EFI_PAGES_TO_SIZE (NumCpuStatePages));
      FreePages ((VOID*)CpuStatePage, NumCpuStatePages);
    } else {
      FrameworkSmst->CpuSaveState = (EFI_SMM_CPU_SAVE_STATE *)CpuStatePage;
      FreePages ((VOID*)(CpuStatePage + EFI_PAGES_TO_SIZE (NumCpuStatePages)), NumCpuStatePages);
    }
    //
    // Add temporary working buffer for hooking
    //
    mShadowSaveState = (EFI_SMM_CPU_SAVE_STATE*) AllocatePool (sizeof (EFI_SMM_CPU_SAVE_STATE));
    ASSERT (mShadowSaveState != NULL);
    //
    // Allocate and initialize 4KB Page Table for hooking CpuSaveState.
    // Replace the original 2MB PDE with new 4KB page table.
    //
    mCpuStatePageTable = InitCpuStatePageTable (FrameworkSmst->CpuSaveState);
    //
    // Mark PTE for CpuSaveState as non-exist.
    //
    HookCpuStateMemory (FrameworkSmst->CpuSaveState);
    HookPageFaultHandler ();
    CpuFlushTlb ();
    mPageTableHookEnabled = TRUE;
  }
  mHookInitialized = TRUE;
}
示例#4
0
文件: Image.c 项目: B-Rich/edk2
/**
  Routine to load image file for subsequent execution by LoadFile Ppi.
  If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE
  XIP image format is used.

  @param PeiServices     - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
  @param FileHandle      - Pointer to the FFS file header of the image.
  @param PeimState       - The dispatch state of the input PEIM handle.
  @param EntryPoint      - Pointer to entry point of specified image file for output.
  @param AuthenticationState - Pointer to attestation authentication state of image.

  @retval EFI_SUCCESS    - Image is successfully loaded.
  @retval EFI_NOT_FOUND  - Fail to locate necessary PPI
  @retval Others         - Fail to load file.

**/
EFI_STATUS
PeiLoadImage (
  IN     CONST EFI_PEI_SERVICES       **PeiServices,
  IN     EFI_PEI_FILE_HANDLE          FileHandle,
  IN     UINT8                        PeimState,
  OUT    EFI_PHYSICAL_ADDRESS         *EntryPoint,
  OUT    UINT32                       *AuthenticationState
  )
{
  EFI_STATUS              PpiStatus;
  EFI_STATUS              Status;
  UINTN                   Index;
  EFI_PEI_LOAD_FILE_PPI   *LoadFile;
  EFI_PHYSICAL_ADDRESS    ImageAddress;
  UINT64                  ImageSize;
  BOOLEAN                 IsStrip;

  IsStrip = FALSE;
  //
  // If any instances of PEI_LOAD_FILE_PPI are installed, they are called.
  // one at a time, until one reports EFI_SUCCESS.
  //
  Index = 0;
  do {
    PpiStatus = PeiServicesLocatePpi (
                  &gEfiPeiLoadFilePpiGuid,
                  Index,
                  NULL,
                  (VOID **)&LoadFile
                  );
    if (!EFI_ERROR (PpiStatus)) {
      Status = LoadFile->LoadFile (
                          LoadFile,
                          FileHandle,
                          &ImageAddress,
                          &ImageSize,
                          EntryPoint,
                          AuthenticationState
                          );
      if (!EFI_ERROR (Status) || Status == EFI_WARN_BUFFER_TOO_SMALL) {
        //
        // The shadowed PEIM must be relocatable.
        //
        if (PeimState == PEIM_STATE_REGISITER_FOR_SHADOW) {
          IsStrip = RelocationIsStrip ((VOID *) (UINTN) ImageAddress);
          ASSERT (!IsStrip);
          if (IsStrip) {
            return EFI_UNSUPPORTED;
          }
        }

        //
        // 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))) {
          return EFI_UNSUPPORTED;
        }
        return EFI_SUCCESS;
      }
    }
    Index++;
  } while (!EFI_ERROR (PpiStatus));

  return PpiStatus;
}
示例#5
0
文件: Image.c 项目: B-Rich/edk2
/**
  Loads a PEIM into memory for subsequent execution. If there are compressed
  images or images that need to be relocated into memory for performance reasons,
  this service performs that transformation.

  @param PeiServices      An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
  @param FileHandle       Pointer to the FFS file header of the image.
  @param ImageAddressArg  Pointer to PE/TE image.
  @param ImageSizeArg     Size of PE/TE image.
  @param EntryPoint       Pointer to entry point of specified image file for output.
  @param AuthenticationState - Pointer to attestation authentication state of image.

  @retval EFI_SUCCESS      Image is successfully loaded.
  @retval EFI_NOT_FOUND    Fail to locate necessary PPI.
  @retval EFI_UNSUPPORTED  Image Machine Type is not supported.
  @retval EFI_WARN_BUFFER_TOO_SMALL 
                           There is not enough heap to allocate the requested size.
                           This will not prevent the XIP image from being invoked.

**/
EFI_STATUS
PeiLoadImageLoadImage (
  IN     CONST EFI_PEI_SERVICES       **PeiServices,
  IN     EFI_PEI_FILE_HANDLE          FileHandle,
  OUT    EFI_PHYSICAL_ADDRESS         *ImageAddressArg,  OPTIONAL
  OUT    UINT64                       *ImageSizeArg,     OPTIONAL
  OUT    EFI_PHYSICAL_ADDRESS         *EntryPoint,
  OUT    UINT32                       *AuthenticationState
  )
{
  EFI_STATUS                  Status;
  VOID                        *Pe32Data;
  EFI_PHYSICAL_ADDRESS        ImageAddress;
  UINT64                      ImageSize;
  EFI_PHYSICAL_ADDRESS        ImageEntryPoint;
  UINT16                      Machine;
  EFI_SECTION_TYPE            SearchType1;
  EFI_SECTION_TYPE            SearchType2;

  *EntryPoint          = 0;
  ImageSize            = 0;
  *AuthenticationState = 0;

  if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) {
    SearchType1 = EFI_SECTION_TE;
    SearchType2 = EFI_SECTION_PE32;
  } else {
    SearchType1 = EFI_SECTION_PE32;
    SearchType2 = EFI_SECTION_TE;
  }

  //
  // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst
  // is true, TE will be searched first).
  //
  Status = PeiServicesFfsFindSectionData3 (
             SearchType1,
             0,
             FileHandle,
             &Pe32Data,
             AuthenticationState
             );
  //
  // If we didn't find a first exe section, try to find the second exe section.
  //
  if (EFI_ERROR (Status)) {
    Status = PeiServicesFfsFindSectionData3 (
               SearchType2,
               0,
               FileHandle,
               &Pe32Data,
               AuthenticationState
               );
    if (EFI_ERROR (Status)) {
      //
      // PEI core only carry the loader function for TE and PE32 executables
      // If this two section does not exist, just return.
      //
      return Status;
    }
  }

  //
  // If memory is installed, perform the shadow operations
  //
  Status = LoadAndRelocatePeCoffImage (
    Pe32Data,
    &ImageAddress,
    &ImageSize,
    &ImageEntryPoint
  );

  ASSERT_EFI_ERROR (Status);


  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // 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;
    }
  }

  if (ImageAddressArg != NULL) {
    *ImageAddressArg = ImageAddress;
  }

  if (ImageSizeArg != NULL) {
    *ImageSizeArg = ImageSize;
  }

  DEBUG_CODE_BEGIN ();
    CHAR8                              *AsciiString;
    CHAR8                              EfiFileName[512];
    INT32                              Index;
    INT32                              StartIndex;

    //
    // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi
    //
    if (Machine != EFI_IMAGE_MACHINE_IA64) {
      DEBUG ((EFI_D_INFO | EFI_D_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 ((EFI_D_INFO | EFI_D_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;
        }
      }

      //
      // 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 redudant characters to avoid overflow in array boundary.
      //
      for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {
        EfiFileName[Index] = AsciiString[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 ((EFI_D_INFO | EFI_D_LOAD, "%a", EfiFileName));
    }

  DEBUG_CODE_END ();

  DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));

  return EFI_SUCCESS;

}
示例#6
0
/**
  Loads a PEIM into memory for subsequent execution. If there are compressed
  images or images that need to be relocated into memory for performance reasons,
  this service performs that transformation.

  @param PeiServices      An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
  @param FileHandle       Pointer to the FFS file header of the image.
  @param ImageAddressArg  Pointer to PE/TE image.
  @param ImageSizeArg     Size of PE/TE image.
  @param EntryPoint       Pointer to entry point of specified image file for output.
  @param AuthenticationState - Pointer to attestation authentication state of image.

  @retval EFI_SUCCESS      Image is successfully loaded.
  @retval EFI_NOT_FOUND    Fail to locate necessary PPI.
  @retval EFI_UNSUPPORTED  Image Machine Type is not supported.

**/
EFI_STATUS
PeiLoadImageLoadImage (
  IN     CONST EFI_PEI_SERVICES       **PeiServices,
  IN     EFI_PEI_FILE_HANDLE          FileHandle,
  OUT    EFI_PHYSICAL_ADDRESS         *ImageAddressArg,  OPTIONAL
  OUT    UINT64                       *ImageSizeArg,     OPTIONAL
  OUT    EFI_PHYSICAL_ADDRESS         *EntryPoint,
  OUT    UINT32                       *AuthenticationState
  )
{
  EFI_STATUS                  Status;
  VOID                        *Pe32Data;
  EFI_PHYSICAL_ADDRESS        ImageAddress;
  UINT64                      ImageSize;
  EFI_PHYSICAL_ADDRESS        ImageEntryPoint;
  UINT16                      Machine;
  EFI_SECTION_TYPE            SearchType1;
  EFI_SECTION_TYPE            SearchType2;

  *EntryPoint          = 0;
  ImageSize            = 0;
  *AuthenticationState = 0;

  if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) {
    SearchType1 = EFI_SECTION_TE;
    SearchType2 = EFI_SECTION_PE32;
  } else {
    SearchType1 = EFI_SECTION_PE32;
    SearchType2 = EFI_SECTION_TE;
  }

  //
  // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst
  // is true, TE will be searched first).
  //
  Status = PeiServicesFfsFindSectionData (
             SearchType1,
             FileHandle,
             &Pe32Data
             );
  //
  // If we didn't find a first exe section, try to find the second exe section.
  //
  if (EFI_ERROR (Status)) {
    Status = PeiServicesFfsFindSectionData (
               SearchType2,
               FileHandle,
               &Pe32Data
               );
    if (EFI_ERROR (Status)) {
      //
      // PEI core only carry the loader function fro TE and PE32 executables
      // If this two section does not exist, just return.
      //
      return Status;
    }
  }

  //
  // If memory is installed, perform the shadow operations
  //
  Status = LoadAndRelocatePeCoffImage (
    Pe32Data,
    &ImageAddress,
    &ImageSize,
    &ImageEntryPoint
  );

  ASSERT_EFI_ERROR (Status);


  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // 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;
    }
  }

  if (ImageAddressArg != NULL) {
    *ImageAddressArg = ImageAddress;
  }

  if (ImageSizeArg != NULL) {
    *ImageSizeArg = ImageSize;
  }

  DEBUG_CODE_BEGIN ();
    CHAR8                              *AsciiString;
    CHAR8                              AsciiBuffer[512];
    INT32                              Index;
    INT32                              Index1;

    //
    // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi
    //
    if (Machine != EFI_IMAGE_MACHINE_IA64) {
      DEBUG ((EFI_D_INFO | EFI_D_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 ((EFI_D_INFO | EFI_D_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) {
      for (Index = (INT32) AsciiStrLen (AsciiString) - 1; Index >= 0; Index --) {
        if (AsciiString[Index] == '\\') {
          break;
        }
      }

      if (Index != 0) {
        for (Index1 = 0; AsciiString[Index + 1 + Index1] != '.'; Index1 ++) {
          AsciiBuffer [Index1] = AsciiString[Index + 1 + Index1];
        }
        AsciiBuffer [Index1] = '\0';
        DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer));
      }
    }

  DEBUG_CODE_END ();

  DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));

  return EFI_SUCCESS;

}
示例#7
0
/**

  Support routine to get the Image read file function.

  @param ImageContext    - The context of the image being loaded

  @retval EFI_SUCCESS - If Image function location is found

**/
EFI_STATUS
GetImageReadFunction (
  IN      PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
  )
{
  PEI_CORE_INSTANCE  *Private;
  VOID*  MemoryBuffer;

  Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());

  if (!Private->PeiMemoryInstalled || (Private->HobList.HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME) || EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_IA64)) {
    ImageContext->ImageRead = PeiImageRead;
  } else {
    if (Private->ShadowedImageRead == NULL) {
      MemoryBuffer = AllocatePages (0x400 / EFI_PAGE_SIZE + 1);
      ASSERT (MemoryBuffer != NULL);
      CopyMem (MemoryBuffer, (CONST VOID *) (UINTN) PeiImageReadForShadow, 0x400);
      Private->ShadowedImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer;
    }

    ImageContext->ImageRead = Private->ShadowedImageRead;
  }

  return EFI_SUCCESS;
}