diff options
Diffstat (limited to 'Core/CORE_PEI/CORE_PEI_PI/Image.c')
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_PI/Image.c | 932 |
1 files changed, 932 insertions, 0 deletions
diff --git a/Core/CORE_PEI/CORE_PEI_PI/Image.c b/Core/CORE_PEI/CORE_PEI_PI/Image.c new file mode 100644 index 0000000..a6967e0 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_PI/Image.c @@ -0,0 +1,932 @@ +/*++ + +Copyright (c) 2004 - 2009, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Image.c + +Abstract: + + Pei Core Load Image Support + +--*/ + +#include "Tiano.h" +#include "PeiCore.h" +#include "PeiLib.h" +#include "PeiApi.h" +#include "EfiImage.h" +#include EFI_PROTOCOL_DEFINITION (CustomizedDecompress) + +#include EFI_PPI_DEFINITION (LoadFile2) +#include EFI_GUID_DEFINITION (PeiPeCoffLoader) +#include EFI_PPI_DEFINITION (SectionExtraction) + + +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 + +--*/ +; + +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: + + 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. + +--*/ +; + + +EFI_STATUS +EFIAPI +PeCoffLoaderGetEntryPoint ( + IN VOID *Pe32Data, + OUT VOID **EntryPoint + ) +/*++ + +Routine Description: + + Routine for get PE image entry point. + +Arguments: + + Pe32Data - Pointer to PE image. + EntryPoint - Pointer to entry point of PE image. + +Returns: + + EFI_SUCCESS. + +--*/ +; + +EFI_IMAGE_NT_HEADERS* +EFIAPI +GetPeHeader ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *Pe32Data + ) +/*++ + +Routine Description: + + Routine for get PE image header. + +Arguments: + PeiServices - The PEI core services table. + Pe32Data - Pointer to PE image. + +Returns: + + Pointer to PE header. + +--*/ +; + +static EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi = { + PeiLoadImageLoadImageWrapper +}; + + +EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiLoadFile2PpiGuid, + &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 EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_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 + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS MemoryBuffer; + + Status = (*PeiServices)->AllocatePages ( + PeiServices, + EfiBootServicesData, + 0x400 / EFI_PAGE_SIZE + 1, + &MemoryBuffer + ); + ASSERT_PEI_ERROR (PeiServices, Status); + + (*PeiServices)->CopyMem ( + (VOID *) (UINTN) MemoryBuffer, + (VOID *) (UINTN) PeiImageRead, + 0x400 + ); + + ImageContext->ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer; + + return Status; +} + +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: + + Status - EFI_SUCCESS - Image is successfully loaded. + EFI_NOT_FOUND - Fail to locate necessary PPI + Others - Fail to load file. + +--*/ +{ + EFI_STATUS Status; + PEI_CORE_INSTANCE *Private; + VOID *Pe32Data; + EFI_TE_IMAGE_HEADER *TEImageHeader; + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeCoffLoader; + +#ifdef EFI_NT_EMULATOR + EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; + NT_PEI_LOAD_FILE_PPI *PeiNtService; +#else + VOID *EntryPointPtr; +#endif +//*** AMI PORTING BEGIN ***// +//This is needed to enable execution of compressed PEIMS +//and PEIMS from the firmware volumes in memory (see below). + BOOLEAN FixupRequired = FALSE; +//*** AMI PORTING END *****// + + Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + *EntryPoint = 0; + *AuthenticationState = 0; + ImageAddress = 0; + ImageSize = 0; + PeHdr = NULL; + + // + // Try to find a TE or PE32 section. + // + Status = PeiFfsFindSectionData ( + PeiServices, + EFI_SECTION_TE, + FileHandle, + (VOID **)&TEImageHeader + ); + Pe32Data = TEImageHeader; + if (EFI_ERROR (Status)) { + Status = PeiFfsFindSectionData ( + PeiServices, + EFI_SECTION_PE32, + FileHandle, + &Pe32Data + ); + } + + if (EFI_ERROR (Status)) { + // + // NO image types we support so exit. + // + return Status; + } + + // + // Check image header machine type. If not supported, skip it. + // + if (TEImageHeader != NULL) { + if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (TEImageHeader->Machine) && + !EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (TEImageHeader->Machine)) { + return EFI_UNSUPPORTED; + } + } else { + // + // Get PE32 Header to check machine type. + // + PeHdr = GetPeHeader(PeiServices, Pe32Data); + if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeHdr->FileHeader.Machine) && + !EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (PeHdr->FileHeader.Machine)) { + return EFI_UNSUPPORTED; + } +//*** AMI PORTING BEGIN ***// +//This is needed to enable execution of compressed PEIMS +//and PEIMS from the firmware volumes in memory. + if (PeHdr->OptionalHeader.ImageBase != (UINTN)Pe32Data) + FixupRequired = TRUE; +//*** AMI PORTING END *****// + } + + if (Private->PeiMemoryInstalled && + (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || FixupRequired)) { + // + // Load, relocate, and run image in memory + // + ZeroMem (&ImageContext, sizeof (ImageContext)); + ImageContext.Handle = Pe32Data; + if (Private->ImageReadFile == NULL) { + GetImageReadFunction (PeiServices, &ImageContext); + Private->ImageReadFile = ImageContext.ImageRead; + } else { + ImageContext.ImageRead = Private->ImageReadFile; + } + PeCoffLoader = Private->PeCoffLoader; + Status = PeCoffLoader->GetImageInfo (PeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Allocate Memory for the image + // + Status = PeiAllocatePages ( + PeiServices, + EfiBootServicesData, + EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize), + &ImageContext.ImageAddress + ); + ASSERT_PEI_ERROR (PeiServices,Status); + + if (ImageContext.IsTeImage && + TEImageHeader->Machine == EFI_IMAGE_MACHINE_IA64) { + ImageContext.ImageAddress = ImageContext.ImageAddress + + TEImageHeader->StrippedSize - + sizeof (EFI_TE_IMAGE_HEADER); + } + + // + // Load the image to our new buffer + // + Status = PeCoffLoader->LoadImage (PeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Relocate the image in our new buffer + // + Status = PeCoffLoader->RelocateImage (PeCoffLoader, &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; + } +#ifndef EFI_NT_EMULATOR + else if (TEImageHeader != NULL) { + // + // Get entry point from the TE image header + // + ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)TEImageHeader; +//*** AMI PORTING BEGIN ***// +//Bug fix: the function must return a valid image size +// The original implmentation always returns NULL for XIP images. + ImageSize = FVSECTION_SIZE(TEImageHeader); +// ImageSize = 0; +//*** AMI PORTING END ***// + *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; +//*** AMI PORTING BEGIN ***// +//Bug fix: the function must return a valid image size +// The original implmentation always returns NULL for XIP images. + ImageSize = PeHdr->OptionalHeader.SizeOfImage; +// ImageSize = 0; +//*** AMI PORTING END ***// + Status = PeCoffLoaderGetEntryPoint (Pe32Data, &EntryPointPtr); + *EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)EntryPointPtr; + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + } +#else + else { + if (TEImageHeader == NULL) { + PeHdr = GetPeHeader(PeiServices,Pe32Data); + } + + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gNtPeiLoadFileGuid, + 0, + &PpiDescriptor, + &PeiNtService + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PeiNtService->PeiLoadFileService ( + Pe32Data, + &ImageAddress, + &ImageSize, + EntryPoint + ); + + if (EFI_ERROR (Status)) { + if (TEImageHeader != NULL) { + *EntryPoint = (EFI_PHYSICAL_ADDRESS)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) + + TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize); + } else { + *EntryPoint = (EFI_PHYSICAL_ADDRESS) ((UINTN) Pe32Data + (UINTN) (PeHdr->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff)); + } + } + } +#endif + + + if (ImageAddressArg != NULL) { + *ImageAddressArg = ImageAddress; + } + + if (ImageSizeArg != NULL) { + *ImageSizeArg = ImageSize; + } + +//*** AMI PORTING BEGIN ***// +//Message is printed later. Disable this one +/* + // + // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi + // + PEI_DEBUG ((PeiServices,EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", Pe32Data, *EntryPoint)); + PEI_DEBUG_CODE ( + { + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINTN DirCount; + UINTN Index; + UINTN Index1; + BOOLEAN FileNameFound; + CHAR8 *AsciiString; + CHAR8 AsciiBuffer[512]; + VOID *CodeViewEntryPointer; + INTN TEImageAdjust; + EFI_IMAGE_DOS_HEADER *DosHeader; + EFI_IMAGE_NT_HEADERS *PeHeader; + + DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header + // + PeHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32Data + (UINTN) ((DosHeader->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base + // + PeHeader = (EFI_IMAGE_NT_HEADERS *) Pe32Data; + } + + // + // Find the codeview info in the image and display the file name + // being loaded. + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + DebugEntry = NULL; + DirectoryEntry = NULL; + TEImageAdjust = 0; + if (TEImageHeader == NULL) { + if (PeHeader->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHeader->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) ImageAddress + DirectoryEntry->VirtualAddress); + } + } else { + if (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) { + DirectoryEntry = &TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG]; + TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize; + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) TEImageHeader + + TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress + + TEImageAdjust); + } + } + + if (DebugEntry != NULL && DirectoryEntry != NULL) { + for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount++, DebugEntry++) { + if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + if (DebugEntry->SizeOfData > 0) { + CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageAddress + (UINTN)TEImageAdjust); + switch (* (UINT32 *) CodeViewEntryPointer) { + case CODEVIEW_SIGNATURE_NB10: + AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY); + break; + + case CODEVIEW_SIGNATURE_RSDS: + AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY); + break; + + default: + AsciiString = NULL; + break; + } + if (AsciiString != NULL) { + FileNameFound = FALSE; + for (Index = 0, Index1 = 0; AsciiString[Index] != 0; Index++) { + if (AsciiString[Index] == '\\') { + Index1 = Index; + FileNameFound = TRUE; + } + } + + if (FileNameFound) { + for (Index = Index1 + 1; AsciiString[Index] != '.'; Index++) { + AsciiBuffer[Index - (Index1 + 1)] = AsciiString[Index]; + } + AsciiBuffer[Index - (Index1 + 1)] = 0; + PEI_DEBUG ((PeiServices,EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer)); + break; + } + } + } + } + } + } + } + ) + + PEI_DEBUG ((PeiServices,EFI_D_INFO | EFI_D_LOAD, "\n")); +*/ +//*** AMI PORTING END ***// + 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; + UINT16 Magic; + UINT16 Machine; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_TE_IMAGE_HEADER *TeHdr; + + // + // 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 = PeiLocatePpi ( + PeiServices, + &gEfiLoadFile2PpiGuid, + Index, + NULL, + (VOID **)&LoadFile + ); + if (!EFI_ERROR (PpiStatus)) { + Status = LoadFile->LoadFile ( + LoadFile, + FileHandle, + &ImageAddress, + &ImageSize, + EntryPoint, + AuthenticationState + ); + if (!EFI_ERROR (Status)) { + // + // Only support image machine type that is the same as PEI core. + // Get the image's machine type to check if supported. + // + Magic = *(UINT16 *)(UINTN) ImageAddress; + if (Magic == EFI_TE_IMAGE_HEADER_SIGNATURE) { + TeHdr = (EFI_TE_IMAGE_HEADER *)(UINTN) ImageAddress; + Machine = TeHdr->Machine; + } else { + if (Magic == EFI_IMAGE_DOS_SIGNATURE) { + PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN) ImageAddress + (UINTN) ((((EFI_IMAGE_DOS_HEADER *)(UINTN) ImageAddress)->e_lfanew) & 0x0ffff)); + } else { + PeHdr = (EFI_IMAGE_NT_HEADERS *)(UINTN) ImageAddress; + } + Machine = PeHdr->FileHeader.Machine; + } + if (Machine == EFI_IMAGE_MACHINE_TYPE) { +//*** AMI PORTING BEGIN ***// +//break from the loop to print debug message (see below) +// return EFI_SUCCESS; + PpiStatus=EFI_SUCCESS; + break; +//*** AMI PORTING END *****// + } else { +//*** AMI PORTING BEGIN ***// +//break from the loop to print debug message (see below) +// return EFI_UNSUPPORTED; + PpiStatus=EFI_SUCCESS; + break; +//*** AMI PORTING END *****// + } + } + } + Index++; + } while (!EFI_ERROR (PpiStatus)); +//*** AMI PORTING BEGIN ***// +//Print debug message +#ifdef EFI_DEBUG +{ + EFI_FFS_FILE_HEADER *PeimFileHeader = (EFI_FFS_FILE_HEADER*)FileHandle; + if(!EFI_ERROR(PpiStatus)) + { + char sName[0x100]; + if (!GetName((VOID*)(UINTN)ImageAddress,sName)) + Sprintf_s(sName,sizeof(sName),"[%G]",&PeimFileHeader->Name); + PeiTrace(TRACE_PEICORE, PeiServices, "%s.Entry(%X)\n", sName, *EntryPoint); + } + else + { + PeiTrace( + TRACE_PEICORE, PeiServices, + "ERROR: attempt to load FFS file [%G] has failed\n", + &PeimFileHeader->Name + ); + } +} +#endif +//New image is loaded and is about to be launched +//Update LoadedImage PPI information + if(!EFI_ERROR(PpiStatus)) + UpdatedLoadedImagePpi(PeiServices,ImageAddress,ImageSize,FileHandle); +//*** AMI PORTING END *****// + return PpiStatus; +} + + +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. + +--*/ +{ + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; + + InstallEfiPeiPeCoffLoader (&PrivateData->PS, &PeiEfiPeiPeCoffLoader, NULL); + PrivateData->PeCoffLoader = PeiEfiPeiPeCoffLoader; + + 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; + PeiInstallPpi (&PrivateData->PS, PrivateData->XipLoadFile); + } else { + // + // 2nd time we are running from memory so replace the XIP version with the + // new memory version. + // + PeiReInstallPpi (&PrivateData->PS, PrivateData->XipLoadFile, &gPpiLoadFilePpiList); + } +} + + +EFI_STATUS +EFIAPI +PeCoffLoaderGetEntryPoint ( + IN VOID *Pe32Data, + OUT VOID **EntryPoint + ) +/*++ + +Routine Description: + + Routine for get PE image entry point. + +Arguments: + + Pe32Data - Pointer to PE image. + EntryPoint - Pointer to entry point of PE image. + +Returns: + + EFI_SUCCESS. + +--*/ +{ + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_PEI_SERVICES **PeiServices; + + PeHdr = NULL; + PeiServices = GetPeiServicesTablePointer(); + + PEI_ASSERT (PeiServices, (Pe32Data != NULL)); + PEI_ASSERT (PeiServices,(EntryPoint != NULL)); + + PeHdr = GetPeHeader(PeiServices, Pe32Data); + + // + // Calculate the entry point relative to the start of the image. + // AddressOfEntryPoint is common for PE32 & PE32+ + // + *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (PeHdr->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff)); + return EFI_SUCCESS; +} + +EFI_IMAGE_NT_HEADERS* +EFIAPI +GetPeHeader ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *Pe32Data + ) +/*++ + +Routine Description: + + Routine for get PE image header. + +Arguments: + PeiServices - The PEI core services table. + Pe32Data - Pointer to PE image. + +Returns: + + Pointer to PE header. + +--*/ +{ + EFI_IMAGE_DOS_HEADER *DosHeader; + EFI_IMAGE_NT_HEADERS *PeHdr; + + PeHdr = NULL; + PEI_ASSERT (PeiServices, (Pe32Data != NULL)); + + DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header. + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32Data + (UINTN) ((((EFI_IMAGE_DOS_HEADER *) Pe32Data)->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base. + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) Pe32Data; + } + return PeHdr; +} + |