3 Library to rebase PE image.
5 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
19 #include <PeCoffLib.h>
20 #include <CommonLib.h>
21 #include <IndustryStandard/PeImage.h>
23 #include "EfiUtilityMsgs.h"
30 IN OUT UINT32
*ReadSize
,
36 IN OUT UINT64 BaseAddress
,
38 IN OUT EFI_FFS_FILE_HEADER
*FfsFile
,
45 This function determines if a file is XIP and should be rebased. It will
46 rebase any PE32 sections found in the file using the base address.
50 FvInfo A pointer to FV_INFO struture.
51 FileName Ffs File PathName
52 FfsFile A pointer to Ffs file image.
53 XipOffset The offset address to use for rebasing the XIP file image.
57 EFI_SUCCESS The image was properly rebased.
58 EFI_INVALID_PARAMETER An input parameter is invalid.
59 EFI_ABORTED An error occurred while rebasing the input file image.
60 EFI_OUT_OF_RESOURCES Could not allocate a required resource.
61 EFI_NOT_FOUND No compressed sections could be found.
66 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
67 PE_COFF_LOADER_IMAGE_CONTEXT OrigImageContext
;
68 EFI_PHYSICAL_ADDRESS XipBase
;
69 EFI_PHYSICAL_ADDRESS NewPe32BaseAddress
;
71 EFI_FILE_SECTION_POINTER CurrentPe32Section
;
72 EFI_FFS_FILE_STATE SavedState
;
73 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
74 EFI_TE_IMAGE_HEADER
*TEImageHeader
;
75 UINT8
*MemoryImagePointer
;
76 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
77 CHAR8 PeFileName
[MAX_LONG_FILE_PATH
];
85 CHAR8
*LongFilePathName
;
88 MemoryImagePointer
= NULL
;
97 // Don't need to relocate image when BaseAddress is zero and no ForceRebase Flag specified.
99 if (BaseAddress
== 0) {
103 XipBase
= BaseAddress
+ XipOffset
;
106 // We only process files potentially containing PE32 sections.
108 switch (FfsFile
->Type
) {
109 case EFI_FV_FILETYPE_SECURITY_CORE
:
110 case EFI_FV_FILETYPE_PEI_CORE
:
111 case EFI_FV_FILETYPE_PEIM
:
112 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
113 case EFI_FV_FILETYPE_DRIVER
:
114 case EFI_FV_FILETYPE_DXE_CORE
:
116 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
118 // Rebase the inside FvImage.
120 GetChildFvFromFfs (BaseAddress
, FfsFile
, XipOffset
);
123 // Search PE/TE section in FV sectin.
130 FfsHeaderSize
= GetFfsHeaderLength(FfsFile
);
132 // Rebase each PE32 section
134 Status
= EFI_SUCCESS
;
135 for (Index
= 1;; Index
++) {
139 NewPe32BaseAddress
= 0;
144 Status
= GetSectionByType(FfsFile
, EFI_SECTION_PE32
, Index
, &CurrentPe32Section
);
145 if (EFI_ERROR(Status
)) {
148 CurSecHdrSize
= GetSectionHeaderLength(CurrentPe32Section
.CommonHeader
);
151 // Initialize context
153 memset(&ImageContext
, 0, sizeof (ImageContext
));
154 ImageContext
.Handle
= (VOID
*)((UINTN
)CurrentPe32Section
.Pe32Section
+ CurSecHdrSize
);
155 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)FfsRebaseImageRead
;
156 Status
= PeCoffLoaderGetImageInfo(&ImageContext
);
157 if (EFI_ERROR(Status
)) {
158 Error(NULL
, 0, 3000, "Invalid PeImage", "The input file is %s and the return status is %x", FileName
, (int)Status
);
162 //if ((ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) ||
163 // (ImageContext.Machine == EFI_IMAGE_MACHINE_AARCH64)) {
168 // Keep Image Context for PE image in FV
170 memcpy(&OrigImageContext
, &ImageContext
, sizeof (ImageContext
));
173 // Get File PdbPointer
175 PdbPointer
= PeCoffLoaderGetPdbPointer(ImageContext
.Handle
);
176 if (PdbPointer
== NULL
) {
177 PdbPointer
= FileName
;
181 // Get PeHeader pointer
183 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)((UINTN
)CurrentPe32Section
.Pe32Section
+ CurSecHdrSize
+ ImageContext
.PeCoffHeaderOffset
);
186 // Calculate the PE32 base address, based on file type
188 switch (FfsFile
->Type
) {
189 case EFI_FV_FILETYPE_SECURITY_CORE
:
190 case EFI_FV_FILETYPE_PEI_CORE
:
191 case EFI_FV_FILETYPE_PEIM
:
192 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
194 // Check if section-alignment and file-alignment match or not
196 if ((ImgHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= ImgHdr
->Pe32
.OptionalHeader
.FileAlignment
)) {
198 // Xip module has the same section alignment and file alignment.
200 Error(NULL
, 0, 3000, "Invalid", "Section-Alignment and File-Alignment do not match : %s.", FileName
);
204 // PeImage has no reloc section. It will try to get reloc data from the original EFI image.
206 if (ImageContext
.RelocationsStripped
) {
208 // Construct the original efi file Name
210 if (strlen (FileName
) > MAX_LONG_FILE_PATH
- 1) {
211 Error(NULL
, 0, 3000, "Invalid", "The file name for %s is too long.", FileName
);
214 strncpy(PeFileName
, FileName
, MAX_LONG_FILE_PATH
- 1);
215 PeFileName
[MAX_LONG_FILE_PATH
- 1] = 0;
216 Cptr
= PeFileName
+ strlen(PeFileName
);
217 while (*Cptr
!= '.') {
221 Error(NULL
, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName
);
230 LongFilePathName
= LongFilePath(PeFileName
);
231 if (LongFilePathName
== NULL
) {
232 Error(NULL
, 0, 3000, "Invalid", "Fail to get long file path for file %s.", FileName
);
235 PeFile
= fopen(LongFilePathName
, "rb");
236 if (PeFile
== NULL
) {
237 Warning(NULL
, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName
);
238 //Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);
239 //return EFI_ABORTED;
245 PeFileSize
= _filelength(fileno(PeFile
));
246 PeFileBuffer
= (UINT8
*)malloc(PeFileSize
);
247 if (PeFileBuffer
== NULL
) {
248 Error(NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
250 return EFI_OUT_OF_RESOURCES
;
255 fread(PeFileBuffer
, sizeof (UINT8
), PeFileSize
, PeFile
);
261 // Handle pointer to the original efi image.
263 ImageContext
.Handle
= PeFileBuffer
;
264 Status
= PeCoffLoaderGetImageInfo(&ImageContext
);
265 if (EFI_ERROR(Status
)) {
266 Error(NULL
, 0, 3000, "Invalid PeImage", "The input file is %s and the return status is %x", FileName
, (int)Status
);
269 ImageContext
.RelocationsStripped
= FALSE
;
272 NewPe32BaseAddress
= XipBase
+ (UINTN
)CurrentPe32Section
.Pe32Section
+ CurSecHdrSize
- (UINTN
)FfsFile
;
275 case EFI_FV_FILETYPE_DRIVER
:
276 case EFI_FV_FILETYPE_DXE_CORE
:
278 // Check if section-alignment and file-alignment match or not
280 if ((ImgHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= ImgHdr
->Pe32
.OptionalHeader
.FileAlignment
)) {
282 // Xip module has the same section alignment and file alignment.
284 Error(NULL
, 0, 3000, "Invalid", "Section-Alignment and File-Alignment do not match : %s.", FileName
);
287 NewPe32BaseAddress
= XipBase
+ (UINTN
)CurrentPe32Section
.Pe32Section
+ CurSecHdrSize
- (UINTN
)FfsFile
;
292 // Not supported file type
298 // Relocation doesn't exist
300 if (ImageContext
.RelocationsStripped
) {
301 Warning(NULL
, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName
);
306 // Relocation exist and rebase
309 // Load and Relocate Image Data
311 MemoryImagePointer
= (UINT8
*)malloc((UINTN
)ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
312 if (MemoryImagePointer
== NULL
) {
313 Error(NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
314 return EFI_OUT_OF_RESOURCES
;
316 memset((VOID
*)MemoryImagePointer
, 0, (UINTN
)ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
317 ImageContext
.ImageAddress
= ((UINTN
)MemoryImagePointer
+ ImageContext
.SectionAlignment
- 1) & (~((UINTN
)ImageContext
.SectionAlignment
- 1));
319 Status
= PeCoffLoaderLoadImage(&ImageContext
);
320 if (EFI_ERROR(Status
)) {
321 Error(NULL
, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName
);
322 free((VOID
*)MemoryImagePointer
);
326 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
327 Status
= PeCoffLoaderRelocateImage(&ImageContext
);
328 if (EFI_ERROR(Status
)) {
329 Error(NULL
, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName
);
330 free((VOID
*)MemoryImagePointer
);
335 // Copy Relocated data to raw image file.
337 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*)(
340 sizeof (EFI_IMAGE_FILE_HEADER
)+
341 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
344 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
346 (UINT8
*)CurrentPe32Section
.Pe32Section
+ CurSecHdrSize
+ SectionHeader
->PointerToRawData
,
347 (VOID
*)(UINTN
)(ImageContext
.ImageAddress
+ SectionHeader
->VirtualAddress
),
348 SectionHeader
->SizeOfRawData
352 free((VOID
*)MemoryImagePointer
);
353 MemoryImagePointer
= NULL
;
354 if (PeFileBuffer
!= NULL
) {
360 // Update Image Base Address
362 if (ImgHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
363 ImgHdr
->Pe32
.OptionalHeader
.ImageBase
= (UINT32
)NewPe32BaseAddress
;
365 else if (ImgHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
366 ImgHdr
->Pe32Plus
.OptionalHeader
.ImageBase
= NewPe32BaseAddress
;
369 Error(NULL
, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
370 ImgHdr
->Pe32
.OptionalHeader
.Magic
,
377 // Now update file checksum
379 if (FfsFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
380 SavedState
= FfsFile
->State
;
381 FfsFile
->IntegrityCheck
.Checksum
.File
= 0;
383 FfsFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8(
384 (UINT8
*)((UINT8
*)FfsFile
+ FfsHeaderSize
),
385 GetFfsFileLength(FfsFile
) - FfsHeaderSize
387 FfsFile
->State
= SavedState
;
392 if (FfsFile
->Type
!= EFI_FV_FILETYPE_SECURITY_CORE
&&
393 FfsFile
->Type
!= EFI_FV_FILETYPE_PEI_CORE
&&
394 FfsFile
->Type
!= EFI_FV_FILETYPE_PEIM
&&
395 FfsFile
->Type
!= EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
&&
396 FfsFile
->Type
!= EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
399 // Only Peim code may have a TE section
405 // Now process TE sections
407 for (Index
= 1;; Index
++) {
408 NewPe32BaseAddress
= 0;
413 Status
= GetSectionByType(FfsFile
, EFI_SECTION_TE
, Index
, &CurrentPe32Section
);
414 if (EFI_ERROR(Status
)) {
418 CurSecHdrSize
= GetSectionHeaderLength(CurrentPe32Section
.CommonHeader
);
421 // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off
424 TEImageHeader
= (EFI_TE_IMAGE_HEADER
*)((UINT8
*)CurrentPe32Section
.Pe32Section
+ CurSecHdrSize
);
427 // Initialize context, load image info.
429 memset(&ImageContext
, 0, sizeof (ImageContext
));
430 ImageContext
.Handle
= (VOID
*)TEImageHeader
;
431 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)FfsRebaseImageRead
;
432 Status
= PeCoffLoaderGetImageInfo(&ImageContext
);
433 if (EFI_ERROR(Status
)) {
434 Error(NULL
, 0, 3000, "Invalid TeImage", "The input file is %s and the return status is %x", FileName
, (int)Status
);
438 //if ((ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) ||
439 // (ImageContext.Machine == EFI_IMAGE_MACHINE_AARCH64)) {
444 // Keep Image Context for TE image in FV
446 memcpy(&OrigImageContext
, &ImageContext
, sizeof (ImageContext
));
449 // Get File PdbPointer
451 PdbPointer
= PeCoffLoaderGetPdbPointer(ImageContext
.Handle
);
452 if (PdbPointer
== NULL
) {
453 PdbPointer
= FileName
;
456 // Set new rebased address.
458 NewPe32BaseAddress
= XipBase
+ (UINTN
)TEImageHeader
+ sizeof (EFI_TE_IMAGE_HEADER
) \
459 - TEImageHeader
->StrippedSize
- (UINTN
)FfsFile
;
462 // if reloc is stripped, try to get the original efi image to get reloc info.
464 if (ImageContext
.RelocationsStripped
) {
466 // Construct the original efi file name
468 if (strlen (FileName
) > MAX_LONG_FILE_PATH
- 1) {
469 Error(NULL
, 0, 3000, "Invalid", "The file name for %s is too long.", FileName
);
472 strncpy(PeFileName
, FileName
, MAX_LONG_FILE_PATH
- 1);
473 PeFileName
[MAX_LONG_FILE_PATH
- 1] = 0;
474 Cptr
= PeFileName
+ strlen(PeFileName
);
475 while (*Cptr
!= '.') {
480 Error(NULL
, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName
);
490 LongFilePathName
= LongFilePath(PeFileName
);
491 if (LongFilePathName
== NULL
) {
492 Error(NULL
, 0, 3000, "Invalid", "Fail to get long file path for file %s.", FileName
);
495 PeFile
= fopen(LongFilePathName
, "rb");
496 if (PeFile
== NULL
) {
497 Warning(NULL
, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName
);
498 //Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);
499 //return EFI_ABORTED;
505 PeFileSize
= _filelength(fileno(PeFile
));
506 PeFileBuffer
= (UINT8
*)malloc(PeFileSize
);
507 if (PeFileBuffer
== NULL
) {
508 Error(NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
510 return EFI_OUT_OF_RESOURCES
;
515 fread(PeFileBuffer
, sizeof (UINT8
), PeFileSize
, PeFile
);
521 // Append reloc section into TeImage
523 ImageContext
.Handle
= PeFileBuffer
;
524 Status
= PeCoffLoaderGetImageInfo(&ImageContext
);
525 if (EFI_ERROR(Status
)) {
526 Error(NULL
, 0, 3000, "Invalid TeImage", "The input file is %s and the return status is %x", FileName
, (int)Status
);
529 ImageContext
.RelocationsStripped
= FALSE
;
533 // Relocation doesn't exist
535 if (ImageContext
.RelocationsStripped
) {
536 Warning(NULL
, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName
);
541 // Relocation exist and rebase
544 // Load and Relocate Image Data
546 MemoryImagePointer
= (UINT8
*)malloc((UINTN
)ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
547 if (MemoryImagePointer
== NULL
) {
548 Error(NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
549 return EFI_OUT_OF_RESOURCES
;
551 memset((VOID
*)MemoryImagePointer
, 0, (UINTN
)ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
552 ImageContext
.ImageAddress
= ((UINTN
)MemoryImagePointer
+ ImageContext
.SectionAlignment
- 1) & (~((UINTN
)ImageContext
.SectionAlignment
- 1));
554 Status
= PeCoffLoaderLoadImage(&ImageContext
);
555 if (EFI_ERROR(Status
)) {
556 Error(NULL
, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName
);
557 free((VOID
*)MemoryImagePointer
);
563 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
564 Status
= PeCoffLoaderRelocateImage(&ImageContext
);
565 if (EFI_ERROR(Status
)) {
566 Error(NULL
, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of TE image %s", FileName
);
567 free((VOID
*)MemoryImagePointer
);
572 // Copy the relocated image into raw image file.
574 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*)(TEImageHeader
+ 1);
575 for (Index
= 0; Index
< TEImageHeader
->NumberOfSections
; Index
++, SectionHeader
++) {
576 if (!ImageContext
.IsTeImage
) {
578 (UINT8
*)TEImageHeader
+ sizeof (EFI_TE_IMAGE_HEADER
)-TEImageHeader
->StrippedSize
+ SectionHeader
->PointerToRawData
,
579 (VOID
*)(UINTN
)(ImageContext
.ImageAddress
+ SectionHeader
->VirtualAddress
),
580 SectionHeader
->SizeOfRawData
585 (UINT8
*)TEImageHeader
+ sizeof (EFI_TE_IMAGE_HEADER
)-TEImageHeader
->StrippedSize
+ SectionHeader
->PointerToRawData
,
586 (VOID
*)(UINTN
)(ImageContext
.ImageAddress
+ sizeof (EFI_TE_IMAGE_HEADER
)-TEImageHeader
->StrippedSize
+ SectionHeader
->VirtualAddress
),
587 SectionHeader
->SizeOfRawData
593 // Free the allocated memory resource
595 free((VOID
*)MemoryImagePointer
);
596 MemoryImagePointer
= NULL
;
597 if (PeFileBuffer
!= NULL
) {
603 // Update Image Base Address
605 TEImageHeader
->ImageBase
= NewPe32BaseAddress
;
608 // Now update file checksum
610 if (FfsFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
611 SavedState
= FfsFile
->State
;
612 FfsFile
->IntegrityCheck
.Checksum
.File
= 0;
614 FfsFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8(
615 (UINT8
*)((UINT8
*)FfsFile
+ FfsHeaderSize
),
616 GetFfsFileLength(FfsFile
) - FfsHeaderSize
618 FfsFile
->State
= SavedState
;
629 IN OUT UINT32
*ReadSize
,
636 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
640 FileHandle - The handle to the PE/COFF file
642 FileOffset - The offset, in bytes, into the file to read
644 ReadSize - The number of bytes to read from the file starting at FileOffset
646 Buffer - A pointer to the buffer to read the data into.
650 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
658 Destination8
= Buffer
;
659 Source8
= (CHAR8
*)((UINTN
)FileHandle
+ FileOffset
);
662 *(Destination8
++) = *(Source8
++);
670 IN UINT64 BaseAddress
,
671 IN EFI_FFS_FILE_HEADER
*FfsFile
,
678 This function gets all child FvImages in the input FfsFile, and records
679 their base address to the parent image.
682 FvInfo A pointer to FV_INFO struture.
683 FfsFile A pointer to Ffs file image that may contain FvImage.
684 XipOffset The offset address to the parent FvImage base.
688 EFI_SUCCESS Base address of child Fv image is recorded.
693 EFI_FILE_SECTION_POINTER SubFvSection
;
694 EFI_FIRMWARE_VOLUME_HEADER
*SubFvImageHeader
;
695 EFI_PHYSICAL_ADDRESS SubFvBaseAddress
;
696 EFI_FIRMWARE_VOLUME_HEADER
*OrigFvHeader
;
698 EFI_PHYSICAL_ADDRESS OrigFvBaseAddress
;
699 EFI_FFS_FILE_HEADER
*CurrentFile
;
702 // Initialize FV library, saving previous values
705 GetFvHeader (&OrigFvHeader
, &OrigFvLength
);
706 OrigFvBaseAddress
= BaseAddress
;
707 for (Index
= 1;; Index
++) {
711 Status
= GetSectionByType (FfsFile
, EFI_SECTION_FIRMWARE_VOLUME_IMAGE
, Index
, &SubFvSection
);
712 if (EFI_ERROR (Status
)) {
715 SubFvImageHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINT8
*) SubFvSection
.FVImageSection
+ GetSectionHeaderLength(SubFvSection
.FVImageSection
));
720 SubFvBaseAddress
= OrigFvBaseAddress
+ (UINTN
) SubFvImageHeader
- (UINTN
) FfsFile
+ XipOffset
;
721 //mFvBaseAddress[mFvBaseAddressNumber ++ ] = SubFvBaseAddress;
722 BaseAddress
= SubFvBaseAddress
;
723 InitializeFvLib(SubFvImageHeader
, (UINT32
) SubFvImageHeader
->FvLength
);
725 Status
= GetNextFile (NULL
, &CurrentFile
);
726 if (EFI_ERROR (Status
)) {
727 Error (NULL
, 0, 0003, "error parsing FV image", "FFS file can't be found");
730 while (CurrentFile
) {
731 RebaseFfs (BaseAddress
, "", CurrentFile
, (UINTN
) CurrentFile
- (UINTN
) SubFvImageHeader
);
732 Status
= GetNextFile (CurrentFile
, &CurrentFile
);
733 if (EFI_ERROR (Status
)) {
739 BaseAddress
= OrigFvBaseAddress
;
740 if (OrigFvHeader
!= NULL
) {
741 InitializeFvLib(OrigFvHeader
, OrigFvLength
);
750 OUT UINT32
*EntryPoint
,
751 OUT UINT32
*BaseOfCode
,
752 OUT UINT16
*MachineType
758 Retrieves the PE32 entry point offset and machine type from PE image or TeImage.
759 See EfiImage.h for machine types. The entry point offset is from the beginning
760 of the PE32 buffer passed in.
764 Pe32 Beginning of the PE32.
765 EntryPoint Offset from the beginning of the PE32 to the image entry point.
766 BaseOfCode Base address of code.
767 MachineType Magic number for the machine type.
771 EFI_SUCCESS Function completed successfully.
772 EFI_ABORTED Error encountered.
773 EFI_INVALID_PARAMETER A required parameter was NULL.
774 EFI_UNSUPPORTED The operation is unsupported.
778 EFI_IMAGE_DOS_HEADER
*DosHeader
;
779 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
780 EFI_TE_IMAGE_HEADER
*TeHeader
;
783 // Verify input parameters
786 return EFI_INVALID_PARAMETER
;
790 // First check whether it is one TE Image.
792 TeHeader
= (EFI_TE_IMAGE_HEADER
*) Pe32
;
793 if (TeHeader
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
795 // By TeImage Header to get output
797 *EntryPoint
= TeHeader
->AddressOfEntryPoint
+ sizeof (EFI_TE_IMAGE_HEADER
) - TeHeader
->StrippedSize
;
798 *BaseOfCode
= TeHeader
->BaseOfCode
+ sizeof (EFI_TE_IMAGE_HEADER
) - TeHeader
->StrippedSize
;
799 *MachineType
= TeHeader
->Machine
;
803 // Then check whether
804 // First is the DOS header
806 DosHeader
= (EFI_IMAGE_DOS_HEADER
*) Pe32
;
809 // Verify DOS header is expected
811 if (DosHeader
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
812 Error (NULL
, 0, 3000, "Invalid", "Unknown magic number in the DOS header, 0x%04X.", DosHeader
->e_magic
);
813 return EFI_UNSUPPORTED
;
816 // Immediately following is the NT header.
818 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*) ((UINTN
) Pe32
+ DosHeader
->e_lfanew
);
821 // Verify NT header is expected
823 if (ImgHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
824 Error (NULL
, 0, 3000, "Invalid", "Unrecognized image signature 0x%08X.", (unsigned) ImgHdr
->Pe32
.Signature
);
825 return EFI_UNSUPPORTED
;
830 *EntryPoint
= ImgHdr
->Pe32
.OptionalHeader
.AddressOfEntryPoint
;
831 *BaseOfCode
= ImgHdr
->Pe32
.OptionalHeader
.BaseOfCode
;
832 *MachineType
= ImgHdr
->Pe32
.FileHeader
.Machine
;
836 // Verify machine type is supported
838 if ((*MachineType
!= EFI_IMAGE_MACHINE_IA32
) && (*MachineType
!= EFI_IMAGE_MACHINE_X64
) && (*MachineType
!= EFI_IMAGE_MACHINE_EBC
) &&
839 (*MachineType
!= EFI_IMAGE_MACHINE_ARMT
) && (*MachineType
!= EFI_IMAGE_MACHINE_AARCH64
)) {
840 Error (NULL
, 0, 3000, "Invalid", "Unrecognized machine type in the PE32 file.");
841 return EFI_UNSUPPORTED
;