+ 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 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
+ 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
+ ZeroMem (&ImageContext, sizeof (ImageContext));\r
+ ImageContext.Handle = Pe32Data;\r
+ Status = GetImageReadFunction (&ImageContext);\r
+\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\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
+ }\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
+ // 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
+ // Load the image to our new buffer\r
+ //\r
+ Status = PeCoffLoaderLoadImage (&ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Relocate the image in our new buffer\r
+ //\r
+ Status = PeCoffLoaderRelocateImage (&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
+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