X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=EdkModulePkg%2FCore%2FPei%2FImage%2FImage.c;h=32f0fe652300822d1f1e58d7d5a5da673d9baa19;hp=15807501422e6fd622fe456455ea3f06fd7a9d78;hb=5b18234d980e3eb199c3a784b2fdfdd3acffef57;hpb=85cf9dcbdd26b2a001cf29d419e919f430918e6f diff --git a/EdkModulePkg/Core/Pei/Image/Image.c b/EdkModulePkg/Core/Pei/Image/Image.c index 1580750142..32f0fe6523 100644 --- a/EdkModulePkg/Core/Pei/Image/Image.c +++ b/EdkModulePkg/Core/Pei/Image/Image.c @@ -1,239 +1,251 @@ -/*++ - -Copyright (c) 2006, 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 - -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_PEI_FV_FILE_LOADER_PPI *FvLoadFilePpi; - EFI_PHYSICAL_ADDRESS ImageAddress; - UINT64 ImageSize; - EFI_PHYSICAL_ADDRESS ImageEntryPoint; - EFI_TE_IMAGE_HEADER *TEImageHeader; - - *EntryPoint = NULL; - TEImageHeader = NULL; - - // - // Try to find a PE32 section. - // - Status = PeiCoreFfsFindSectionData ( - EFI_SECTION_PE32, - PeimFileHeader, - &Pe32Data - ); - // - // If we didn't find a PE32 section, try to find a TE section. - // - if (EFI_ERROR (Status)) { - Status = PeiCoreFfsFindSectionData ( - EFI_SECTION_TE, - PeimFileHeader, - (VOID **) &TEImageHeader - ); - if (EFI_ERROR (Status) || TEImageHeader == NULL) { - // - // There was not a PE32 or a TE section, so assume that it's a Compressed section - // and use the LoadFile - // - Status = PeiCoreLocatePpi ( - &gEfiPeiFvFileLoaderPpiGuid, - 0, - NULL, - (VOID **)&FvLoadFilePpi - ); - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - - Status = FvLoadFilePpi->FvLoadFile ( - FvLoadFilePpi, - PeimFileHeader, - &ImageAddress, - &ImageSize, - &ImageEntryPoint - ); - - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - - // - // Retrieve the entry point from the PE/COFF image header - // - Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)ImageAddress, EntryPoint); - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - } else { - // - // Retrieve the entry point from the TE image header - // - ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) TEImageHeader; - *EntryPoint = (VOID *)((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; - } - } - - // - // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi - // - DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", Pe32Data, *EntryPoint)); - 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; - - // - // Pe32Data is NULL when load TE image - // - PeHeader = NULL; - if (TEImageHeader == 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 - // - 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; - DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer)); - break; - } - } - } - } - } - } - ); - - DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n")); - - return EFI_SUCCESS; -} +/*++ + +Copyright (c) 2006, 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 + + + +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_PEI_FV_FILE_LOADER_PPI *FvLoadFilePpi; + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + EFI_PHYSICAL_ADDRESS ImageEntryPoint; + EFI_TE_IMAGE_HEADER *TEImageHeader; + + *EntryPoint = NULL; + TEImageHeader = NULL; + + // + // Try to find a PE32 section. + // + Status = PeiServicesFfsFindSectionData ( + EFI_SECTION_PE32, + PeimFileHeader, + &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 + ); + if (EFI_ERROR (Status) || TEImageHeader == NULL) { + // + // There was not a PE32 or a TE section, so assume that it's a Compressed section + // and use the LoadFile + // + Status = PeiServicesLocatePpi ( + &gEfiPeiFvFileLoaderPpiGuid, + 0, + NULL, + (VOID **)&FvLoadFilePpi + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + Status = FvLoadFilePpi->FvLoadFile ( + FvLoadFilePpi, + PeimFileHeader, + &ImageAddress, + &ImageSize, + &ImageEntryPoint + ); + + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // Got the entry point from ImageEntryPoint + // + *EntryPoint = (VOID *) ((UINTN) ImageEntryPoint); + return EFI_SUCCESS; + } else { + // + // Retrieve the entry point from the TE image header + // + ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) TEImageHeader; + *EntryPoint = (VOID *)((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; + } + } + + // + // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi + // + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", Pe32Data, *EntryPoint)); + DEBUG_CODE_BEGIN (); + 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_OPTIONAL_HEADER_PTR_UNION Hdr; + UINT32 NumberOfRvaAndSizes; + + Hdr.Pe32 = NULL; + if (TEImageHeader == 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 + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHeader->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)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 (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset + // + NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + } else { + // + // Use PE32+ offset + // + NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + } + + if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DirectoryEntry = NULL; + DebugEntry = NULL; + } + } 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 < sizeof (AsciiString)); 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; + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer)); + break; + } + } + } + } + } + } + DEBUG_CODE_END (); + + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n")); + + return EFI_SUCCESS; +}