2 Pei Core Load Image Support
4 Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
11 EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi
= {
12 PeiLoadImageLoadImageWrapper
15 EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList
= {
16 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
17 &gEfiPeiLoadFilePpiGuid
,
23 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file.
24 The function is used for XIP code to have optimized memory copy.
26 @param FileHandle - The handle to the PE/COFF file
27 @param FileOffset - The offset, in bytes, into the file to read
28 @param ReadSize - The number of bytes to read from the file starting at FileOffset
29 @param Buffer - A pointer to the buffer to read the data into.
31 @return EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
46 Destination8
= Buffer
;
47 Source8
= (CHAR8
*)((UINTN
)FileHandle
+ FileOffset
);
48 if (Destination8
!= Source8
) {
49 CopyMem (Destination8
, Source8
, *ReadSize
);
56 To check memory usage bit map array to figure out if the memory range the image will be loaded in is available or not. If
57 memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.
58 The function is only invoked when load modules at fixed address feature is enabled.
60 @param Private Pointer to the private data passed in from caller
61 @param ImageBase The base address the image will be loaded at.
62 @param ImageSize The size of the image
64 @retval EFI_SUCCESS The memory range the image will be loaded in is available
65 @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available
68 CheckAndMarkFixLoadingMemoryUsageBitMap (
69 IN PEI_CORE_INSTANCE
*Private
,
70 IN EFI_PHYSICAL_ADDRESS ImageBase
,
74 UINT32 DxeCodePageNumber
;
75 UINT64 ReservedCodeSize
;
76 EFI_PHYSICAL_ADDRESS PeiCodeBase
;
77 UINT32 BaseOffsetPageNumber
;
78 UINT32 TopOffsetPageNumber
;
80 UINT64
*MemoryUsageBitMap
;
83 // The reserved code range includes RuntimeCodePage range, Boot time code range and PEI code range.
85 DxeCodePageNumber
= PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber
);
86 DxeCodePageNumber
+= PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber
);
87 ReservedCodeSize
= EFI_PAGES_TO_SIZE (DxeCodePageNumber
+ PcdGet32 (PcdLoadFixAddressPeiCodePageNumber
));
88 PeiCodeBase
= Private
->LoadModuleAtFixAddressTopAddress
- ReservedCodeSize
;
91 // Test the memory range for loading the image in the PEI code range.
93 if (((Private
->LoadModuleAtFixAddressTopAddress
- EFI_PAGES_TO_SIZE (DxeCodePageNumber
)) < (ImageBase
+ ImageSize
)) ||
94 (PeiCodeBase
> ImageBase
))
100 // Test if the memory is available or not.
102 MemoryUsageBitMap
= Private
->PeiCodeMemoryRangeUsageBitMap
;
103 BaseOffsetPageNumber
= EFI_SIZE_TO_PAGES ((UINT32
)(ImageBase
- PeiCodeBase
));
104 TopOffsetPageNumber
= EFI_SIZE_TO_PAGES ((UINT32
)(ImageBase
+ ImageSize
- PeiCodeBase
));
105 for (Index
= BaseOffsetPageNumber
; Index
< TopOffsetPageNumber
; Index
++) {
106 if ((MemoryUsageBitMap
[Index
/ 64] & LShiftU64 (1, (Index
% 64))) != 0) {
108 // This page is already used.
110 return EFI_NOT_FOUND
;
115 // Being here means the memory range is available. So mark the bits for the memory range
117 for (Index
= BaseOffsetPageNumber
; Index
< TopOffsetPageNumber
; Index
++) {
118 MemoryUsageBitMap
[Index
/ 64] |= LShiftU64 (1, (Index
% 64));
126 Get the fixed loading address from image header assigned by build tool. This function only be called
127 when Loading module at Fixed address feature enabled.
129 @param ImageContext Pointer to the image context structure that describes the PE/COFF
130 image that needs to be examined by this function.
131 @param Private Pointer to the private data passed in from caller
133 @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .
134 @retval EFI_NOT_FOUND The image has no assigned fixed loading address.
138 GetPeCoffImageFixLoadingAssignedAddress (
139 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
140 IN PEI_CORE_INSTANCE
*Private
143 UINTN SectionHeaderOffset
;
145 EFI_IMAGE_SECTION_HEADER SectionHeader
;
146 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
147 EFI_PHYSICAL_ADDRESS FixLoadingAddress
;
150 UINT16 NumberOfSections
;
151 UINT64 ValueInSectionHeader
;
153 FixLoadingAddress
= 0;
154 Status
= EFI_NOT_FOUND
;
157 // Get PeHeader pointer
159 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)((CHAR8
*)ImageContext
->Handle
+ ImageContext
->PeCoffHeaderOffset
);
160 if (ImageContext
->IsTeImage
) {
162 // for TE image, the fix loading address is saved in first section header that doesn't point
165 SectionHeaderOffset
= sizeof (EFI_TE_IMAGE_HEADER
);
166 NumberOfSections
= ImgHdr
->Te
.NumberOfSections
;
168 SectionHeaderOffset
= ImageContext
->PeCoffHeaderOffset
+
170 sizeof (EFI_IMAGE_FILE_HEADER
) +
171 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
;
172 NumberOfSections
= ImgHdr
->Pe32
.FileHeader
.NumberOfSections
;
176 // Get base address from the first section header that doesn't point to code section.
178 for (Index
= 0; Index
< NumberOfSections
; Index
++) {
180 // Read section header from file
182 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
183 Status
= ImageContext
->ImageRead (
184 ImageContext
->Handle
,
189 if (EFI_ERROR (Status
)) {
193 Status
= EFI_NOT_FOUND
;
195 if ((SectionHeader
.Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
197 // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
198 // that doesn't point to code section in image header, as well as ImageBase field of image header. A notable thing is
199 // that for PEIM, the value in ImageBase field may not be equal to the value in PointerToRelocations & PointerToLineNumbers because
200 // for XIP PEIM, ImageBase field holds the image base address running on the Flash. And PointerToRelocations & PointerToLineNumbers
201 // hold the image base address when it is shadow to the memory. And there is an assumption that when the feature is enabled, if a
202 // module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers fields should NOT be Zero, or
203 // else, these 2 fields should be set to Zero
205 ValueInSectionHeader
= ReadUnaligned64 ((UINT64
*)&SectionHeader
.PointerToRelocations
);
206 if (ValueInSectionHeader
!= 0) {
208 // Found first section header that doesn't point to code section.
210 if ((INT64
)PcdGet64 (PcdLoadModuleAtFixAddressEnable
) > 0) {
212 // When LMFA feature is configured as Load Module at Fixed Absolute Address mode, PointerToRelocations & PointerToLineNumbers field
213 // hold the absolute address of image base running in memory
215 FixLoadingAddress
= ValueInSectionHeader
;
218 // When LMFA feature is configured as Load Module at Fixed offset mode, PointerToRelocations & PointerToLineNumbers field
219 // hold the offset relative to a platform-specific top address.
221 FixLoadingAddress
= (EFI_PHYSICAL_ADDRESS
)(Private
->LoadModuleAtFixAddressTopAddress
+ (INT64
)ValueInSectionHeader
);
225 // Check if the memory range is available.
227 Status
= CheckAndMarkFixLoadingMemoryUsageBitMap (Private
, FixLoadingAddress
, (UINT32
)ImageContext
->ImageSize
);
228 if (!EFI_ERROR (Status
)) {
230 // The assigned address is valid. Return the specified loading address
232 ImageContext
->ImageAddress
= FixLoadingAddress
;
239 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
242 DEBUG ((DEBUG_INFO
|DEBUG_LOAD
, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status= %r \n", (VOID
*)(UINTN
)FixLoadingAddress
, Status
));
248 Loads and relocates a PE/COFF image into memory.
249 If the image is not relocatable, it will not be loaded into memory and be loaded as XIP image.
251 @param FileHandle - Pointer to the FFS file header of the image.
252 @param Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
253 @param ImageAddress - The base address of the relocated PE/COFF image
254 @param ImageSize - The size of the relocated PE/COFF image
255 @param EntryPoint - The entry point of the relocated PE/COFF image
257 @retval EFI_SUCCESS The file was loaded and relocated
258 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file
259 @retval EFI_WARN_BUFFER_TOO_SMALL
260 There is not enough heap to allocate the requested size.
261 This will not prevent the XIP image from being invoked.
265 LoadAndRelocatePeCoffImage (
266 IN EFI_PEI_FILE_HANDLE FileHandle
,
268 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
269 OUT UINT64
*ImageSize
,
270 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
274 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
275 PEI_CORE_INSTANCE
*Private
;
276 UINT64 AlignImageSize
;
278 EFI_STATUS ReturnStatus
;
281 BOOLEAN IsRegisterForShadow
;
282 EFI_FV_FILE_INFO FileInfo
;
284 Private
= PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
286 ReturnStatus
= EFI_SUCCESS
;
288 ZeroMem (&ImageContext
, sizeof (ImageContext
));
289 ImageContext
.Handle
= Pe32Data
;
290 ImageContext
.ImageRead
= PeiImageRead
;
292 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
293 if (EFI_ERROR (Status
)) {
298 // Initialize local IsS3Boot and IsRegisterForShadow variable
301 if (Private
->HobList
.HandoffInformationTable
->BootMode
== BOOT_ON_S3_RESUME
) {
305 IsRegisterForShadow
= FALSE
;
306 if ( (Private
->CurrentFileHandle
== FileHandle
)
307 && (Private
->Fv
[Private
->CurrentPeimFvCount
].PeimState
[Private
->CurrentPeimCount
] == PEIM_STATE_REGISTER_FOR_SHADOW
))
309 IsRegisterForShadow
= TRUE
;
313 // XIP image that ImageAddress is same to Image handle.
315 if (ImageContext
.ImageAddress
== (EFI_PHYSICAL_ADDRESS
)(UINTN
)Pe32Data
) {
320 // Get file type first
322 Status
= PeiServicesFfsGetFileInfo (FileHandle
, &FileInfo
);
323 ASSERT_EFI_ERROR (Status
);
326 // Check whether the file type is PEI module.
329 if ((FileInfo
.FileType
== EFI_FV_FILETYPE_PEI_CORE
) ||
330 (FileInfo
.FileType
== EFI_FV_FILETYPE_PEIM
) ||
331 (FileInfo
.FileType
== EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
))
337 // When Image has no reloc section, it can't be relocated into memory.
339 if (ImageContext
.RelocationsStripped
&& (Private
->PeiMemoryInstalled
) &&
340 ((!IsPeiModule
) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes
) ||
341 (!IsS3Boot
&& (PcdGetBool (PcdShadowPeimOnBoot
) || IsRegisterForShadow
)) ||
342 (IsS3Boot
&& PcdGetBool (PcdShadowPeimOnS3Boot
)))
345 DEBUG ((DEBUG_INFO
|DEBUG_LOAD
, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN
)Pe32Data
));
349 // Set default base address to current image address.
351 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Pe32Data
;
354 // Allocate Memory for the image when memory is ready, and image is relocatable.
355 // On normal boot, PcdShadowPeimOnBoot decides whether load PEIM or PeiCore into memory.
356 // On S3 boot, PcdShadowPeimOnS3Boot decides whether load PEIM or PeiCore into memory.
358 if ((!ImageContext
.RelocationsStripped
) && (Private
->PeiMemoryInstalled
) &&
359 ((!IsPeiModule
) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes
) ||
360 (!IsS3Boot
&& (PcdGetBool (PcdShadowPeimOnBoot
) || IsRegisterForShadow
)) ||
361 (IsS3Boot
&& PcdGetBool (PcdShadowPeimOnS3Boot
)))
365 // Allocate more buffer to avoid buffer overflow.
367 if (ImageContext
.IsTeImage
) {
368 AlignImageSize
= ImageContext
.ImageSize
+ ((EFI_TE_IMAGE_HEADER
*)Pe32Data
)->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
);
370 AlignImageSize
= ImageContext
.ImageSize
;
373 if (ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
374 AlignImageSize
+= ImageContext
.SectionAlignment
;
377 if ((PcdGet64 (PcdLoadModuleAtFixAddressEnable
) != 0) && (Private
->HobList
.HandoffInformationTable
->BootMode
!= BOOT_ON_S3_RESUME
)) {
378 Status
= GetPeCoffImageFixLoadingAssignedAddress (&ImageContext
, Private
);
379 if (EFI_ERROR (Status
)) {
380 DEBUG ((DEBUG_INFO
|DEBUG_LOAD
, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));
382 // The PEIM is not assigned valid address, try to allocate page to load it.
384 Status
= PeiServicesAllocatePages (
386 EFI_SIZE_TO_PAGES ((UINT32
)AlignImageSize
),
387 &ImageContext
.ImageAddress
391 Status
= PeiServicesAllocatePages (
393 EFI_SIZE_TO_PAGES ((UINT32
)AlignImageSize
),
394 &ImageContext
.ImageAddress
398 if (!EFI_ERROR (Status
)) {
400 // Adjust the Image Address to make sure it is section alignment.
402 if (ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
403 ImageContext
.ImageAddress
=
404 (ImageContext
.ImageAddress
+ ImageContext
.SectionAlignment
- 1) &
405 ~((UINTN
)ImageContext
.SectionAlignment
- 1);
409 // Fix alignment requirement when Load IPF TeImage into memory.
410 // Skip the reserved space for the stripped PeHeader when load TeImage into memory.
412 if (ImageContext
.IsTeImage
) {
413 ImageContext
.ImageAddress
= ImageContext
.ImageAddress
+
414 ((EFI_TE_IMAGE_HEADER
*)Pe32Data
)->StrippedSize
-
415 sizeof (EFI_TE_IMAGE_HEADER
);
419 // No enough memory resource.
423 // XIP image can still be invoked.
425 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Pe32Data
;
426 ReturnStatus
= EFI_WARN_BUFFER_TOO_SMALL
;
429 // Non XIP image can't be loaded because no enough memory is allocated.
432 return EFI_OUT_OF_RESOURCES
;
438 // Load the image to our new buffer
440 Status
= PeCoffLoaderLoadImage (&ImageContext
);
441 if (EFI_ERROR (Status
)) {
442 if (ImageContext
.ImageError
== IMAGE_ERROR_INVALID_SECTION_ALIGNMENT
) {
443 DEBUG ((DEBUG_ERROR
, "PEIM Image Address 0x%11p doesn't meet with section alignment 0x%x.\n", (VOID
*)(UINTN
)ImageContext
.ImageAddress
, ImageContext
.SectionAlignment
));
450 // Relocate the image in our new buffer
452 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
453 if (EFI_ERROR (Status
)) {
458 // Flush the instruction cache so the image data is written before we execute it
460 if (ImageContext
.ImageAddress
!= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Pe32Data
) {
461 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
464 *ImageAddress
= ImageContext
.ImageAddress
;
465 *ImageSize
= ImageContext
.ImageSize
;
466 *EntryPoint
= ImageContext
.EntryPoint
;
472 Loads and relocates a PE/COFF image in place.
474 @param Pe32Data The base address of the PE/COFF file that is to be loaded and relocated
475 @param ImageAddress The base address of the relocated PE/COFF image
477 @retval EFI_SUCCESS The file was loaded and relocated.
478 @retval Others The file not be loaded and error occurred.
482 LoadAndRelocatePeCoffImageInPlace (
484 IN VOID
*ImageAddress
488 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
490 ZeroMem (&ImageContext
, sizeof (ImageContext
));
491 ImageContext
.Handle
= Pe32Data
;
492 ImageContext
.ImageRead
= PeiImageRead
;
494 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
495 if (EFI_ERROR (Status
)) {
496 ASSERT_EFI_ERROR (Status
);
500 ImageContext
.ImageAddress
= (PHYSICAL_ADDRESS
)(UINTN
)ImageAddress
;
503 // Load the image in place
505 Status
= PeCoffLoaderLoadImage (&ImageContext
);
506 if (EFI_ERROR (Status
)) {
507 ASSERT_EFI_ERROR (Status
);
512 // Relocate the image in place
514 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
515 if (EFI_ERROR (Status
)) {
516 ASSERT_EFI_ERROR (Status
);
521 // Flush the instruction cache so the image data is written before we execute it
523 if (ImageContext
.ImageAddress
!= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Pe32Data
) {
524 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
531 Find the PE32 Data for an FFS file.
533 @param FileHandle Pointer to the FFS file header of the image.
534 @param Pe32Data Pointer to a (VOID *) PE32 Data pointer.
536 @retval EFI_SUCCESS Image is successfully loaded.
537 @retval EFI_NOT_FOUND Fail to locate PE32 Data.
542 IN EFI_PEI_FILE_HANDLE FileHandle
,
547 EFI_SECTION_TYPE SearchType1
;
548 EFI_SECTION_TYPE SearchType2
;
549 UINT32 AuthenticationState
;
553 if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst
)) {
554 SearchType1
= EFI_SECTION_TE
;
555 SearchType2
= EFI_SECTION_PE32
;
557 SearchType1
= EFI_SECTION_PE32
;
558 SearchType2
= EFI_SECTION_TE
;
562 // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst
563 // is true, TE will be searched first).
565 Status
= PeiServicesFfsFindSectionData3 (
573 // If we didn't find a first exe section, try to find the second exe section.
575 if (EFI_ERROR (Status
)) {
576 Status
= PeiServicesFfsFindSectionData3 (
589 Loads a PEIM into memory for subsequent execution. If there are compressed
590 images or images that need to be relocated into memory for performance reasons,
591 this service performs that transformation.
593 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
594 @param FileHandle Pointer to the FFS file header of the image.
595 @param ImageAddressArg Pointer to PE/TE image.
596 @param ImageSizeArg Size of PE/TE image.
597 @param EntryPoint Pointer to entry point of specified image file for output.
598 @param AuthenticationState - Pointer to attestation authentication state of image.
600 @retval EFI_SUCCESS Image is successfully loaded.
601 @retval EFI_NOT_FOUND Fail to locate necessary PPI.
602 @retval EFI_UNSUPPORTED Image Machine Type is not supported.
603 @retval EFI_WARN_BUFFER_TOO_SMALL
604 There is not enough heap to allocate the requested size.
605 This will not prevent the XIP image from being invoked.
609 PeiLoadImageLoadImage (
610 IN CONST EFI_PEI_SERVICES
**PeiServices
,
611 IN EFI_PEI_FILE_HANDLE FileHandle
,
612 OUT EFI_PHYSICAL_ADDRESS
*ImageAddressArg OPTIONAL
,
613 OUT UINT64
*ImageSizeArg OPTIONAL
,
614 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
,
615 OUT UINT32
*AuthenticationState
620 EFI_PHYSICAL_ADDRESS ImageAddress
;
622 EFI_PHYSICAL_ADDRESS ImageEntryPoint
;
624 EFI_SECTION_TYPE SearchType1
;
625 EFI_SECTION_TYPE SearchType2
;
629 *AuthenticationState
= 0;
631 if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst
)) {
632 SearchType1
= EFI_SECTION_TE
;
633 SearchType2
= EFI_SECTION_PE32
;
635 SearchType1
= EFI_SECTION_PE32
;
636 SearchType2
= EFI_SECTION_TE
;
640 // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst
641 // is true, TE will be searched first).
643 Status
= PeiServicesFfsFindSectionData3 (
651 // If we didn't find a first exe section, try to find the second exe section.
653 if (EFI_ERROR (Status
)) {
654 Status
= PeiServicesFfsFindSectionData3 (
661 if (EFI_ERROR (Status
)) {
663 // PEI core only carry the loader function for TE and PE32 executables
664 // If this two section does not exist, just return.
670 DEBUG ((DEBUG_INFO
, "Loading PEIM %g\n", FileHandle
));
673 // If memory is installed, perform the shadow operations
675 Status
= LoadAndRelocatePeCoffImage (
683 if (EFI_ERROR (Status
)) {
688 // Got the entry point from the loaded Pe32Data
690 Pe32Data
= (VOID
*)((UINTN
)ImageAddress
);
691 *EntryPoint
= ImageEntryPoint
;
693 Machine
= PeCoffLoaderGetMachineType (Pe32Data
);
695 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine
)) {
696 if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Machine
)) {
697 return EFI_UNSUPPORTED
;
701 if (ImageAddressArg
!= NULL
) {
702 *ImageAddressArg
= ImageAddress
;
705 if (ImageSizeArg
!= NULL
) {
706 *ImageSizeArg
= ImageSize
;
711 CHAR8 EfiFileName
[512];
716 // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi
718 if (Machine
!= EFI_IMAGE_MACHINE_IA64
) {
719 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID
*)(UINTN
)ImageAddress
, (VOID
*)(UINTN
)*EntryPoint
));
722 // For IPF Image, the real entry point should be print.
724 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID
*)(UINTN
)ImageAddress
, (VOID
*)(UINTN
)(*(UINT64
*)(UINTN
)*EntryPoint
)));
728 // Print Module Name by PeImage PDB file name.
730 AsciiString
= PeCoffLoaderGetPdbPointer (Pe32Data
);
732 if (AsciiString
!= NULL
) {
734 for (Index
= 0; AsciiString
[Index
] != 0; Index
++) {
735 if ((AsciiString
[Index
] == '\\') || (AsciiString
[Index
] == '/')) {
736 StartIndex
= Index
+ 1;
741 // Copy the PDB file name to our temporary string, and replace .pdb with .efi
742 // The PDB file name is limited in the range of 0~511.
743 // If the length is bigger than 511, trim the redundant characters to avoid overflow in array boundary.
745 for (Index
= 0; Index
< sizeof (EfiFileName
) - 4; Index
++) {
746 EfiFileName
[Index
] = AsciiString
[Index
+ StartIndex
];
747 if (EfiFileName
[Index
] == 0) {
748 EfiFileName
[Index
] = '.';
751 if (EfiFileName
[Index
] == '.') {
752 EfiFileName
[Index
+ 1] = 'e';
753 EfiFileName
[Index
+ 2] = 'f';
754 EfiFileName
[Index
+ 3] = 'i';
755 EfiFileName
[Index
+ 4] = 0;
760 if (Index
== sizeof (EfiFileName
) - 4) {
761 EfiFileName
[Index
] = 0;
764 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "%a", EfiFileName
));
769 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "\n"));
775 The wrapper function of PeiLoadImageLoadImage().
777 @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.
778 @param FileHandle - Pointer to the FFS file header of the image.
779 @param ImageAddressArg - Pointer to PE/TE image.
780 @param ImageSizeArg - Size of PE/TE image.
781 @param EntryPoint - Pointer to entry point of specified image file for output.
782 @param AuthenticationState - Pointer to attestation authentication state of image.
784 @return Status of PeiLoadImageLoadImage().
789 PeiLoadImageLoadImageWrapper (
790 IN CONST EFI_PEI_LOAD_FILE_PPI
*This
,
791 IN EFI_PEI_FILE_HANDLE FileHandle
,
792 OUT EFI_PHYSICAL_ADDRESS
*ImageAddressArg OPTIONAL
,
793 OUT UINT64
*ImageSizeArg OPTIONAL
,
794 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
,
795 OUT UINT32
*AuthenticationState
798 return PeiLoadImageLoadImage (
799 GetPeiServicesTablePointer (),
809 Check whether the input image has the relocation.
811 @param Pe32Data Pointer to the PE/COFF or TE image.
813 @retval TRUE Relocation is stripped.
814 @retval FALSE Relocation is not stripped.
822 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
823 EFI_IMAGE_DOS_HEADER
*DosHdr
;
825 ASSERT (Pe32Data
!= NULL
);
827 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Pe32Data
;
828 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
830 // DOS image header is present, so read the PE header after the DOS image header.
832 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
)Pe32Data
+ (UINTN
)((DosHdr
->e_lfanew
) & 0x0ffff));
835 // DOS image header is not present, so PE header is at the image base.
837 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
841 // Three cases with regards to relocations:
842 // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable
843 // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable
844 // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but
845 // has no base relocs to apply
846 // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.
848 // Look at the file header to determine if relocations have been stripped, and
849 // save this info in the image context for later use.
851 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
852 if ((Hdr
.Te
->DataDirectory
[0].Size
== 0) && (Hdr
.Te
->DataDirectory
[0].VirtualAddress
== 0)) {
857 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
858 if ((Hdr
.Pe32
->FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) != 0) {
869 Routine to load image file for subsequent execution by LoadFile Ppi.
870 If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE
871 XIP image format is used.
873 @param PeiServices - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
874 @param FileHandle - Pointer to the FFS file header of the image.
875 @param PeimState - The dispatch state of the input PEIM handle.
876 @param EntryPoint - Pointer to entry point of specified image file for output.
877 @param AuthenticationState - Pointer to attestation authentication state of image.
879 @retval EFI_SUCCESS - Image is successfully loaded.
880 @retval EFI_NOT_FOUND - Fail to locate necessary PPI
881 @retval Others - Fail to load file.
886 IN CONST EFI_PEI_SERVICES
**PeiServices
,
887 IN EFI_PEI_FILE_HANDLE FileHandle
,
889 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
,
890 OUT UINT32
*AuthenticationState
893 EFI_STATUS PpiStatus
;
896 EFI_PEI_LOAD_FILE_PPI
*LoadFile
;
897 EFI_PHYSICAL_ADDRESS ImageAddress
;
903 // If any instances of PEI_LOAD_FILE_PPI are installed, they are called.
904 // one at a time, until one reports EFI_SUCCESS.
908 PpiStatus
= PeiServicesLocatePpi (
909 &gEfiPeiLoadFilePpiGuid
,
914 if (!EFI_ERROR (PpiStatus
)) {
915 Status
= LoadFile
->LoadFile (
923 if (!EFI_ERROR (Status
) || (Status
== EFI_WARN_BUFFER_TOO_SMALL
)) {
925 // The shadowed PEIM must be relocatable.
927 if (PeimState
== PEIM_STATE_REGISTER_FOR_SHADOW
) {
928 IsStrip
= RelocationIsStrip ((VOID
*)(UINTN
)ImageAddress
);
931 return EFI_UNSUPPORTED
;
936 // The image to be started must have the machine type supported by PeiCore.
938 ASSERT (EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCoffLoaderGetMachineType ((VOID
*)(UINTN
)ImageAddress
)));
939 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCoffLoaderGetMachineType ((VOID
*)(UINTN
)ImageAddress
))) {
940 return EFI_UNSUPPORTED
;
948 } while (!EFI_ERROR (PpiStatus
));
955 Install Pei Load File PPI.
958 @param PrivateData - Pointer to PEI_CORE_INSTANCE.
959 @param OldCoreData - Pointer to PEI_CORE_INSTANCE.
963 InitializeImageServices (
964 IN PEI_CORE_INSTANCE
*PrivateData
,
965 IN PEI_CORE_INSTANCE
*OldCoreData
968 if (OldCoreData
== NULL
) {
970 // The first time we are XIP (running from FLASH). We need to remember the
971 // FLASH address so we can reinstall the memory version that runs faster
973 PrivateData
->XipLoadFile
= &gPpiLoadFilePpiList
;
974 PeiServicesInstallPpi (PrivateData
->XipLoadFile
);
977 // 2nd time we are running from memory so replace the XIP version with the
978 // new memory version.
980 PeiServicesReInstallPpi (PrivateData
->XipLoadFile
, &gPpiLoadFilePpiList
);