From b0d803fe3e5c55a9a0c75bc90ccf40ebbbc9ffa3 Mon Sep 17 00:00:00 2001 From: klu2 Date: Mon, 24 Sep 2007 11:38:43 +0000 Subject: 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 --- MdeModulePkg/Core/Pei/Image/Image.c | 542 +++++++++++++++++++++++++++++++++--- 1 file changed, 496 insertions(+), 46 deletions(-) (limited to 'MdeModulePkg/Core/Pei/Image/Image.c') 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 +/*++ + +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); + } +} + + + -- cgit v1.2.3