2 Pei Core Load Image Support
4 Copyright (c) 2006 - 2007, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Routine for loading file image.
20 @param PeiServices The PEI core services table.
21 @param FileHandle Pointer to the FFS file header of the image.
22 @param ImageAddressArg Pointer to PE/TE image.
23 @param ImageSizeArg Size of PE/TE image.
24 @param EntryPoint Pointer to entry point of specified image file for output.
25 @param AuthenticationState - Pointer to attestation authentication state of image.
27 @retval EFI_SUCCESS - Image is successfully loaded.
28 @retval EFI_NOT_FOUND - Fail to locate necessary PPI
29 @retval Others - Fail to load file.
33 PeiLoadImageLoadImage (
34 IN EFI_PEI_SERVICES
**PeiServices
,
35 IN EFI_PEI_FILE_HANDLE FileHandle
,
36 OUT EFI_PHYSICAL_ADDRESS
*ImageAddressArg
, OPTIONAL
37 OUT UINT64
*ImageSizeArg
, OPTIONAL
38 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
,
39 OUT UINT32
*AuthenticationState
44 The wrapper function of PeiLoadImageLoadImage().
46 @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.
47 @param FileHandle - Pointer to the FFS file header of the image.
48 @param ImageAddressArg - Pointer to PE/TE image.
49 @param ImageSizeArg - Size of PE/TE image.
50 @param EntryPoint - Pointer to entry point of specified image file for output.
51 @param AuthenticationState - Pointer to attestation authentication state of image.
53 @return Status of PeiLoadImageLoadImage().
58 PeiLoadImageLoadImageWrapper (
59 IN CONST EFI_PEI_LOAD_FILE_PPI
*This
,
60 IN EFI_PEI_FILE_HANDLE FileHandle
,
61 OUT EFI_PHYSICAL_ADDRESS
*ImageAddressArg
, OPTIONAL
62 OUT UINT64
*ImageSizeArg
, OPTIONAL
63 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
,
64 OUT UINT32
*AuthenticationState
68 STATIC EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi
= {
69 PeiLoadImageLoadImageWrapper
73 STATIC EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList
= {
74 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
75 &gEfiPeiLoadFilePpiGuid
,
81 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
84 @param FileHandle - The handle to the PE/COFF file
85 @param FileOffset - The offset, in bytes, into the file to read
86 @param ReadSize - The number of bytes to read from the file starting at FileOffset
87 @param Buffer - A pointer to the buffer to read the data into.
89 @return EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
97 IN OUT UINTN
*ReadSize
,
105 Destination8
= Buffer
;
106 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
109 *(Destination8
++) = *(Source8
++);
117 Support routine to return the Image Read.
119 @param ImageContext - The context of the image being loaded
121 @retval EFI_SUCCESS - If Image function location is found
125 GetImageReadFunction (
126 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
131 MemoryBuffer
= AllocatePages (0x400 / EFI_PAGE_SIZE
+ 1);
132 ASSERT (MemoryBuffer
!= NULL
);
134 CopyMem (MemoryBuffer
, (CONST VOID
*) (UINTN
) PeiImageRead
, 0x400);
136 ImageContext
->ImageRead
= (PE_COFF_LOADER_READ_FILE
) (UINTN
) MemoryBuffer
;
143 Loads and relocates a PE/COFF image into memory.
146 @param Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
147 @param ImageAddress - The base address of the relocated PE/COFF image
148 @param ImageSize - The size of the relocated PE/COFF image
149 @param EntryPoint - The entry point of the relocated PE/COFF image
151 @retval EFI_SUCCESS The file was loaded and relocated
152 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file
156 LoadAndRelocatePeCoffImage (
158 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
159 OUT UINT64
*ImageSize
,
160 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
164 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
166 ZeroMem (&ImageContext
, sizeof (ImageContext
));
167 ImageContext
.Handle
= Pe32Data
;
168 Status
= GetImageReadFunction (&ImageContext
);
170 ASSERT_EFI_ERROR (Status
);
172 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
173 if (EFI_ERROR (Status
)) {
177 // When Image has no reloc section, it can't be relocated into memory.
179 if (ImageContext
.RelocationsStripped
) {
180 DEBUG ((EFI_D_ERROR
, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN
) Pe32Data
));
181 return EFI_INVALID_PARAMETER
;
184 // Allocate Memory for the image
186 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
));
187 ASSERT (ImageContext
.ImageAddress
!= 0);
190 // Skip the reserved space for the stripped PeHeader when load TeImage into memory.
192 if (ImageContext
.IsTeImage
) {
193 ImageContext
.ImageAddress
= ImageContext
.ImageAddress
+
194 ((EFI_TE_IMAGE_HEADER
*) Pe32Data
)->StrippedSize
-
195 sizeof (EFI_TE_IMAGE_HEADER
);
199 // Load the image to our new buffer
201 Status
= PeCoffLoaderLoadImage (&ImageContext
);
202 if (EFI_ERROR (Status
)) {
206 // Relocate the image in our new buffer
208 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
209 if (EFI_ERROR (Status
)) {
214 // Flush the instruction cache so the image data is written before we execute it
216 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
218 *ImageAddress
= ImageContext
.ImageAddress
;
219 *ImageSize
= ImageContext
.ImageSize
;
220 *EntryPoint
= ImageContext
.EntryPoint
;
226 Routine for loading file image.
228 @param PeiServices The PEI core services table.
229 @param FileHandle Pointer to the FFS file header of the image.
230 @param ImageAddressArg Pointer to PE/TE image.
231 @param ImageSizeArg Size of PE/TE image.
232 @param EntryPoint Pointer to entry point of specified image file for output.
233 @param AuthenticationState - Pointer to attestation authentication state of image.
235 @retval EFI_SUCCESS - Image is successfully loaded.
236 @retval EFI_NOT_FOUND - Fail to locate necessary PPI
237 @retval Others - Fail to load file.
241 PeiLoadImageLoadImage (
242 IN EFI_PEI_SERVICES
**PeiServices
,
243 IN EFI_PEI_FILE_HANDLE FileHandle
,
244 OUT EFI_PHYSICAL_ADDRESS
*ImageAddressArg
, OPTIONAL
245 OUT UINT64
*ImageSizeArg
, OPTIONAL
246 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
,
247 OUT UINT32
*AuthenticationState
252 EFI_PHYSICAL_ADDRESS ImageAddress
;
254 EFI_PHYSICAL_ADDRESS ImageEntryPoint
;
256 PEI_CORE_INSTANCE
*Private
;
258 EFI_SECTION_TYPE SearchType1
;
259 EFI_SECTION_TYPE SearchType2
;
263 *AuthenticationState
= 0;
265 if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst
)) {
266 SearchType1
= EFI_SECTION_TE
;
267 SearchType2
= EFI_SECTION_PE32
;
269 SearchType1
= EFI_SECTION_PE32
;
270 SearchType2
= EFI_SECTION_TE
;
273 // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst
274 // is true, TE will be searched first).
276 Status
= PeiServicesFfsFindSectionData (
282 // If we didn't find a first exe section, try to find the second exe section.
284 if (EFI_ERROR (Status
)) {
285 Status
= PeiServicesFfsFindSectionData (
290 if (EFI_ERROR (Status
)) {
292 // PEI core only carry the loader function fro TE and PE32 executables
293 // If this two section does not exist, just return.
299 Private
= PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices
);
301 if (Private
->PeiMemoryInstalled
&&
302 (Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
)) {
304 // If memory is installed, perform the shadow operations
306 Status
= LoadAndRelocatePeCoffImage (
313 if (EFI_ERROR (Status
)) {
318 // Got the entry point from the loaded Pe32Data
320 Pe32Data
= (VOID
*) ((UINTN
) ImageAddress
);
321 *EntryPoint
= ImageEntryPoint
;
324 // Retrieve the entry point from the PE/COFF or TE image header
326 ImageAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Pe32Data
;
327 Status
= PeCoffLoaderGetEntryPoint (Pe32Data
, &EntryPointArg
);
328 if (EFI_ERROR (Status
)) {
331 *EntryPoint
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) EntryPointArg
;
334 Machine
= PeCoffLoaderGetMachineType (Pe32Data
);
336 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine
)) {
337 return EFI_UNSUPPORTED
;
340 if (ImageAddressArg
!= NULL
) {
341 *ImageAddressArg
= ImageAddress
;
344 if (ImageSizeArg
!= NULL
) {
345 *ImageSizeArg
= ImageSize
;
350 CHAR8 AsciiBuffer
[512];
355 // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi
357 if (Machine
!= IMAGE_FILE_MACHINE_IA64
) {
358 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Loading PEIM at 0x%10p EntryPoint=0x%10p ", (VOID
*)(UINTN
)ImageAddress
, (VOID
*)(UINTN
)*EntryPoint
));
361 // For IPF Image, the real entry point should be print.
363 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Loading PEIM at 0x%10p EntryPoint=0x%10p ", (VOID
*)(UINTN
)ImageAddress
, (VOID
*)(UINTN
)(*(UINT64
*)(UINTN
)*EntryPoint
)));
367 // Print Module Name by PeImage PDB file name.
369 AsciiString
= PeCoffLoaderGetPdbPointer (Pe32Data
);
371 if (AsciiString
!= NULL
) {
372 for (Index
= (INT32
) AsciiStrLen (AsciiString
) - 1; Index
>= 0; Index
--) {
373 if (AsciiString
[Index
] == '\\') {
379 for (Index1
= 0; AsciiString
[Index
+ 1 + Index1
] != '.'; Index1
++) {
380 AsciiBuffer
[Index1
] = AsciiString
[Index
+ 1 + Index1
];
382 AsciiBuffer
[Index1
] = '\0';
383 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a.efi", AsciiBuffer
));
389 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));
397 The wrapper function of PeiLoadImageLoadImage().
399 @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.
400 @param FileHandle - Pointer to the FFS file header of the image.
401 @param ImageAddressArg - Pointer to PE/TE image.
402 @param ImageSizeArg - Size of PE/TE image.
403 @param EntryPoint - Pointer to entry point of specified image file for output.
404 @param AuthenticationState - Pointer to attestation authentication state of image.
406 @return Status of PeiLoadImageLoadImage().
411 PeiLoadImageLoadImageWrapper (
412 IN CONST EFI_PEI_LOAD_FILE_PPI
*This
,
413 IN EFI_PEI_FILE_HANDLE FileHandle
,
414 OUT EFI_PHYSICAL_ADDRESS
*ImageAddressArg
, OPTIONAL
415 OUT UINT64
*ImageSizeArg
, OPTIONAL
416 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
,
417 OUT UINT32
*AuthenticationState
420 return PeiLoadImageLoadImage (
421 GetPeiServicesTablePointer (),
432 Routine for load image file.
435 @param PeiServices - The PEI core services table.
436 @param FileHandle - Pointer to the FFS file header of the image.
437 @param EntryPoint - Pointer to entry point of specified image file for output.
438 @param AuthenticationState - Pointer to attestation authentication state of image.
440 @retval EFI_SUCCESS - Image is successfully loaded.
441 @retval EFI_NOT_FOUND - Fail to locate necessary PPI
442 @retval Others - Fail to load file.
447 IN EFI_PEI_SERVICES
**PeiServices
,
448 IN EFI_PEI_FILE_HANDLE FileHandle
,
449 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
,
450 OUT UINT32
*AuthenticationState
453 EFI_STATUS PpiStatus
;
456 EFI_PEI_LOAD_FILE_PPI
*LoadFile
;
457 EFI_PHYSICAL_ADDRESS ImageAddress
;
461 // If any instances of PEI_LOAD_FILE_PPI are installed, they are called.
462 // one at a time, until one reports EFI_SUCCESS.
466 PpiStatus
= PeiServicesLocatePpi (
467 &gEfiPeiLoadFilePpiGuid
,
472 if (!EFI_ERROR (PpiStatus
)) {
473 Status
= LoadFile
->LoadFile (
481 if (!EFI_ERROR (Status
)) {
486 } while (!EFI_ERROR (PpiStatus
));
489 // If no instances reports EFI_SUCCESS, then build-in support for
490 // the PE32+/TE XIP image format is used.
492 Status
= PeiLoadImageLoadImage (
506 Install Pei Load File PPI.
509 @param PrivateData - Pointer to PEI_CORE_INSTANCE.
510 @param OldCoreData - Pointer to PEI_CORE_INSTANCE.
514 InitializeImageServices (
515 IN PEI_CORE_INSTANCE
*PrivateData
,
516 IN PEI_CORE_INSTANCE
*OldCoreData
519 if (OldCoreData
== NULL
) {
521 // The first time we are XIP (running from FLASH). We need to remember the
522 // FLASH address so we can reinstall the memory version that runs faster
524 PrivateData
->XipLoadFile
= &gPpiLoadFilePpiList
;
525 PeiServicesInstallPpi (PrivateData
->XipLoadFile
);
528 // 2nd time we are running from memory so replace the XIP version with the
529 // new memory version.
531 PeiServicesReInstallPpi (PrivateData
->XipLoadFile
, &gPpiLoadFilePpiList
);