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
75 CopyMem (Buffer
, (VOID
*)((UINTN
) FileHandle
+ FileOffset
), *ReadSize
);
81 Support routine to get the Image read file function.
83 @param ImageContext - The context of the image being loaded
85 @retval EFI_SUCCESS - If Image function location is found
89 GetImageReadFunction (
90 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
95 MemoryBuffer
= AllocatePages (0x400 / EFI_PAGE_SIZE
+ 1);
96 ASSERT (MemoryBuffer
!= NULL
);
98 CopyMem (MemoryBuffer
, (CONST VOID
*) (UINTN
) PeiImageRead
, 0x400);
100 ImageContext
->ImageRead
= (PE_COFF_LOADER_READ_FILE
) (UINTN
) MemoryBuffer
;
107 Loads and relocates a PE/COFF image into memory.
110 @param Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
111 @param ImageAddress - The base address of the relocated PE/COFF image
112 @param ImageSize - The size of the relocated PE/COFF image
113 @param EntryPoint - The entry point of the relocated PE/COFF image
115 @retval EFI_SUCCESS The file was loaded and relocated
116 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file
117 @retval EFI_INVALID_PARAMETER The image withou .reloc section can't be relocated.
121 LoadAndRelocatePeCoffImage (
123 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
124 OUT UINT64
*ImageSize
,
125 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
129 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
131 ZeroMem (&ImageContext
, sizeof (ImageContext
));
132 ImageContext
.Handle
= Pe32Data
;
133 Status
= GetImageReadFunction (&ImageContext
);
135 ASSERT_EFI_ERROR (Status
);
137 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
138 if (EFI_ERROR (Status
)) {
142 // When Image has no reloc section, it can't be relocated into memory.
144 if (ImageContext
.RelocationsStripped
) {
145 DEBUG ((EFI_D_ERROR
, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN
) Pe32Data
));
146 return EFI_INVALID_PARAMETER
;
149 // Allocate Memory for the image
151 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
));
152 ASSERT (ImageContext
.ImageAddress
!= 0);
155 // Skip the reserved space for the stripped PeHeader when load TeImage into memory.
157 if (ImageContext
.IsTeImage
) {
158 ImageContext
.ImageAddress
= ImageContext
.ImageAddress
+
159 ((EFI_TE_IMAGE_HEADER
*) Pe32Data
)->StrippedSize
-
160 sizeof (EFI_TE_IMAGE_HEADER
);
164 // Load the image to our new buffer
166 Status
= PeCoffLoaderLoadImage (&ImageContext
);
167 if (EFI_ERROR (Status
)) {
171 // Relocate the image in our new buffer
173 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
174 if (EFI_ERROR (Status
)) {
179 // Flush the instruction cache so the image data is written before we execute it
181 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
183 *ImageAddress
= ImageContext
.ImageAddress
;
184 *ImageSize
= ImageContext
.ImageSize
;
185 *EntryPoint
= ImageContext
.EntryPoint
;
191 Loads a PEIM into memory for subsequent execution. If there are compressed
192 images or images that need to be relocated into memory for performance reasons,
193 this service performs that transformation.
195 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
196 @param FileHandle Pointer to the FFS file header of the image.
197 @param ImageAddressArg Pointer to PE/TE image.
198 @param ImageSizeArg Size of PE/TE image.
199 @param EntryPoint Pointer to entry point of specified image file for output.
200 @param AuthenticationState - Pointer to attestation authentication state of image.
202 @retval EFI_SUCCESS Image is successfully loaded.
203 @retval EFI_NOT_FOUND Fail to locate necessary PPI.
204 @retval EFI_UNSUPPORTED Image Machine Type is not supported.
208 PeiLoadImageLoadImage (
209 IN EFI_PEI_SERVICES
**PeiServices
,
210 IN EFI_PEI_FILE_HANDLE FileHandle
,
211 OUT EFI_PHYSICAL_ADDRESS
*ImageAddressArg
, OPTIONAL
212 OUT UINT64
*ImageSizeArg
, OPTIONAL
213 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
,
214 OUT UINT32
*AuthenticationState
219 EFI_PHYSICAL_ADDRESS ImageAddress
;
221 EFI_PHYSICAL_ADDRESS ImageEntryPoint
;
223 PEI_CORE_INSTANCE
*Private
;
225 EFI_SECTION_TYPE SearchType1
;
226 EFI_SECTION_TYPE SearchType2
;
230 *AuthenticationState
= 0;
232 if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst
)) {
233 SearchType1
= EFI_SECTION_TE
;
234 SearchType2
= EFI_SECTION_PE32
;
236 SearchType1
= EFI_SECTION_PE32
;
237 SearchType2
= EFI_SECTION_TE
;
240 // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst
241 // is true, TE will be searched first).
243 Status
= PeiServicesFfsFindSectionData (
249 // If we didn't find a first exe section, try to find the second exe section.
251 if (EFI_ERROR (Status
)) {
252 Status
= PeiServicesFfsFindSectionData (
257 if (EFI_ERROR (Status
)) {
259 // PEI core only carry the loader function fro TE and PE32 executables
260 // If this two section does not exist, just return.
266 Private
= PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices
);
268 if (Private
->PeiMemoryInstalled
&&
269 (Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
)) {
271 // If memory is installed, perform the shadow operations
273 Status
= LoadAndRelocatePeCoffImage (
280 if (EFI_ERROR (Status
)) {
285 // Got the entry point from the loaded Pe32Data
287 Pe32Data
= (VOID
*) ((UINTN
) ImageAddress
);
288 *EntryPoint
= ImageEntryPoint
;
291 // Retrieve the entry point from the PE/COFF or TE image header
293 ImageAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Pe32Data
;
294 Status
= PeCoffLoaderGetEntryPoint (Pe32Data
, &EntryPointArg
);
295 if (EFI_ERROR (Status
)) {
298 *EntryPoint
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) EntryPointArg
;
301 Machine
= PeCoffLoaderGetMachineType (Pe32Data
);
303 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine
)) {
304 return EFI_UNSUPPORTED
;
307 if (ImageAddressArg
!= NULL
) {
308 *ImageAddressArg
= ImageAddress
;
311 if (ImageSizeArg
!= NULL
) {
312 *ImageSizeArg
= ImageSize
;
317 CHAR8 AsciiBuffer
[512];
322 // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi
324 if (Machine
!= IMAGE_FILE_MACHINE_IA64
) {
325 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID
*)(UINTN
)ImageAddress
, (VOID
*)(UINTN
)*EntryPoint
));
328 // For IPF Image, the real entry point should be print.
330 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID
*)(UINTN
)ImageAddress
, (VOID
*)(UINTN
)(*(UINT64
*)(UINTN
)*EntryPoint
)));
334 // Print Module Name by PeImage PDB file name.
336 AsciiString
= PeCoffLoaderGetPdbPointer (Pe32Data
);
338 if (AsciiString
!= NULL
) {
339 for (Index
= (INT32
) AsciiStrLen (AsciiString
) - 1; Index
>= 0; Index
--) {
340 if (AsciiString
[Index
] == '\\') {
346 for (Index1
= 0; AsciiString
[Index
+ 1 + Index1
] != '.'; Index1
++) {
347 AsciiBuffer
[Index1
] = AsciiString
[Index
+ 1 + Index1
];
349 AsciiBuffer
[Index1
] = '\0';
350 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "%a.efi", AsciiBuffer
));
356 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "\n"));
364 The wrapper function of PeiLoadImageLoadImage().
366 @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.
367 @param FileHandle - Pointer to the FFS file header of the image.
368 @param ImageAddressArg - Pointer to PE/TE image.
369 @param ImageSizeArg - Size of PE/TE image.
370 @param EntryPoint - Pointer to entry point of specified image file for output.
371 @param AuthenticationState - Pointer to attestation authentication state of image.
373 @return Status of PeiLoadImageLoadImage().
378 PeiLoadImageLoadImageWrapper (
379 IN CONST EFI_PEI_LOAD_FILE_PPI
*This
,
380 IN EFI_PEI_FILE_HANDLE FileHandle
,
381 OUT EFI_PHYSICAL_ADDRESS
*ImageAddressArg
, OPTIONAL
382 OUT UINT64
*ImageSizeArg
, OPTIONAL
383 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
,
384 OUT UINT32
*AuthenticationState
387 return PeiLoadImageLoadImage (
388 GetPeiServicesTablePointer (),
398 Routine to load image file for subsequent execution by LoadFile Ppi.
399 If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE
400 XIP image format is used.
402 @param PeiServices - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
403 @param FileHandle - Pointer to the FFS file header of the image.
404 @param EntryPoint - Pointer to entry point of specified image file for output.
405 @param AuthenticationState - Pointer to attestation authentication state of image.
407 @retval EFI_SUCCESS - Image is successfully loaded.
408 @retval EFI_NOT_FOUND - Fail to locate necessary PPI
409 @retval Others - Fail to load file.
414 IN EFI_PEI_SERVICES
**PeiServices
,
415 IN EFI_PEI_FILE_HANDLE FileHandle
,
416 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
,
417 OUT UINT32
*AuthenticationState
420 EFI_STATUS PpiStatus
;
423 EFI_PEI_LOAD_FILE_PPI
*LoadFile
;
424 EFI_PHYSICAL_ADDRESS ImageAddress
;
428 // If any instances of PEI_LOAD_FILE_PPI are installed, they are called.
429 // one at a time, until one reports EFI_SUCCESS.
433 PpiStatus
= PeiServicesLocatePpi (
434 &gEfiPeiLoadFilePpiGuid
,
439 if (!EFI_ERROR (PpiStatus
)) {
440 Status
= LoadFile
->LoadFile (
448 if (!EFI_ERROR (Status
)) {
453 } while (!EFI_ERROR (PpiStatus
));
456 // If no instances reports EFI_SUCCESS, then build-in support for
457 // the PE32+/TE XIP image format is used.
459 Status
= PeiLoadImageLoadImage (
473 Install Pei Load File PPI.
476 @param PrivateData - Pointer to PEI_CORE_INSTANCE.
477 @param OldCoreData - Pointer to PEI_CORE_INSTANCE.
481 InitializeImageServices (
482 IN PEI_CORE_INSTANCE
*PrivateData
,
483 IN PEI_CORE_INSTANCE
*OldCoreData
486 if (OldCoreData
== NULL
) {
488 // The first time we are XIP (running from FLASH). We need to remember the
489 // FLASH address so we can reinstall the memory version that runs faster
491 PrivateData
->XipLoadFile
= &gPpiLoadFilePpiList
;
492 PeiServicesInstallPpi (PrivateData
->XipLoadFile
);
495 // 2nd time we are running from memory so replace the XIP version with the
496 // new memory version.
498 PeiServicesReInstallPpi (PrivateData
->XipLoadFile
, &gPpiLoadFilePpiList
);