\r
--*/\r
\r
-//\r
-// Include common header file for this module.\r
-//\r
-#include "CommonHeader.h"\r
-\r
#include <PeiMain.h>\r
\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
+\r
+Arguments:\r
\r
+ FileHandle - The handle to the PE/COFF file\r
+ FileOffset - The offset, in bytes, into the file to read\r
+ ReadSize - The number of bytes to read from the file starting at FileOffset\r
+ Buffer - A pointer to the buffer to read the data into.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
+\r
+--*/ \r
\r
EFI_STATUS\r
-PeiLoadImage (\r
- IN EFI_PEI_SERVICES **PeiServices,\r
- IN EFI_FFS_FILE_HEADER *PeimFileHeader,\r
- OUT VOID **EntryPoint\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
+Routine Description:\r
+\r
+ Routine for loading file image.\r
+\r
+Arguments:\r
+\r
+ PeiServices - The PEI core services table.\r
+ FileHandle - Pointer to the FFS file header of the image.\r
+ ImageAddressArg - Pointer to PE/TE image.\r
+ ImageSizeArg - Size of PE/TE image.\r
+ EntryPoint - Pointer to entry point of specified image file for output.\r
+ AuthenticationState - Pointer to attestation authentication state of image.\r
+\r
+Returns:\r
+\r
+ Status - EFI_SUCCESS - Image is successfully loaded.\r
+ EFI_NOT_FOUND - Fail to locate necessary PPI\r
+ Others - Fail to load file.\r
+\r
+--*/\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
+Routine Description:\r
+\r
+ The wrapper function of PeiLoadImageLoadImage().\r
+\r
+Arguments:\r
+\r
+ This - Pointer to EFI_PEI_LOAD_FILE_PPI.\r
+ PeiServices - The PEI core services table.\r
+ FileHandle - Pointer to the FFS file header of the image.\r
+ ImageAddressArg - Pointer to PE/TE image.\r
+ ImageSizeArg - Size of PE/TE image.\r
+ EntryPoint - Pointer to entry point of specified image file for output.\r
+ AuthenticationState - Pointer to attestation authentication state of image.\r
+\r
+Returns:\r
+\r
+ EFI_STATUS.\r
+ \r
+--*/ \r
+;\r
+\r
+STATIC EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi = {\r
+ PeiLoadImageLoadImageWrapper\r
+};\r
+\r
+\r
+STATIC EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {\r
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+ &gEfiPeiLoadFilePpiGuid,\r
+ &mPeiLoadImagePpi\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PeiImageRead (\r
+ IN VOID *FileHandle,\r
+ IN UINTN FileOffset,\r
+ IN OUT UINTN *ReadSize,\r
+ OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
+\r
+Arguments:\r
+\r
+ FileHandle - The handle to the PE/COFF file\r
+ FileOffset - The offset, in bytes, into the file to read\r
+ ReadSize - The number of bytes to read from the file starting at FileOffset\r
+ Buffer - A pointer to the buffer to read the data into.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
+\r
+--*/\r
+{\r
+ CHAR8 *Destination8;\r
+ CHAR8 *Source8;\r
+ UINTN Length;\r
+\r
+ Destination8 = Buffer;\r
+ Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
+ Length = *ReadSize;\r
+ while (Length--) {\r
+ *(Destination8++) = *(Source8++);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetImageReadFunction (\r
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Support routine to return the Image Read\r
+\r
+Arguments:\r
+\r
+ PeiServices - PEI Services Table\r
+\r
+ ImageContext - The context of the image being loaded\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - If Image function location is found\r
+\r
+--*/\r
+{\r
+ VOID* MemoryBuffer;\r
+\r
+ MemoryBuffer = AllocatePages (0x400 / EFI_PAGE_SIZE + 1);\r
+ ASSERT (MemoryBuffer != NULL);\r
+\r
+ CopyMem (MemoryBuffer, (CONST VOID *) (UINTN) PeiImageRead, 0x400);\r
+\r
+ ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+LoadAndRelocatePeCoffImage (\r
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader,\r
+ IN VOID *Pe32Data,\r
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddress,\r
+ OUT UINT64 *ImageSize,\r
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Loads and relocates a PE/COFF image into memory.\r
+\r
+Arguments:\r
+\r
+ PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol\r
+\r
+ Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated\r
+\r
+ ImageAddress - The base address of the relocated PE/COFF image\r
+\r
+ ImageSize - The size of the relocated PE/COFF image\r
+\r
+ EntryPoint - The entry point of the relocated PE/COFF image\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - The file was loaded and relocated\r
+\r
+ EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
+\r
+ ASSERT (PeiEfiPeiPeCoffLoader != NULL);\r
+\r
+ ZeroMem (&ImageContext, sizeof (ImageContext));\r
+ ImageContext.Handle = Pe32Data;\r
+ Status = GetImageReadFunction (&ImageContext);\r
+\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = PeiEfiPeiPeCoffLoader->GetImageInfo (PeiEfiPeiPeCoffLoader, &ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Allocate Memory for the image\r
+ //\r
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
+ ASSERT (ImageContext.ImageAddress != 0);\r
+\r
+ //\r
+ // Load the image to our new buffer\r
+ //\r
+ Status = PeiEfiPeiPeCoffLoader->LoadImage (PeiEfiPeiPeCoffLoader, &ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Relocate the image in our new buffer\r
+ //\r
+ Status = PeiEfiPeiPeCoffLoader->RelocateImage (PeiEfiPeiPeCoffLoader, &ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\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
+\r
+ *ImageAddress = ImageContext.ImageAddress;\r
+ *ImageSize = ImageContext.ImageSize;\r
+ *EntryPoint = ImageContext.EntryPoint;\r
+\r
+ return EFI_SUCCESS;\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
Arguments:\r
\r
- PeiServices - The PEI core services table.\r
- PeimFileHeader - Pointer to the FFS file header of the image.\r
- EntryPoint - Pointer to entry point of specified image file for output.\r
+ PeiServices - The PEI core services table.\r
+ FileHandle - Pointer to the FFS file header of the image.\r
+ ImageAddressArg - Pointer to PE/TE image.\r
+ ImageSizeArg - Size of PE/TE image.\r
+ EntryPoint - Pointer to entry point of specified image file for output.\r
+ AuthenticationState - Pointer to attestation authentication state of image.\r
\r
Returns:\r
\r
{\r
EFI_STATUS Status;\r
VOID *Pe32Data;\r
- EFI_PEI_FV_FILE_LOADER_PPI *FvLoadFilePpi;\r
EFI_PHYSICAL_ADDRESS ImageAddress;\r
UINT64 ImageSize;\r
EFI_PHYSICAL_ADDRESS ImageEntryPoint;\r
EFI_TE_IMAGE_HEADER *TEImageHeader;\r
UINT16 Machine;\r
+ PEI_CORE_INSTANCE *Private;\r
+ VOID *EntryPointArg;\r
\r
- *EntryPoint = NULL;\r
+ *EntryPoint = 0;\r
TEImageHeader = NULL;\r
+ ImageSize = 0;\r
+ *AuthenticationState = 0;\r
\r
//\r
- // Try to find a PE32 section.\r
+ // Try to find a TE section.\r
//\r
Status = PeiServicesFfsFindSectionData (\r
- EFI_SECTION_PE32,\r
- PeimFileHeader,\r
+ EFI_SECTION_TE,\r
+ FileHandle,\r
&Pe32Data\r
);\r
+ if (!EFI_ERROR (Status)) {\r
+ TEImageHeader = (EFI_TE_IMAGE_HEADER *)Pe32Data;\r
+ }\r
//\r
// If we didn't find a PE32 section, try to find a TE section.\r
//\r
if (EFI_ERROR (Status)) {\r
Status = PeiServicesFfsFindSectionData (\r
- EFI_SECTION_TE,\r
- PeimFileHeader,\r
- (VOID **) &TEImageHeader\r
+ EFI_SECTION_PE32,\r
+ FileHandle,\r
+ &Pe32Data\r
);\r
- if (EFI_ERROR (Status) || TEImageHeader == NULL) {\r
+ if (EFI_ERROR (Status)) {\r
//\r
- // There was not a PE32 or a TE section, so assume that it's a Compressed section\r
- // and use the LoadFile\r
+ // PEI core only carry the loader function fro TE and PE32 executables\r
+ // If this two section does not exist, just return.\r
//\r
- Status = PeiServicesLocatePpi (\r
- &gEfiPeiFvFileLoaderPpiGuid,\r
- 0,\r
- NULL,\r
- (VOID **)&FvLoadFilePpi\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_NOT_FOUND;\r
- }\r
+ return Status;\r
+ }\r
+ }\r
+ \r
+ Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
\r
- Status = FvLoadFilePpi->FvLoadFile (\r
- FvLoadFilePpi,\r
- PeimFileHeader,\r
- &ImageAddress,\r
- &ImageSize,\r
- &ImageEntryPoint\r
- );\r
+ if (Private->PeiMemoryInstalled && \r
+ (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
+ {\r
+ //\r
+ // If memory is installed, perform the shadow operations\r
+ //\r
+ Status = LoadAndRelocatePeCoffImage (\r
+ Private->PeCoffLoader,\r
+ Pe32Data,\r
+ &ImageAddress,\r
+ &ImageSize,\r
+ &ImageEntryPoint\r
+ );\r
\r
if (EFI_ERROR (Status)) {\r
return EFI_NOT_FOUND;\r
// Got the entry point from ImageEntryPoint and ImageStartAddress\r
//\r
Pe32Data = (VOID *) ((UINTN) ImageAddress);\r
- *EntryPoint = (VOID *) ((UINTN) ImageEntryPoint);\r
- } else {\r
+ *EntryPoint = ImageEntryPoint;\r
+ }\r
+ } else {\r
+ if (TEImageHeader != NULL) {\r
//\r
// Retrieve the entry point from the TE image header\r
//\r
ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) TEImageHeader;\r
- *EntryPoint = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) +\r
+ ImageSize = 0;\r
+ *EntryPoint = (EFI_PHYSICAL_ADDRESS)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) +\r
TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize);\r
- }\r
- } else {\r
- //\r
- // Retrieve the entry point from the PE/COFF image header\r
- //\r
- ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data;\r
- Status = PeCoffLoaderGetEntryPoint (Pe32Data, EntryPoint);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_NOT_FOUND;\r
+ } else {\r
+ //\r
+ // Retrieve the entry point from the PE/COFF image header\r
+ //\r
+ ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data;\r
+ ImageSize = 0;\r
+ Status = PeCoffLoaderGetEntryPoint (Pe32Data, &EntryPointArg);\r
+ *EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) EntryPointArg;\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
}\r
}\r
\r
return EFI_UNSUPPORTED; \r
}\r
\r
+ if (ImageAddressArg != NULL) {\r
+ *ImageAddressArg = ImageAddress;\r
+ }\r
+\r
+ if (ImageSizeArg != NULL) {\r
+ *ImageSizeArg = ImageSize;\r
+ }\r
+ \r
//\r
// Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi\r
//\r
DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));\r
\r
return EFI_SUCCESS;\r
+\r
}\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
+Routine Description:\r
+\r
+ The wrapper function of PeiLoadImageLoadImage().\r
+\r
+Arguments:\r
+\r
+ This - Pointer to EFI_PEI_LOAD_FILE_PPI.\r
+ PeiServices - The PEI core services table.\r
+ FileHandle - Pointer to the FFS file header of the image.\r
+ ImageAddressArg - Pointer to PE/TE image.\r
+ ImageSizeArg - Size of PE/TE image.\r
+ EntryPoint - Pointer to entry point of specified image file for output.\r
+ AuthenticationState - Pointer to attestation authentication state of image.\r
+\r
+Returns:\r
+\r
+ EFI_STATUS.\r
+ \r
+--*/ \r
+{\r
+ return PeiLoadImageLoadImage (\r
+ GetPeiServicesTablePointer (),\r
+ FileHandle,\r
+ ImageAddressArg,\r
+ ImageSizeArg,\r
+ EntryPoint,\r
+ AuthenticationState\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+PeiLoadImage (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN EFI_PEI_FILE_HANDLE FileHandle,\r
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint,\r
+ OUT UINT32 *AuthenticationState\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Routine for load image file.\r
+\r
+Arguments:\r
+\r
+ PeiServices - The PEI core services table.\r
+ FileHandle - Pointer to the FFS file header of the image.\r
+ EntryPoint - Pointer to entry point of specified image file for output.\r
+ AuthenticationState - Pointer to attestation authentication state of image.\r
+\r
+Returns:\r
+\r
+ Status - EFI_SUCCESS - Image is successfully loaded.\r
+ EFI_NOT_FOUND - Fail to locate necessary PPI\r
+ Others - Fail to load file.\r
+ \r
+--*/ \r
+{\r
+ EFI_STATUS PpiStatus;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ EFI_PEI_LOAD_FILE_PPI *LoadFile;\r
+ EFI_PHYSICAL_ADDRESS ImageAddress;\r
+ UINT64 ImageSize;\r
+\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
+ Index = 0;\r
+ do {\r
+ PpiStatus = PeiServicesLocatePpi (\r
+ &gEfiPeiLoadFilePpiGuid,\r
+ Index,\r
+ NULL,\r
+ (VOID **)&LoadFile\r
+ );\r
+ if (!EFI_ERROR (PpiStatus)) {\r
+ Status = LoadFile->LoadFile (\r
+ LoadFile, \r
+ FileHandle, \r
+ &ImageAddress, \r
+ &ImageSize,\r
+ EntryPoint,\r
+ AuthenticationState\r
+ );\r
+ if (!EFI_ERROR (Status)) {\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
+}\r
+\r
+\r
+VOID\r
+InitializeImageServices (\r
+ IN PEI_CORE_INSTANCE *PrivateData,\r
+ IN PEI_CORE_INSTANCE *OldCoreData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Regitser PeCoffLoader to PeiCore PrivateData. And install\r
+ Pei Load File PPI.\r
+\r
+Arguments:\r
+\r
+ PrivateData - Pointer to PEI_CORE_INSTANCE.\r
+ OldCoreData - Pointer to PEI_CORE_INSTANCE.\r
+\r
+Returns:\r
+\r
+ NONE.\r
+ \r
+--*/ \r
+{\r
+ //\r
+ // Always update PeCoffLoader pointer as PEI core itself may get \r
+ // shadowed into memory\r
+ //\r
+ PrivateData->PeCoffLoader = GetPeCoffLoaderProtocol ();\r
+ \r
+ if (OldCoreData == NULL) {\r
+ //\r
+ // The first time we are XIP (running from FLASH). We need to remember the\r
+ // FLASH address so we can reinstall the memory version that runs faster\r
+ //\r
+ PrivateData->XipLoadFile = &gPpiLoadFilePpiList;\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
+ //\r
+ PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList); \r
+ }\r
+}\r
+\r
+\r
+\r