2 Pei Core Load Image Support
4 Copyright (c) 2006 - 2008, 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 The wrapper function of PeiLoadImageLoadImage().
20 @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.
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 @return Status of PeiLoadImageLoadImage().
32 PeiLoadImageLoadImageWrapper (
33 IN CONST EFI_PEI_LOAD_FILE_PPI
*This
,
34 IN EFI_PEI_FILE_HANDLE FileHandle
,
35 OUT EFI_PHYSICAL_ADDRESS
*ImageAddressArg
, OPTIONAL
36 OUT UINT64
*ImageSizeArg
, OPTIONAL
37 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
,
38 OUT UINT32
*AuthenticationState
42 STATIC EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi
= {
43 PeiLoadImageLoadImageWrapper
47 STATIC EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList
= {
48 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
49 &gEfiPeiLoadFilePpiGuid
,
55 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
58 @param FileHandle - The handle to the PE/COFF file
59 @param FileOffset - The offset, in bytes, into the file to read
60 @param ReadSize - The number of bytes to read from the file starting at FileOffset
61 @param Buffer - A pointer to the buffer to read the data into.
63 @return EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
79 Destination8
= Buffer
;
80 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
83 *(Destination8
++) = *(Source8
++);
91 Support routine to get the Image read file function.
93 @param ImageContext - The context of the image being loaded
95 @retval EFI_SUCCESS - If Image function location is found
99 GetImageReadFunction (
100 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
105 MemoryBuffer
= AllocatePages (0x400 / EFI_PAGE_SIZE
+ 1);
106 ASSERT (MemoryBuffer
!= NULL
);
108 CopyMem (MemoryBuffer
, (CONST VOID
*) (UINTN
) PeiImageRead
, 0x400);
110 ImageContext
->ImageRead
= (PE_COFF_LOADER_READ_FILE
) (UINTN
) MemoryBuffer
;
117 Loads and relocates a PE/COFF image into memory.
120 @param Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
121 @param ImageAddress - The base address of the relocated PE/COFF image
122 @param ImageSize - The size of the relocated PE/COFF image
123 @param EntryPoint - The entry point of the relocated PE/COFF image
125 @retval EFI_SUCCESS The file was loaded and relocated
126 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file
127 @retval EFI_INVALID_PARAMETER The image withou .reloc section can't be relocated.
131 LoadAndRelocatePeCoffImage (
133 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
134 OUT UINT64
*ImageSize
,
135 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
139 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
141 ZeroMem (&ImageContext
, sizeof (ImageContext
));
142 ImageContext
.Handle
= Pe32Data
;
143 Status
= GetImageReadFunction (&ImageContext
);
145 ASSERT_EFI_ERROR (Status
);
147 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
148 if (EFI_ERROR (Status
)) {
152 // When Image has no reloc section, it can't be relocated into memory.
154 if (ImageContext
.RelocationsStripped
) {
155 DEBUG ((EFI_D_ERROR
, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN
) Pe32Data
));
156 return EFI_INVALID_PARAMETER
;
159 // Allocate Memory for the image
161 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
));
162 ASSERT (ImageContext
.ImageAddress
!= 0);
165 // Skip the reserved space for the stripped PeHeader when load TeImage into memory.
167 if (ImageContext
.IsTeImage
) {
168 ImageContext
.ImageAddress
= ImageContext
.ImageAddress
+
169 ((EFI_TE_IMAGE_HEADER
*) Pe32Data
)->StrippedSize
-
170 sizeof (EFI_TE_IMAGE_HEADER
);
174 // Load the image to our new buffer
176 Status
= PeCoffLoaderLoadImage (&ImageContext
);
177 if (EFI_ERROR (Status
)) {
181 // Relocate the image in our new buffer
183 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
184 if (EFI_ERROR (Status
)) {
189 // Flush the instruction cache so the image data is written before we execute it
191 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
193 *ImageAddress
= ImageContext
.ImageAddress
;
194 *ImageSize
= ImageContext
.ImageSize
;
195 *EntryPoint
= ImageContext
.EntryPoint
;
201 Loads a PEIM into memory for subsequent execution. If there are compressed
202 images or images that need to be relocated into memory for performance reasons,
203 this service performs that transformation.
205 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
206 @param FileHandle Pointer to the FFS file header of the image.
207 @param ImageAddressArg Pointer to PE/TE image.
208 @param ImageSizeArg Size of PE/TE image.
209 @param EntryPoint Pointer to entry point of specified image file for output.
210 @param AuthenticationState - Pointer to attestation authentication state of image.
212 @retval EFI_SUCCESS Image is successfully loaded.
213 @retval EFI_NOT_FOUND Fail to locate necessary PPI.
214 @retval EFI_UNSUPPORTED Image Machine Type is not supported.
218 PeiLoadImageLoadImage (
219 IN EFI_PEI_SERVICES
**PeiServices
,
220 IN EFI_PEI_FILE_HANDLE FileHandle
,
221 OUT EFI_PHYSICAL_ADDRESS
*ImageAddressArg
, OPTIONAL
222 OUT UINT64
*ImageSizeArg
, OPTIONAL
223 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
,
224 OUT UINT32
*AuthenticationState
229 EFI_PHYSICAL_ADDRESS ImageAddress
;
231 EFI_PHYSICAL_ADDRESS ImageEntryPoint
;
233 PEI_CORE_INSTANCE
*Private
;
235 EFI_SECTION_TYPE SearchType1
;
236 EFI_SECTION_TYPE SearchType2
;
240 *AuthenticationState
= 0;
242 if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst
)) {
243 SearchType1
= EFI_SECTION_TE
;
244 SearchType2
= EFI_SECTION_PE32
;
246 SearchType1
= EFI_SECTION_PE32
;
247 SearchType2
= EFI_SECTION_TE
;
250 // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst
251 // is true, TE will be searched first).
253 Status
= PeiServicesFfsFindSectionData (
259 // If we didn't find a first exe section, try to find the second exe section.
261 if (EFI_ERROR (Status
)) {
262 Status
= PeiServicesFfsFindSectionData (
267 if (EFI_ERROR (Status
)) {
269 // PEI core only carry the loader function fro TE and PE32 executables
270 // If this two section does not exist, just return.
276 Private
= PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices
);
278 if (Private
->PeiMemoryInstalled
&&
279 (Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
)) {
281 // If memory is installed, perform the shadow operations
283 Status
= LoadAndRelocatePeCoffImage (
290 if (EFI_ERROR (Status
)) {
295 // Got the entry point from the loaded Pe32Data
297 Pe32Data
= (VOID
*) ((UINTN
) ImageAddress
);
298 *EntryPoint
= ImageEntryPoint
;
301 // Retrieve the entry point from the PE/COFF or TE image header
303 ImageAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Pe32Data
;
304 Status
= PeCoffLoaderGetEntryPoint (Pe32Data
, &EntryPointArg
);
305 if (EFI_ERROR (Status
)) {
308 *EntryPoint
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) EntryPointArg
;
311 Machine
= PeCoffLoaderGetMachineType (Pe32Data
);
313 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine
)) {
314 return EFI_UNSUPPORTED
;
317 if (ImageAddressArg
!= NULL
) {
318 *ImageAddressArg
= ImageAddress
;
321 if (ImageSizeArg
!= NULL
) {
322 *ImageSizeArg
= ImageSize
;
327 CHAR8 AsciiBuffer
[512];
332 // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi
334 if (Machine
!= IMAGE_FILE_MACHINE_IA64
) {
335 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID
*)(UINTN
)ImageAddress
, (VOID
*)(UINTN
)*EntryPoint
));
338 // For IPF Image, the real entry point should be print.
340 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID
*)(UINTN
)ImageAddress
, (VOID
*)(UINTN
)(*(UINT64
*)(UINTN
)*EntryPoint
)));
344 // Print Module Name by PeImage PDB file name.
346 AsciiString
= PeCoffLoaderGetPdbPointer (Pe32Data
);
348 if (AsciiString
!= NULL
) {
349 for (Index
= (INT32
) AsciiStrLen (AsciiString
) - 1; Index
>= 0; Index
--) {
350 if (AsciiString
[Index
] == '\\') {
356 for (Index1
= 0; AsciiString
[Index
+ 1 + Index1
] != '.'; Index1
++) {
357 AsciiBuffer
[Index1
] = AsciiString
[Index
+ 1 + Index1
];
359 AsciiBuffer
[Index1
] = '\0';
360 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a.efi", AsciiBuffer
));
366 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));
374 The wrapper function of PeiLoadImageLoadImage().
376 @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.
377 @param FileHandle - Pointer to the FFS file header of the image.
378 @param ImageAddressArg - Pointer to PE/TE image.
379 @param ImageSizeArg - Size of PE/TE image.
380 @param EntryPoint - Pointer to entry point of specified image file for output.
381 @param AuthenticationState - Pointer to attestation authentication state of image.
383 @return Status of PeiLoadImageLoadImage().
388 PeiLoadImageLoadImageWrapper (
389 IN CONST EFI_PEI_LOAD_FILE_PPI
*This
,
390 IN EFI_PEI_FILE_HANDLE FileHandle
,
391 OUT EFI_PHYSICAL_ADDRESS
*ImageAddressArg
, OPTIONAL
392 OUT UINT64
*ImageSizeArg
, OPTIONAL
393 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
,
394 OUT UINT32
*AuthenticationState
397 return PeiLoadImageLoadImage (
398 GetPeiServicesTablePointer (),
408 Routine to load image file for subsequent execution by LoadFile Ppi.
409 If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE
410 XIP image format is used.
412 @param PeiServices - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
413 @param FileHandle - Pointer to the FFS file header of the image.
414 @param EntryPoint - Pointer to entry point of specified image file for output.
415 @param AuthenticationState - Pointer to attestation authentication state of image.
417 @retval EFI_SUCCESS - Image is successfully loaded.
418 @retval EFI_NOT_FOUND - Fail to locate necessary PPI
419 @retval Others - Fail to load file.
424 IN EFI_PEI_SERVICES
**PeiServices
,
425 IN EFI_PEI_FILE_HANDLE FileHandle
,
426 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
,
427 OUT UINT32
*AuthenticationState
430 EFI_STATUS PpiStatus
;
433 EFI_PEI_LOAD_FILE_PPI
*LoadFile
;
434 EFI_PHYSICAL_ADDRESS ImageAddress
;
438 // If any instances of PEI_LOAD_FILE_PPI are installed, they are called.
439 // one at a time, until one reports EFI_SUCCESS.
443 PpiStatus
= PeiServicesLocatePpi (
444 &gEfiPeiLoadFilePpiGuid
,
449 if (!EFI_ERROR (PpiStatus
)) {
450 Status
= LoadFile
->LoadFile (
458 if (!EFI_ERROR (Status
)) {
463 } while (!EFI_ERROR (PpiStatus
));
466 // If no instances reports EFI_SUCCESS, then build-in support for
467 // the PE32+/TE XIP image format is used.
469 Status
= PeiLoadImageLoadImage (
483 Install Pei Load File PPI.
486 @param PrivateData - Pointer to PEI_CORE_INSTANCE.
487 @param OldCoreData - Pointer to PEI_CORE_INSTANCE.
491 InitializeImageServices (
492 IN PEI_CORE_INSTANCE
*PrivateData
,
493 IN PEI_CORE_INSTANCE
*OldCoreData
496 if (OldCoreData
== NULL
) {
498 // The first time we are XIP (running from FLASH). We need to remember the
499 // FLASH address so we can reinstall the memory version that runs faster
501 PrivateData
->XipLoadFile
= &gPpiLoadFilePpiList
;
502 PeiServicesInstallPpi (PrivateData
->XipLoadFile
);
505 // 2nd time we are running from memory so replace the XIP version with the
506 // new memory version.
508 PeiServicesReInstallPpi (PrivateData
->XipLoadFile
, &gPpiLoadFilePpiList
);