diff options
Diffstat (limited to 'Core/CORE_PEI/CORE_PEI_FRAMEWORK/Image.c')
-rw-r--r-- | Core/CORE_PEI/CORE_PEI_FRAMEWORK/Image.c | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Image.c b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Image.c new file mode 100644 index 0000000..8ccbd68 --- /dev/null +++ b/Core/CORE_PEI/CORE_PEI_FRAMEWORK/Image.c @@ -0,0 +1,341 @@ +/*++ + +Copyright (c) 2004 - 2007, 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 EFI_PPI_DEFINITION (LoadFile) + +EFI_STATUS +PeiLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *PeimFileHeader, + OUT VOID **EntryPoint + ) +/*++ + +Routine Description: + + Routine for loading file image. + +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. + +Returns: + + Status - EFI_SUCCESS - Image is successfully loaded. + EFI_NOT_FOUND - Fail to locate necessary PPI + Others - Fail to load file. + +--*/ +{ + EFI_STATUS Status; + VOID *Pe32Data; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_PEI_FV_FILE_LOADER_PPI *FvLoadFilePpi; +#ifdef EFI_NT_EMULATOR + EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; + NT_PEI_LOAD_FILE_PPI *PeiNtService; + EFI_PHYSICAL_ADDRESS NtEntryPoint; +#endif + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + EFI_PHYSICAL_ADDRESS ImageEntryPoint; + EFI_TE_IMAGE_HEADER *TEImageHeader; + UINT16 Machine; + + PEI_DEBUG_CODE (ImageAddress = 0;) + + *EntryPoint = NULL; + TEImageHeader = NULL; + PeHdr = NULL; + // + // Try to find a PE32 section. + // + Status = PeiFfsFindSectionData ( + PeiServices, + EFI_SECTION_PE32, + PeimFileHeader, + &Pe32Data + ); + // + // If we didn't find a PE32 section, try to find a TE section. + // + if (Status != EFI_SUCCESS) { + Status = PeiFfsFindSectionData ( + PeiServices, + EFI_SECTION_TE, + PeimFileHeader, + (VOID **) &TEImageHeader + ); + Pe32Data = (VOID *) TEImageHeader; + } + if (Status == EFI_SUCCESS) { + if (TEImageHeader == NULL) { + if (((EFI_IMAGE_DOS_HEADER *) Pe32Data)->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; + } + Machine = PeHdr->FileHeader.Machine; +//*** AMI PORTING BEGIN ***// +//This is needed to enable execution of the PEIMS +//from the firmware volumes in memory. + if ( PeHdr->OptionalHeader.ImageBase + !=(UINTN)Pe32Data + ) Status=EFI_NOT_FOUND; +//Init ImageSize for to pass into UpdatedLoadedImagePpi + ImageSize = PeHdr->OptionalHeader.SizeOfImage; +//*** AMI PORTING END *****// + } else { +//*** AMI PORTING BEGIN ***// + Machine = TEImageHeader->Machine; +//This is needed to enable execution of the PEIMS +//from the firmware volumes in memory. +//The following two lines are not needed because +//we don't support reallocation of TE image into memory. +// if ( TEImageHeader->ImageBase!=(UINTN)(TEImageHeader)) +// Status=EFI_NOT_FOUND; + +//Init ImageSize for to pass into UpdatedLoadedImagePpi. +//Let's get size from the FFS section header + ImageSize = FVSECTION_SIZE(TEImageHeader); +//*** AMI PORTING END *****// + } + // + // Check PEIM image machine. A PEIM image for different processor architecture + // from the host can't be started. + // + if (Machine != EFI_IMAGE_MACHINE_TYPE) { + return EFI_UNSUPPORTED; + } + +#ifdef EFI_NT_EMULATOR + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gNtPeiLoadFileGuid, + 0, + &PpiDescriptor, + &PeiNtService + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PeiNtService->PeiLoadFileService ( + Pe32Data, + &ImageAddress, + &ImageSize, + &NtEntryPoint + ); + + if (EFI_ERROR (Status)) { + if (TEImageHeader != NULL) { + *EntryPoint = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) + + TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize); + } else { + *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (PeHdr->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff)); + } + } else { + *EntryPoint = (VOID *) (UINTN) NtEntryPoint; + } + +#else + ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data; + if (TEImageHeader != NULL) { + *EntryPoint = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) + + TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize); + } else { + *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (PeHdr->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff)); + } +#endif +//*** AMI PORTING BEGIN ***// +// } else { + } + if (Status!=EFI_SUCCESS){ +//*** AMI PORTING END *****// + // + // There was not a PE32 section, so assume that it's a Compressed section + // and use the LoadFile + // + Status = PeiLocatePpi ( + PeiServices, + &gPeiFvFileLoaderPpiGuid, + 0, + NULL, + &FvLoadFilePpi + ); + + if (!EFI_ERROR (Status)) { + Status = FvLoadFilePpi->FvLoadFile ( + FvLoadFilePpi, + PeimFileHeader, + &ImageAddress, + &ImageSize, + &ImageEntryPoint + ); + + if (!EFI_ERROR (Status)) { + *EntryPoint = (VOID *) ((UINTN) ImageEntryPoint); + if (((EFI_TE_IMAGE_HEADER *) (UINTN) ImageAddress)->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + TEImageHeader = (EFI_TE_IMAGE_HEADER *) (UINTN) ImageAddress; + Machine = TEImageHeader->Machine; + } else { + if (((EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress)->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) ImageAddress + (UINTN) ((((EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress)->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) (UINTN) ImageAddress; + } + Machine = PeHdr->FileHeader.Machine; + } + // + // Check PEIM image machine. A PEIM image for different processor architecture + // from the host can't be started. + // + if (Machine != EFI_IMAGE_MACHINE_TYPE) { + return EFI_UNSUPPORTED; + } + } + } + } +//*** AMI PORTING BEGIN ***// +//Message is printed later. Disable this one +/* + 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; + + if (Status == EFI_SUCCESS) { + // + // 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 ", (UINTN) ImageAddress, *EntryPoint)); + + // + // 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 (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHdr->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")); + } + } + ) +*/ +#ifdef EFI_DEBUG +if (!EFI_ERROR (Status)){ + 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 (Status)) + UpdatedLoadedImagePpi(PeiServices,ImageAddress,ImageSize,PeimFileHeader); +//*** AMI PORTING END *****// + return Status; +} |