3 Copyright (c) 2004 - 2010, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Converts a pe32+ image to an FW, Te image type, or other specific image.
22 #include "WinNtInclude.h"
27 #include <sys/types.h>
36 #include <Common/UefiBaseTypes.h>
37 #include <IndustryStandard/PeImage.h>
38 #include <Common/UefiInternalFormRepresentation.h>
41 // Acpi Table definition
43 #include <IndustryStandard/Acpi.h>
44 #include <IndustryStandard/Acpi1_0.h>
45 #include <IndustryStandard/Acpi2_0.h>
46 #include <IndustryStandard/Acpi3_0.h>
47 #include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
49 #include "CommonLib.h"
50 #include "PeCoffLib.h"
52 #include "EfiUtilityMsgs.h"
54 #include "elf_common.h"
60 // Version of this utility
62 #define UTILITY_NAME "GenFw"
63 #define UTILITY_MAJOR_VERSION 0
64 #define UTILITY_MINOR_VERSION 2
66 #define HII_RESOURCE_SECTION_INDEX 1
67 #define HII_RESOURCE_SECTION_NAME "HII"
69 // Action for this tool.
71 #define FW_DUMMY_IMAGE 0
72 #define FW_EFI_IMAGE 1
74 #define FW_ACPI_IMAGE 3
75 #define FW_BIN_IMAGE 4
76 #define FW_ZERO_DEBUG_IMAGE 5
77 #define FW_SET_STAMP_IMAGE 6
78 #define FW_MCI_IMAGE 7
79 #define FW_MERGE_IMAGE 8
80 #define FW_RELOC_STRIPEED_IMAGE 9
81 #define FW_HII_PACKAGE_LIST_RCIMAGE 10
82 #define FW_HII_PACKAGE_LIST_BINIMAGE 11
83 #define FW_REBASE_IMAGE 12
84 #define FW_SET_ADDRESS_IMAGE 13
86 #define DUMP_TE_HEADER 0x11
88 #define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
89 #define DEFAULT_MC_ALIGNMENT 16
95 #define STATUS_IGNORE 0xA
97 // Structure definition for a microcode header
100 UINT32 HeaderVersion
;
105 UINT32 LoaderVersion
;
107 UINT32 DataSize
; // if 0, then TotalSize = 2048, and TotalSize field is invalid
108 UINT32 TotalSize
; // number of bytes
110 } MICROCODE_IMAGE_HEADER
;
112 static EFI_GUID mZeroGuid
= {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
114 static const char *gHiiPackageRCFileHeader
[] = {
116 "// DO NOT EDIT -- auto-generated file",
121 STATIC CHAR8
*mInImageName
;
124 // Module image information
126 STATIC UINT32 mImageTimeStamp
= 0;
127 STATIC UINT32 mImageSize
= 0;
132 IN OUT UINT8
*FileBuffer
,
139 IN OUT UINT8
*FileBuffer
,
159 Print out version information for this utility.
171 fprintf (stdout
, "%s Version %d.%d\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
);
198 fprintf (stdout
, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME
);
201 // Copyright declaration
203 fprintf (stdout
, "Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.\n\n");
208 fprintf (stdout
, "Options:\n");
209 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
210 File will be created to store the ouput content.\n");
211 fprintf (stdout
, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\
212 Create Efi Image. EFI_FILETYPE is one of BASE,SMM_CORE,\n\
213 PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\
214 SEC, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER,\n\
215 DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER,\n\
216 PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\
217 APPLICATION, SAL_RT_DRIVER to support all module types\n\
218 It can only be used together with --keepexceptiontable,\n\
219 --keepzeropending, -r, -o option.It is a action option.\n\
220 If it is combined with other action options, the later\n\
221 input action option will override the previous one.\n");
222 fprintf (stdout
, " -c, --acpi Create Acpi table.\n\
223 It can't be combined with other action options\n\
224 except for -o, -r option. It is a action option.\n\
225 If it is combined with other action options, the later\n\
226 input action option will override the previous one.\n");
227 fprintf (stdout
, " -t, --terse Create Te Image.\n\
228 It can only be used together with --keepexceptiontable,\n\
229 --keepzeropending, -r, -o option.It is a action option.\n\
230 If it is combined with other action options, the later\n\
231 input action option will override the previous one.\n");
232 fprintf (stdout
, " -u, --dump Dump TeImage Header.\n\
233 It can't be combined with other action options\n\
234 except for -o, -r option. It is a action option.\n\
235 If it is combined with other action options, the later\n\
236 input action option will override the previous one.\n");
237 fprintf (stdout
, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\
238 It also zeros the time stamp fields.\n\
239 This option can be used to compare the binary efi image.\n\
240 It can't be combined with other action options\n\
241 except for -o, -r option. It is a action option.\n\
242 If it is combined with other action options, the later\n\
243 input action option will override the previous one.\n");
244 fprintf (stdout
, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\
245 It can't be combined with other action options\n\
246 except for -o, -r option. It is a action option.\n\
247 If it is combined with other action options, the later\n\
248 input action option will override the previous one.\n");;
249 fprintf (stdout
, " -l, --stripped Strip off the relocation info from PE or TE image.\n\
250 It can't be combined with other action options\n\
251 except for -o, -r option. It is a action option.\n\
252 If it is combined with other action options, the later\n\
253 input action option will override the previous one.\n");
254 fprintf (stdout
, " -s timedate, --stamp timedate\n\
255 timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\
256 is set to NOW, current system time is used. The support\n\
257 date scope is 1970-01-01 00+timezone:00:00\n\
258 ~ 2038-01-19 03+timezone:14:07\n\
259 The scope is adjusted according to the different zones.\n\
260 It can't be combined with other action options\n\
261 except for -o, -r option. It is a action option.\n\
262 If it is combined with other action options, the later\n\
263 input action option will override the previous one.\n");
264 fprintf (stdout
, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\
265 It can't be combined with other action options\n\
266 except for -o option. It is a action option.\n\
267 If it is combined with other action options, the later\n\
268 input action option will override the previous one.\n");
269 fprintf (stdout
, " -j, --join Combine multi microcode bin files to one file.\n\
270 It can be specified with -a, -p, -o option.\n\
271 No other options can be combined with it.\n\
272 If it is combined with other action options, the later\n\
273 input action option will override the previous one.\n");
274 fprintf (stdout
, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\
275 This option is only used together with -j option.\n");
276 fprintf (stdout
, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\
277 This option is only used together with -j option.\n");
278 fprintf (stdout
, " --keepexceptiontable Don't clear exception table.\n\
279 This option can be used together with -e or -t.\n\
280 It doesn't work for other options.\n");
281 fprintf (stdout
, " --keepzeropending Don't strip zero pending of .reloc.\n\
282 This option can be used together with -e or -t.\n\
283 It doesn't work for other options.\n");
284 fprintf (stdout
, " -r, --replace Overwrite the input file with the output content.\n\
285 If more input files are specified,\n\
286 the last input file will be as the output file.\n");
287 fprintf (stdout
, " -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\
288 Guid is used to specify hii package list guid.\n\
289 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\
290 If not specified, the first Form FormSet guid is used.\n");
291 fprintf (stdout
, " --hiipackage Combine all input binary hii pacakges into \n\
292 a single package list as the text resource data(RC).\n\
293 It can't be combined with other action options\n\
294 except for -o option. It is a action option.\n\
295 If it is combined with other action options, the later\n\
296 input action option will override the previous one.\n");
297 fprintf (stdout
, " --hiibinpackage Combine all input binary hii pacakges into \n\
298 a single package list as the binary resource section.\n\
299 It can't be combined with other action options\n\
300 except for -o option. It is a action option.\n\
301 If it is combined with other action options, the later\n\
302 input action option will override the previous one.\n");
303 fprintf (stdout
, " --rebase NewAddress Rebase image to new base address. New address \n\
304 is also set to the first none code section header.\n\
305 It can't be combined with other action options\n\
306 except for -o or -r option. It is a action option.\n\
307 If it is combined with other action options, the later\n\
308 input action option will override the previous one.\n");
309 fprintf (stdout
, " --address NewAddress Set new address into the first none code \n\
310 section header of the input image.\n\
311 It can't be combined with other action options\n\
312 except for -o or -r option. It is a action option.\n\
313 If it is combined with other action options, the later\n\
314 input action option will override the previous one.\n");
315 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
316 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
317 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
318 fprintf (stdout
, " --version Show program's version number and exit\n");
319 fprintf (stdout
, " -h, --help Show this help message and exit\n");
336 AcpiTable Buffer for AcpiSection
337 Length AcpiSection Length
346 EFI_ACPI_DESCRIPTION_HEADER
*AcpiHeader
;
347 EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs
;
348 UINT32 ExpectedLength
;
350 AcpiHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTable
;
353 // Generic check for AcpiTable length.
355 if (AcpiHeader
->Length
> Length
) {
356 Error (NULL
, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL
);
361 // Currently, we only check must-have tables: FADT, FACS, DSDT,
362 // and some important tables: MADT, MCFG.
364 switch (AcpiHeader
->Signature
) {
367 // "FACP" Fixed ACPI Description Table
369 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
:
370 switch (AcpiHeader
->Revision
) {
371 case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
372 ExpectedLength
= sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
);
374 case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
375 ExpectedLength
= sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
);
377 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
378 ExpectedLength
= sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
);
381 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
) {
382 ExpectedLength
= AcpiHeader
->Length
;
385 Error (NULL
, 0, 3000, "Invalid", "FACP revision check failed.");
388 if (ExpectedLength
!= AcpiHeader
->Length
) {
389 Error (NULL
, 0, 3000, "Invalid", "FACP length check failed.");
395 // "FACS" Firmware ACPI Control Structure
397 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE
:
398 Facs
= (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)AcpiTable
;
399 if (Facs
->Version
> EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) {
402 if ((Facs
->Version
!= EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
403 (Facs
->Version
!= EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
404 (Facs
->Version
!= EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
)){
405 Error (NULL
, 0, 3000, "Invalid", "FACS version check failed.");
408 if ((Facs
->Length
!= sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
409 (Facs
->Length
!= sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
410 (Facs
->Length
!= sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
))) {
411 Error (NULL
, 0, 3000, "Invalid", "FACS length check failed.");
417 // "DSDT" Differentiated System Description Table
419 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
420 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION
) {
423 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
)) {
424 Error (NULL
, 0, 3000, "Invalid", "DSDT length check failed.");
430 // "APIC" Multiple APIC Description Table
432 case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE
:
433 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) {
436 if ((AcpiHeader
->Revision
!= EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
437 (AcpiHeader
->Revision
!= EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
438 (AcpiHeader
->Revision
!= EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
)) {
439 Error (NULL
, 0, 3000, "Invalid", "APIC revision check failed.");
442 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT32
) + sizeof(UINT32
)) {
443 Error (NULL
, 0, 3000, "Invalid", "APIC length check failed.");
449 // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
451 case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE
:
452 if (AcpiHeader
->Revision
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
455 if (AcpiHeader
->Revision
!= EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
456 Error (NULL
, 0, 3000, "Invalid", "MCFG revision check failed.");
459 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT64
)) {
460 Error (NULL
, 0, 3000, "Invalid", "MCFG length check failed.");
466 // Other table pass check
472 return STATUS_SUCCESS
;
481 return (FileBuffer
[EI_MAG0
] == ELFMAG0
482 && FileBuffer
[EI_MAG1
] == ELFMAG1
483 && FileBuffer
[EI_MAG2
] == ELFMAG2
484 && FileBuffer
[EI_MAG3
] == ELFMAG3
);
487 typedef Elf32_Shdr Elf_Shdr
;
488 typedef Elf32_Ehdr Elf_Ehdr
;
489 typedef Elf32_Rel Elf_Rel
;
490 typedef Elf32_Sym Elf_Sym
;
491 typedef Elf32_Phdr Elf_Phdr
;
492 typedef Elf32_Dyn Elf_Dyn
;
494 #define ELFCLASS ELFCLASS32
495 #define ELF_R_TYPE(r) ELF32_R_TYPE(r)
496 #define ELF_R_SYM(r) ELF32_R_SYM(r)
497 #define ELF_HII_SECTION_NAME ".hii"
499 // Well known ELF structures.
506 // PE section alignment.
508 const UINT32 CoffAlignment
= 0x20;
509 const UINT16 CoffNbrSections
= 5;
512 // Current offset in coff file.
517 // Result Coff file in memory.
519 UINT8
*CoffFile
= NULL
;
521 // ELF sections to offset in Coff file.
523 UINT32
*CoffSectionsOffset
= NULL
;
526 // Offset in Coff file of headers and sections.
532 UINT32 HiiRsrcOffset
;
535 EFI_IMAGE_BASE_RELOCATION
*CoffBaseRel
;
536 UINT16
*CoffEntryRel
;
543 return (Offset
+ CoffAlignment
- 1) & ~(CoffAlignment
- 1);
551 if (Num
>= Ehdr
->e_shnum
)
553 return (Elf_Shdr
*)((UINT8
*)ShdrBase
+ Num
* Ehdr
->e_shentsize
);
562 // Note: Magic has already been tested.
564 if (Ehdr
->e_ident
[EI_CLASS
] != ELFCLASS
) {
565 Error (NULL
, 0, 3000, "Unsupported", "%s needs to be ported for 64-bit ELF.", mInImageName
);
568 if (Ehdr
->e_ident
[EI_DATA
] != ELFDATA2LSB
) {
569 Error (NULL
, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");
572 if ((Ehdr
->e_type
!= ET_EXEC
) && (Ehdr
->e_type
!= ET_DYN
)) {
573 Error (NULL
, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");
576 if (!((Ehdr
->e_machine
== EM_386
) || (Ehdr
->e_machine
== EM_ARM
))) {
577 Error (NULL
, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM");
580 if (Ehdr
->e_version
!= EV_CURRENT
) {
581 Error (NULL
, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) Ehdr
->e_version
, EV_CURRENT
);
586 // Find the section header table
588 ShdrBase
= (Elf_Shdr
*)((UINT8
*)Ehdr
+ Ehdr
->e_shoff
);
589 gPhdrBase
= (Elf_Phdr
*)((UINT8
*)Ehdr
+ Ehdr
->e_phoff
);
591 CoffSectionsOffset
= (UINT32
*)malloc(Ehdr
->e_shnum
* sizeof (UINT32
));
593 memset(CoffSectionsOffset
, 0, Ehdr
->e_shnum
* sizeof(UINT32
));
602 return (Shdr
->sh_flags
& (SHF_WRITE
| SHF_ALLOC
)) == SHF_ALLOC
;
610 Elf_Shdr
*Namedr
= GetShdrByIndex(Ehdr
->e_shstrndx
);
612 if (strcmp((CHAR8
*)Ehdr
+ Namedr
->sh_offset
+ Shdr
->sh_name
, ELF_HII_SECTION_NAME
) == 0) {
624 if (IsHiiRsrcShdr(Shdr
)) {
627 return (Shdr
->sh_flags
& (SHF_WRITE
| SHF_ALLOC
)) == (SHF_ALLOC
| SHF_WRITE
);
638 EFI_IMAGE_SECTION_HEADER
*Hdr
;
639 Hdr
= (EFI_IMAGE_SECTION_HEADER
*)(CoffFile
+ TableOffset
);
641 strcpy((char *)Hdr
->Name
, Name
);
642 Hdr
->Misc
.VirtualSize
= Size
;
643 Hdr
->VirtualAddress
= Offset
;
644 Hdr
->SizeOfRawData
= Size
;
645 Hdr
->PointerToRawData
= Offset
;
646 Hdr
->PointerToRelocations
= 0;
647 Hdr
->PointerToLinenumbers
= 0;
648 Hdr
->NumberOfRelocations
= 0;
649 Hdr
->NumberOfLinenumbers
= 0;
650 Hdr
->Characteristics
= Flags
;
652 TableOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
656 SetHiiResourceHeader (
662 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
663 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*ResourceDirectoryEntry
;
664 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
665 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
668 // Fill Resource section entry
670 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
);
671 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
672 for (Index
= 0; Index
< ResourceDirectory
->NumberOfNamedEntries
; Index
++) {
673 if (ResourceDirectoryEntry
->u1
.s
.NameIsString
) {
674 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiBinData
+ ResourceDirectoryEntry
->u1
.s
.NameOffset
);
676 if (ResourceDirectoryString
->Length
== 3 &&
677 ResourceDirectoryString
->String
[0] == L
'H' &&
678 ResourceDirectoryString
->String
[1] == L
'I' &&
679 ResourceDirectoryString
->String
[2] == L
'I') {
681 // Resource Type "HII" found
683 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
685 // Move to next level - resource Name
687 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
688 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
690 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
692 // Move to next level - resource Language
694 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
695 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
700 // Now it ought to be resource Data and update its OffsetToData value
702 if (!ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
703 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.OffsetToData
);
704 ResourceDataEntry
->OffsetToData
= ResourceDataEntry
->OffsetToData
+ OffsetToFile
;
709 ResourceDirectoryEntry
++;
721 EFI_IMAGE_DOS_HEADER
*DosHdr
;
722 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
729 // Coff file start with a DOS header.
731 CoffOffset
= sizeof(EFI_IMAGE_DOS_HEADER
) + 0x40;
732 NtHdrOffset
= CoffOffset
;
733 switch (Ehdr
->e_machine
) {
736 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS32
);
740 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS64
);
743 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN
)Ehdr
->e_machine
);
744 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS32
);
748 TableOffset
= CoffOffset
;
749 CoffOffset
+= CoffNbrSections
* sizeof(EFI_IMAGE_SECTION_HEADER
);
752 // First text sections.
754 CoffOffset
= CoffAlign(CoffOffset
);
755 TextOffset
= CoffOffset
;
756 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
757 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
758 if (IsTextShdr(shdr
)) {
759 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
760 // the alignment field is valid
761 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
762 // if the section address is aligned we must align PE/COFF
763 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
764 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
765 // ARM RVCT tools have behavior outside of the ELF specification to try
766 // and make images smaller. If sh_addr is not aligned to sh_addralign
767 // then the section needs to preserve sh_addr MOD sh_addralign.
768 // Normally doing nothing here works great.
769 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
773 /* Relocate entry. */
774 if ((Ehdr
->e_entry
>= shdr
->sh_addr
) &&
775 (Ehdr
->e_entry
< shdr
->sh_addr
+ shdr
->sh_size
)) {
776 CoffEntry
= CoffOffset
+ Ehdr
->e_entry
- shdr
->sh_addr
;
778 CoffSectionsOffset
[i
] = CoffOffset
;
779 CoffOffset
+= shdr
->sh_size
;
783 if (Ehdr
->e_machine
!= EM_ARM
) {
784 CoffOffset
= CoffAlign(CoffOffset
);
788 // Then data sections.
790 DataOffset
= CoffOffset
;
791 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
792 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
793 if (IsDataShdr(shdr
)) {
794 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
795 // the alignment field is valid
796 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
797 // if the section address is aligned we must align PE/COFF
798 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
799 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
800 // ARM RVCT tools have behavior outside of the ELF specification to try
801 // and make images smaller. If sh_addr is not aligned to sh_addralign
802 // then the section needs to preserve sh_addr MOD sh_addralign.
803 // Normally doing nothing here works great.
804 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
807 CoffSectionsOffset
[i
] = CoffOffset
;
808 CoffOffset
+= shdr
->sh_size
;
811 CoffOffset
= CoffAlign(CoffOffset
);
814 // The HII resource sections.
816 HiiRsrcOffset
= CoffOffset
;
817 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
818 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
819 if (IsHiiRsrcShdr(shdr
)) {
820 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
821 // the alignment field is valid
822 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
823 // if the section address is aligned we must align PE/COFF
824 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
825 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
826 // ARM RVCT tools have behavior outside of the ELF specification to try
827 // and make images smaller. If sh_addr is not aligned to sh_addralign
828 // then the section needs to preserve sh_addr MOD sh_addralign.
829 // Normally doing nothing here works great.
830 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
833 if (shdr
->sh_size
!= 0) {
834 CoffSectionsOffset
[i
] = CoffOffset
;
835 CoffOffset
+= shdr
->sh_size
;
836 CoffOffset
= CoffAlign(CoffOffset
);
837 SetHiiResourceHeader ((UINT8
*) Ehdr
+ shdr
->sh_offset
, HiiRsrcOffset
);
843 RelocOffset
= CoffOffset
;
846 // Allocate base Coff file. Will be expanded later for relocations.
848 CoffFile
= (UINT8
*)malloc(CoffOffset
);
849 memset(CoffFile
, 0, CoffOffset
);
854 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)CoffFile
;
855 DosHdr
->e_magic
= EFI_IMAGE_DOS_SIGNATURE
;
856 DosHdr
->e_lfanew
= NtHdrOffset
;
858 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
860 NtHdr
->Pe32
.Signature
= EFI_IMAGE_NT_SIGNATURE
;
862 switch (Ehdr
->e_machine
) {
864 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IA32
;
865 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
868 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_X64
;
869 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
872 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IPF
;
873 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
876 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_ARMT
;
877 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
880 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN
)Ehdr
->e_machine
);
881 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IA32
;
882 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
885 NtHdr
->Pe32
.FileHeader
.NumberOfSections
= CoffNbrSections
;
886 NtHdr
->Pe32
.FileHeader
.TimeDateStamp
= (UINT32
) time(NULL
);
887 mImageTimeStamp
= NtHdr
->Pe32
.FileHeader
.TimeDateStamp
;
888 NtHdr
->Pe32
.FileHeader
.PointerToSymbolTable
= 0;
889 NtHdr
->Pe32
.FileHeader
.NumberOfSymbols
= 0;
890 NtHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
= sizeof(NtHdr
->Pe32
.OptionalHeader
);
891 NtHdr
->Pe32
.FileHeader
.Characteristics
= EFI_IMAGE_FILE_EXECUTABLE_IMAGE
892 | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED
893 | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED
894 | EFI_IMAGE_FILE_32BIT_MACHINE
;
896 NtHdr
->Pe32
.OptionalHeader
.SizeOfCode
= DataOffset
- TextOffset
;
897 NtHdr
->Pe32
.OptionalHeader
.SizeOfInitializedData
= RelocOffset
- DataOffset
;
898 NtHdr
->Pe32
.OptionalHeader
.SizeOfUninitializedData
= 0;
899 NtHdr
->Pe32
.OptionalHeader
.AddressOfEntryPoint
= CoffEntry
;
901 NtHdr
->Pe32
.OptionalHeader
.BaseOfCode
= TextOffset
;
903 NtHdr
->Pe32
.OptionalHeader
.BaseOfData
= DataOffset
;
904 NtHdr
->Pe32
.OptionalHeader
.ImageBase
= 0;
905 NtHdr
->Pe32
.OptionalHeader
.SectionAlignment
= CoffAlignment
;
906 NtHdr
->Pe32
.OptionalHeader
.FileAlignment
= CoffAlignment
;
907 NtHdr
->Pe32
.OptionalHeader
.SizeOfImage
= 0;
909 NtHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
= TextOffset
;
910 NtHdr
->Pe32
.OptionalHeader
.NumberOfRvaAndSizes
= EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES
;
915 if ((DataOffset
- TextOffset
) > 0) {
916 CreateSectionHeader (".text", TextOffset
, DataOffset
- TextOffset
,
917 EFI_IMAGE_SCN_CNT_CODE
918 | EFI_IMAGE_SCN_MEM_EXECUTE
919 | EFI_IMAGE_SCN_MEM_READ
);
921 // Don't make a section of size 0.
922 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
925 if ((HiiRsrcOffset
- DataOffset
) > 0) {
926 CreateSectionHeader (".data", DataOffset
, HiiRsrcOffset
- DataOffset
,
927 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
928 | EFI_IMAGE_SCN_MEM_WRITE
929 | EFI_IMAGE_SCN_MEM_READ
);
931 // Don't make a section of size 0.
932 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
935 if ((RelocOffset
- HiiRsrcOffset
) > 0) {
936 CreateSectionHeader (".rsrc", HiiRsrcOffset
, RelocOffset
- HiiRsrcOffset
,
937 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
938 | EFI_IMAGE_SCN_MEM_READ
);
940 NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= RelocOffset
- HiiRsrcOffset
;
941 NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= HiiRsrcOffset
;
943 // Don't make a section of size 0.
944 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
951 int (*Filter
)(Elf_Shdr
*)
959 // First: copy sections.
961 for (Idx
= 0; Idx
< Ehdr
->e_shnum
; Idx
++) {
962 Elf_Shdr
*Shdr
= GetShdrByIndex(Idx
);
963 if ((*Filter
)(Shdr
)) {
964 switch (Shdr
->sh_type
) {
967 memcpy(CoffFile
+ CoffSectionsOffset
[Idx
],
968 (UINT8
*)Ehdr
+ Shdr
->sh_offset
,
973 memset(CoffFile
+ CoffSectionsOffset
[Idx
], 0, Shdr
->sh_size
);
978 // Ignore for unkown section type.
980 VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName
, (unsigned)Shdr
->sh_type
);
987 // Second: apply relocations.
989 for (Idx
= 0; Idx
< Ehdr
->e_shnum
; Idx
++) {
990 Elf_Shdr
*RelShdr
= GetShdrByIndex(Idx
);
991 if (RelShdr
->sh_type
!= SHT_REL
)
993 SecShdr
= GetShdrByIndex(RelShdr
->sh_info
);
994 SecOffset
= CoffSectionsOffset
[RelShdr
->sh_info
];
995 if (RelShdr
->sh_type
== SHT_REL
&& (*Filter
)(SecShdr
)) {
997 Elf_Shdr
*SymtabShdr
= GetShdrByIndex(RelShdr
->sh_link
);
998 UINT8
*Symtab
= (UINT8
*)Ehdr
+ SymtabShdr
->sh_offset
;
1000 for (RelIdx
= 0; RelIdx
< RelShdr
->sh_size
; RelIdx
+= RelShdr
->sh_entsize
) {
1001 Elf_Rel
*Rel
= (Elf_Rel
*)((UINT8
*)Ehdr
+ RelShdr
->sh_offset
+ RelIdx
);
1002 Elf_Sym
*Sym
= (Elf_Sym
*)(Symtab
+ ELF_R_SYM(Rel
->r_info
) * SymtabShdr
->sh_entsize
);
1006 if (Sym
->st_shndx
== SHN_UNDEF
1007 || Sym
->st_shndx
== SHN_ABS
1008 || Sym
->st_shndx
> Ehdr
->e_shnum
) {
1009 Error (NULL
, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName
);
1011 SymShdr
= GetShdrByIndex(Sym
->st_shndx
);
1014 // Note: r_offset in a memory address.
1015 // Convert it to a pointer in the coff file.
1017 Targ
= CoffFile
+ SecOffset
+ (Rel
->r_offset
- SecShdr
->sh_addr
);
1019 if (Ehdr
->e_machine
== EM_386
) {
1020 switch (ELF_R_TYPE(Rel
->r_info
)) {
1025 // Absolute relocation.
1027 *(UINT32
*)Targ
= *(UINT32
*)Targ
- SymShdr
->sh_addr
1028 + CoffSectionsOffset
[Sym
->st_shndx
];
1032 // Relative relocation: Symbol - Ip + Addend
1034 *(UINT32
*)Targ
= *(UINT32
*)Targ
1035 + (CoffSectionsOffset
[Sym
->st_shndx
] - SymShdr
->sh_addr
)
1036 - (SecOffset
- SecShdr
->sh_addr
);
1039 Error (NULL
, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName
, (unsigned) ELF_R_TYPE(Rel
->r_info
));
1041 } else if (Ehdr
->e_machine
== EM_ARM
) {
1042 switch (ELF32_R_TYPE(Rel
->r_info
)) {
1043 case R_ARM_RBASE
: // No relocation - no action required
1045 // Thease are all PC-relative relocations and don't require modification
1048 case R_ARM_THM_PC22
:
1049 case R_ARM_THM_JUMP19
:
1056 // Absolute relocation.
1058 *(UINT32
*)Targ
= *(UINT32
*)Targ
- SymShdr
->sh_addr
+ CoffSectionsOffset
[Sym
->st_shndx
];
1061 Error (NULL
, 0, 3000, "Invalid", "WriteSections (): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName
, (unsigned) ELF32_R_TYPE(Rel
->r_info
));
1074 *CoffEntryRel
= Val
;
1076 CoffBaseRel
->SizeOfBlock
+= 2;
1086 if (CoffBaseRel
== NULL
1087 || CoffBaseRel
->VirtualAddress
!= (Offset
& ~0xfff)) {
1088 if (CoffBaseRel
!= NULL
) {
1090 // Add a null entry (is it required ?)
1092 CoffAddFixupEntry (0);
1094 // Pad for alignment.
1096 if (CoffOffset
% 4 != 0)
1097 CoffAddFixupEntry (0);
1102 CoffOffset
+ sizeof(EFI_IMAGE_BASE_RELOCATION
) + 2*0x1000);
1103 memset(CoffFile
+ CoffOffset
, 0,
1104 sizeof(EFI_IMAGE_BASE_RELOCATION
) + 2*0x1000);
1106 CoffBaseRel
= (EFI_IMAGE_BASE_RELOCATION
*)(CoffFile
+ CoffOffset
);
1107 CoffBaseRel
->VirtualAddress
= Offset
& ~0xfff;
1108 CoffBaseRel
->SizeOfBlock
= sizeof(EFI_IMAGE_BASE_RELOCATION
);
1110 CoffEntryRel
= (UINT16
*)(CoffBaseRel
+ 1);
1111 CoffOffset
+= sizeof(EFI_IMAGE_BASE_RELOCATION
);
1117 CoffAddFixupEntry((UINT16
) ((Type
<< 12) | (Offset
& 0xfff)));
1126 if (num
>= Ehdr
->e_phnum
) {
1130 return (Elf32_Phdr
*)((UINT8
*)gPhdrBase
+ num
* Ehdr
->e_phentsize
);
1140 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1141 EFI_IMAGE_DATA_DIRECTORY
*Dir
;
1142 BOOLEAN FoundRelocations
;
1145 UINTN RelElementSize
;
1150 Elf32_Phdr
*DynamicSegment
;
1151 Elf32_Phdr
*TargetSegment
;
1153 for (Index
= 0, FoundRelocations
= FALSE
; Index
< Ehdr
->e_shnum
; Index
++) {
1154 Elf_Shdr
*RelShdr
= GetShdrByIndex(Index
);
1155 if (RelShdr
->sh_type
== SHT_REL
) {
1156 Elf_Shdr
*SecShdr
= GetShdrByIndex(RelShdr
->sh_info
);
1157 if (IsTextShdr(SecShdr
) || IsDataShdr(SecShdr
)) {
1159 FoundRelocations
= TRUE
;
1160 for (RelIdx
= 0; RelIdx
< RelShdr
->sh_size
; RelIdx
+= RelShdr
->sh_entsize
) {
1161 Elf_Rel
*Rel
= (Elf_Rel
*)
1162 ((UINT8
*)Ehdr
+ RelShdr
->sh_offset
+ RelIdx
);
1164 if (Ehdr
->e_machine
== EM_386
) {
1165 switch (ELF_R_TYPE(Rel
->r_info
)) {
1170 CoffAddFixup(CoffSectionsOffset
[RelShdr
->sh_info
]
1171 + (Rel
->r_offset
- SecShdr
->sh_addr
),
1172 EFI_IMAGE_REL_BASED_HIGHLOW
);
1175 Error (NULL
, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName
, (unsigned) ELF_R_TYPE(Rel
->r_info
));
1177 } else if (Ehdr
->e_machine
== EM_ARM
) {
1178 switch (ELF32_R_TYPE(Rel
->r_info
)) {
1179 case R_ARM_RBASE
: // No relocation - no action required
1181 // Thease are all PC-relative relocations and don't require modification
1184 case R_ARM_THM_PC22
:
1185 case R_ARM_THM_JUMP19
:
1191 CoffSectionsOffset
[RelShdr
->sh_info
]
1192 + (Rel
->r_offset
- SecShdr
->sh_addr
),
1193 EFI_IMAGE_REL_BASED_HIGHLOW
1198 Error (NULL
, 0, 3000, "Invalid", "WriteRelocations(): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName
, (unsigned) ELF32_R_TYPE(Rel
->r_info
));
1201 Error (NULL
, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) Ehdr
->e_machine
);
1208 if (!FoundRelocations
&& (Ehdr
->e_machine
== EM_ARM
)) {
1209 /* Try again, but look for PT_DYNAMIC instead of SHT_REL */
1211 for (Index
= 0; Index
< Ehdr
->e_phnum
; Index
++) {
1216 DynamicSegment
= GetPhdrByIndex (Index
);
1218 if (DynamicSegment
->p_type
== PT_DYNAMIC
) {
1219 Dyn
= (Elf32_Dyn
*) ((UINT8
*)Ehdr
+ DynamicSegment
->p_offset
);
1221 while (Dyn
->d_tag
!= DT_NULL
) {
1222 switch (Dyn
->d_tag
) {
1224 RelOffset
= Dyn
->d_un
.d_val
;
1228 RelSize
= Dyn
->d_un
.d_val
;
1232 RelElementSize
= Dyn
->d_un
.d_val
;
1240 if (( RelOffset
== 0 ) || ( RelSize
== 0 ) || ( RelElementSize
== 0 )) {
1241 Error (NULL
, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName
);
1244 for (K
= 0; K
< RelSize
; K
+= RelElementSize
) {
1246 if (DynamicSegment
->p_paddr
== 0) {
1247 // This seems to be how it works on armcc???? Have the email in to find out?
1248 Rel
= (Elf32_Rel
*) ((UINT8
*) Ehdr
+ DynamicSegment
->p_offset
+ RelOffset
+ K
);
1250 // This is how it reads in the ELF specification
1251 Rel
= (Elf32_Rel
*) ((UINT8
*) Ehdr
+ RelOffset
+ K
);
1254 switch (ELF32_R_TYPE (Rel
->r_info
)) {
1258 TargetSegment
= GetPhdrByIndex (ELF32_R_SYM (Rel
->r_info
) - 1);
1260 // Note: r_offset in a memory address. Convert it to a pointer in the coff file.
1261 Targ
= CoffFile
+ CoffSectionsOffset
[ ELF32_R_SYM( Rel
->r_info
) ] + Rel
->r_offset
- TargetSegment
->p_vaddr
;
1263 *(UINT32
*)Targ
= *(UINT32
*)Targ
+ CoffSectionsOffset
[ELF32_R_SYM( Rel
->r_info
)];
1265 CoffAddFixup (CoffSectionsOffset
[ELF32_R_SYM (Rel
->r_info
)] + (Rel
->r_offset
- TargetSegment
->p_vaddr
), EFI_IMAGE_REL_BASED_HIGHLOW
);
1268 Error (NULL
, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type %d.", mInImageName
, ELF32_R_TYPE (Rel
->r_info
));
1278 // Pad by adding empty entries.
1280 while (CoffOffset
& (CoffAlignment
- 1)) {
1281 CoffAddFixupEntry(0);
1285 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1286 Dir
= &NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1287 Dir
->Size
= CoffOffset
- RelocOffset
;
1288 if (Dir
->Size
== 0) {
1289 // If no relocations, null out the directory entry and don't add the .reloc section
1290 Dir
->VirtualAddress
= 0;
1291 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
1293 Dir
->VirtualAddress
= RelocOffset
;
1294 CreateSectionHeader (".reloc", RelocOffset
, CoffOffset
- RelocOffset
,
1295 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
1296 | EFI_IMAGE_SCN_MEM_DISCARDABLE
1297 | EFI_IMAGE_SCN_MEM_READ
);
1309 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1310 EFI_IMAGE_DATA_DIRECTORY
*DataDir
;
1311 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*Dir
;
1312 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
*Nb10
;
1314 Len
= strlen(mInImageName
) + 1;
1315 DebugOffset
= CoffOffset
;
1317 CoffOffset
+= sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
)
1318 + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
)
1320 CoffOffset
= CoffAlign(CoffOffset
);
1322 CoffFile
= realloc(CoffFile
, CoffOffset
);
1323 memset(CoffFile
+ DebugOffset
, 0, CoffOffset
- DebugOffset
);
1325 Dir
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)(CoffFile
+ DebugOffset
);
1326 Dir
->Type
= EFI_IMAGE_DEBUG_TYPE_CODEVIEW
;
1327 Dir
->SizeOfData
= sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
) + Len
;
1328 Dir
->RVA
= DebugOffset
+ sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
1329 Dir
->FileOffset
= DebugOffset
+ sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
1331 Nb10
= (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
*)(Dir
+ 1);
1332 Nb10
->Signature
= CODEVIEW_SIGNATURE_NB10
;
1333 strcpy ((char *)(Nb10
+ 1), mInImageName
);
1336 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1337 DataDir
= &NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
];
1338 DataDir
->VirtualAddress
= DebugOffset
;
1339 DataDir
->Size
= CoffOffset
- DebugOffset
;
1340 if (DataDir
->Size
== 0) {
1341 // If no debug, null out the directory entry and don't add the .debug section
1342 DataDir
->VirtualAddress
= 0;
1343 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
1345 DataDir
->VirtualAddress
= DebugOffset
;
1346 CreateSectionHeader (".debug", DebugOffset
, CoffOffset
- DebugOffset
,
1347 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
1348 | EFI_IMAGE_SCN_MEM_DISCARDABLE
1349 | EFI_IMAGE_SCN_MEM_READ
);
1360 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1363 // Check header, read section table.
1365 Ehdr
= (Elf32_Ehdr
*)*FileBuffer
;
1366 if (!CheckElfHeader())
1369 VerboseMsg ("Check Efl Image Header");
1371 // Compute sections new address.
1376 VerboseMsg ("Compute sections new address.");
1379 // Write and relocate sections.
1381 WriteSections(IsTextShdr
);
1382 WriteSections(IsDataShdr
);
1383 WriteSections(IsHiiRsrcShdr
);
1384 VerboseMsg ("Write and relocate sections.");
1387 // Translate and write relocations.
1390 VerboseMsg ("Translate and write relocations.");
1393 // Write debug info.
1396 VerboseMsg ("Write debug info.");
1398 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1399 NtHdr
->Pe32
.OptionalHeader
.SizeOfImage
= CoffOffset
;
1405 *FileBuffer
= CoffFile
;
1406 *FileLength
= CoffOffset
;
1409 // Free memory space
1411 if (CoffSectionsOffset
!= NULL
) {
1412 free (CoffSectionsOffset
);
1417 EFI_IMAGE_OPTIONAL_HEADER_UNION
*
1422 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1423 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1426 // Read the dos & pe hdrs of the image
1428 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Data
;
1429 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
1430 // NO DOS header, check for PE/COFF header
1431 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(Data
);
1432 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1437 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(((UINT8
*)Data
) + DosHdr
->e_lfanew
);
1438 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1447 PeCoffConvertImageToXip (
1452 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1453 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NewPeHdr
;
1454 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1455 UINTN TotalNecessaryFileSize
;
1460 UINTN FirstSectionOffset
;
1461 BOOLEAN ConversionNeeded
;
1463 PeHdr
= GetPeCoffHeader ((void *) *FileBuffer
);
1464 if (PeHdr
== NULL
) {
1468 if (PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
) {
1470 // The only reason to expand zero fill sections is to make them compatible with XIP images.
1471 // If SectionAlignment is not equal to FileAlginment then it is not an XIP type image.
1477 // Calculate size of XIP file, and determine if the conversion is needed.
1479 ConversionNeeded
= FALSE
;
1481 FirstSectionOffset
= *FileLength
;
1482 TotalNecessaryFileSize
= 0;
1483 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
1484 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1485 SectionSize
= MAX (SectionHeader
->Misc
.VirtualSize
, SectionHeader
->SizeOfRawData
);
1486 TotalNecessaryFileSize
+= SectionSize
;
1487 if (SectionSize
> 0) {
1488 FirstSectionOffset
= MIN (FirstSectionOffset
, SectionHeader
->VirtualAddress
);
1489 XipLength
= MAX (XipLength
, SectionHeader
->VirtualAddress
+ SectionSize
);
1490 if (SectionHeader
->VirtualAddress
!= SectionHeader
->PointerToRawData
) {
1491 ConversionNeeded
= TRUE
;
1494 if (SectionHeader
->Misc
.VirtualSize
> SectionHeader
->SizeOfRawData
) {
1495 ConversionNeeded
= TRUE
;
1499 if (FirstSectionOffset
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
1501 // If one of the sections should be loaded to an offset overlapping with
1502 // the executable header, then it cannot be made into an XIP image.
1504 VerboseMsg ("PE/COFF conversion to XIP is impossible due to overlap");
1505 VerboseMsg ("of section data with the executable header.");
1509 if (FirstSectionOffset
== *FileLength
) {
1511 // If we never found a section with a non-zero size, then we
1512 // skip the conversion.
1517 TotalNecessaryFileSize
+= FirstSectionOffset
;
1519 if (!ConversionNeeded
) {
1523 if (XipLength
> (2 * TotalNecessaryFileSize
)) {
1524 VerboseMsg ("PE/COFF conversion to XIP appears to be larger than necessary.");
1525 VerboseMsg ("The image linking process may have left unused memory ranges.");
1528 if (PeHdr
->Pe32
.FileHeader
.PointerToSymbolTable
!= 0) {
1530 // This field is obsolete and should be zero
1532 PeHdr
->Pe32
.FileHeader
.PointerToSymbolTable
= 0;
1536 // Allocate the extra space that we need to grow the image
1538 XipFile
= malloc (XipLength
);
1539 memset (XipFile
, 0, XipLength
);
1542 // Copy the file headers
1544 memcpy (XipFile
, *FileBuffer
, PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
);
1546 NewPeHdr
= GetPeCoffHeader ((void *)XipFile
);
1547 if (NewPeHdr
== NULL
) {
1553 // Copy the section data over to the appropriate XIP offsets
1555 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(NewPeHdr
->Pe32
.OptionalHeader
) + NewPeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
1556 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1557 if (SectionHeader
->SizeOfRawData
> 0) {
1559 XipFile
+ SectionHeader
->VirtualAddress
,
1560 *FileBuffer
+ SectionHeader
->PointerToRawData
,
1561 SectionHeader
->SizeOfRawData
1564 SectionHeader
->SizeOfRawData
= SectionHeader
->Misc
.VirtualSize
;
1565 SectionHeader
->PointerToRawData
= SectionHeader
->VirtualAddress
;
1569 *FileLength
= XipLength
;
1570 *FileBuffer
= XipFile
;
1574 CreateHiiResouceSectionHeader (
1575 UINT32
*pSectionHeaderSize
,
1580 Routine Description:
1582 Create COFF resource section header
1586 pSectionHeaderSize - Pointer to section header size.
1587 HiiDataSize - Size of the total HII data in section.
1590 The created section header buffer.
1594 UINT32 HiiSectionHeaderSize
;
1595 UINT32 HiiSectionOffset
;
1596 UINT8
*HiiSectionHeader
;
1597 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
1598 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*TypeResourceDirectoryEntry
;
1599 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*NameResourceDirectoryEntry
;
1600 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*LanguageResourceDirectoryEntry
;
1601 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
1602 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
1605 // Calculate the total size for the resource header (include Type, Name and Language)
1606 // then allocate memory for the resource header.
1608 HiiSectionHeaderSize
= 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
))
1609 + 3 * (sizeof (UINT16
) + 3 * sizeof (CHAR16
))
1610 + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
1611 HiiSectionHeader
= malloc (HiiSectionHeaderSize
);
1612 memset (HiiSectionHeader
, 0, HiiSectionHeaderSize
);
1614 HiiSectionOffset
= 0;
1616 // Create Type entry
1618 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1619 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
1620 ResourceDirectory
->NumberOfNamedEntries
= 1;
1621 TypeResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1622 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
1623 TypeResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
1624 TypeResourceDirectoryEntry
->u2
.s
.DataIsDirectory
= 1;
1625 TypeResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
= HiiSectionOffset
;
1627 // Create Name entry
1629 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1630 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
1631 ResourceDirectory
->NumberOfNamedEntries
= 1;
1632 NameResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1633 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
1634 NameResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
1635 NameResourceDirectoryEntry
->u2
.s
.DataIsDirectory
= 1;
1636 NameResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
= HiiSectionOffset
;
1638 // Create Language entry
1640 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1641 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
1642 ResourceDirectory
->NumberOfNamedEntries
= 1;
1643 LanguageResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1644 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
1645 LanguageResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
1647 // Create string entry for Type
1649 TypeResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
1650 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
1651 ResourceDirectoryString
->Length
= 3;
1652 ResourceDirectoryString
->String
[0] = L
'H';
1653 ResourceDirectoryString
->String
[1] = L
'I';
1654 ResourceDirectoryString
->String
[2] = L
'I';
1655 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
1657 // Create string entry for Name
1659 NameResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
1660 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
1661 ResourceDirectoryString
->Length
= 3;
1662 ResourceDirectoryString
->String
[0] = L
'E';
1663 ResourceDirectoryString
->String
[1] = L
'F';
1664 ResourceDirectoryString
->String
[2] = L
'I';
1665 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
1667 // Create string entry for Language
1669 LanguageResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
1670 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
1671 ResourceDirectoryString
->Length
= 3;
1672 ResourceDirectoryString
->String
[0] = L
'B';
1673 ResourceDirectoryString
->String
[1] = L
'I';
1674 ResourceDirectoryString
->String
[2] = L
'N';
1675 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
1679 LanguageResourceDirectoryEntry
->u2
.OffsetToData
= HiiSectionOffset
;
1680 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1681 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
1682 ResourceDataEntry
->OffsetToData
= HiiSectionOffset
;
1683 ResourceDataEntry
->Size
= HiiDataSize
;
1685 *pSectionHeaderSize
= HiiSectionHeaderSize
;
1686 return HiiSectionHeader
;
1691 IN VOID
*FileHandle
,
1692 IN UINTN FileOffset
,
1693 IN OUT UINT32
*ReadSize
,
1698 Routine Description:
1700 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1704 FileHandle - The handle to the PE/COFF file
1706 FileOffset - The offset, in bytes, into the file to read
1708 ReadSize - The number of bytes to read from the file starting at FileOffset
1710 Buffer - A pointer to the buffer to read the data into.
1714 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1718 CHAR8
*Destination8
;
1722 Destination8
= Buffer
;
1723 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
1726 *(Destination8
++) = *(Source8
++);
1733 SetAddressToSectionHeader (
1735 IN OUT UINT8
*FileBuffer
,
1736 IN UINT64 NewPe32BaseAddress
1740 Routine Description:
1742 Set new base address into the section header of PeImage
1746 FileName - Name of file
1747 FileBuffer - Pointer to PeImage.
1748 NewPe32BaseAddress - New Base Address for PE image.
1752 EFI_SUCCESS Set new base address into this image successfully.
1757 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1759 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1760 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1763 // Initialize context
1765 memset (&ImageContext
, 0, sizeof (ImageContext
));
1766 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1767 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1768 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1769 if (EFI_ERROR (Status
)) {
1770 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1774 if (ImageContext
.RelocationsStripped
) {
1775 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1780 // Get PeHeader pointer
1782 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1785 // Get section header list
1787 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1790 sizeof (EFI_IMAGE_FILE_HEADER
) +
1791 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1795 // Set base address into the first section header that doesn't point to code section.
1797 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1798 if ((SectionHeader
->Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
1799 *(UINT64
*) &SectionHeader
->PointerToRelocations
= NewPe32BaseAddress
;
1805 // No available section header is found.
1807 if (Index
== ImgHdr
->Pe32
.FileHeader
.NumberOfSections
) {
1808 return EFI_NOT_FOUND
;
1812 // BaseAddress is set to section header.
1820 IN OUT UINT8
*FileBuffer
,
1821 IN UINT64 NewPe32BaseAddress
1825 Routine Description:
1827 Set new base address into PeImage, and fix up PeImage based on new address.
1831 FileName - Name of file
1832 FileBuffer - Pointer to PeImage.
1833 NewPe32BaseAddress - New Base Address for PE image.
1837 EFI_INVALID_PARAMETER - BaseAddress is not valid.
1838 EFI_SUCCESS - Update PeImage is correctly.
1843 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1845 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1846 UINT8
*MemoryImagePointer
;
1847 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1850 // Initialize context
1852 memset (&ImageContext
, 0, sizeof (ImageContext
));
1853 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1854 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1855 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1856 if (EFI_ERROR (Status
)) {
1857 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1861 if (ImageContext
.RelocationsStripped
) {
1862 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1867 // Get PeHeader pointer
1869 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1872 // Load and Relocate Image Data
1874 MemoryImagePointer
= (UINT8
*) malloc ((UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1875 if (MemoryImagePointer
== NULL
) {
1876 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
1877 return EFI_OUT_OF_RESOURCES
;
1879 memset ((VOID
*) MemoryImagePointer
, 0, (UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1880 ImageContext
.ImageAddress
= ((UINTN
) MemoryImagePointer
+ ImageContext
.SectionAlignment
- 1) & (~((INT64
)ImageContext
.SectionAlignment
- 1));
1882 Status
= PeCoffLoaderLoadImage (&ImageContext
);
1883 if (EFI_ERROR (Status
)) {
1884 Error (NULL
, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName
);
1885 free ((VOID
*) MemoryImagePointer
);
1889 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
1890 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
1891 if (EFI_ERROR (Status
)) {
1892 Error (NULL
, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName
);
1893 free ((VOID
*) MemoryImagePointer
);
1898 // Copy Relocated data to raw image file.
1900 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1903 sizeof (EFI_IMAGE_FILE_HEADER
) +
1904 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1907 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1909 FileBuffer
+ SectionHeader
->PointerToRawData
,
1910 (VOID
*) (UINTN
) (ImageContext
.ImageAddress
+ SectionHeader
->VirtualAddress
),
1911 SectionHeader
->SizeOfRawData
1915 free ((VOID
*) MemoryImagePointer
);
1918 // Update Image Base Address
1920 if ((ImgHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) && (ImgHdr
->Pe32
.FileHeader
.Machine
!= IMAGE_FILE_MACHINE_IA64
)) {
1921 ImgHdr
->Pe32
.OptionalHeader
.ImageBase
= (UINT32
) NewPe32BaseAddress
;
1922 } else if (ImgHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1923 ImgHdr
->Pe32Plus
.OptionalHeader
.ImageBase
= NewPe32BaseAddress
;
1925 Error (NULL
, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
1926 ImgHdr
->Pe32
.OptionalHeader
.Magic
,
1933 // Set new base address into section header
1935 Status
= SetAddressToSectionHeader (FileName
, FileBuffer
, NewPe32BaseAddress
);
1947 Routine Description:
1953 argc - Number of command line parameters.
1954 argv - Array of pointers to command line parameter strings.
1957 STATUS_SUCCESS - Utility exits successfully.
1958 STATUS_ERROR - Some error occurred during execution.
1963 UINT32 InputFileNum
;
1964 CHAR8
**InputFileName
;
1968 UINT32 OutImageType
;
1973 UINT32
*DataPointer
;
1974 UINT32
*OldDataPointer
;
1980 UINT32 MciAlignment
;
1982 UINT32 AllignedRelocSize
;
1985 UINT8
*OutputFileBuffer
;
1986 UINT32 OutputFileLength
;
1987 UINT8
*InputFileBuffer
;
1988 UINT32 InputFileLength
;
1989 RUNTIME_FUNCTION
*RuntimeFunction
;
1990 UNWIND_INFO
*UnwindInfo
;
1992 BOOLEAN ReplaceFlag
;
1993 BOOLEAN KeepExceptionTableFlag
;
1994 BOOLEAN KeepZeroPendingFlag
;
1996 EFI_TE_IMAGE_HEADER TEImageHeader
;
1997 EFI_TE_IMAGE_HEADER
*TeHdr
;
1998 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1999 EFI_IMAGE_DOS_HEADER
*DosHdr
;
2000 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
2001 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32
;
2002 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64
;
2003 EFI_IMAGE_DOS_HEADER BackupDosHdr
;
2004 MICROCODE_IMAGE_HEADER
*MciHeader
;
2005 UINT8
*HiiPackageListBuffer
;
2006 UINT8
*HiiPackageDataPointer
;
2007 EFI_GUID HiiPackageListGuid
;
2008 EFI_HII_PACKAGE_LIST_HEADER HiiPackageListHeader
;
2009 EFI_HII_PACKAGE_HEADER HiiPackageHeader
;
2010 EFI_IFR_FORM_SET IfrFormSet
;
2011 UINT8 NumberOfFormPacakge
;
2012 EFI_HII_PACKAGE_HEADER EndPackage
;
2013 UINT32 HiiSectionHeaderSize
;
2014 UINT8
*HiiSectionHeader
;
2015 UINT64 NewBaseAddress
;
2016 BOOLEAN NegativeAddr
;
2018 CHAR8
*ReportFileName
;
2020 time_t InputFileTime
;
2021 time_t OutputFileTime
;
2022 struct stat Stat_Buf
;
2024 SetUtilityName (UTILITY_NAME
);
2027 // Assign to fix compile warning
2031 InputFileName
= NULL
;
2032 mInImageName
= NULL
;
2033 OutImageName
= NULL
;
2035 OutImageType
= FW_DUMMY_IMAGE
;
2037 Status
= STATUS_SUCCESS
;
2043 MciAlignment
= DEFAULT_MC_ALIGNMENT
;
2044 MciPadValue
= DEFAULT_MC_PAD_BYTE_VALUE
;
2048 ReplaceFlag
= FALSE
;
2050 OutputFileBuffer
= NULL
;
2051 OutputFileLength
= 0;
2052 InputFileBuffer
= NULL
;
2053 InputFileLength
= 0;
2056 KeepExceptionTableFlag
= FALSE
;
2057 KeepZeroPendingFlag
= FALSE
;
2058 NumberOfFormPacakge
= 0;
2059 HiiPackageListBuffer
= NULL
;
2060 HiiPackageDataPointer
= NULL
;
2061 EndPackage
.Length
= sizeof (EFI_HII_PACKAGE_HEADER
);
2062 EndPackage
.Type
= EFI_HII_PACKAGE_END
;
2063 memset (&HiiPackageListGuid
, 0, sizeof (HiiPackageListGuid
));
2064 HiiSectionHeaderSize
= 0;
2065 HiiSectionHeader
= NULL
;
2067 NegativeAddr
= FALSE
;
2072 Error (NULL
, 0, 1001, "Missing options", "No input options.");
2074 return STATUS_ERROR
;
2080 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
2083 return STATUS_SUCCESS
;
2086 if (stricmp (argv
[0], "--version") == 0) {
2088 return STATUS_SUCCESS
;
2092 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
2093 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
2094 Error (NULL
, 0, 1003, "Invalid option value", "Output file name is missing for -o option");
2097 OutImageName
= argv
[1];
2103 if ((stricmp (argv
[0], "-e") == 0) || (stricmp (argv
[0], "--efiImage") == 0)) {
2104 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
2105 Error (NULL
, 0, 1003, "Invalid option value", "Module Type is missing for -o option");
2108 ModuleType
= argv
[1];
2109 if (OutImageType
!= FW_TE_IMAGE
) {
2110 OutImageType
= FW_EFI_IMAGE
;
2117 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--stripped") == 0)) {
2118 OutImageType
= FW_RELOC_STRIPEED_IMAGE
;
2124 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--acpi") == 0)) {
2125 OutImageType
= FW_ACPI_IMAGE
;
2131 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--terse") == 0)) {
2132 OutImageType
= FW_TE_IMAGE
;
2138 if ((stricmp (argv
[0], "-u") == 0) || (stricmp (argv
[0], "--dump") == 0)) {
2139 OutImageType
= DUMP_TE_HEADER
;
2145 if ((stricmp (argv
[0], "-b") == 0) || (stricmp (argv
[0], "--exe2bin") == 0)) {
2146 OutImageType
= FW_BIN_IMAGE
;
2152 if ((stricmp (argv
[0], "-z") == 0) || (stricmp (argv
[0], "--zero") == 0)) {
2153 OutImageType
= FW_ZERO_DEBUG_IMAGE
;
2159 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--stamp") == 0)) {
2160 OutImageType
= FW_SET_STAMP_IMAGE
;
2161 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
2162 Error (NULL
, 0, 1003, "Invalid option value", "time stamp is missing for -s option");
2165 TimeStamp
= argv
[1];
2171 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--replace") == 0)) {
2178 if (stricmp (argv
[0], "--keepexceptiontable") == 0) {
2179 KeepExceptionTableFlag
= TRUE
;
2185 if (stricmp (argv
[0], "--keepzeropending") == 0) {
2186 KeepZeroPendingFlag
= TRUE
;
2192 if ((stricmp (argv
[0], "-m") == 0) || (stricmp (argv
[0], "--mcifile") == 0)) {
2193 OutImageType
= FW_MCI_IMAGE
;
2199 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--join") == 0)) {
2200 OutImageType
= FW_MERGE_IMAGE
;
2206 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
2207 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
2208 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
2211 MciAlignment
= (UINT32
) Temp64
;
2217 if ((stricmp (argv
[0], "--rebase") == 0)) {
2218 if (argv
[1][0] == '-') {
2219 NegativeAddr
= TRUE
;
2220 Status
= AsciiStringToUint64 (argv
[1] + 1, FALSE
, &Temp64
);
2222 NegativeAddr
= FALSE
;
2223 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
);
2225 if (Status
!= EFI_SUCCESS
) {
2226 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
2229 OutImageType
= FW_REBASE_IMAGE
;
2230 NewBaseAddress
= (UINT64
) Temp64
;
2236 if ((stricmp (argv
[0], "--address") == 0)) {
2237 if (argv
[1][0] == '-') {
2238 NegativeAddr
= TRUE
;
2239 Status
= AsciiStringToUint64 (argv
[1] + 1, FALSE
, &Temp64
);
2241 NegativeAddr
= FALSE
;
2242 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
);
2244 if (Status
!= EFI_SUCCESS
) {
2245 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
2248 OutImageType
= FW_SET_ADDRESS_IMAGE
;
2249 NewBaseAddress
= (UINT64
) Temp64
;
2255 if ((stricmp (argv
[0], "-p") == 0) || (stricmp (argv
[0], "--pad") == 0)) {
2256 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
2257 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
2260 MciPadValue
= (UINT8
) Temp64
;
2266 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
2267 SetPrintLevel (VERBOSE_LOG_LEVEL
);
2268 VerboseMsg ("Verbose output Mode Set!");
2274 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
2275 SetPrintLevel (KEY_LOG_LEVEL
);
2276 KeyMsg ("Quiet output Mode Set!");
2282 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
2283 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
2284 if (EFI_ERROR (Status
)) {
2285 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
2289 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel
);
2292 SetPrintLevel (LogLevel
);
2293 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
2299 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--hiiguid") == 0)) {
2300 Status
= StringToGuid (argv
[1], &HiiPackageListGuid
);
2301 if (EFI_ERROR (Status
)) {
2302 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
2310 if (stricmp (argv
[0], "--hiipackage") == 0) {
2311 OutImageType
= FW_HII_PACKAGE_LIST_RCIMAGE
;
2317 if (stricmp (argv
[0], "--hiibinpackage") == 0) {
2318 OutImageType
= FW_HII_PACKAGE_LIST_BINIMAGE
;
2324 if (argv
[0][0] == '-') {
2325 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
2329 // Get Input file name
2331 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
2332 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
2333 if (InputFileName
== NULL
) {
2334 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2338 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
2339 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
2341 // InputFileName buffer too small, need to realloc
2343 InputFileName
= (CHAR8
**) realloc (
2345 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
2348 if (InputFileName
== NULL
) {
2349 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2353 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
2356 InputFileName
[InputFileNum
++] = argv
[0];
2361 VerboseMsg ("%s tool start.", UTILITY_NAME
);
2363 if (OutImageType
== FW_DUMMY_IMAGE
) {
2364 Error (NULL
, 0, 1001, "Missing option", "No create file action specified; pls specify -e, -c or -t option to create efi image, or acpi table or TeImage!");
2366 Error (NULL
, 0, 1001, "Missing option", "-r option is not supported as the independent option. It can be used together with other create file option specified at the above.");
2372 // check input files
2374 if (InputFileNum
== 0) {
2375 Error (NULL
, 0, 1001, "Missing option", "Input files");
2380 // Combine MciBinary files to one file
2382 if ((OutImageType
== FW_MERGE_IMAGE
) && ReplaceFlag
) {
2383 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");
2388 // Combine HiiBinary packages to a single package list
2390 if ((OutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) && ReplaceFlag
) {
2391 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option.");
2395 if ((OutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) && ReplaceFlag
) {
2396 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiibinpackage merge files option.");
2403 mInImageName
= InputFileName
[InputFileNum
- 1];
2404 VerboseMsg ("the input file name is %s", mInImageName
);
2407 // Action will be taken for the input file.
2409 switch (OutImageType
) {
2411 VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType
);
2414 VerboseMsg ("Create Te Image based on the input PE image.");
2417 VerboseMsg ("Get acpi table data from the input PE image.");
2419 case FW_RELOC_STRIPEED_IMAGE
:
2420 VerboseMsg ("Remove relocation section from Pe or Te image.");
2423 VerboseMsg ("Convert the input EXE to the output BIN file.");
2425 case FW_ZERO_DEBUG_IMAGE
:
2426 VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");
2428 case FW_SET_STAMP_IMAGE
:
2429 VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp
);
2431 case DUMP_TE_HEADER
:
2432 VerboseMsg ("Dump the TE header information of the input TE image.");
2435 VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");
2437 case FW_MERGE_IMAGE
:
2438 VerboseMsg ("Combine the input multi microcode bin files to one bin file.");
2440 case FW_HII_PACKAGE_LIST_RCIMAGE
:
2441 VerboseMsg ("Combine the input multi hii bin packages to one text pacakge list RC file.");
2443 case FW_HII_PACKAGE_LIST_BINIMAGE
:
2444 VerboseMsg ("Combine the input multi hii bin packages to one binary pacakge list file.");
2446 case FW_REBASE_IMAGE
:
2447 VerboseMsg ("Rebase the input image to new base address.");
2449 case FW_SET_ADDRESS_IMAGE
:
2450 VerboseMsg ("Set the preferred address into the section header of the input image");
2457 VerboseMsg ("Overwrite the input file with the output content.");
2461 // Open output file and Write image into the output file.
2463 if (OutImageName
!= NULL
) {
2464 fpOut
= fopen (OutImageName
, "rb");
2465 if (fpOut
!= NULL
) {
2467 // Get Output file time stamp
2469 fstat(fileno (fpOut
), &Stat_Buf
);
2470 OutputFileTime
= Stat_Buf
.st_mtime
;
2472 // Get Output file data
2474 OutputFileLength
= _filelength (fileno (fpOut
));
2475 OutputFileBuffer
= malloc (OutputFileLength
);
2476 if (OutputFileBuffer
== NULL
) {
2477 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2482 fread (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
2486 VerboseMsg ("Output file name is %s", OutImageName
);
2487 } else if (!ReplaceFlag
&& OutImageType
!= DUMP_TE_HEADER
) {
2488 Error (NULL
, 0, 1001, "Missing option", "output file");
2493 // Open input file and read file data into file buffer.
2495 fpIn
= fopen (mInImageName
, "rb");
2497 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2501 // Get Iutput file time stamp
2503 fstat(fileno (fpIn
), &Stat_Buf
);
2504 InputFileTime
= Stat_Buf
.st_mtime
;
2506 // Get Input file data
2508 InputFileLength
= _filelength (fileno (fpIn
));
2509 InputFileBuffer
= malloc (InputFileLength
);
2510 if (InputFileBuffer
== NULL
) {
2511 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2515 fread (InputFileBuffer
, 1, InputFileLength
, fpIn
);
2517 DebugMsg (NULL
, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) InputFileLength
);
2520 // Combine multi binary HII package files.
2522 if (OutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
|| OutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) {
2524 // Open output file handle.
2526 fpOut
= fopen (OutImageName
, "wb");
2528 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
2532 // Get hii package list lenght
2534 HiiPackageListHeader
.PackageLength
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
2535 for (Index
= 0; Index
< InputFileNum
; Index
++) {
2536 fpIn
= fopen (InputFileName
[Index
], "rb");
2538 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
2541 FileLength
= _filelength (fileno (fpIn
));
2542 fread (&HiiPackageHeader
, 1, sizeof (HiiPackageHeader
), fpIn
);
2543 if (HiiPackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) {
2544 if (HiiPackageHeader
.Length
!= FileLength
) {
2545 Error (NULL
, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName
[Index
]);
2549 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
2550 fread (&IfrFormSet
, 1, sizeof (IfrFormSet
), fpIn
);
2551 memcpy (&HiiPackageListGuid
, &IfrFormSet
.Guid
, sizeof (EFI_GUID
));
2553 NumberOfFormPacakge
++;
2555 HiiPackageListHeader
.PackageLength
+= FileLength
;
2558 HiiPackageListHeader
.PackageLength
+= sizeof (EndPackage
);
2560 // Check whether hii packages are valid
2562 if (NumberOfFormPacakge
> 1) {
2563 Error (NULL
, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package");
2566 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
2567 Error (NULL
, 0, 3000, "Invalid", "HII pacakge list guid is not specified!");
2570 memcpy (&HiiPackageListHeader
.PackageListGuid
, &HiiPackageListGuid
, sizeof (EFI_GUID
));
2572 // read hii packages
2574 HiiPackageListBuffer
= malloc (HiiPackageListHeader
.PackageLength
);
2575 if (HiiPackageListBuffer
== NULL
) {
2576 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2579 memcpy (HiiPackageListBuffer
, &HiiPackageListHeader
, sizeof (HiiPackageListHeader
));
2580 HiiPackageDataPointer
= HiiPackageListBuffer
+ sizeof (HiiPackageListHeader
);
2581 for (Index
= 0; Index
< InputFileNum
; Index
++) {
2582 fpIn
= fopen (InputFileName
[Index
], "rb");
2584 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
2585 free (HiiPackageListBuffer
);
2589 FileLength
= _filelength (fileno (fpIn
));
2590 fread (HiiPackageDataPointer
, 1, FileLength
, fpIn
);
2592 HiiPackageDataPointer
= HiiPackageDataPointer
+ FileLength
;
2594 memcpy (HiiPackageDataPointer
, &EndPackage
, sizeof (EndPackage
));
2597 // write the hii package into the binary package list file with the resource section header
2599 if (OutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) {
2601 // Create the resource section header
2603 HiiSectionHeader
= CreateHiiResouceSectionHeader (&HiiSectionHeaderSize
, HiiPackageListHeader
.PackageLength
);
2605 // Wrtie section header and HiiData into File.
2607 fwrite (HiiSectionHeader
, 1, HiiSectionHeaderSize
, fpOut
);
2608 fwrite (HiiPackageListBuffer
, 1, HiiPackageListHeader
.PackageLength
, fpOut
);
2610 // Free allocated resources.
2612 free (HiiSectionHeader
);
2613 free (HiiPackageListBuffer
);
2615 // Done successfully
2621 // write the hii package into the text package list rc file.
2623 if (OutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) {
2624 for (Index
= 0; gHiiPackageRCFileHeader
[Index
] != NULL
; Index
++) {
2625 fprintf (fpOut
, "%s\n", gHiiPackageRCFileHeader
[Index
]);
2627 fprintf (fpOut
, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX
, HII_RESOURCE_SECTION_NAME
);
2629 HiiPackageDataPointer
= HiiPackageListBuffer
;
2630 for (Index
= 0; Index
+ 2 < HiiPackageListHeader
.PackageLength
; Index
+= 2) {
2631 if (Index
% 16 == 0) {
2632 fprintf (fpOut
, "\n ");
2634 fprintf (fpOut
, " 0x%04X,", *(UINT16
*) HiiPackageDataPointer
);
2635 HiiPackageDataPointer
+= 2;
2638 if (Index
% 16 == 0) {
2639 fprintf (fpOut
, "\n ");
2641 if ((Index
+ 2) == HiiPackageListHeader
.PackageLength
) {
2642 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT16
*) HiiPackageDataPointer
);
2644 if ((Index
+ 1) == HiiPackageListHeader
.PackageLength
) {
2645 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT8
*) HiiPackageDataPointer
);
2647 free (HiiPackageListBuffer
);
2649 // Done successfully
2656 // Combine MciBinary files to one file
2658 if (OutImageType
== FW_MERGE_IMAGE
) {
2660 // Open output file handle.
2662 fpOut
= fopen (OutImageName
, "wb");
2664 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
2667 for (Index
= 0; Index
< InputFileNum
; Index
++) {
2668 fpIn
= fopen (InputFileName
[Index
], "rb");
2670 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
2674 FileLength
= _filelength (fileno (fpIn
));
2675 FileBuffer
= malloc (FileLength
);
2676 if (FileBuffer
== NULL
) {
2677 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2682 fread (FileBuffer
, 1, FileLength
, fpIn
);
2685 // write input file to out file
2687 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2689 // write pad value to out file.
2691 while (FileLength
++ % MciAlignment
!= 0) {
2692 fwrite (&MciPadValue
, 1, 1, fpOut
);
2695 // free allocated memory space
2701 // Done successfully
2707 // Convert MicroCode.txt file to MicroCode.bin file
2709 if (OutImageType
== FW_MCI_IMAGE
) {
2710 fpIn
= fopen (mInImageName
, "r");
2712 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2717 // The first pass is to determine
2718 // how much data is in the file so we can allocate a working buffer.
2722 Status
= MicrocodeReadData (fpIn
, &Data
);
2723 if (Status
== STATUS_SUCCESS
) {
2724 FileLength
+= sizeof (Data
);
2726 if (Status
== STATUS_IGNORE
) {
2727 Status
= STATUS_SUCCESS
;
2729 } while (Status
== STATUS_SUCCESS
);
2731 // Error if no data.
2733 if (FileLength
== 0) {
2734 Error (NULL
, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName
);
2737 if (FileLength
< sizeof (MICROCODE_IMAGE_HEADER
)) {
2738 Error (NULL
, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName
);
2743 // Allocate a buffer for the data
2745 FileBuffer
= malloc (FileLength
);
2746 if (FileBuffer
== NULL
) {
2747 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2751 // Re-read the file, storing the data into our buffer
2753 fseek (fpIn
, 0, SEEK_SET
);
2754 DataPointer
= (UINT32
*) FileBuffer
;
2755 OldDataPointer
= DataPointer
;
2757 OldDataPointer
= DataPointer
;
2758 Status
= MicrocodeReadData (fpIn
, DataPointer
++);
2759 if (Status
== STATUS_IGNORE
) {
2760 DataPointer
= OldDataPointer
;
2761 Status
= STATUS_SUCCESS
;
2763 } while (Status
== STATUS_SUCCESS
);
2765 // close input file after read data
2770 // Can't do much checking on the header because, per the spec, the
2771 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
2772 // and the TotalSize field is invalid (actually missing). Thus we can't
2773 // even verify the Reserved fields are 0.
2775 MciHeader
= (MICROCODE_IMAGE_HEADER
*) FileBuffer
;
2776 if (MciHeader
->DataSize
== 0) {
2779 Index
= MciHeader
->TotalSize
;
2782 if (Index
!= FileLength
) {
2783 Error (NULL
, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName
, (unsigned) FileLength
, (unsigned) Index
);
2788 // Checksum the contents
2790 DataPointer
= (UINT32
*) FileBuffer
;
2793 while (Index
< FileLength
) {
2794 CheckSum
+= *DataPointer
;
2796 Index
+= sizeof (*DataPointer
);
2798 if (CheckSum
!= 0) {
2799 Error (NULL
, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum
, mInImageName
);
2803 // Open the output file and write the buffer contents
2805 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2810 // Open input file and read file data into file buffer.
2812 FileLength
= InputFileLength
;
2813 FileBuffer
= malloc (FileLength
);
2814 if (FileBuffer
== NULL
) {
2815 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2818 memcpy (FileBuffer
, InputFileBuffer
, InputFileLength
);
2821 // Dump TeImage Header into output file.
2823 if (OutImageType
== DUMP_TE_HEADER
) {
2824 memcpy (&TEImageHeader
, FileBuffer
, sizeof (TEImageHeader
));
2825 if (TEImageHeader
.Signature
!= EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2826 Error (NULL
, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName
);
2830 // Open the output file handle.
2833 fpInOut
= fopen (mInImageName
, "wb");
2834 if (fpInOut
== NULL
) {
2835 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2839 if (OutImageName
!= NULL
) {
2840 fpOut
= fopen (OutImageName
, "wb");
2844 if (fpOut
== NULL
) {
2845 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
2849 if (fpInOut
!= NULL
) {
2850 fprintf (fpInOut
, "Dump of file %s\n\n", mInImageName
);
2851 fprintf (fpInOut
, "TE IMAGE HEADER VALUES\n");
2852 fprintf (fpInOut
, "%17X machine\n", TEImageHeader
.Machine
);
2853 fprintf (fpInOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
2854 fprintf (fpInOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
2855 fprintf (fpInOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
2856 fprintf (fpInOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
2857 fprintf (fpInOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
2858 fprintf (fpInOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
2859 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
2860 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
2862 if (fpOut
!= NULL
) {
2863 fprintf (fpOut
, "Dump of file %s\n\n", mInImageName
);
2864 fprintf (fpOut
, "TE IMAGE HEADER VALUES\n");
2865 fprintf (fpOut
, "%17X machine\n", TEImageHeader
.Machine
);
2866 fprintf (fpOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
2867 fprintf (fpOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
2868 fprintf (fpOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
2869 fprintf (fpOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
2870 fprintf (fpOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
2871 fprintf (fpOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
2872 fprintf (fpOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
2873 fprintf (fpOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
2879 // Following code to convert dll to efi image or te image.
2880 // Get new image type
2882 if ((OutImageType
== FW_EFI_IMAGE
) || (OutImageType
== FW_TE_IMAGE
)) {
2883 if (ModuleType
== NULL
) {
2884 if (OutImageType
== FW_EFI_IMAGE
) {
2885 Error (NULL
, 0, 1001, "Missing option", "EFI_FILETYPE");
2887 } else if (OutImageType
== FW_TE_IMAGE
) {
2889 // Default TE Image Type is Boot service driver
2891 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2892 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2895 if (stricmp (ModuleType
, "BASE") == 0 ||
2896 stricmp (ModuleType
, "SEC") == 0 ||
2897 stricmp (ModuleType
, "SECURITY_CORE") == 0 ||
2898 stricmp (ModuleType
, "PEI_CORE") == 0 ||
2899 stricmp (ModuleType
, "PEIM") == 0 ||
2900 stricmp (ModuleType
, "COMBINED_PEIM_DRIVER") == 0 ||
2901 stricmp (ModuleType
, "PIC_PEIM") == 0 ||
2902 stricmp (ModuleType
, "RELOCATABLE_PEIM") == 0 ||
2903 stricmp (ModuleType
, "DXE_CORE") == 0 ||
2904 stricmp (ModuleType
, "BS_DRIVER") == 0 ||
2905 stricmp (ModuleType
, "DXE_DRIVER") == 0 ||
2906 stricmp (ModuleType
, "DXE_SMM_DRIVER") == 0 ||
2907 stricmp (ModuleType
, "UEFI_DRIVER") == 0 ||
2908 stricmp (ModuleType
, "SMM_CORE") == 0) {
2909 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2910 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2912 } else if (stricmp (ModuleType
, "UEFI_APPLICATION") == 0 ||
2913 stricmp (ModuleType
, "APPLICATION") == 0) {
2914 Type
= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
;
2915 VerboseMsg ("Efi Image subsystem type is efi application.");
2917 } else if (stricmp (ModuleType
, "DXE_RUNTIME_DRIVER") == 0 ||
2918 stricmp (ModuleType
, "RT_DRIVER") == 0) {
2919 Type
= EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
;
2920 VerboseMsg ("Efi Image subsystem type is efi runtime driver.");
2922 } else if (stricmp (ModuleType
, "DXE_SAL_DRIVER") == 0 ||
2923 stricmp (ModuleType
, "SAL_RT_DRIVER") == 0) {
2924 Type
= EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
;
2925 VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");
2928 Error (NULL
, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType
);
2935 // Convert EFL image to PeImage
2937 if (IsElfHeader(FileBuffer
)) {
2938 VerboseMsg ("Convert the input ELF Image to Pe Image");
2939 ConvertElf(&FileBuffer
, &FileLength
);
2943 // Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP
2944 // XIP == eXecute In Place
2946 PeCoffConvertImageToXip (&FileBuffer
, &FileLength
);
2949 // Remove reloc section from PE or TE image
2951 if (OutImageType
== FW_RELOC_STRIPEED_IMAGE
) {
2955 TeHdr
= (EFI_TE_IMAGE_HEADER
*) FileBuffer
;
2956 if (TeHdr
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2957 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (TeHdr
+ 1);
2958 for (Index
= 0; Index
< TeHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2959 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2961 // Check the reloc section is in the end of image.
2963 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) ==
2964 (FileLength
+ TeHdr
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
))) {
2966 // Remove .reloc section and update TeImage Header
2968 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2969 SectionHeader
->SizeOfRawData
= 0;
2970 SectionHeader
->Misc
.VirtualSize
= 0;
2971 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2972 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2981 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2982 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2983 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2984 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2985 Error (NULL
, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName
);
2990 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2991 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2992 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2996 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2997 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2998 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
3000 // Check the reloc section is in the end of image.
3002 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) == FileLength
) {
3004 // Remove .reloc section and update PeImage Header
3006 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
3008 PeHdr
->Pe32
.FileHeader
.Characteristics
|= EFI_IMAGE_FILE_RELOCS_STRIPPED
;
3009 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
3010 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
3011 Optional32
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
3012 Optional32
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
3013 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
3014 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
3015 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
3018 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
3019 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
3020 Optional64
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
3021 Optional64
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
3022 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
3023 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
3024 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
3027 SectionHeader
->Misc
.VirtualSize
= 0;
3028 SectionHeader
->SizeOfRawData
= 0;
3040 // Read the dos & pe hdrs of the image
3042 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
3043 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
3044 // NO DOS header, check for PE/COFF header
3045 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
3046 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
3047 Error (NULL
, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName
);
3053 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
3054 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
3055 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
3060 if (PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_ARM
) {
3061 // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
3062 // so patch back to the offical UEFI value.
3063 PeHdr
->Pe32
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_ARMT
;
3067 // Set new base address into image
3069 if (OutImageType
== FW_REBASE_IMAGE
|| OutImageType
== FW_SET_ADDRESS_IMAGE
) {
3070 if ((PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) && (PeHdr
->Pe32
.FileHeader
.Machine
!= IMAGE_FILE_MACHINE_IA64
)) {
3071 if (NewBaseAddress
>= 0x100000000ULL
) {
3072 Error (NULL
, 0, 3000, "Invalid", "New base address is larger than 4G for 32bit PE image");
3079 // Set Base Address to a negative value.
3081 NewBaseAddress
= (UINT64
) (0 - NewBaseAddress
);
3083 if (OutImageType
== FW_REBASE_IMAGE
) {
3084 Status
= RebaseImage (mInImageName
, FileBuffer
, NewBaseAddress
);
3086 Status
= SetAddressToSectionHeader (mInImageName
, FileBuffer
, NewBaseAddress
);
3088 if (EFI_ERROR (Status
)) {
3090 Error (NULL
, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address -0x%llx can't success", mInImageName
, 0 - NewBaseAddress
);
3092 Error (NULL
, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address 0x%llx can't success", mInImageName
, NewBaseAddress
);
3104 // Extract bin data from Pe image.
3106 if (OutImageType
== FW_BIN_IMAGE
) {
3107 if (FileLength
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
3108 Error (NULL
, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName
);
3112 // Output bin data from exe file
3114 FileLength
= FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
;
3115 memcpy (FileBuffer
, FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, FileLength
);
3116 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
3121 // Zero Debug Information of Pe Image
3123 if (OutImageType
== FW_ZERO_DEBUG_IMAGE
) {
3124 Status
= ZeroDebugData (FileBuffer
, TRUE
);
3125 if (EFI_ERROR (Status
)) {
3126 Error (NULL
, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status
);
3131 // Write the updated Image
3133 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
3138 // Set Time Stamp of Pe Image
3140 if (OutImageType
== FW_SET_STAMP_IMAGE
) {
3141 Status
= SetStamp (FileBuffer
, TimeStamp
);
3142 if (EFI_ERROR (Status
)) {
3147 // Write the updated Image
3149 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
3154 // Extract acpi data from pe image.
3156 if (OutImageType
== FW_ACPI_IMAGE
) {
3157 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3158 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
3159 if (strcmp ((char *)SectionHeader
->Name
, ".data") == 0 || strcmp ((char *)SectionHeader
->Name
, ".sdata") == 0) {
3163 if (SectionHeader
->Misc
.VirtualSize
< SectionHeader
->SizeOfRawData
) {
3164 FileLength
= SectionHeader
->Misc
.VirtualSize
;
3166 FileLength
= SectionHeader
->SizeOfRawData
;
3169 if (CheckAcpiTable (FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
) != STATUS_SUCCESS
) {
3170 Error (NULL
, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName
);
3175 // Output Apci data to file
3177 memcpy (FileBuffer
, FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
);
3178 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
3182 Error (NULL
, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName
);
3186 // Zero all unused fields of the DOS header
3188 if (DosHdr
!= NULL
) {
3189 memcpy (&BackupDosHdr
, DosHdr
, sizeof (EFI_IMAGE_DOS_HEADER
));
3190 memset (DosHdr
, 0, sizeof (EFI_IMAGE_DOS_HEADER
));
3191 DosHdr
->e_magic
= BackupDosHdr
.e_magic
;
3192 DosHdr
->e_lfanew
= BackupDosHdr
.e_lfanew
;
3194 for (Index
= sizeof (EFI_IMAGE_DOS_HEADER
); Index
< (UINT32
) DosHdr
->e_lfanew
; Index
++) {
3195 FileBuffer
[Index
] = (UINT8
) DosHdr
->e_cp
;
3200 // Initialize TeImage Header
3202 memset (&TEImageHeader
, 0, sizeof (EFI_TE_IMAGE_HEADER
));
3203 TEImageHeader
.Signature
= EFI_TE_IMAGE_HEADER_SIGNATURE
;
3204 TEImageHeader
.Machine
= PeHdr
->Pe32
.FileHeader
.Machine
;
3205 TEImageHeader
.NumberOfSections
= (UINT8
) PeHdr
->Pe32
.FileHeader
.NumberOfSections
;
3206 TEImageHeader
.StrippedSize
= (UINT16
) ((UINTN
) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
) - (UINTN
) FileBuffer
);
3207 TEImageHeader
.Subsystem
= (UINT8
) Type
;
3210 // Patch the PE header
3212 PeHdr
->Pe32
.OptionalHeader
.Subsystem
= (UINT16
) Type
;
3214 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
3215 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
3216 Optional32
->MajorOperatingSystemVersion
= 0;
3217 Optional32
->MinorOperatingSystemVersion
= 0;
3218 Optional32
->MajorImageVersion
= 0;
3219 Optional32
->MinorImageVersion
= 0;
3220 Optional32
->MajorSubsystemVersion
= 0;
3221 Optional32
->MinorSubsystemVersion
= 0;
3222 Optional32
->Win32VersionValue
= 0;
3223 Optional32
->CheckSum
= 0;
3224 Optional32
->SizeOfStackReserve
= 0;
3225 Optional32
->SizeOfStackCommit
= 0;
3226 Optional32
->SizeOfHeapReserve
= 0;
3227 Optional32
->SizeOfHeapCommit
= 0;
3229 TEImageHeader
.AddressOfEntryPoint
= Optional32
->AddressOfEntryPoint
;
3230 TEImageHeader
.BaseOfCode
= Optional32
->BaseOfCode
;
3231 TEImageHeader
.ImageBase
= (UINT64
) (Optional32
->ImageBase
);
3233 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
3234 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
3235 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
3238 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
3239 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3240 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
3244 // Zero .pdata section data.
3246 if (!KeepExceptionTableFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
3247 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
3248 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
3249 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3250 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
3251 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
3253 // Zero .pdata Section data
3255 memset (FileBuffer
+ SectionHeader
->PointerToRawData
, 0, SectionHeader
->SizeOfRawData
);
3257 // Zero .pdata Section header name
3259 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
3261 // Zero Execption Table
3263 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
3264 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
3265 DebugMsg (NULL
, 0, 9, "Zero the .pdata section for PE image", NULL
);
3272 // Strip zero padding at the end of the .reloc section
3274 if (!KeepZeroPendingFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
3275 if (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
3276 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3277 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
3279 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
3281 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
3282 SectionHeader
->Misc
.VirtualSize
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
3283 AllignedRelocSize
= (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional32
->FileAlignment
- 1) & (~(Optional32
->FileAlignment
- 1));
3285 // Check to see if there is zero padding at the end of the base relocations
3287 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
3289 // Check to see if the base relocations are at the end of the file
3291 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional32
->SizeOfImage
) {
3293 // All the required conditions are met to strip the zero padding of the end of the base relocations section
3295 Optional32
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
3296 Optional32
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
3297 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
3298 FileLength
= Optional32
->SizeOfImage
;
3299 DebugMsg (NULL
, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader
->SizeOfRawData
- AllignedRelocSize
));
3306 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
3307 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
3308 Optional64
->MajorOperatingSystemVersion
= 0;
3309 Optional64
->MinorOperatingSystemVersion
= 0;
3310 Optional64
->MajorImageVersion
= 0;
3311 Optional64
->MinorImageVersion
= 0;
3312 Optional64
->MajorSubsystemVersion
= 0;
3313 Optional64
->MinorSubsystemVersion
= 0;
3314 Optional64
->Win32VersionValue
= 0;
3315 Optional64
->CheckSum
= 0;
3316 Optional64
->SizeOfStackReserve
= 0;
3317 Optional64
->SizeOfStackCommit
= 0;
3318 Optional64
->SizeOfHeapReserve
= 0;
3319 Optional64
->SizeOfHeapCommit
= 0;
3321 TEImageHeader
.AddressOfEntryPoint
= Optional64
->AddressOfEntryPoint
;
3322 TEImageHeader
.BaseOfCode
= Optional64
->BaseOfCode
;
3323 TEImageHeader
.ImageBase
= (UINT64
) (Optional64
->ImageBase
);
3325 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
3326 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
3327 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
3330 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
3331 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3332 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
3336 // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
3337 // For Itaninum and X64 Image, remove .pdata section.
3339 if ((!KeepExceptionTableFlag
&& PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_X64
) || PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
) {
3340 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
3341 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
3342 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
3343 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3344 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
3345 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
3347 // Zero .pdata Section header name
3349 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
3351 RuntimeFunction
= (RUNTIME_FUNCTION
*)(FileBuffer
+ SectionHeader
->PointerToRawData
);
3352 for (Index1
= 0; Index1
< Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
/ sizeof (RUNTIME_FUNCTION
); Index1
++, RuntimeFunction
++) {
3353 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3354 for (Index2
= 0; Index2
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index2
++, SectionHeader
++) {
3355 if (RuntimeFunction
->UnwindInfoAddress
>= SectionHeader
->VirtualAddress
&& RuntimeFunction
->UnwindInfoAddress
< (SectionHeader
->VirtualAddress
+ SectionHeader
->SizeOfRawData
)) {
3356 UnwindInfo
= (UNWIND_INFO
*)(FileBuffer
+ SectionHeader
->PointerToRawData
+ (RuntimeFunction
->UnwindInfoAddress
- SectionHeader
->VirtualAddress
));
3357 if (UnwindInfo
->Version
== 1) {
3358 memset (UnwindInfo
+ 1, 0, UnwindInfo
->CountOfUnwindCodes
* sizeof (UINT16
));
3359 memset (UnwindInfo
, 0, sizeof (UNWIND_INFO
));
3364 memset (RuntimeFunction
, 0, sizeof (RUNTIME_FUNCTION
));
3367 // Zero Execption Table
3369 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
3370 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
3371 DebugMsg (NULL
, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL
);
3379 // Strip zero padding at the end of the .reloc section
3381 if (!KeepZeroPendingFlag
&& Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
3382 if (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
3383 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3384 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
3386 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
3388 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
3389 SectionHeader
->Misc
.VirtualSize
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
3390 AllignedRelocSize
= (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional64
->FileAlignment
- 1) & (~(Optional64
->FileAlignment
- 1));
3392 // Check to see if there is zero padding at the end of the base relocations
3394 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
3396 // Check to see if the base relocations are at the end of the file
3398 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional64
->SizeOfImage
) {
3400 // All the required conditions are met to strip the zero padding of the end of the base relocations section
3402 Optional64
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
3403 Optional64
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
3404 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
3405 FileLength
= Optional64
->SizeOfImage
;
3406 DebugMsg (NULL
, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader
->SizeOfRawData
- AllignedRelocSize
));
3414 Error (NULL
, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr
->Pe32
.OptionalHeader
.Magic
, mInImageName
);
3418 if (((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) == 0) && \
3419 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
== 0) && \
3420 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
== 0)) {
3422 // PeImage can be loaded into memory, but it has no relocation section.
3423 // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
3425 if (Optional32
!= NULL
) {
3426 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
3427 } else if (Optional64
!= NULL
) {
3428 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
3433 // Fill HII section data
3435 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3436 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++) {
3437 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".hii") == 0) {
3439 // Update resource section header offset
3441 SetHiiResourceHeader ((UINT8
*) FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, SectionHeader
[Index
].VirtualAddress
);
3443 // Update resource section name
3445 strcpy((char *) SectionHeader
[Index
].Name
, ".rsrc");
3447 // Update resource data directory.
3449 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
3450 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
3451 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= SectionHeader
[Index
].VirtualAddress
;
3452 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= SectionHeader
[Index
].Misc
.VirtualSize
;
3453 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
3454 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
3455 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= SectionHeader
[Index
].VirtualAddress
;
3456 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= SectionHeader
[Index
].Misc
.VirtualSize
;
3463 // Zero ExceptionTable Xdata
3465 if (!KeepExceptionTableFlag
) {
3466 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3467 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++) {
3468 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".xdata") == 0) {
3470 // zero .xdata section
3472 memset (FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, 0, SectionHeader
[Index
].SizeOfRawData
);
3473 DebugMsg (NULL
, 0, 9, NULL
, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", (unsigned) SectionHeader
[Index
].PointerToRawData
, (unsigned) SectionHeader
[Index
].SizeOfRawData
);
3480 // Zero Time/Data field
3482 ZeroDebugData (FileBuffer
, FALSE
);
3484 if (OutImageType
== FW_TE_IMAGE
) {
3485 if ((PeHdr
->Pe32
.FileHeader
.NumberOfSections
&~0xFF) || (Type
&~0xFF)) {
3487 // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
3489 Error (NULL
, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName
);
3493 if ((PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
)) {
3495 // TeImage has the same section alignment and file alignment.
3497 Error (NULL
, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName
);
3501 DebugMsg (NULL
, 0, 9, "TeImage Header Info", "Machine type is %X, Number of sections is %X, Stripped size is %X, EntryPoint is %X, BaseOfCode is %X, ImageBase is %llX",
3502 TEImageHeader
.Machine
, TEImageHeader
.NumberOfSections
, TEImageHeader
.StrippedSize
, (unsigned) TEImageHeader
.AddressOfEntryPoint
, (unsigned) TEImageHeader
.BaseOfCode
, (unsigned long long) TEImageHeader
.ImageBase
);
3504 // Update Image to TeImage
3506 FileLength
= FileLength
- TEImageHeader
.StrippedSize
;
3507 memcpy (FileBuffer
+ sizeof (EFI_TE_IMAGE_HEADER
), FileBuffer
+ TEImageHeader
.StrippedSize
, FileLength
);
3508 FileLength
= FileLength
+ sizeof (EFI_TE_IMAGE_HEADER
);
3509 memcpy (FileBuffer
, &TEImageHeader
, sizeof (EFI_TE_IMAGE_HEADER
));
3510 VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength
));
3514 // Following codes are to fix the objcopy's issue:
3515 // objcopy in binutil 2.50.18 will set PE image's charactices to "RELOC_STRIPPED" if image has no ".reloc" section
3516 // It cause issue for EFI image which has no ".reloc" sections.
3517 // Following codes will be removed when objcopy in binutil fix this problem for PE image.
3519 if ((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) != 0) {
3520 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
3521 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
3522 if (Optional32
->ImageBase
== 0) {
3523 PeHdr
->Pe32
.FileHeader
.Characteristics
&= ~EFI_IMAGE_FILE_RELOCS_STRIPPED
;
3525 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
3526 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
3527 if (Optional64
->ImageBase
== 0) {
3528 PeHdr
->Pe32
.FileHeader
.Characteristics
&= ~EFI_IMAGE_FILE_RELOCS_STRIPPED
;
3536 // Update Image to EfiImage or TE image
3539 if ((FileLength
!= InputFileLength
) || (memcmp (FileBuffer
, InputFileBuffer
, FileLength
) != 0)) {
3541 // Update File when File is changed.
3543 fpInOut
= fopen (mInImageName
, "wb");
3544 if (fpInOut
== NULL
) {
3545 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
3548 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
3549 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
3552 if ((OutputFileTime
< InputFileTime
) || (FileLength
!= OutputFileLength
) || (memcmp (FileBuffer
, OutputFileBuffer
, FileLength
) != 0)) {
3554 // Update File when File is changed or File is old.
3556 fpOut
= fopen (OutImageName
, "wb");
3557 if (fpOut
== NULL
) {
3558 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
3561 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
3562 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
3565 mImageSize
= FileLength
;
3568 if (fpInOut
!= NULL
) {
3569 if (GetUtilityStatus () != STATUS_SUCCESS
) {
3571 // when file updates failed, original file is still recovered.
3573 fwrite (InputFileBuffer
, 1, InputFileLength
, fpInOut
);
3576 // Write converted data into fpInOut file and close input file.
3581 if (FileBuffer
!= NULL
) {
3585 if (InputFileName
!= NULL
) {
3586 free (InputFileName
);
3589 if (fpOut
!= NULL
) {
3591 // Write converted data into fpOut file and close output file.
3594 if (GetUtilityStatus () != STATUS_SUCCESS
) {
3595 if (OutputFileBuffer
== NULL
) {
3596 remove (OutImageName
);
3598 fpOut
= fopen (OutImageName
, "wb");
3599 fwrite (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
3605 if (InputFileBuffer
!= NULL
) {
3606 free (InputFileBuffer
);
3609 if (OutputFileBuffer
!= NULL
) {
3610 free (OutputFileBuffer
);
3614 // Write module size and time stamp to report file.
3616 if (OutImageName
!= NULL
) {
3617 FileLen
= strlen (OutImageName
);
3619 if (FileLen
>= 4 && strcmp (OutImageName
+ (FileLen
- 4), ".efi") == 0) {
3620 ReportFileName
= (CHAR8
*) malloc (FileLen
+ 1);
3621 if (ReportFileName
!= NULL
) {
3622 strcpy (ReportFileName
, OutImageName
);
3623 strcpy (ReportFileName
+ (FileLen
- 4), ".txt");
3624 ReportFile
= fopen (ReportFileName
, "w+");
3625 if (ReportFile
!= NULL
) {
3626 fprintf (ReportFile
, "MODULE_SIZE = %u\n", (unsigned) mImageSize
);
3627 fprintf (ReportFile
, "TIME_STAMP = %u\n", (unsigned) mImageTimeStamp
);
3630 free (ReportFileName
);
3633 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
3635 return GetUtilityStatus ();
3641 IN OUT UINT8
*FileBuffer
,
3642 BOOLEAN ZeroDebugFlag
3646 Routine Description:
3648 Zero debug information in PeImage.
3652 FileBuffer - Pointer to PeImage.
3653 ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp
3657 EFI_ABORTED - PeImage is invalid.
3658 EFI_SUCCESS - Zero debug data successfully.
3663 UINT32 DebugDirectoryEntryRva
;
3664 UINT32 DebugDirectoryEntryFileOffset
;
3665 UINT32 ExportDirectoryEntryRva
;
3666 UINT32 ExportDirectoryEntryFileOffset
;
3667 UINT32 ResourceDirectoryEntryRva
;
3668 UINT32 ResourceDirectoryEntryFileOffset
;
3669 EFI_IMAGE_DOS_HEADER
*DosHdr
;
3670 EFI_IMAGE_FILE_HEADER
*FileHdr
;
3671 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
3672 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
3673 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
3674 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
3675 UINT32
*NewTimeStamp
;
3680 DebugDirectoryEntryRva
= 0;
3681 ExportDirectoryEntryRva
= 0;
3682 ResourceDirectoryEntryRva
= 0;
3683 DebugDirectoryEntryFileOffset
= 0;
3684 ExportDirectoryEntryFileOffset
= 0;
3685 ResourceDirectoryEntryFileOffset
= 0;
3686 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
3687 FileHdr
= (EFI_IMAGE_FILE_HEADER
*) (FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
3690 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
3691 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
3692 // NO DOS header, must start with PE/COFF header
3693 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
3695 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
3699 // Get Debug, Export and Resource EntryTable RVA address.
3700 // Resource Directory entry need to review.
3702 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
3703 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3704 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3705 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3706 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3707 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3709 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3710 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3711 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3713 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3714 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3715 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3716 if (ZeroDebugFlag
) {
3717 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
3718 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
3722 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3723 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3724 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3725 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3726 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3728 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3729 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3730 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3732 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3733 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3734 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3735 if (ZeroDebugFlag
) {
3736 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
3737 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
3743 // Get DirectoryEntryTable file offset.
3745 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
3746 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3747 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3748 DebugDirectoryEntryFileOffset
=
3749 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3751 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3752 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3753 ExportDirectoryEntryFileOffset
=
3754 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3756 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3757 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3758 ResourceDirectoryEntryFileOffset
=
3759 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3764 //Zero Debug Data and TimeStamp
3766 FileHdr
->TimeDateStamp
= 0;
3767 mImageTimeStamp
= 0;
3768 if (ExportDirectoryEntryFileOffset
!= 0) {
3769 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
3773 if (ResourceDirectoryEntryFileOffset
!= 0) {
3774 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
3778 if (DebugDirectoryEntryFileOffset
!= 0) {
3779 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
);
3780 DebugEntry
->TimeDateStamp
= 0;
3781 mImageTimeStamp
= 0;
3782 if (ZeroDebugFlag
) {
3783 memset (FileBuffer
+ DebugEntry
->FileOffset
, 0, DebugEntry
->SizeOfData
);
3784 memset (DebugEntry
, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
3794 IN OUT UINT8
*FileBuffer
,
3799 Routine Description:
3801 Set new time stamp into PeImage FileHdr and Directory table:
3802 Debug, Export and Resource.
3806 FileBuffer - Pointer to PeImage.
3807 TimeStamp - Time stamp string.
3811 EFI_INVALID_PARAMETER - TimeStamp format is not recognized.
3812 EFI_SUCCESS - Set new time stamp in this image successfully.
3820 UINT32 DebugDirectoryEntryRva
;
3821 UINT32 DebugDirectoryEntryFileOffset
;
3822 UINT32 ExportDirectoryEntryRva
;
3823 UINT32 ExportDirectoryEntryFileOffset
;
3824 UINT32 ResourceDirectoryEntryRva
;
3825 UINT32 ResourceDirectoryEntryFileOffset
;
3826 EFI_IMAGE_DOS_HEADER
*DosHdr
;
3827 EFI_IMAGE_FILE_HEADER
*FileHdr
;
3828 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
3829 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
3830 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
3831 UINT32
*NewTimeStamp
;
3836 DebugDirectoryEntryRva
= 0;
3837 DebugDirectoryEntryFileOffset
= 0;
3838 ExportDirectoryEntryRva
= 0;
3839 ExportDirectoryEntryFileOffset
= 0;
3840 ResourceDirectoryEntryRva
= 0;
3841 ResourceDirectoryEntryFileOffset
= 0;
3843 // Get time and date that will be set.
3845 if (TimeStamp
== NULL
) {
3846 Error (NULL
, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");
3847 return EFI_INVALID_PARAMETER
;
3850 // compare the value with "NOW", if yes, current system time is set.
3852 if (stricmp (TimeStamp
, "NOW") == 0) {
3854 // get system current time and date
3859 // Check Time Format strictly yyyy-mm-dd 00:00:00
3861 for (Index
= 0; TimeStamp
[Index
] != '\0' && Index
< 20; Index
++) {
3862 if (Index
== 4 || Index
== 7) {
3863 if (TimeStamp
[Index
] == '-') {
3866 } else if (Index
== 13 || Index
== 16) {
3867 if (TimeStamp
[Index
] == ':') {
3870 } else if (Index
== 10 && TimeStamp
[Index
] == ' ') {
3872 } else if ((TimeStamp
[Index
] < '0') || (TimeStamp
[Index
] > '9')) {
3877 if (Index
< 19 || TimeStamp
[19] != '\0') {
3878 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
3879 return EFI_INVALID_PARAMETER
;
3883 // get the date and time from TimeStamp
3885 if (sscanf (TimeStamp
, "%d-%d-%d %d:%d:%d",
3893 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
3894 return EFI_INVALID_PARAMETER
;
3898 // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
3900 if (stime
.tm_mon
<= 0 || stime
.tm_mday
<=0) {
3901 Error (NULL
, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp
);
3902 return EFI_INVALID_PARAMETER
;
3907 // in struct, Year (current year minus 1900)
3908 // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
3911 // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
3913 if (stime
.tm_year
>= 1970 && stime
.tm_year
<= 2038) {
3915 // convert 1970 -> 70, 2000 -> 100, ...
3917 stime
.tm_year
-= 1900;
3919 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
3920 return EFI_INVALID_PARAMETER
;
3924 // convert the date and time to time_t format
3926 newtime
= mktime (&stime
);
3927 if (newtime
== (time_t) - 1) {
3928 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
3929 return EFI_INVALID_PARAMETER
;
3933 ptime
= localtime (&newtime
);
3934 DebugMsg (NULL
, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",
3935 ptime
->tm_year
+ 1900, ptime
->tm_mon
+ 1, ptime
->tm_mday
, ptime
->tm_hour
, ptime
->tm_min
, ptime
->tm_sec
);
3937 // Set new time and data into PeImage.
3939 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
3940 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
3941 // NO DOS header, must start with PE/COFF header
3942 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
3944 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
3948 // Get Debug, Export and Resource EntryTable RVA address.
3949 // Resource Directory entry need to review.
3951 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
3952 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3953 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3954 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3955 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3956 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3958 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3959 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3960 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3962 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3963 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3964 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3967 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3968 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3969 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3970 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3971 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3973 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3974 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3975 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3977 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3978 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3979 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3984 // Get DirectoryEntryTable file offset.
3986 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
3987 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3988 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3989 DebugDirectoryEntryFileOffset
=
3990 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3992 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3993 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3994 ExportDirectoryEntryFileOffset
=
3995 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3997 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3998 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3999 ResourceDirectoryEntryFileOffset
=
4000 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
4007 FileHdr
->TimeDateStamp
= (UINT32
) newtime
;
4008 mImageTimeStamp
= (UINT32
) newtime
;
4009 if (ExportDirectoryEntryRva
!= 0) {
4010 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
4011 *NewTimeStamp
= (UINT32
) newtime
;
4014 if (ResourceDirectoryEntryRva
!= 0) {
4015 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
4016 *NewTimeStamp
= (UINT32
) newtime
;
4019 if (DebugDirectoryEntryRva
!= 0) {
4020 NewTimeStamp
= (UINT32
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
+ sizeof (UINT32
));
4021 *NewTimeStamp
= (UINT32
) newtime
;
4035 Routine Description:
4036 Read a 32-bit microcode data value from a text file and convert to raw binary form.
4039 InFptr - file pointer to input text file
4040 Data - pointer to where to return the data parsed
4043 STATUS_SUCCESS - no errors or warnings, Data contains valid information
4044 STATUS_ERROR - errors were encountered
4048 CHAR8 Line
[MAX_LINE_LEN
];
4050 unsigned ScannedData
= 0;
4052 Line
[MAX_LINE_LEN
- 1] = 0;
4054 if (fgets (Line
, MAX_LINE_LEN
, InFptr
) == NULL
) {
4055 return STATUS_ERROR
;
4058 // If it was a binary file, then it may have overwritten our null terminator
4060 if (Line
[MAX_LINE_LEN
- 1] != 0) {
4061 return STATUS_ERROR
;
4067 for (cptr
= Line
; *cptr
&& isspace((int)*cptr
); cptr
++) {
4070 // Skip Blank Lines and Comment Lines
4071 if ((strlen(cptr
) != 0) && (*cptr
!= ';')) {
4077 // dd 000000001h ; comment
4082 if ((tolower((int)cptr
[0]) == 'd') && (tolower((int)cptr
[1]) == 'd') && isspace ((int)cptr
[2])) {
4084 // Skip blanks and look for a hex digit
4087 for (; *cptr
&& isspace((int)*cptr
); cptr
++) {
4089 if (isxdigit ((int)*cptr
)) {
4090 if (sscanf (cptr
, "%X", &ScannedData
) != 1) {
4091 return STATUS_ERROR
;
4094 *Data
= (UINT32
) ScannedData
;
4095 return STATUS_SUCCESS
;
4098 return STATUS_ERROR
;