3 Copyright (c) 1999 - 2005 Intel Corporation. All rights reserved
4 This software and associated documentation (if any) is furnished
5 under a license and may only be used or copied in accordance
6 with the terms of the license. Except as permitted by such
7 license, no part of this software or documentation may be
8 reproduced, stored in a retrieval system, or transmitted in any
9 form or by any means without the express written consent of
19 This contains all code necessary to build the PeiRebase.exe utility.
20 This utility relies heavily on the PeiRebase DLL. Definitions for both
21 can be found in the PEI Rebase Utility Specification, review draft.
25 #include "PeiRebaseExe.h"
29 #include "CommonLib.h"
31 #include EFI_GUID_DEFINITION (PeiPeCoffLoader)
34 #include "EfiUtilityMsgs.h"
36 extern EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader
;
42 OUT BOOLEAN
*ErasePolarity
54 This utility relocates PEI XIP PE32s in a FV.
58 argc - Number of command line arguments
60 BaseAddress The base address to use for rebasing the FV. The correct
61 format is a hex number preceded by 0x.
62 InputFileName The name of the input FV file.
63 OutputFileName The name of the output FV file.
65 Arguments come in pair in any order.
72 0 No error conditions detected.
73 1 One or more of the input parameters is invalid.
74 2 A resource required by the utility was unavailable.
75 Most commonly this will be memory allocation or file creation.
76 3 PeiRebase.dll could not be loaded.
77 4 Error executing the PEI rebase.
82 CHAR8 InputFileName
[_MAX_PATH
];
83 CHAR8 OutputFileName
[_MAX_PATH
];
84 EFI_PHYSICAL_ADDRESS BaseAddress
;
85 BOOLEAN BaseAddressSet
;
92 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
;
94 EFI_FFS_FILE_HEADER
*CurrentFile
;
95 BOOLEAN ErasePolarity
;
96 EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress
;
98 ErasePolarity
= FALSE
;
100 // Set utility name for error/warning reporting purposes.
102 SetUtilityName (UTILITY_NAME
);
104 // Verify the correct number of arguments
106 if (argc
!= MAX_ARGS
) {
111 // Initialize variables
113 InputFileName
[0] = 0;
114 OutputFileName
[0] = 0;
116 BaseAddressSet
= FALSE
;
119 ErasePolarity
= FALSE
;
124 // Parse the command line arguments
126 for (Index
= 1; Index
< MAX_ARGS
; Index
+= 2) {
128 // Make sure argument pair begin with - or /
130 if (argv
[Index
][0] != '-' && argv
[Index
][0] != '/') {
132 Error (NULL
, 0, 0, argv
[Index
], "unrecognized option");
136 // Make sure argument specifier is only one letter
138 if (argv
[Index
][2] != 0) {
140 Error (NULL
, 0, 0, argv
[Index
], "unrecognized option");
144 // Determine argument to read
146 switch (argv
[Index
][1]) {
149 if (strlen (InputFileName
) == 0) {
150 strcpy (InputFileName
, argv
[Index
+ 1]);
153 Error (NULL
, 0, 0, argv
[Index
+ 1], "only one -i InputFileName may be specified");
160 if (strlen (OutputFileName
) == 0) {
161 strcpy (OutputFileName
, argv
[Index
+ 1]);
164 Error (NULL
, 0, 0, argv
[Index
+ 1], "only one -o OutputFileName may be specified");
171 if (!BaseAddressSet
) {
172 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &BaseAddress
);
173 if (EFI_ERROR (Status
)) {
175 Error (NULL
, 0, 0, argv
[Index
+ 1], "invalid hex digit given for the base address");
179 BaseAddressSet
= TRUE
;
182 Error (NULL
, 0, 0, argv
[Index
+ 1], "-b BaseAddress may only be specified once");
189 Error (NULL
, 0, 0, argv
[Index
], "unrecognized argument");
195 // Open the file containing the FV
197 InputFile
= fopen (InputFileName
, "rb");
198 if (InputFile
== NULL
) {
199 Error (NULL
, 0, 0, InputFileName
, "could not open input file for reading");
203 // Determine size of FV
205 Status
= ReadHeader (InputFile
, &FvSize
, &ErasePolarity
);
206 if (EFI_ERROR (Status
)) {
207 Error (NULL
, 0, 0, "could not parse the FV header", NULL
);
211 // Allocate a buffer for the FV image
213 FvImage
= malloc (FvSize
);
214 if (FvImage
== NULL
) {
215 Error (NULL
, 0, 0, "application error", "memory allocation failed");
219 // Read the entire FV to the buffer
221 BytesRead
= fread (FvImage
, 1, FvSize
, InputFile
);
224 if ((unsigned int) BytesRead
!= FvSize
) {
225 Error (NULL
, 0, 0, InputFileName
, "failed to read from file");
229 // Prepare to walk the FV image
231 InitializeFvLib (FvImage
, FvSize
);
233 // Get the first file
235 Status
= GetNextFile (NULL
, &CurrentFile
);
236 if (EFI_ERROR (Status
)) {
237 Error (NULL
, 0, 0, "cannot find the first file in the FV image", NULL
);
241 // Check if each file should be rebased
243 while (CurrentFile
!= NULL
) {
247 CurrentFileBaseAddress
= BaseAddress
+ ((UINTN
) CurrentFile
- (UINTN
) FvImage
);
248 Status
= FfsRebase (CurrentFile
, CurrentFileBaseAddress
);
250 if (EFI_ERROR (Status
)) {
253 case EFI_INVALID_PARAMETER
:
254 Error (NULL
, 0, 0, "invalid parameter passed to FfsRebase", NULL
);
258 Error (NULL
, 0, 0, "error detected while rebasing -- aborted", NULL
);
261 case EFI_OUT_OF_RESOURCES
:
262 Error (NULL
, 0, 0, "FfsRebase could not allocate required resources", NULL
);
266 Error (NULL
, 0, 0, "FfsRebase could not locate a PE32 section", NULL
);
270 Error (NULL
, 0, 0, "FfsRebase returned unknown status", "status=0x%08X", Status
);
279 Status
= GetNextFile (CurrentFile
, &CurrentFile
);
280 if (EFI_ERROR (Status
)) {
281 Error (NULL
, 0, 0, "cannot find the next file in the FV image", NULL
);
286 // Open the output file
288 OutputFile
= fopen (OutputFileName
, "wb");
289 if (OutputFile
== NULL
) {
290 Error (NULL
, 0, 0, OutputFileName
, "failed to open output file");
294 if (fwrite (FvImage
, 1, FvSize
, OutputFile
) != FvSize
) {
295 Error (NULL
, 0, 0, "failed to write to output file", 0);
300 if (InputFile
!= NULL
) {
304 // If we created an output file, and there was an error, remove it so
305 // subsequent builds will rebuild it.
307 if (OutputFile
!= NULL
) {
308 if (GetUtilityStatus () == STATUS_ERROR
) {
309 remove (OutputFileName
);
315 if (FvImage
!= NULL
) {
319 return GetUtilityStatus ();
326 OUT BOOLEAN
*ErasePolarity
332 This function determines the size of the FV and the erase polarity. The
333 erase polarity is the FALSE value for file state.
337 InputFile The file that contains the FV image.
338 FvSize The size of the FV.
339 ErasePolarity The FV erase polarity.
343 EFI_SUCCESS Function completed successfully.
344 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
345 EFI_ABORTED The function encountered an error.
349 EFI_FIRMWARE_VOLUME_HEADER VolumeHeader
;
350 EFI_FV_BLOCK_MAP_ENTRY BlockMap
;
358 // Check input parameters
360 if ((InputFile
== NULL
) || (FvSize
== NULL
) || (ErasePolarity
== NULL
)) {
361 Error (NULL
, 0, 0, "ReadHeader()", "invalid input parameter");
362 return EFI_INVALID_PARAMETER
;
367 fread (&VolumeHeader
, sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
368 BytesRead
= sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
369 Signature
[0] = VolumeHeader
.Signature
;
373 // Get erase polarity
375 if (VolumeHeader
.Attributes
& EFI_FVB_ERASE_POLARITY
) {
376 *ErasePolarity
= TRUE
;
380 fread (&BlockMap
, sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
381 BytesRead
+= sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
383 if (BlockMap
.NumBlocks
!= 0) {
384 Size
+= BlockMap
.NumBlocks
* BlockMap
.BlockLength
;
387 } while (!(BlockMap
.NumBlocks
== 0 && BlockMap
.BlockLength
== 0));
389 if (VolumeHeader
.FvLength
!= Size
) {
390 Error (NULL
, 0, 0, "volume size not consistant with block maps", NULL
);
409 Displays the standard utility information to SDTOUT
422 "%s, PEI Rebase Utility. Version %i.%i, %s.\n\n",
424 UTILITY_MAJOR_VERSION
,
425 UTILITY_MINOR_VERSION
,
438 Displays the utility usage syntax to STDOUT
451 "Usage: %s -I InputFileName -O OutputFileName -B BaseAddress\n",
454 printf (" Where:\n");
455 printf (" InputFileName is the name of the EFI FV file to rebase.\n");
456 printf (" OutputFileName is the desired output file name.\n");
457 printf (" BaseAddress is the FV base address to rebase agains.\n");
458 printf (" Argument pair may be in any order.\n\n");
463 IN OUT EFI_FFS_FILE_HEADER
*FfsFile
,
464 IN EFI_PHYSICAL_ADDRESS BaseAddress
470 This function determines if a file is XIP and should be rebased. It will
471 rebase any PE32 sections found in the file using the base address.
475 FfsFile A pointer to Ffs file image.
476 BaseAddress The base address to use for rebasing the file image.
480 EFI_SUCCESS The image was properly rebased.
481 EFI_INVALID_PARAMETER An input parameter is invalid.
482 EFI_ABORTED An error occurred while rebasing the input file image.
483 EFI_OUT_OF_RESOURCES Could not allocate a required resource.
484 EFI_NOT_FOUND No compressed sections could be found.
489 EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
490 UINTN MemoryImagePointer
;
491 UINTN MemoryImagePointerAligned
;
492 EFI_PHYSICAL_ADDRESS ImageAddress
;
494 EFI_PHYSICAL_ADDRESS EntryPoint
;
495 UINT32 Pe32ImageSize
;
496 UINT32 NewPe32BaseAddress
;
498 EFI_FILE_SECTION_POINTER CurrentPe32Section
;
499 EFI_FFS_FILE_STATE SavedState
;
500 EFI_IMAGE_NT_HEADERS
*PeHdr
;
501 UINT32
*PeHdrSizeOfImage
;
502 UINT32
*PeHdrChecksum
;
504 EFI_TE_IMAGE_HEADER
*TEImageHeader
;
506 EFI_IMAGE_DOS_HEADER
*DosHeader
;
507 UINT8 FileGuidString
[80];
509 EFI_FFS_FILE_TAIL TailValue
;
512 // Verify input parameters
514 if (FfsFile
== NULL
) {
515 return EFI_INVALID_PARAMETER
;
518 // Convert the GUID to a string so we can at least report which file
519 // if we find an error.
521 PrintGuidToBuffer (&FfsFile
->Name
, FileGuidString
, sizeof (FileGuidString
), TRUE
);
522 if (FfsFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
523 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
528 // Do some cursory checks on the FFS file contents
530 Status
= VerifyFfsFile (FfsFile
);
531 if (EFI_ERROR (Status
)) {
532 Error (NULL
, 0, 0, "file does not appear to be a valid FFS file, cannot be rebased", FileGuidString
);
533 return EFI_INVALID_PARAMETER
;
536 // Check if XIP file type. If not XIP, don't rebase.
538 if (FfsFile
->Type
!= EFI_FV_FILETYPE_PEI_CORE
&&
539 FfsFile
->Type
!= EFI_FV_FILETYPE_PEIM
&&
540 FfsFile
->Type
!= EFI_FV_FILETYPE_SECURITY_CORE
&&
541 FfsFile
->Type
!= EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
546 // Rebase each PE32 section
548 Status
= EFI_SUCCESS
;
550 for (Index
= 1;; Index
++) {
551 Status
= GetSectionByType (FfsFile
, EFI_SECTION_PE32
, Index
, &CurrentPe32Section
);
552 if (EFI_ERROR (Status
)) {
559 // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section
561 NewPe32BaseAddress
= ((UINT32
) BaseAddress
) + ((UINTN
) CurrentPe32Section
.Pe32Section
+ sizeof (EFI_COMMON_SECTION_HEADER
) - (UINTN
) FfsFile
);
564 // Initialize context
566 memset (&ImageContext
, 0, sizeof (ImageContext
));
567 ImageContext
.Handle
= (VOID
*) ((UINTN
) CurrentPe32Section
.Pe32Section
+ sizeof (EFI_PE32_SECTION
));
568 ImageContext
.ImageRead
= (EFI_PEI_PE_COFF_LOADER_READ_FILE
) FfsRebaseImageRead
;
570 Status
= mPeCoffLoader
.GetImageInfo (&mPeCoffLoader
, &ImageContext
);
572 if (EFI_ERROR (Status
)) {
573 Error (NULL
, 0, 0, "GetImageInfo() call failed on rebase", FileGuidString
);
577 // Allocate a buffer for the image to be loaded into.
579 Pe32ImageSize
= GetLength (CurrentPe32Section
.Pe32Section
->CommonHeader
.Size
) - sizeof (EFI_PE32_SECTION
);
580 MemoryImagePointer
= (UINTN
) (malloc (Pe32ImageSize
+ 0x1000));
581 if (MemoryImagePointer
== 0) {
582 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
583 return EFI_OUT_OF_RESOURCES
;
585 memset ((void *) MemoryImagePointer
, 0, Pe32ImageSize
+ 0x1000);
586 MemoryImagePointerAligned
= (MemoryImagePointer
+ 0x0FFF) & (-1 << 12);
589 ImageContext
.ImageAddress
= MemoryImagePointerAligned
;
591 Status
= mPeCoffLoader
.LoadImage (&mPeCoffLoader
, &ImageContext
);
592 if (EFI_ERROR (Status
)) {
593 Error (NULL
, 0, 0, "LoadImage() call failed on rebase", FileGuidString
);
594 free ((VOID
*) MemoryImagePointer
);
598 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
599 Status
= mPeCoffLoader
.RelocateImage (&mPeCoffLoader
, &ImageContext
);
600 if (EFI_ERROR (Status
)) {
601 Error (NULL
, 0, 0, "RelocateImage() call failed on rebase", FileGuidString
);
602 free ((VOID
*) MemoryImagePointer
);
606 ImageAddress
= ImageContext
.ImageAddress
;
607 ImageSize
= ImageContext
.ImageSize
;
608 EntryPoint
= ImageContext
.EntryPoint
;
610 if (ImageSize
> Pe32ImageSize
) {
615 "rebased image is larger than original PE32 image",
616 "0x%X > 0x%X, file %s",
621 free ((VOID
*) MemoryImagePointer
);
625 // Since we may have updated the Codeview RVA, we need to insure the PE
626 // header indicates the image is large enough to contain the Codeview data
627 // so it will be loaded properly later if the PEIM is reloaded into memory...
629 PeHdr
= (VOID
*) ((UINTN
) ImageAddress
+ ImageContext
.PeCoffHeaderOffset
);
630 if (PeHdr
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
) {
631 PeHdrSizeOfImage
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER32
*) &PeHdr
->OptionalHeader
).SizeOfImage
);
632 PeHdrChecksum
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER32
*) &PeHdr
->OptionalHeader
).CheckSum
);
633 } else if (PeHdr
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
) {
634 PeHdrSizeOfImage
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER64
*) &PeHdr
->OptionalHeader
).SizeOfImage
);
635 PeHdrChecksum
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER64
*) &PeHdr
->OptionalHeader
).CheckSum
);
636 } else if (PeHdr
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
) {
637 PeHdrSizeOfImage
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER64
*) &PeHdr
->OptionalHeader
).SizeOfImage
);
638 PeHdrChecksum
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER64
*) &PeHdr
->OptionalHeader
).CheckSum
);
644 "unknown machine type in PE32 image",
645 "machine type=0x%X, file=%s",
646 (UINT32
) PeHdr
->FileHeader
.Machine
,
649 free ((VOID
*) MemoryImagePointer
);
653 if (*PeHdrSizeOfImage
!= ImageContext
.ImageSize
) {
654 *PeHdrSizeOfImage
= (UINT32
) ImageContext
.ImageSize
;
655 if (*PeHdrChecksum
) {
660 memcpy (CurrentPe32Section
.Pe32Section
+ 1, (VOID
*) MemoryImagePointerAligned
, (UINT32
) ImageSize
);
662 free ((VOID
*) MemoryImagePointer
);
665 // Now update file checksum
667 if (FfsFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
668 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
673 if (FfsFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
674 SavedState
= FfsFile
->State
;
675 FfsFile
->IntegrityCheck
.Checksum
.File
= 0;
677 if (FfsFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
678 FfsFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
680 GetLength (FfsFile
->Size
) - TailSize
683 FfsFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
686 FfsFile
->State
= SavedState
;
689 // Update tail if present
691 if (FfsFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
692 TailValue
= (EFI_FFS_FILE_TAIL
) (~(FfsFile
->IntegrityCheck
.TailReference
));
693 *(EFI_FFS_FILE_TAIL
*) (((UINTN
) FfsFile
+ GetLength (FfsFile
->Size
) - sizeof (EFI_FFS_FILE_TAIL
))) = TailValue
;
697 // Now process TE sections
699 for (Index
= 1;; Index
++) {
700 Status
= GetSectionByType (FfsFile
, EFI_SECTION_TE
, Index
, &CurrentPe32Section
);
701 if (EFI_ERROR (Status
)) {
708 // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off
711 TEImageHeader
= (EFI_TE_IMAGE_HEADER
*) ((UINT8
*) CurrentPe32Section
.Pe32Section
+ sizeof (EFI_COMMON_SECTION_HEADER
));
713 NewPe32BaseAddress
= ((UINT32
) BaseAddress
) +
715 (UINTN
) CurrentPe32Section
.Pe32Section
+
716 sizeof (EFI_COMMON_SECTION_HEADER
) +
717 sizeof (EFI_TE_IMAGE_HEADER
) -
718 TEImageHeader
->StrippedSize
-
723 // Allocate a buffer to unshrink the image into.
725 Pe32ImageSize
= GetLength (CurrentPe32Section
.Pe32Section
->CommonHeader
.Size
) - sizeof (EFI_PE32_SECTION
) -
726 sizeof (EFI_TE_IMAGE_HEADER
);
727 Pe32ImageSize
+= TEImageHeader
->StrippedSize
;
728 TEBuffer
= (UINT8
*) malloc (Pe32ImageSize
);
729 if (TEBuffer
== NULL
) {
730 Error (NULL
, 0, 0, "failed to allocate memory", NULL
);
731 return EFI_OUT_OF_RESOURCES
;
734 // Expand the image into our buffer and fill in critical fields in the DOS header
735 // Fill in fields required by the loader.
736 // At offset 0x3C is the offset to the PE signature. We'll put it immediately following the offset value
739 memset (TEBuffer
, 0, Pe32ImageSize
);
740 DosHeader
= (EFI_IMAGE_DOS_HEADER
*) TEBuffer
;
741 DosHeader
->e_magic
= EFI_IMAGE_DOS_SIGNATURE
;
742 *(UINT32
*) (TEBuffer
+ 0x3C) = 0x40;
743 PeHdr
= (EFI_IMAGE_NT_HEADERS
*) (TEBuffer
+ 0x40);
744 PeHdr
->Signature
= EFI_IMAGE_NT_SIGNATURE
;
745 PeHdr
->FileHeader
.Machine
= TEImageHeader
->Machine
;
746 PeHdr
->FileHeader
.NumberOfSections
= TEImageHeader
->NumberOfSections
;
749 // Say the size of the optional header is the total we stripped off less the size of a PE file header and PE signature and
750 // the 0x40 bytes for our DOS header.
752 PeHdr
->FileHeader
.SizeOfOptionalHeader
= (UINT16
) (TEImageHeader
->StrippedSize
- 0x40 - sizeof (UINT32
) - sizeof (EFI_IMAGE_FILE_HEADER
));
753 PeHdr
->OptionalHeader
.ImageBase
= (UINTN
) (TEImageHeader
->ImageBase
- TEImageHeader
->StrippedSize
+ sizeof (EFI_TE_IMAGE_HEADER
));
754 PeHdr
->OptionalHeader
.SizeOfImage
= Pe32ImageSize
;
755 PeHdr
->OptionalHeader
.Subsystem
= TEImageHeader
->Subsystem
;
756 PeHdr
->OptionalHeader
.SizeOfImage
= Pe32ImageSize
;
757 PeHdr
->OptionalHeader
.SizeOfHeaders
= TEImageHeader
->StrippedSize
+ TEImageHeader
->NumberOfSections
*
758 sizeof (EFI_IMAGE_SECTION_HEADER
) - 12;
761 // Set NumberOfRvaAndSizes in the optional header to what we had available in the original image
763 if ((TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
!= 0) ||
764 (TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0)
766 PeHdr
->OptionalHeader
.NumberOfRvaAndSizes
= EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
+ 1;
767 PeHdr
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
768 PeHdr
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
771 if ((TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
!= 0) ||
772 (TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0)
774 PeHdr
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
775 PeHdr
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
776 if (PeHdr
->OptionalHeader
.NumberOfRvaAndSizes
< EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
+ 1) {
777 PeHdr
->OptionalHeader
.NumberOfRvaAndSizes
= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
+ 1;
781 // NOTE: These values are defaults, and should be verified to be correct in the GenTE utility
783 PeHdr
->OptionalHeader
.SectionAlignment
= 0x10;
786 // Copy the rest of the image to its original offset
789 TEBuffer
+ TEImageHeader
->StrippedSize
,
790 (UINT8
*) CurrentPe32Section
.Pe32Section
+ sizeof (EFI_PE32_SECTION
) + sizeof (EFI_TE_IMAGE_HEADER
),
791 GetLength (CurrentPe32Section
.Pe32Section
->CommonHeader
.Size
) - sizeof (EFI_PE32_SECTION
) -
792 sizeof (EFI_TE_IMAGE_HEADER
)
796 // Initialize context
798 memset (&ImageContext
, 0, sizeof (ImageContext
));
799 ImageContext
.Handle
= (VOID
*) TEBuffer
;
800 ImageContext
.ImageRead
= (EFI_PEI_PE_COFF_LOADER_READ_FILE
) FfsRebaseImageRead
;
802 Status
= mPeCoffLoader
.GetImageInfo (&mPeCoffLoader
, &ImageContext
);
804 if (EFI_ERROR (Status
)) {
805 Error (NULL
, 0, 0, "GetImageInfo() call failed on rebase of TE image", FileGuidString
);
810 // Allocate a buffer for the image to be loaded into.
812 MemoryImagePointer
= (UINTN
) (malloc (Pe32ImageSize
+ 0x1000));
813 if (MemoryImagePointer
== 0) {
814 Error (NULL
, 0, 0, "memory allocation error on rebase of TE image", FileGuidString
);
816 return EFI_OUT_OF_RESOURCES
;
818 memset ((void *) MemoryImagePointer
, 0, Pe32ImageSize
+ 0x1000);
819 MemoryImagePointerAligned
= (MemoryImagePointer
+ 0x0FFF) & (-1 << 12);
822 ImageContext
.ImageAddress
= MemoryImagePointerAligned
;
823 Status
= mPeCoffLoader
.LoadImage (&mPeCoffLoader
, &ImageContext
);
824 if (EFI_ERROR (Status
)) {
825 Error (NULL
, 0, 0, "LoadImage() call failed on rebase of TE image", FileGuidString
);
827 free ((VOID
*) MemoryImagePointer
);
831 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
832 Status
= mPeCoffLoader
.RelocateImage (&mPeCoffLoader
, &ImageContext
);
833 if (EFI_ERROR (Status
)) {
834 Error (NULL
, 0, 0, "RelocateImage() call failed on rebase of TE image", FileGuidString
);
835 free ((VOID
*) MemoryImagePointer
);
840 ImageAddress
= ImageContext
.ImageAddress
;
841 ImageSize
= ImageContext
.ImageSize
;
842 EntryPoint
= ImageContext
.EntryPoint
;
845 // Since we may have updated the Codeview RVA, we need to insure the PE
846 // header indicates the image is large enough to contain the Codeview data
847 // so it will be loaded properly later if the PEIM is reloaded into memory...
849 PeHdr
= (VOID
*) ((UINTN
) ImageAddress
+ ImageContext
.PeCoffHeaderOffset
);
850 if (PeHdr
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
) {
851 PeHdrSizeOfImage
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER32
*) &PeHdr
->OptionalHeader
).SizeOfImage
);
852 PeHdrChecksum
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER32
*) &PeHdr
->OptionalHeader
).CheckSum
);
853 } else if (PeHdr
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
) {
854 PeHdrSizeOfImage
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER64
*) &PeHdr
->OptionalHeader
).SizeOfImage
);
855 PeHdrChecksum
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER64
*) &PeHdr
->OptionalHeader
).CheckSum
);
861 "unknown machine type in TE image",
862 "machine type=0x%X, file=%s",
863 (UINT32
) PeHdr
->FileHeader
.Machine
,
866 free ((VOID
*) MemoryImagePointer
);
871 if (*PeHdrSizeOfImage
!= ImageContext
.ImageSize
) {
872 *PeHdrSizeOfImage
= (UINT32
) ImageContext
.ImageSize
;
873 if (*PeHdrChecksum
) {
878 TEImageHeader
->ImageBase
= (UINT64
) (NewPe32BaseAddress
+ TEImageHeader
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
));
880 (UINT8
*) (CurrentPe32Section
.Pe32Section
+ 1) + sizeof (EFI_TE_IMAGE_HEADER
),
881 (VOID
*) ((UINT8
*) MemoryImagePointerAligned
+ TEImageHeader
->StrippedSize
),
882 GetLength (CurrentPe32Section
.Pe32Section
->CommonHeader
.Size
) - sizeof (EFI_PE32_SECTION
) -
883 sizeof (EFI_TE_IMAGE_HEADER
)
885 free ((VOID
*) MemoryImagePointer
);
887 if (FfsFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
888 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
893 // Now update file checksum
895 if (FfsFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
896 SavedState
= FfsFile
->State
;
897 FfsFile
->IntegrityCheck
.Checksum
.File
= 0;
899 if (FfsFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
900 FfsFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
902 GetLength (FfsFile
->Size
) - TailSize
905 FfsFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
908 FfsFile
->State
= SavedState
;
911 // Update tail if present
913 if (FfsFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
914 TailValue
= (EFI_FFS_FILE_TAIL
) (~(FfsFile
->IntegrityCheck
.TailReference
));
915 *(EFI_FFS_FILE_TAIL
*) (((UINTN
) FfsFile
+ GetLength (FfsFile
->Size
) - sizeof (EFI_FFS_FILE_TAIL
))) = TailValue
;
919 // If we found no files, then emit an error if no compressed sections either
921 if (FoundCount
== 0) {
922 Status
= GetSectionByType (FfsFile
, EFI_SECTION_COMPRESSION
, Index
, &CurrentPe32Section
);
923 if (EFI_ERROR (Status
)) {
924 Error (NULL
, 0, 0, "no PE32, TE, nor compressed section found in FV file", FileGuidString
);
925 return EFI_NOT_FOUND
;
936 IN OUT UINT32
*ReadSize
,
943 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
947 FileHandle - The handle to the PE/COFF file
949 FileOffset - The offset, in bytes, into the file to read
951 ReadSize - The number of bytes to read from the file starting at FileOffset
953 Buffer - A pointer to the buffer to read the data into.
957 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
965 Destination8
= Buffer
;
966 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
969 *(Destination8
++) = *(Source8
++);