summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Core/Pei/Image
diff options
context:
space:
mode:
authorklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>2007-09-24 11:38:43 +0000
committerklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>2007-09-24 11:38:43 +0000
commitb0d803fe3e5c55a9a0c75bc90ccf40ebbbc9ffa3 (patch)
tree071d183f0cf4e1be4345e64f10a6228639187135 /MdeModulePkg/Core/Pei/Image
parentf6203b71926848e7b197ee99a3a86a487d7b334a (diff)
downloadedk2-platforms-b0d803fe3e5c55a9a0c75bc90ccf40ebbbc9ffa3.tar.xz
Merge branch of PI tree to main trunk
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3918 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Core/Pei/Image')
-rw-r--r--MdeModulePkg/Core/Pei/Image/Image.c542
1 files changed, 496 insertions, 46 deletions
diff --git a/MdeModulePkg/Core/Pei/Image/Image.c b/MdeModulePkg/Core/Pei/Image/Image.c
index 202936869b..ebe79a6c50 100644
--- a/MdeModulePkg/Core/Pei/Image/Image.c
+++ b/MdeModulePkg/Core/Pei/Image/Image.c
@@ -21,13 +21,33 @@ Abstract:
#include <PeiMain.h>
+/*++
+
+Routine Description:
+
+ Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
+Arguments:
+
+ FileHandle - The handle to the PE/COFF file
+ FileOffset - The offset, in bytes, into the file to read
+ ReadSize - The number of bytes to read from the file starting at FileOffset
+ Buffer - A pointer to the buffer to read the data into.
+
+Returns:
+
+ EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
+
+--*/
EFI_STATUS
-PeiLoadImage (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_FFS_FILE_HEADER *PeimFileHeader,
- OUT VOID **EntryPoint
+PeiLoadImageLoadImage (
+ IN 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
)
/*++
@@ -37,9 +57,247 @@ Routine Description:
Arguments:
- PeiServices - The PEI core services table.
- PeimFileHeader - Pointer to the FFS file header of the image.
- EntryPoint - Pointer to entry point of specified image file for output.
+ PeiServices - The PEI core services table.
+ FileHandle - Pointer to the FFS file header of the image.
+ ImageAddressArg - Pointer to PE/TE image.
+ ImageSizeArg - Size of PE/TE image.
+ EntryPoint - Pointer to entry point of specified image file for output.
+ AuthenticationState - Pointer to attestation authentication state of image.
+
+Returns:
+
+ Status - EFI_SUCCESS - Image is successfully loaded.
+ EFI_NOT_FOUND - Fail to locate necessary PPI
+ Others - Fail to load file.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PeiLoadImageLoadImageWrapper (
+ IN CONST EFI_PEI_LOAD_FILE_PPI *This,
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL
+ OUT UINT64 *ImageSizeArg, OPTIONAL
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
+ OUT UINT32 *AuthenticationState
+ )
+/*++
+
+Routine Description:
+
+ The wrapper function of PeiLoadImageLoadImage().
+
+Arguments:
+
+ This - Pointer to EFI_PEI_LOAD_FILE_PPI.
+ PeiServices - The PEI core services table.
+ FileHandle - Pointer to the FFS file header of the image.
+ ImageAddressArg - Pointer to PE/TE image.
+ ImageSizeArg - Size of PE/TE image.
+ EntryPoint - Pointer to entry point of specified image file for output.
+ AuthenticationState - Pointer to attestation authentication state of image.
+
+Returns:
+
+ EFI_STATUS.
+
+--*/
+;
+
+STATIC EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi = {
+ PeiLoadImageLoadImageWrapper
+};
+
+
+STATIC EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiLoadFilePpiGuid,
+ &mPeiLoadImagePpi
+};
+
+EFI_STATUS
+EFIAPI
+PeiImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
+
+Arguments:
+
+ FileHandle - The handle to the PE/COFF file
+ FileOffset - The offset, in bytes, into the file to read
+ ReadSize - The number of bytes to read from the file starting at FileOffset
+ Buffer - A pointer to the buffer to read the data into.
+
+Returns:
+
+ EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
+
+--*/
+{
+ CHAR8 *Destination8;
+ CHAR8 *Source8;
+ UINTN Length;
+
+ Destination8 = Buffer;
+ Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
+ Length = *ReadSize;
+ while (Length--) {
+ *(Destination8++) = *(Source8++);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetImageReadFunction (
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+/*++
+
+Routine Description:
+
+ Support routine to return the Image Read
+
+Arguments:
+
+ PeiServices - PEI Services Table
+
+ ImageContext - The context of the image being loaded
+
+Returns:
+
+ EFI_SUCCESS - If Image function location is found
+
+--*/
+{
+ VOID* MemoryBuffer;
+
+ MemoryBuffer = AllocatePages (0x400 / EFI_PAGE_SIZE + 1);
+ ASSERT (MemoryBuffer != NULL);
+
+ CopyMem (MemoryBuffer, (CONST VOID *) (UINTN) PeiImageRead, 0x400);
+
+ ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer;
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+LoadAndRelocatePeCoffImage (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader,
+ IN VOID *Pe32Data,
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
+ OUT UINT64 *ImageSize,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint
+ )
+/*++
+
+Routine Description:
+
+ Loads and relocates a PE/COFF image into memory.
+
+Arguments:
+
+ PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
+
+ Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
+
+ ImageAddress - The base address of the relocated PE/COFF image
+
+ ImageSize - The size of the relocated PE/COFF image
+
+ EntryPoint - The entry point of the relocated PE/COFF image
+
+Returns:
+
+ EFI_SUCCESS - The file was loaded and relocated
+
+ EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
+
+--*/
+{
+ EFI_STATUS Status;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+
+ ASSERT (PeiEfiPeiPeCoffLoader != NULL);
+
+ ZeroMem (&ImageContext, sizeof (ImageContext));
+ ImageContext.Handle = Pe32Data;
+ Status = GetImageReadFunction (&ImageContext);
+
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiEfiPeiPeCoffLoader->GetImageInfo (PeiEfiPeiPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Allocate Memory for the image
+ //
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));
+ ASSERT (ImageContext.ImageAddress != 0);
+
+ //
+ // Load the image to our new buffer
+ //
+ Status = PeiEfiPeiPeCoffLoader->LoadImage (PeiEfiPeiPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Relocate the image in our new buffer
+ //
+ Status = PeiEfiPeiPeCoffLoader->RelocateImage (PeiEfiPeiPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Flush the instruction cache so the image data is written before we execute it
+ //
+ InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
+
+ *ImageAddress = ImageContext.ImageAddress;
+ *ImageSize = ImageContext.ImageSize;
+ *EntryPoint = ImageContext.EntryPoint;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PeiLoadImageLoadImage (
+ IN 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
+ )
+/*++
+
+Routine Description:
+
+ Routine for loading file image.
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ FileHandle - Pointer to the FFS file header of the image.
+ ImageAddressArg - Pointer to PE/TE image.
+ ImageSizeArg - Size of PE/TE image.
+ EntryPoint - Pointer to entry point of specified image file for output.
+ AuthenticationState - Pointer to attestation authentication state of image.
Returns:
@@ -51,55 +309,63 @@ Returns:
{
EFI_STATUS Status;
VOID *Pe32Data;
- EFI_PEI_FV_FILE_LOADER_PPI *FvLoadFilePpi;
EFI_PHYSICAL_ADDRESS ImageAddress;
UINT64 ImageSize;
EFI_PHYSICAL_ADDRESS ImageEntryPoint;
EFI_TE_IMAGE_HEADER *TEImageHeader;
UINT16 Machine;
+ PEI_CORE_INSTANCE *Private;
+ VOID *EntryPointArg;
- *EntryPoint = NULL;
+ *EntryPoint = 0;
TEImageHeader = NULL;
+ ImageSize = 0;
+ *AuthenticationState = 0;
//
- // Try to find a PE32 section.
+ // Try to find a TE section.
//
Status = PeiServicesFfsFindSectionData (
- EFI_SECTION_PE32,
- PeimFileHeader,
+ EFI_SECTION_TE,
+ FileHandle,
&Pe32Data
);
+ if (!EFI_ERROR (Status)) {
+ TEImageHeader = (EFI_TE_IMAGE_HEADER *)Pe32Data;
+ }
//
// If we didn't find a PE32 section, try to find a TE section.
//
if (EFI_ERROR (Status)) {
Status = PeiServicesFfsFindSectionData (
- EFI_SECTION_TE,
- PeimFileHeader,
- (VOID **) &TEImageHeader
+ EFI_SECTION_PE32,
+ FileHandle,
+ &Pe32Data
);
- if (EFI_ERROR (Status) || TEImageHeader == NULL) {
+ if (EFI_ERROR (Status)) {
//
- // There was not a PE32 or a TE section, so assume that it's a Compressed section
- // and use the LoadFile
+ // PEI core only carry the loader function fro TE and PE32 executables
+ // If this two section does not exist, just return.
//
- Status = PeiServicesLocatePpi (
- &gEfiPeiFvFileLoaderPpiGuid,
- 0,
- NULL,
- (VOID **)&FvLoadFilePpi
- );
- if (EFI_ERROR (Status)) {
- return EFI_NOT_FOUND;
- }
+ return Status;
+ }
+ }
+
+ Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
- Status = FvLoadFilePpi->FvLoadFile (
- FvLoadFilePpi,
- PeimFileHeader,
- &ImageAddress,
- &ImageSize,
- &ImageEntryPoint
- );
+ if (Private->PeiMemoryInstalled &&
+ (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
+ {
+ //
+ // If memory is installed, perform the shadow operations
+ //
+ Status = LoadAndRelocatePeCoffImage (
+ Private->PeCoffLoader,
+ Pe32Data,
+ &ImageAddress,
+ &ImageSize,
+ &ImageEntryPoint
+ );
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
@@ -109,23 +375,28 @@ Returns:
// Got the entry point from ImageEntryPoint and ImageStartAddress
//
Pe32Data = (VOID *) ((UINTN) ImageAddress);
- *EntryPoint = (VOID *) ((UINTN) ImageEntryPoint);
- } else {
+ *EntryPoint = ImageEntryPoint;
+ }
+ } else {
+ if (TEImageHeader != NULL) {
//
// Retrieve the entry point from the TE image header
//
ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) TEImageHeader;
- *EntryPoint = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) +
+ ImageSize = 0;
+ *EntryPoint = (EFI_PHYSICAL_ADDRESS)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) +
TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize);
- }
- } else {
- //
- // Retrieve the entry point from the PE/COFF image header
- //
- ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data;
- Status = PeCoffLoaderGetEntryPoint (Pe32Data, EntryPoint);
- if (EFI_ERROR (Status)) {
- return EFI_NOT_FOUND;
+ } else {
+ //
+ // Retrieve the entry point from the PE/COFF image header
+ //
+ ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data;
+ ImageSize = 0;
+ Status = PeCoffLoaderGetEntryPoint (Pe32Data, &EntryPointArg);
+ *EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) EntryPointArg;
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
}
}
@@ -140,6 +411,14 @@ Returns:
return EFI_UNSUPPORTED;
}
+ if (ImageAddressArg != NULL) {
+ *ImageAddressArg = ImageAddress;
+ }
+
+ if (ImageSizeArg != NULL) {
+ *ImageSizeArg = ImageSize;
+ }
+
//
// Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi
//
@@ -264,4 +543,175 @@ Returns:
DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));
return EFI_SUCCESS;
+
+}
+
+
+EFI_STATUS
+EFIAPI
+PeiLoadImageLoadImageWrapper (
+ IN CONST EFI_PEI_LOAD_FILE_PPI *This,
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL
+ OUT UINT64 *ImageSizeArg, OPTIONAL
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
+ OUT UINT32 *AuthenticationState
+ )
+/*++
+
+Routine Description:
+
+ The wrapper function of PeiLoadImageLoadImage().
+
+Arguments:
+
+ This - Pointer to EFI_PEI_LOAD_FILE_PPI.
+ PeiServices - The PEI core services table.
+ FileHandle - Pointer to the FFS file header of the image.
+ ImageAddressArg - Pointer to PE/TE image.
+ ImageSizeArg - Size of PE/TE image.
+ EntryPoint - Pointer to entry point of specified image file for output.
+ AuthenticationState - Pointer to attestation authentication state of image.
+
+Returns:
+
+ EFI_STATUS.
+
+--*/
+{
+ return PeiLoadImageLoadImage (
+ GetPeiServicesTablePointer (),
+ FileHandle,
+ ImageAddressArg,
+ ImageSizeArg,
+ EntryPoint,
+ AuthenticationState
+ );
}
+
+EFI_STATUS
+PeiLoadImage (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
+ OUT UINT32 *AuthenticationState
+ )
+/*++
+
+Routine Description:
+
+ Routine for load image file.
+
+Arguments:
+
+ PeiServices - The PEI core services table.
+ FileHandle - Pointer to the FFS file header of the image.
+ EntryPoint - Pointer to entry point of specified image file for output.
+ AuthenticationState - Pointer to attestation authentication state of image.
+
+Returns:
+
+ Status - EFI_SUCCESS - Image is successfully loaded.
+ EFI_NOT_FOUND - Fail to locate necessary PPI
+ Others - Fail to load file.
+
+--*/
+{
+ EFI_STATUS PpiStatus;
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_PEI_LOAD_FILE_PPI *LoadFile;
+ EFI_PHYSICAL_ADDRESS ImageAddress;
+ UINT64 ImageSize;
+
+ //
+ // 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)) {
+ return Status;
+ }
+ }
+ Index++;
+ } while (!EFI_ERROR (PpiStatus));
+
+ //
+ // If no instances reports EFI_SUCCESS, then build-in support for
+ // the PE32+/TE XIP image format is used.
+ //
+ Status = PeiLoadImageLoadImage (
+ PeiServices,
+ FileHandle,
+ NULL,
+ NULL,
+ EntryPoint,
+ AuthenticationState
+ );
+ return Status;
+}
+
+
+VOID
+InitializeImageServices (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN PEI_CORE_INSTANCE *OldCoreData
+ )
+/*++
+
+Routine Description:
+
+ Regitser PeCoffLoader to PeiCore PrivateData. And install
+ Pei Load File PPI.
+
+Arguments:
+
+ PrivateData - Pointer to PEI_CORE_INSTANCE.
+ OldCoreData - Pointer to PEI_CORE_INSTANCE.
+
+Returns:
+
+ NONE.
+
+--*/
+{
+ //
+ // Always update PeCoffLoader pointer as PEI core itself may get
+ // shadowed into memory
+ //
+ PrivateData->PeCoffLoader = GetPeCoffLoaderProtocol ();
+
+ if (OldCoreData == NULL) {
+ //
+ // The first time we are XIP (running from FLASH). We need to remember the
+ // FLASH address so we can reinstall the memory version that runs faster
+ //
+ PrivateData->XipLoadFile = &gPpiLoadFilePpiList;
+ PeiServicesInstallPpi (PrivateData->XipLoadFile);
+ } else {
+ //
+ // 2nd time we are running from memory so replace the XIP version with the
+ // new memory version.
+ //
+ PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList);
+ }
+}
+
+
+