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 <UefiBaseTypes.h>
30 #include "CommonLib.h"
32 // #include <Guid/PeiPeCoffLoader.h>
35 #include "EfiUtilityMsgs.h"
36 #include "FirmwareFileSystem.h"
37 #include "PeCoffLib.h"
39 #include "PeiRebaseExe.h"
41 extern PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader
;
47 OUT BOOLEAN
*ErasePolarity
59 This utility relocates PEI XIP PE32s in a FV.
63 argc - Number of command line arguments
65 BaseAddress The base address to use for rebasing the FV. The correct
66 format is a hex number preceded by 0x.
67 InputFileName The name of the input FV file.
68 OutputFileName The name of the output FV file.
70 Arguments come in pair in any order.
77 0 No error conditions detected.
78 1 One or more of the input parameters is invalid.
79 2 A resource required by the utility was unavailable.
80 Most commonly this will be memory allocation or file creation.
81 3 PeiRebase.dll could not be loaded.
82 4 Error executing the PEI rebase.
87 CHAR8 InputFileName
[_MAX_PATH
];
88 CHAR8 OutputFileName
[_MAX_PATH
];
89 EFI_PHYSICAL_ADDRESS BaseAddress
;
90 BOOLEAN BaseAddressSet
;
97 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
;
99 EFI_FFS_FILE_HEADER
*CurrentFile
;
100 BOOLEAN ErasePolarity
;
101 EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress
;
103 ErasePolarity
= FALSE
;
105 // Set utility name for error/warning reporting purposes.
107 SetUtilityName (UTILITY_NAME
);
109 // Verify the correct number of arguments
111 if (argc
!= MAX_ARGS
) {
116 // Initialize variables
118 InputFileName
[0] = 0;
119 OutputFileName
[0] = 0;
121 BaseAddressSet
= FALSE
;
124 ErasePolarity
= FALSE
;
129 // Parse the command line arguments
131 for (Index
= 1; Index
< MAX_ARGS
; Index
+= 2) {
133 // Make sure argument pair begin with - or /
135 if (argv
[Index
][0] != '-' && argv
[Index
][0] != '/') {
137 Error (NULL
, 0, 0, argv
[Index
], "unrecognized option");
141 // Make sure argument specifier is only one letter
143 if (argv
[Index
][2] != 0) {
145 Error (NULL
, 0, 0, argv
[Index
], "unrecognized option");
149 // Determine argument to read
151 switch (argv
[Index
][1]) {
154 if (strlen (InputFileName
) == 0) {
155 strcpy (InputFileName
, argv
[Index
+ 1]);
158 Error (NULL
, 0, 0, argv
[Index
+ 1], "only one -i InputFileName may be specified");
165 if (strlen (OutputFileName
) == 0) {
166 strcpy (OutputFileName
, argv
[Index
+ 1]);
169 Error (NULL
, 0, 0, argv
[Index
+ 1], "only one -o OutputFileName may be specified");
176 if (!BaseAddressSet
) {
177 Status
= AsciiStringToUint64 (argv
[Index
+ 1], FALSE
, &BaseAddress
);
178 if (EFI_ERROR (Status
)) {
180 Error (NULL
, 0, 0, argv
[Index
+ 1], "invalid hex digit given for the base address");
184 BaseAddressSet
= TRUE
;
187 Error (NULL
, 0, 0, argv
[Index
+ 1], "-b BaseAddress may only be specified once");
194 Error (NULL
, 0, 0, argv
[Index
], "unrecognized argument");
200 // Open the file containing the FV
202 InputFile
= fopen (InputFileName
, "rb");
203 if (InputFile
== NULL
) {
204 Error (NULL
, 0, 0, InputFileName
, "could not open input file for reading");
208 // Determine size of FV
210 Status
= ReadHeader (InputFile
, &FvSize
, &ErasePolarity
);
211 if (EFI_ERROR (Status
)) {
212 Error (NULL
, 0, 0, "could not parse the FV header", NULL
);
216 // Allocate a buffer for the FV image
218 FvImage
= malloc (FvSize
);
219 if (FvImage
== NULL
) {
220 Error (NULL
, 0, 0, "application error", "memory allocation failed");
224 // Read the entire FV to the buffer
226 BytesRead
= fread (FvImage
, 1, FvSize
, InputFile
);
229 if ((unsigned int) BytesRead
!= FvSize
) {
230 Error (NULL
, 0, 0, InputFileName
, "failed to read from file");
234 // Prepare to walk the FV image
236 InitializeFvLib (FvImage
, FvSize
);
238 // Get the first file
240 Status
= GetNextFile (NULL
, &CurrentFile
);
241 if (EFI_ERROR (Status
)) {
242 Error (NULL
, 0, 0, "cannot find the first file in the FV image", NULL
);
246 // Check if each file should be rebased
248 while (CurrentFile
!= NULL
) {
252 CurrentFileBaseAddress
= BaseAddress
+ ((UINTN
) CurrentFile
- (UINTN
) FvImage
);
253 Status
= FfsRebase (CurrentFile
, CurrentFileBaseAddress
);
255 if (EFI_ERROR (Status
)) {
258 case EFI_INVALID_PARAMETER
:
259 Error (NULL
, 0, 0, "invalid parameter passed to FfsRebase", NULL
);
263 Error (NULL
, 0, 0, "error detected while rebasing -- aborted", NULL
);
266 case EFI_OUT_OF_RESOURCES
:
267 Error (NULL
, 0, 0, "FfsRebase could not allocate required resources", NULL
);
271 Error (NULL
, 0, 0, "FfsRebase could not locate a PE32 section", NULL
);
275 Error (NULL
, 0, 0, "FfsRebase returned unknown status", "status=0x%08X", Status
);
284 Status
= GetNextFile (CurrentFile
, &CurrentFile
);
285 if (EFI_ERROR (Status
)) {
286 Error (NULL
, 0, 0, "cannot find the next file in the FV image", NULL
);
291 // Open the output file
293 OutputFile
= fopen (OutputFileName
, "wb");
294 if (OutputFile
== NULL
) {
295 Error (NULL
, 0, 0, OutputFileName
, "failed to open output file");
299 if (fwrite (FvImage
, 1, FvSize
, OutputFile
) != FvSize
) {
300 Error (NULL
, 0, 0, "failed to write to output file", 0);
305 if (InputFile
!= NULL
) {
309 // If we created an output file, and there was an error, remove it so
310 // subsequent builds will rebuild it.
312 if (OutputFile
!= NULL
) {
313 if (GetUtilityStatus () == STATUS_ERROR
) {
314 remove (OutputFileName
);
320 if (FvImage
!= NULL
) {
324 return GetUtilityStatus ();
331 OUT BOOLEAN
*ErasePolarity
337 This function determines the size of the FV and the erase polarity. The
338 erase polarity is the FALSE value for file state.
342 InputFile The file that contains the FV image.
343 FvSize The size of the FV.
344 ErasePolarity The FV erase polarity.
348 EFI_SUCCESS Function completed successfully.
349 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
350 EFI_ABORTED The function encountered an error.
354 EFI_FIRMWARE_VOLUME_HEADER VolumeHeader
;
355 EFI_FV_BLOCK_MAP_ENTRY BlockMap
;
363 // Check input parameters
365 if ((InputFile
== NULL
) || (FvSize
== NULL
) || (ErasePolarity
== NULL
)) {
366 Error (NULL
, 0, 0, "ReadHeader()", "invalid input parameter");
367 return EFI_INVALID_PARAMETER
;
372 fread (&VolumeHeader
, sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
373 BytesRead
= sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
374 Signature
[0] = VolumeHeader
.Signature
;
378 // Get erase polarity
380 if (VolumeHeader
.Attributes
& EFI_FVB_ERASE_POLARITY
) {
381 *ErasePolarity
= TRUE
;
385 fread (&BlockMap
, sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
386 BytesRead
+= sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
388 if (BlockMap
.NumBlocks
!= 0) {
389 Size
+= BlockMap
.NumBlocks
* BlockMap
.BlockLength
;
392 } while (!(BlockMap
.NumBlocks
== 0 && BlockMap
.BlockLength
== 0));
394 if (VolumeHeader
.FvLength
!= Size
) {
395 Error (NULL
, 0, 0, "volume size not consistant with block maps", NULL
);
414 Displays the standard utility information to SDTOUT
427 "%s, PEI Rebase Utility. Version %i.%i, %s.\n\n",
429 UTILITY_MAJOR_VERSION
,
430 UTILITY_MINOR_VERSION
,
443 Displays the utility usage syntax to STDOUT
456 "Usage: %s -I InputFileName -O OutputFileName -B BaseAddress\n",
459 printf (" Where:\n");
460 printf (" InputFileName is the name of the EFI FV file to rebase.\n");
461 printf (" OutputFileName is the desired output file name.\n");
462 printf (" BaseAddress is the FV base address to rebase agains.\n");
463 printf (" Argument pair may be in any order.\n\n");
468 IN OUT EFI_FFS_FILE_HEADER
*FfsFile
,
469 IN EFI_PHYSICAL_ADDRESS BaseAddress
475 This function determines if a file is XIP and should be rebased. It will
476 rebase any PE32 sections found in the file using the base address.
480 FfsFile A pointer to Ffs file image.
481 BaseAddress The base address to use for rebasing the file image.
485 EFI_SUCCESS The image was properly rebased.
486 EFI_INVALID_PARAMETER An input parameter is invalid.
487 EFI_ABORTED An error occurred while rebasing the input file image.
488 EFI_OUT_OF_RESOURCES Could not allocate a required resource.
489 EFI_NOT_FOUND No compressed sections could be found.
494 EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
495 UINTN MemoryImagePointer
;
496 UINTN MemoryImagePointerAligned
;
497 EFI_PHYSICAL_ADDRESS ImageAddress
;
499 EFI_PHYSICAL_ADDRESS EntryPoint
;
500 UINT32 Pe32ImageSize
;
501 UINT32 NewPe32BaseAddress
;
503 EFI_FILE_SECTION_POINTER CurrentPe32Section
;
504 EFI_FFS_FILE_STATE SavedState
;
505 EFI_IMAGE_NT_HEADERS
*PeHdr
;
506 UINT32
*PeHdrSizeOfImage
;
507 UINT32
*PeHdrChecksum
;
509 EFI_TE_IMAGE_HEADER
*TEImageHeader
;
511 EFI_IMAGE_DOS_HEADER
*DosHeader
;
512 UINT8 FileGuidString
[80];
514 EFI_FFS_FILE_TAIL TailValue
;
517 // Verify input parameters
519 if (FfsFile
== NULL
) {
520 return EFI_INVALID_PARAMETER
;
523 // Convert the GUID to a string so we can at least report which file
524 // if we find an error.
526 PrintGuidToBuffer (&FfsFile
->Name
, FileGuidString
, sizeof (FileGuidString
), TRUE
);
527 if (FfsFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
528 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
533 // Do some cursory checks on the FFS file contents
535 Status
= VerifyFfsFile (FfsFile
);
536 if (EFI_ERROR (Status
)) {
537 Error (NULL
, 0, 0, "file does not appear to be a valid FFS file, cannot be rebased", FileGuidString
);
538 return EFI_INVALID_PARAMETER
;
541 // Check if XIP file type. If not XIP, don't rebase.
543 if (FfsFile
->Type
!= EFI_FV_FILETYPE_PEI_CORE
&&
544 FfsFile
->Type
!= EFI_FV_FILETYPE_PEIM
&&
545 FfsFile
->Type
!= EFI_FV_FILETYPE_SECURITY_CORE
&&
546 FfsFile
->Type
!= EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
551 // Rebase each PE32 section
553 Status
= EFI_SUCCESS
;
555 for (Index
= 1;; Index
++) {
556 Status
= GetSectionByType (FfsFile
, EFI_SECTION_PE32
, Index
, &CurrentPe32Section
);
557 if (EFI_ERROR (Status
)) {
564 // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section
566 NewPe32BaseAddress
= ((UINT32
) BaseAddress
) + ((UINTN
) CurrentPe32Section
.Pe32Section
+ sizeof (EFI_COMMON_SECTION_HEADER
) - (UINTN
) FfsFile
);
569 // Initialize context
571 memset (&ImageContext
, 0, sizeof (ImageContext
));
572 ImageContext
.Handle
= (VOID
*) ((UINTN
) CurrentPe32Section
.Pe32Section
+ sizeof (EFI_PE32_SECTION
));
573 ImageContext
.ImageRead
= (EFI_PEI_PE_COFF_LOADER_READ_FILE
) FfsRebaseImageRead
;
575 Status
= mPeCoffLoader
.GetImageInfo (&mPeCoffLoader
, &ImageContext
);
577 if (EFI_ERROR (Status
)) {
578 Error (NULL
, 0, 0, "GetImageInfo() call failed on rebase", FileGuidString
);
582 // Allocate a buffer for the image to be loaded into.
584 Pe32ImageSize
= GetLength (CurrentPe32Section
.Pe32Section
->CommonHeader
.Size
) - sizeof (EFI_PE32_SECTION
);
585 MemoryImagePointer
= (UINTN
) (malloc (Pe32ImageSize
+ 0x1000));
586 if (MemoryImagePointer
== 0) {
587 Error (NULL
, 0, 0, "memory allocation failure", NULL
);
588 return EFI_OUT_OF_RESOURCES
;
590 memset ((void *) MemoryImagePointer
, 0, Pe32ImageSize
+ 0x1000);
591 MemoryImagePointerAligned
= (MemoryImagePointer
+ 0x0FFF) & (-1 << 12);
594 ImageContext
.ImageAddress
= MemoryImagePointerAligned
;
596 Status
= mPeCoffLoader
.LoadImage (&mPeCoffLoader
, &ImageContext
);
597 if (EFI_ERROR (Status
)) {
598 Error (NULL
, 0, 0, "LoadImage() call failed on rebase", FileGuidString
);
599 free ((VOID
*) MemoryImagePointer
);
603 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
604 Status
= mPeCoffLoader
.RelocateImage (&mPeCoffLoader
, &ImageContext
);
605 if (EFI_ERROR (Status
)) {
606 Error (NULL
, 0, 0, "RelocateImage() call failed on rebase", FileGuidString
);
607 free ((VOID
*) MemoryImagePointer
);
611 ImageAddress
= ImageContext
.ImageAddress
;
612 ImageSize
= ImageContext
.ImageSize
;
613 EntryPoint
= ImageContext
.EntryPoint
;
615 if (ImageSize
> Pe32ImageSize
) {
620 "rebased image is larger than original PE32 image",
621 "0x%X > 0x%X, file %s",
626 free ((VOID
*) MemoryImagePointer
);
630 // Since we may have updated the Codeview RVA, we need to insure the PE
631 // header indicates the image is large enough to contain the Codeview data
632 // so it will be loaded properly later if the PEIM is reloaded into memory...
634 PeHdr
= (VOID
*) ((UINTN
) ImageAddress
+ ImageContext
.PeCoffHeaderOffset
);
635 if (PeHdr
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
) {
636 PeHdrSizeOfImage
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER32
*) &PeHdr
->OptionalHeader
).SizeOfImage
);
637 PeHdrChecksum
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER32
*) &PeHdr
->OptionalHeader
).CheckSum
);
638 } else if (PeHdr
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
) {
639 PeHdrSizeOfImage
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER64
*) &PeHdr
->OptionalHeader
).SizeOfImage
);
640 PeHdrChecksum
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER64
*) &PeHdr
->OptionalHeader
).CheckSum
);
641 } else if (PeHdr
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
) {
642 PeHdrSizeOfImage
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER64
*) &PeHdr
->OptionalHeader
).SizeOfImage
);
643 PeHdrChecksum
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER64
*) &PeHdr
->OptionalHeader
).CheckSum
);
649 "unknown machine type in PE32 image",
650 "machine type=0x%X, file=%s",
651 (UINT32
) PeHdr
->FileHeader
.Machine
,
654 free ((VOID
*) MemoryImagePointer
);
658 if (*PeHdrSizeOfImage
!= ImageContext
.ImageSize
) {
659 *PeHdrSizeOfImage
= (UINT32
) ImageContext
.ImageSize
;
660 if (*PeHdrChecksum
) {
665 memcpy (CurrentPe32Section
.Pe32Section
+ 1, (VOID
*) MemoryImagePointerAligned
, (UINT32
) ImageSize
);
667 free ((VOID
*) MemoryImagePointer
);
670 // Now update file checksum
672 if (FfsFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
673 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
678 if (FfsFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
679 SavedState
= FfsFile
->State
;
680 FfsFile
->IntegrityCheck
.Checksum
.File
= 0;
682 if (FfsFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
683 FfsFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
685 GetLength (FfsFile
->Size
) - TailSize
688 FfsFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
691 FfsFile
->State
= SavedState
;
694 // Update tail if present
696 if (FfsFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
697 TailValue
= (EFI_FFS_FILE_TAIL
) (~(FfsFile
->IntegrityCheck
.TailReference
));
698 *(EFI_FFS_FILE_TAIL
*) (((UINTN
) FfsFile
+ GetLength (FfsFile
->Size
) - sizeof (EFI_FFS_FILE_TAIL
))) = TailValue
;
702 // Now process TE sections
704 for (Index
= 1;; Index
++) {
705 Status
= GetSectionByType (FfsFile
, EFI_SECTION_TE
, Index
, &CurrentPe32Section
);
706 if (EFI_ERROR (Status
)) {
713 // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off
716 TEImageHeader
= (EFI_TE_IMAGE_HEADER
*) ((UINT8
*) CurrentPe32Section
.Pe32Section
+ sizeof (EFI_COMMON_SECTION_HEADER
));
718 NewPe32BaseAddress
= ((UINT32
) BaseAddress
) +
720 (UINTN
) CurrentPe32Section
.Pe32Section
+
721 sizeof (EFI_COMMON_SECTION_HEADER
) +
722 sizeof (EFI_TE_IMAGE_HEADER
) -
723 TEImageHeader
->StrippedSize
-
728 // Allocate a buffer to unshrink the image into.
730 Pe32ImageSize
= GetLength (CurrentPe32Section
.Pe32Section
->CommonHeader
.Size
) - sizeof (EFI_PE32_SECTION
) -
731 sizeof (EFI_TE_IMAGE_HEADER
);
732 Pe32ImageSize
+= TEImageHeader
->StrippedSize
;
733 TEBuffer
= (UINT8
*) malloc (Pe32ImageSize
);
734 if (TEBuffer
== NULL
) {
735 Error (NULL
, 0, 0, "failed to allocate memory", NULL
);
736 return EFI_OUT_OF_RESOURCES
;
739 // Expand the image into our buffer and fill in critical fields in the DOS header
740 // Fill in fields required by the loader.
741 // At offset 0x3C is the offset to the PE signature. We'll put it immediately following the offset value
744 memset (TEBuffer
, 0, Pe32ImageSize
);
745 DosHeader
= (EFI_IMAGE_DOS_HEADER
*) TEBuffer
;
746 DosHeader
->e_magic
= EFI_IMAGE_DOS_SIGNATURE
;
747 *(UINT32
*) (TEBuffer
+ 0x3C) = 0x40;
748 PeHdr
= (EFI_IMAGE_NT_HEADERS
*) (TEBuffer
+ 0x40);
749 PeHdr
->Signature
= EFI_IMAGE_NT_SIGNATURE
;
750 PeHdr
->FileHeader
.Machine
= TEImageHeader
->Machine
;
751 PeHdr
->FileHeader
.NumberOfSections
= TEImageHeader
->NumberOfSections
;
754 // 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
755 // the 0x40 bytes for our DOS header.
757 PeHdr
->FileHeader
.SizeOfOptionalHeader
= (UINT16
) (TEImageHeader
->StrippedSize
- 0x40 - sizeof (UINT32
) - sizeof (EFI_IMAGE_FILE_HEADER
));
758 PeHdr
->OptionalHeader
.ImageBase
= (UINTN
) (TEImageHeader
->ImageBase
- TEImageHeader
->StrippedSize
+ sizeof (EFI_TE_IMAGE_HEADER
));
759 PeHdr
->OptionalHeader
.SizeOfImage
= Pe32ImageSize
;
760 PeHdr
->OptionalHeader
.Subsystem
= TEImageHeader
->Subsystem
;
761 PeHdr
->OptionalHeader
.SizeOfImage
= Pe32ImageSize
;
762 PeHdr
->OptionalHeader
.SizeOfHeaders
= TEImageHeader
->StrippedSize
+ TEImageHeader
->NumberOfSections
*
763 sizeof (EFI_IMAGE_SECTION_HEADER
) - 12;
766 // Set NumberOfRvaAndSizes in the optional header to what we had available in the original image
768 if ((TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
!= 0) ||
769 (TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0)
771 PeHdr
->OptionalHeader
.NumberOfRvaAndSizes
= EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
+ 1;
772 PeHdr
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
773 PeHdr
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
776 if ((TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
!= 0) ||
777 (TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0)
779 PeHdr
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
780 PeHdr
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= TEImageHeader
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
781 if (PeHdr
->OptionalHeader
.NumberOfRvaAndSizes
< EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
+ 1) {
782 PeHdr
->OptionalHeader
.NumberOfRvaAndSizes
= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
+ 1;
786 // NOTE: These values are defaults, and should be verified to be correct in the GenTE utility
788 PeHdr
->OptionalHeader
.SectionAlignment
= 0x10;
791 // Copy the rest of the image to its original offset
794 TEBuffer
+ TEImageHeader
->StrippedSize
,
795 (UINT8
*) CurrentPe32Section
.Pe32Section
+ sizeof (EFI_PE32_SECTION
) + sizeof (EFI_TE_IMAGE_HEADER
),
796 GetLength (CurrentPe32Section
.Pe32Section
->CommonHeader
.Size
) - sizeof (EFI_PE32_SECTION
) -
797 sizeof (EFI_TE_IMAGE_HEADER
)
801 // Initialize context
803 memset (&ImageContext
, 0, sizeof (ImageContext
));
804 ImageContext
.Handle
= (VOID
*) TEBuffer
;
805 ImageContext
.ImageRead
= (EFI_PEI_PE_COFF_LOADER_READ_FILE
) FfsRebaseImageRead
;
807 Status
= mPeCoffLoader
.GetImageInfo (&mPeCoffLoader
, &ImageContext
);
809 if (EFI_ERROR (Status
)) {
810 Error (NULL
, 0, 0, "GetImageInfo() call failed on rebase of TE image", FileGuidString
);
815 // Allocate a buffer for the image to be loaded into.
817 MemoryImagePointer
= (UINTN
) (malloc (Pe32ImageSize
+ 0x1000));
818 if (MemoryImagePointer
== 0) {
819 Error (NULL
, 0, 0, "memory allocation error on rebase of TE image", FileGuidString
);
821 return EFI_OUT_OF_RESOURCES
;
823 memset ((void *) MemoryImagePointer
, 0, Pe32ImageSize
+ 0x1000);
824 MemoryImagePointerAligned
= (MemoryImagePointer
+ 0x0FFF) & (-1 << 12);
827 ImageContext
.ImageAddress
= MemoryImagePointerAligned
;
828 Status
= mPeCoffLoader
.LoadImage (&mPeCoffLoader
, &ImageContext
);
829 if (EFI_ERROR (Status
)) {
830 Error (NULL
, 0, 0, "LoadImage() call failed on rebase of TE image", FileGuidString
);
832 free ((VOID
*) MemoryImagePointer
);
836 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
837 Status
= mPeCoffLoader
.RelocateImage (&mPeCoffLoader
, &ImageContext
);
838 if (EFI_ERROR (Status
)) {
839 Error (NULL
, 0, 0, "RelocateImage() call failed on rebase of TE image", FileGuidString
);
840 free ((VOID
*) MemoryImagePointer
);
845 ImageAddress
= ImageContext
.ImageAddress
;
846 ImageSize
= ImageContext
.ImageSize
;
847 EntryPoint
= ImageContext
.EntryPoint
;
850 // Since we may have updated the Codeview RVA, we need to insure the PE
851 // header indicates the image is large enough to contain the Codeview data
852 // so it will be loaded properly later if the PEIM is reloaded into memory...
854 PeHdr
= (VOID
*) ((UINTN
) ImageAddress
+ ImageContext
.PeCoffHeaderOffset
);
855 if (PeHdr
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
) {
856 PeHdrSizeOfImage
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER32
*) &PeHdr
->OptionalHeader
).SizeOfImage
);
857 PeHdrChecksum
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER32
*) &PeHdr
->OptionalHeader
).CheckSum
);
858 } else if (PeHdr
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
) {
859 PeHdrSizeOfImage
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER64
*) &PeHdr
->OptionalHeader
).SizeOfImage
);
860 PeHdrChecksum
= (UINT32
*) (&(*(EFI_IMAGE_OPTIONAL_HEADER64
*) &PeHdr
->OptionalHeader
).CheckSum
);
866 "unknown machine type in TE image",
867 "machine type=0x%X, file=%s",
868 (UINT32
) PeHdr
->FileHeader
.Machine
,
871 free ((VOID
*) MemoryImagePointer
);
876 if (*PeHdrSizeOfImage
!= ImageContext
.ImageSize
) {
877 *PeHdrSizeOfImage
= (UINT32
) ImageContext
.ImageSize
;
878 if (*PeHdrChecksum
) {
883 TEImageHeader
->ImageBase
= (UINT64
) (NewPe32BaseAddress
+ TEImageHeader
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
));
885 (UINT8
*) (CurrentPe32Section
.Pe32Section
+ 1) + sizeof (EFI_TE_IMAGE_HEADER
),
886 (VOID
*) ((UINT8
*) MemoryImagePointerAligned
+ TEImageHeader
->StrippedSize
),
887 GetLength (CurrentPe32Section
.Pe32Section
->CommonHeader
.Size
) - sizeof (EFI_PE32_SECTION
) -
888 sizeof (EFI_TE_IMAGE_HEADER
)
890 free ((VOID
*) MemoryImagePointer
);
892 if (FfsFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
893 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
898 // Now update file checksum
900 if (FfsFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
901 SavedState
= FfsFile
->State
;
902 FfsFile
->IntegrityCheck
.Checksum
.File
= 0;
904 if (FfsFile
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
905 FfsFile
->IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
907 GetLength (FfsFile
->Size
) - TailSize
910 FfsFile
->IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
913 FfsFile
->State
= SavedState
;
916 // Update tail if present
918 if (FfsFile
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
919 TailValue
= (EFI_FFS_FILE_TAIL
) (~(FfsFile
->IntegrityCheck
.TailReference
));
920 *(EFI_FFS_FILE_TAIL
*) (((UINTN
) FfsFile
+ GetLength (FfsFile
->Size
) - sizeof (EFI_FFS_FILE_TAIL
))) = TailValue
;
924 // If we found no files, then emit an error if no compressed sections either
926 if (FoundCount
== 0) {
927 Status
= GetSectionByType (FfsFile
, EFI_SECTION_COMPRESSION
, Index
, &CurrentPe32Section
);
928 if (EFI_ERROR (Status
)) {
929 Error (NULL
, 0, 0, "no PE32, TE, nor compressed section found in FV file", FileGuidString
);
930 return EFI_NOT_FOUND
;
941 IN OUT UINT32
*ReadSize
,
948 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
952 FileHandle - The handle to the PE/COFF file
954 FileOffset - The offset, in bytes, into the file to read
956 ReadSize - The number of bytes to read from the file starting at FileOffset
958 Buffer - A pointer to the buffer to read the data into.
962 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
970 Destination8
= Buffer
;
971 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
974 *(Destination8
++) = *(Source8
++);