/** @file\r
Pei Core Load Image Support\r
- \r
-Copyright (c) 2006 - 2007, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-**/\r
\r
-#include <PeiMain.h>\r
-\r
-/**\r
- Routine for loading file image.\r
+Copyright (c) 2006 - 2010, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
\r
- @param PeiServices The PEI core services table.\r
- @param FileHandle Pointer to the FFS file header of the image.\r
- @param ImageAddressArg Pointer to PE/TE image.\r
- @param ImageSizeArg Size of PE/TE image.\r
- @param EntryPoint Pointer to entry point of specified image file for output.\r
- @param AuthenticationState - Pointer to attestation authentication state of image.\r
-\r
- @retval EFI_SUCCESS - Image is successfully loaded.\r
- @retval EFI_NOT_FOUND - Fail to locate necessary PPI\r
- @retval Others - Fail to load file.\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
\r
**/\r
-EFI_STATUS\r
-PeiLoadImageLoadImage (\r
- IN EFI_PEI_SERVICES **PeiServices,\r
- IN EFI_PEI_FILE_HANDLE FileHandle,\r
- OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL\r
- OUT UINT64 *ImageSizeArg, OPTIONAL\r
- OUT EFI_PHYSICAL_ADDRESS *EntryPoint,\r
- OUT UINT32 *AuthenticationState\r
- )\r
-;\r
\r
-/**\r
- The wrapper function of PeiLoadImageLoadImage().\r
-\r
- @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.\r
- @param FileHandle - Pointer to the FFS file header of the image.\r
- @param ImageAddressArg - Pointer to PE/TE image.\r
- @param ImageSizeArg - Size of PE/TE image.\r
- @param EntryPoint - Pointer to entry point of specified image file for output.\r
- @param AuthenticationState - Pointer to attestation authentication state of image.\r
+#include "PeiMain.h"\r
\r
- @return Status of PeiLoadImageLoadImage().\r
\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-PeiLoadImageLoadImageWrapper (\r
- IN CONST EFI_PEI_LOAD_FILE_PPI *This,\r
- IN EFI_PEI_FILE_HANDLE FileHandle,\r
- OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL\r
- OUT UINT64 *ImageSizeArg, OPTIONAL\r
- OUT EFI_PHYSICAL_ADDRESS *EntryPoint,\r
- OUT UINT32 *AuthenticationState\r
- )\r
-;\r
-\r
-STATIC EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi = {\r
+EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi = {\r
PeiLoadImageLoadImageWrapper\r
};\r
\r
\r
-STATIC EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {\r
+EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {\r
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
&gEfiPeiLoadFilePpiGuid,\r
&mPeiLoadImagePpi\r
PeiImageRead (\r
IN VOID *FileHandle,\r
IN UINTN FileOffset,\r
- IN OUT UINTN *ReadSize,\r
+ IN UINTN *ReadSize,\r
OUT VOID *Buffer\r
)\r
{\r
\r
Destination8 = Buffer;\r
Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
- Length = *ReadSize;\r
- while (Length--) {\r
- *(Destination8++) = *(Source8++);\r
+ if (Destination8 != Source8) {\r
+ Length = *ReadSize;\r
+ while ((Length--) > 0) {\r
+ *(Destination8++) = *(Source8++);\r
+ }\r
}\r
\r
return EFI_SUCCESS;\r
\r
/**\r
\r
- Support routine to return the Image Read.\r
+ Support routine to get the Image read file function.\r
\r
@param ImageContext - The context of the image being loaded\r
\r
IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
)\r
{\r
+ PEI_CORE_INSTANCE *Private;\r
VOID* MemoryBuffer;\r
\r
- MemoryBuffer = AllocatePages (0x400 / EFI_PAGE_SIZE + 1);\r
- ASSERT (MemoryBuffer != NULL);\r
+ Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());\r
+\r
+ if (!Private->PeiMemoryInstalled || (Private->HobList.HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME)) {\r
+ ImageContext->ImageRead = PeiImageRead;\r
+ } else {\r
+ MemoryBuffer = AllocatePages (0x400 / EFI_PAGE_SIZE + 1);\r
+ ASSERT (MemoryBuffer != NULL);\r
\r
- CopyMem (MemoryBuffer, (CONST VOID *) (UINTN) PeiImageRead, 0x400);\r
+ CopyMem (MemoryBuffer, (CONST VOID *) (UINTN) PeiImageRead, 0x400);\r
\r
- ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer;\r
+ ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer;\r
+ }\r
\r
return EFI_SUCCESS;\r
}\r
+/**\r
+ To check memory usage bit map arry to figure out if the memory range the image will be loaded in is available or not. If \r
+ memory range is avaliable, the function will mark the correponding bits to 1 which indicates the memory range is used.\r
+ The function is only invoked when load modules at fixed address feature is enabled. \r
+ \r
+ @param Private Pointer to the private data passed in from caller\r
+ @param ImageBase The base addres the image will be loaded at.\r
+ @param ImageSize The size of the image\r
+ \r
+ @retval EFI_SUCCESS The memory range the image will be loaded in is available\r
+ @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available\r
+**/\r
+EFI_STATUS\r
+CheckAndMarkFixLoadingMemoryUsageBitMap (\r
+ IN PEI_CORE_INSTANCE *Private,\r
+ IN EFI_PHYSICAL_ADDRESS ImageBase,\r
+ IN UINT32 ImageSize\r
+ )\r
+{\r
+ UINT32 DxeCodePageNumber;\r
+ UINT64 ReservedCodeSize;\r
+ EFI_PHYSICAL_ADDRESS PeiCodeBase;\r
+ UINT32 BaseOffsetPageNumber;\r
+ UINT32 TopOffsetPageNumber;\r
+ UINT32 Index;\r
+ UINT64 *MemoryUsageBitMap;\r
+ \r
+\r
+ //\r
+ // The reserved code range includes RuntimeCodePage range, Boot time code range and PEI code range.\r
+ //\r
+ DxeCodePageNumber = PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
+ DxeCodePageNumber += PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
+ ReservedCodeSize = EFI_PAGES_TO_SIZE(DxeCodePageNumber + PcdGet32(PcdLoadFixAddressPeiCodePageNumber));\r
+ PeiCodeBase = Private->LoadModuleAtFixAddressTopAddress - ReservedCodeSize;\r
+ \r
+ //\r
+ // Test the memory range for loading the image in the PEI code range.\r
+ //\r
+ if ((Private->LoadModuleAtFixAddressTopAddress - EFI_PAGES_TO_SIZE(DxeCodePageNumber)) < (ImageBase + ImageSize) ||\r
+ (PeiCodeBase > ImageBase)) { \r
+ return EFI_NOT_FOUND; \r
+ }\r
+ \r
+ //\r
+ // Test if the memory is avalaible or not.\r
+ //\r
+ MemoryUsageBitMap = Private->PeiCodeMemoryRangeUsageBitMap; \r
+ BaseOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase - PeiCodeBase));\r
+ TopOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - PeiCodeBase));\r
+ for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
+ if ((MemoryUsageBitMap[Index / 64] & LShiftU64(1, (Index % 64))) != 0) {\r
+ //\r
+ // This page is already used.\r
+ //\r
+ return EFI_NOT_FOUND; \r
+ }\r
+ }\r
+ \r
+ //\r
+ // Being here means the memory range is available. So mark the bits for the memory range\r
+ // \r
+ for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
+ MemoryUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));\r
+ }\r
+ return EFI_SUCCESS; \r
+}\r
+/**\r
+\r
+ Get the fixed loadding address from image header assigned by build tool. This function only be called\r
+ when Loading module at Fixed address feature enabled.\r
+\r
+ @param ImageContext Pointer to the image context structure that describes the PE/COFF\r
+ image that needs to be examined by this function.\r
+ @param Private Pointer to the private data passed in from caller\r
+\r
+ @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .\r
+ @retval EFI_NOT_FOUND The image has no assigned fixed loadding address.\r
\r
+**/\r
+EFI_STATUS\r
+GetPeCoffImageFixLoadingAssignedAddress(\r
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
+ IN PEI_CORE_INSTANCE *Private\r
+ )\r
+{\r
+ UINTN SectionHeaderOffset;\r
+ EFI_STATUS Status;\r
+ EFI_IMAGE_SECTION_HEADER SectionHeader;\r
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;\r
+ EFI_PHYSICAL_ADDRESS FixLoaddingAddress;\r
+ UINT16 Index;\r
+ UINTN Size;\r
+ UINT16 NumberOfSections;\r
+ UINT64 ValueInSectionHeader;\r
+ \r
+\r
+ FixLoaddingAddress = 0;\r
+ Status = EFI_NOT_FOUND;\r
+\r
+ //\r
+ // Get PeHeader pointer\r
+ //\r
+ ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + ImageContext->PeCoffHeaderOffset);\r
+ if (ImageContext->IsTeImage) {\r
+ //\r
+ // for TE image, the fix loadding address is saved in first section header that doesn't point\r
+ // to code section.\r
+ //\r
+ SectionHeaderOffset = sizeof (EFI_TE_IMAGE_HEADER);\r
+ NumberOfSections = ImgHdr->Te.NumberOfSections;\r
+ } else {\r
+ SectionHeaderOffset = (UINTN)(\r
+ ImageContext->PeCoffHeaderOffset +\r
+ sizeof (UINT32) +\r
+ sizeof (EFI_IMAGE_FILE_HEADER) +\r
+ ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
+ );\r
+ NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;\r
+ }\r
+ //\r
+ // Get base address from the first section header that doesn't point to code section.\r
+ //\r
+ for (Index = 0; Index < NumberOfSections; Index++) {\r
+ //\r
+ // Read section header from file\r
+ //\r
+ Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
+ Status = ImageContext->ImageRead (\r
+ ImageContext->Handle,\r
+ SectionHeaderOffset,\r
+ &Size,\r
+ &SectionHeader\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = EFI_NOT_FOUND;\r
+\r
+ if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
+ //\r
+ // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header\r
+ // that doesn't point to code section in image header, as well as ImageBase field of image header. A notable thing is\r
+ // that for PEIM, the value in ImageBase field may not be equal to the value in PointerToRelocations & PointerToLineNumbers because\r
+ // for XIP PEIM, ImageBase field holds the image base address running on the Flash. And PointerToRelocations & PointerToLineNumbers\r
+ // hold the image base address when it is shadow to the memory. And there is an assumption that when the feature is enabled, if a\r
+ // module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers fields should NOT be Zero, or\r
+ // else, these 2 fileds should be set to Zero\r
+ //\r
+ ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);\r
+ if (ValueInSectionHeader != 0) {\r
+ //\r
+ // Found first section header that doesn't point to code section.\r
+ //\r
+ if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) > 0) {\r
+ //\r
+ // When LMFA feature is configured as Load Module at Fixed Absolute Address mode, PointerToRelocations & PointerToLineNumbers field\r
+ // hold the absolute address of image base runing in memory\r
+ //\r
+ FixLoaddingAddress = ValueInSectionHeader;\r
+ } else {\r
+ //\r
+ // When LMFA feature is configured as Load Module at Fixed offset mode, PointerToRelocations & PointerToLineNumbers field\r
+ // hold the offset relative to a platform-specific top address.\r
+ //\r
+ FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(Private->LoadModuleAtFixAddressTopAddress + (INT64)ValueInSectionHeader);\r
+ }\r
+ //\r
+ // Check if the memory range is avaliable.\r
+ //\r
+ Status = CheckAndMarkFixLoadingMemoryUsageBitMap (Private, FixLoaddingAddress, (UINT32) ImageContext->ImageSize);\r
+ if (!EFI_ERROR(Status)) {\r
+ //\r
+ // The assigned address is valid. Return the specified loadding address\r
+ //\r
+ ImageContext->ImageAddress = FixLoaddingAddress;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
+ }\r
+ DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status= %r \n", (VOID *)(UINTN)FixLoaddingAddress, Status));\r
+ return Status;\r
+}\r
/**\r
\r
Loads and relocates a PE/COFF image into memory.\r
-\r
+ If the image is not relocatable, it will not be loaded into memory and be loaded as XIP image.\r
\r
@param Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated\r
@param ImageAddress - The base address of the relocated PE/COFF image\r
{\r
EFI_STATUS Status;\r
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
+ PEI_CORE_INSTANCE *Private;\r
+\r
+ Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());\r
\r
ZeroMem (&ImageContext, sizeof (ImageContext));\r
ImageContext.Handle = Pe32Data;\r
//\r
// When Image has no reloc section, it can't be relocated into memory.\r
//\r
- if (ImageContext.RelocationsStripped) {\r
- DEBUG ((EFI_D_ERROR, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN) Pe32Data));\r
- return EFI_INVALID_PARAMETER;\r
+ if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
+ DEBUG ((EFI_D_INFO|EFI_D_LOAD, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN) Pe32Data));\r
}\r
+\r
//\r
- // Allocate Memory for the image\r
+ // Set default base address to current image address.\r
//\r
- ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
- ASSERT (ImageContext.ImageAddress != 0);\r
- \r
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Pe32Data;\r
+\r
//\r
- // Skip the reserved space for the stripped PeHeader when load TeImage into memory.\r
+ // Allocate Memory for the image when memory is ready, boot mode is not S3, and image is relocatable.\r
//\r
- if (ImageContext.IsTeImage) {\r
- ImageContext.ImageAddress = ImageContext.ImageAddress + \r
- ((EFI_TE_IMAGE_HEADER *) Pe32Data)->StrippedSize -\r
- sizeof (EFI_TE_IMAGE_HEADER);\r
+ if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
+ if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
+ Status = GetPeCoffImageFixLoadingAssignedAddress(&ImageContext, Private);\r
+ if (EFI_ERROR (Status)){\r
+ DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));\r
+ //\r
+ // The PEIM is not assiged valid address, try to allocate page to load it.\r
+ //\r
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
+ }\r
+ } else {\r
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
+ }\r
+ ASSERT (ImageContext.ImageAddress != 0);\r
+ if (ImageContext.ImageAddress == 0) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Skip the reserved space for the stripped PeHeader when load TeImage into memory.\r
+ //\r
+ if (ImageContext.IsTeImage) {\r
+ ImageContext.ImageAddress = ImageContext.ImageAddress +\r
+ ((EFI_TE_IMAGE_HEADER *) Pe32Data)->StrippedSize -\r
+ sizeof (EFI_TE_IMAGE_HEADER);\r
+ }\r
}\r
\r
//\r
//\r
// Flush the instruction cache so the image data is written before we execute it\r
//\r
- InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
+ if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
+ InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
+ }\r
\r
*ImageAddress = ImageContext.ImageAddress;\r
*ImageSize = ImageContext.ImageSize;\r
}\r
\r
/**\r
- Routine for loading file image.\r
+ Loads a PEIM into memory for subsequent execution. If there are compressed\r
+ images or images that need to be relocated into memory for performance reasons,\r
+ this service performs that transformation.\r
\r
- @param PeiServices The PEI core services table.\r
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
@param FileHandle Pointer to the FFS file header of the image.\r
@param ImageAddressArg Pointer to PE/TE image.\r
@param ImageSizeArg Size of PE/TE image.\r
@param EntryPoint Pointer to entry point of specified image file for output.\r
@param AuthenticationState - Pointer to attestation authentication state of image.\r
\r
- @retval EFI_SUCCESS - Image is successfully loaded.\r
- @retval EFI_NOT_FOUND - Fail to locate necessary PPI\r
- @retval Others - Fail to load file.\r
+ @retval EFI_SUCCESS Image is successfully loaded.\r
+ @retval EFI_NOT_FOUND Fail to locate necessary PPI.\r
+ @retval EFI_UNSUPPORTED Image Machine Type is not supported.\r
\r
**/\r
EFI_STATUS\r
PeiLoadImageLoadImage (\r
- IN EFI_PEI_SERVICES **PeiServices,\r
+ IN CONST EFI_PEI_SERVICES **PeiServices,\r
IN EFI_PEI_FILE_HANDLE FileHandle,\r
OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL\r
OUT UINT64 *ImageSizeArg, OPTIONAL\r
UINT64 ImageSize;\r
EFI_PHYSICAL_ADDRESS ImageEntryPoint;\r
UINT16 Machine;\r
- PEI_CORE_INSTANCE *Private;\r
- VOID *EntryPointArg;\r
EFI_SECTION_TYPE SearchType1;\r
EFI_SECTION_TYPE SearchType2;\r
\r
SearchType1 = EFI_SECTION_PE32;\r
SearchType2 = EFI_SECTION_TE;\r
}\r
+\r
//\r
- // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst \r
+ // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst\r
// is true, TE will be searched first).\r
//\r
Status = PeiServicesFfsFindSectionData (\r
return Status;\r
}\r
}\r
- \r
- Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
\r
- if (Private->PeiMemoryInstalled && \r
- (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
- //\r
- // If memory is installed, perform the shadow operations\r
- //\r
- Status = LoadAndRelocatePeCoffImage (\r
- Pe32Data,\r
- &ImageAddress,\r
- &ImageSize,\r
- &ImageEntryPoint\r
- );\r
+ //\r
+ // If memory is installed, perform the shadow operations\r
+ //\r
+ Status = LoadAndRelocatePeCoffImage (\r
+ Pe32Data,\r
+ &ImageAddress,\r
+ &ImageSize,\r
+ &ImageEntryPoint\r
+ );\r
\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ ASSERT_EFI_ERROR (Status);\r
\r
- //\r
- // Got the entry point from the loaded Pe32Data\r
- //\r
- Pe32Data = (VOID *) ((UINTN) ImageAddress);\r
- *EntryPoint = ImageEntryPoint;\r
- } else {\r
- //\r
- // Retrieve the entry point from the PE/COFF or TE image header\r
- //\r
- ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data;\r
- Status = PeCoffLoaderGetEntryPoint (Pe32Data, &EntryPointArg);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- *EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) EntryPointArg;\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
- \r
+\r
+ //\r
+ // Got the entry point from the loaded Pe32Data\r
+ //\r
+ Pe32Data = (VOID *) ((UINTN) ImageAddress);\r
+ *EntryPoint = ImageEntryPoint;\r
+\r
Machine = PeCoffLoaderGetMachineType (Pe32Data);\r
- \r
+\r
if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {\r
- return EFI_UNSUPPORTED; \r
+ if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Machine)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
}\r
\r
if (ImageAddressArg != NULL) {\r
if (ImageSizeArg != NULL) {\r
*ImageSizeArg = ImageSize;\r
}\r
- \r
+\r
DEBUG_CODE_BEGIN ();\r
CHAR8 *AsciiString;\r
CHAR8 AsciiBuffer[512];\r
//\r
// Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi\r
//\r
- if (Machine != IMAGE_FILE_MACHINE_IA64) {\r
- DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%10p EntryPoint=0x%10p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)*EntryPoint));\r
+ if (Machine != EFI_IMAGE_MACHINE_IA64) {\r
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)*EntryPoint));\r
} else {\r
//\r
// For IPF Image, the real entry point should be print.\r
//\r
- DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%10p EntryPoint=0x%10p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint)));\r
+ DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint)));\r
}\r
- \r
+\r
//\r
// Print Module Name by PeImage PDB file name.\r
//\r
AsciiString = PeCoffLoaderGetPdbPointer (Pe32Data);\r
- \r
+\r
if (AsciiString != NULL) {\r
for (Index = (INT32) AsciiStrLen (AsciiString) - 1; Index >= 0; Index --) {\r
if (AsciiString[Index] == '\\') {\r
}\r
\r
/**\r
+ Check whether the input image has the relocation.\r
+\r
+ @param Pe32Data Pointer to the PE/COFF or TE image.\r
+\r
+ @retval TRUE Relocation is stripped.\r
+ @retval FALSE Relocation is not stripped.\r
+\r
+**/\r
+BOOLEAN\r
+RelocationIsStrip (\r
+ IN VOID *Pe32Data\r
+ )\r
+{\r
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
+ EFI_IMAGE_DOS_HEADER *DosHdr;\r
+\r
+ ASSERT (Pe32Data != NULL);\r
+\r
+ DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
+ if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+ //\r
+ // DOS image header is present, so read the PE header after the DOS image header.\r
+ //\r
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
+ } else {\r
+ //\r
+ // DOS image header is not present, so PE header is at the image base.\r
+ //\r
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
+ }\r
+\r
+ //\r
+ // Three cases with regards to relocations:\r
+ // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable\r
+ // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable\r
+ // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but\r
+ // has no base relocs to apply\r
+ // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.\r
+ //\r
+ // Look at the file header to determine if relocations have been stripped, and\r
+ // save this info in the image context for later use.\r
+ //\r
+ if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+ if ((Hdr.Te->DataDirectory[0].Size == 0) && (Hdr.Te->DataDirectory[0].VirtualAddress == 0)) {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+ } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
+ if ((Hdr.Pe32->FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0) {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+ }\r
\r
- Routine for load image file.\r
+ return FALSE;\r
+}\r
\r
+/**\r
+ Routine to load image file for subsequent execution by LoadFile Ppi.\r
+ If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE\r
+ XIP image format is used.\r
\r
- @param PeiServices - The PEI core services table.\r
+ @param PeiServices - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
@param FileHandle - Pointer to the FFS file header of the image.\r
+ @param PeimState - The dispatch state of the input PEIM handle.\r
@param EntryPoint - Pointer to entry point of specified image file for output.\r
@param AuthenticationState - Pointer to attestation authentication state of image.\r
\r
**/\r
EFI_STATUS\r
PeiLoadImage (\r
- IN EFI_PEI_SERVICES **PeiServices,\r
+ IN CONST EFI_PEI_SERVICES **PeiServices,\r
IN EFI_PEI_FILE_HANDLE FileHandle,\r
+ IN UINT8 PeimState,\r
OUT EFI_PHYSICAL_ADDRESS *EntryPoint,\r
OUT UINT32 *AuthenticationState\r
)\r
EFI_PEI_LOAD_FILE_PPI *LoadFile;\r
EFI_PHYSICAL_ADDRESS ImageAddress;\r
UINT64 ImageSize;\r
+ BOOLEAN IsStrip;\r
\r
+ IsStrip = FALSE;\r
//\r
// If any instances of PEI_LOAD_FILE_PPI are installed, they are called.\r
// one at a time, until one reports EFI_SUCCESS.\r
);\r
if (!EFI_ERROR (PpiStatus)) {\r
Status = LoadFile->LoadFile (\r
- LoadFile, \r
- FileHandle, \r
- &ImageAddress, \r
+ LoadFile,\r
+ FileHandle,\r
+ &ImageAddress,\r
&ImageSize,\r
EntryPoint,\r
AuthenticationState\r
);\r
if (!EFI_ERROR (Status)) {\r
+ //\r
+ // The shadowed PEIM must be relocatable.\r
+ //\r
+ if (PeimState == PEIM_STATE_REGISITER_FOR_SHADOW) {\r
+ IsStrip = RelocationIsStrip ((VOID *) (UINTN) ImageAddress);\r
+ ASSERT (!IsStrip);\r
+ if (IsStrip) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ //\r
+ // The image to be started must have the machine type supported by PeiCore.\r
+ //\r
+ ASSERT (EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCoffLoaderGetMachineType ((VOID *) (UINTN) ImageAddress)));\r
+ if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCoffLoaderGetMachineType ((VOID *) (UINTN) ImageAddress))) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
return Status;\r
}\r
}\r
Index++;\r
} while (!EFI_ERROR (PpiStatus));\r
\r
- //\r
- // If no instances reports EFI_SUCCESS, then build-in support for\r
- // the PE32+/TE XIP image format is used.\r
- //\r
- Status = PeiLoadImageLoadImage (\r
- PeiServices, \r
- FileHandle, \r
- NULL, \r
- NULL, \r
- EntryPoint, \r
- AuthenticationState\r
- );\r
- return Status;\r
+ return PpiStatus;\r
}\r
\r
\r
PeiServicesInstallPpi (PrivateData->XipLoadFile);\r
} else {\r
//\r
- // 2nd time we are running from memory so replace the XIP version with the \r
- // new memory version. \r
+ // 2nd time we are running from memory so replace the XIP version with the\r
+ // new memory version.\r
//\r
- PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList); \r
+ PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList);\r
}\r
}\r
\r
\r
\r
+\r