3 Copyright (c) 2004 - 2009, 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"
34 #include <Common/UefiBaseTypes.h>
35 #include <IndustryStandard/PeImage.h>
38 // Acpi Table definition
40 #include <IndustryStandard/Acpi.h>
41 #include <IndustryStandard/Acpi1_0.h>
42 #include <IndustryStandard/Acpi2_0.h>
43 #include <IndustryStandard/Acpi3_0.h>
44 #include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
46 #include "CommonLib.h"
47 #include "PeCoffLib.h"
49 #include "EfiUtilityMsgs.h"
51 #include "elf_common.h"
57 // Version of this utility
59 #define UTILITY_NAME "GenFw"
60 #define UTILITY_MAJOR_VERSION 0
61 #define UTILITY_MINOR_VERSION 2
64 // Action for this tool.
66 #define FW_DUMMY_IMAGE 0
67 #define FW_EFI_IMAGE 1
69 #define FW_ACPI_IMAGE 3
70 #define FW_BIN_IMAGE 4
71 #define FW_ZERO_DEBUG_IMAGE 5
72 #define FW_SET_STAMP_IMAGE 6
73 #define FW_MCI_IMAGE 7
74 #define FW_MERGE_IMAGE 8
75 #define FW_RELOC_STRIPEED_IMAGE 9
77 #define DUMP_TE_HEADER 0x11
79 #define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
80 #define DEFAULT_MC_ALIGNMENT 16
86 #define STATUS_IGNORE 0xA
88 // Structure definition for a microcode header
98 UINT32 DataSize
; // if 0, then TotalSize = 2048, and TotalSize field is invalid
99 UINT32 TotalSize
; // number of bytes
101 } MICROCODE_IMAGE_HEADER
;
103 STATIC CHAR8
*mInImageName
;
108 IN OUT UINT8
*FileBuffer
,
115 IN OUT UINT8
*FileBuffer
,
135 Print out version information for this utility.
147 fprintf (stdout
, "%s Version %d.%d\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
);
174 fprintf (stdout
, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME
);
177 // Copyright declaration
179 fprintf (stdout
, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");
184 fprintf (stdout
, "Options:\n");
185 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
186 File will be created to store the ouput content.\n");
187 fprintf (stdout
, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\
188 Create Efi Image. EFI_FILETYPE is one of BASE, SEC,\n\
189 PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\
190 DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER, \n\
191 DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER, \n\
192 PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\
193 APPLICATION, SAL_RT_DRIVER to support all module types\n\
194 It can only be used together with --keepexceptiontable,\n\
195 --keepzeropending, -r, -o option.It is a action option.\n\
196 If it is combined with other action options, the later\n\
197 input action option will override the previous one.\n");
198 fprintf (stdout
, " -c, --acpi Create Acpi table.\n\
199 It can't be combined with other action options\n\
200 except for -o, -r option. It is a action option.\n\
201 If it is combined with other action options, the later\n\
202 input action option will override the previous one.\n");
203 fprintf (stdout
, " -t, --terse Create Te Image.\n\
204 It can only be used together with --keepexceptiontable,\n\
205 --keepzeropending, -r, -o option.It is a action option.\n\
206 If it is combined with other action options, the later\n\
207 input action option will override the previous one.\n");
208 fprintf (stdout
, " -u, --dump Dump TeImage Header.\n\
209 It can't be combined with other action options\n\
210 except for -o, -r option. It is a action option.\n\
211 If it is combined with other action options, the later\n\
212 input action option will override the previous one.\n");
213 fprintf (stdout
, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\
214 It also zeros the time stamp fields.\n\
215 This option can be used to compare the binary efi image.\n\
216 It can't be combined with other action options\n\
217 except for -o, -r option. It is a action option.\n\
218 If it is combined with other action options, the later\n\
219 input action option will override the previous one.\n");
220 fprintf (stdout
, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\
221 It can't be combined with other action options\n\
222 except for -o, -r option. It is a action option.\n\
223 If it is combined with other action options, the later\n\
224 input action option will override the previous one.\n");;
225 fprintf (stdout
, " -l, --stripped Relocation info stripped from the input PE or TE image.\n\
226 It can't be combined with other action options\n\
227 except for -o, -r option. It is a action option.\n\
228 If it is combined with other action options, the later\n\
229 input action option will override the previous one.\n");
230 fprintf (stdout
, " -s timedate, --stamp timedate\n\
231 timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\
232 is set to NOW, current system time is used. The support\n\
233 date scope is 1970-1-1 8:0:0 ~ 2038-1-19 3:14:07\n\
234 It can't be combined with other action options\n\
235 except for -o, -r option. It is a action option.\n\
236 If it is combined with other action options, the later\n\
237 input action option will override the previous one.\n");
238 fprintf (stdout
, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\
239 It can't be combined with other action options\n\
240 except for -o option. It is a action option.\n\
241 If it is combined with other action options, the later\n\
242 input action option will override the previous one.\n");
243 fprintf (stdout
, " -j, --join Combine multi microcode bin files to one file.\n\
244 It can be specified with -a, -p, -o option.\n\
245 No other options can be combined with it.\n\
246 If it is combined with other action options, the later\n\
247 input action option will override the previous one.\n");
248 fprintf (stdout
, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\
249 This option is only used together with -j option.\n");
250 fprintf (stdout
, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\
251 This option is only used together with -j option.\n");
252 fprintf (stdout
, " --keepexceptiontable Don't clear exception table.\n\
253 This option can be used together with -e or -t.\n\
254 It doesn't work for other options.\n");
255 fprintf (stdout
, " --keepzeropending Don't strip zero pending of .reloc.\n\
256 This option can be used together with -e or -t.\n\
257 It doesn't work for other options.\n");
258 fprintf (stdout
, " -r, --replace Overwrite the input file with the output content.\n\
259 If more input files are specified,\n\
260 the last input file will be as the output file.\n");
261 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
262 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
263 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
264 fprintf (stdout
, " --version Show program's version number and exit\n");
265 fprintf (stdout
, " -h, --help Show this help message and exit\n");
282 AcpiTable Buffer for AcpiSection
283 Length AcpiSection Length
292 EFI_ACPI_DESCRIPTION_HEADER
*AcpiHeader
;
293 EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs
;
294 UINT32 ExpectedLength
;
296 AcpiHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTable
;
299 // Generic check for AcpiTable length.
301 if (AcpiHeader
->Length
> Length
) {
302 Error (NULL
, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL
);
307 // Currently, we only check must-have tables: FADT, FACS, DSDT,
308 // and some important tables: MADT, MCFG.
310 switch (AcpiHeader
->Signature
) {
313 // "FACP" Fixed ACPI Description Table
315 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
:
316 switch (AcpiHeader
->Revision
) {
317 case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
318 ExpectedLength
= sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
);
320 case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
321 ExpectedLength
= sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
);
323 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
324 ExpectedLength
= sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
);
327 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
) {
328 ExpectedLength
= AcpiHeader
->Length
;
331 Error (NULL
, 0, 3000, "Invalid", "FACP revision check failed.");
334 if (ExpectedLength
!= AcpiHeader
->Length
) {
335 Error (NULL
, 0, 3000, "Invalid", "FACP length check failed.");
341 // "FACS" Firmware ACPI Control Structure
343 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE
:
344 Facs
= (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)AcpiTable
;
345 if (Facs
->Version
> EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) {
348 if ((Facs
->Version
!= EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
349 (Facs
->Version
!= EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
350 (Facs
->Version
!= EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
)){
351 Error (NULL
, 0, 3000, "Invalid", "FACS version check failed.");
354 if ((Facs
->Length
!= sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
355 (Facs
->Length
!= sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
356 (Facs
->Length
!= sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
))) {
357 Error (NULL
, 0, 3000, "Invalid", "FACS length check failed.");
363 // "DSDT" Differentiated System Description Table
365 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
366 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION
) {
369 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
)) {
370 Error (NULL
, 0, 3000, "Invalid", "DSDT length check failed.");
376 // "APIC" Multiple APIC Description Table
378 case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE
:
379 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) {
382 if ((AcpiHeader
->Revision
!= EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
383 (AcpiHeader
->Revision
!= EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
384 (AcpiHeader
->Revision
!= EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
)) {
385 Error (NULL
, 0, 3000, "Invalid", "APIC revision check failed.");
388 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT32
) + sizeof(UINT32
)) {
389 Error (NULL
, 0, 3000, "Invalid", "APIC length check failed.");
395 // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
397 case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE
:
398 if (AcpiHeader
->Revision
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
401 if (AcpiHeader
->Revision
!= EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
402 Error (NULL
, 0, 3000, "Invalid", "MCFG revision check failed.");
405 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT64
)) {
406 Error (NULL
, 0, 3000, "Invalid", "MCFG length check failed.");
412 // Other table pass check
418 return STATUS_SUCCESS
;
427 return (FileBuffer
[EI_MAG0
] == ELFMAG0
428 && FileBuffer
[EI_MAG1
] == ELFMAG1
429 && FileBuffer
[EI_MAG2
] == ELFMAG2
430 && FileBuffer
[EI_MAG3
] == ELFMAG3
);
433 typedef Elf32_Shdr Elf_Shdr
;
434 typedef Elf32_Ehdr Elf_Ehdr
;
435 typedef Elf32_Rel Elf_Rel
;
436 typedef Elf32_Sym Elf_Sym
;
437 typedef Elf32_Phdr Elf_Phdr
;
438 typedef Elf32_Dyn Elf_Dyn
;
440 #define ELFCLASS ELFCLASS32
441 #define ELF_R_TYPE(r) ELF32_R_TYPE(r)
442 #define ELF_R_SYM(r) ELF32_R_SYM(r)
445 // Well known ELF structures.
452 // PE section alignment.
454 const UINT32 CoffAlignment
= 0x20;
455 const UINT16 CoffNbrSections
= 4;
458 // Current offset in coff file.
463 // Result Coff file in memory.
465 UINT8
*CoffFile
= NULL
;
467 // ELF sections to offset in Coff file.
469 UINT32
*CoffSectionsOffset
= NULL
;
472 // Offset in Coff file of headers and sections.
480 EFI_IMAGE_BASE_RELOCATION
*CoffBaseRel
;
481 UINT16
*CoffEntryRel
;
488 return (Offset
+ CoffAlignment
- 1) & ~(CoffAlignment
- 1);
496 if (Num
>= Ehdr
->e_shnum
)
498 return (Elf_Shdr
*)((UINT8
*)ShdrBase
+ Num
* Ehdr
->e_shentsize
);
507 // Note: Magic has already been tested.
509 if (Ehdr
->e_ident
[EI_CLASS
] != ELFCLASS
) {
510 Error (NULL
, 0, 3000, "Unsupported", "%s needs to be ported for 64-bit ELF.", mInImageName
);
513 if (Ehdr
->e_ident
[EI_DATA
] != ELFDATA2LSB
) {
514 Error (NULL
, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");
517 if ((Ehdr
->e_type
!= ET_EXEC
) && (Ehdr
->e_type
!= ET_DYN
)) {
518 Error (NULL
, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");
521 if (!((Ehdr
->e_machine
== EM_386
) || (Ehdr
->e_machine
== EM_ARM
))) {
522 Error (NULL
, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM");
525 if (Ehdr
->e_version
!= EV_CURRENT
) {
526 Error (NULL
, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) Ehdr
->e_version
, EV_CURRENT
);
531 // Find the section header table
533 ShdrBase
= (Elf_Shdr
*)((UINT8
*)Ehdr
+ Ehdr
->e_shoff
);
534 gPhdrBase
= (Elf_Phdr
*)((UINT8
*)Ehdr
+ Ehdr
->e_phoff
);
536 CoffSectionsOffset
= (UINT32
*)malloc(Ehdr
->e_shnum
* sizeof (UINT32
));
538 memset(CoffSectionsOffset
, 0, Ehdr
->e_shnum
* sizeof(UINT32
));
547 return (Shdr
->sh_flags
& (SHF_WRITE
| SHF_ALLOC
)) == SHF_ALLOC
;
555 return (Shdr
->sh_flags
& (SHF_WRITE
| SHF_ALLOC
)) == (SHF_ALLOC
| SHF_WRITE
);
566 EFI_IMAGE_SECTION_HEADER
*Hdr
;
567 Hdr
= (EFI_IMAGE_SECTION_HEADER
*)(CoffFile
+ TableOffset
);
569 strcpy((char *)Hdr
->Name
, Name
);
570 Hdr
->Misc
.VirtualSize
= Size
;
571 Hdr
->VirtualAddress
= Offset
;
572 Hdr
->SizeOfRawData
= Size
;
573 Hdr
->PointerToRawData
= Offset
;
574 Hdr
->PointerToRelocations
= 0;
575 Hdr
->PointerToLinenumbers
= 0;
576 Hdr
->NumberOfRelocations
= 0;
577 Hdr
->NumberOfLinenumbers
= 0;
578 Hdr
->Characteristics
= Flags
;
580 TableOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
589 EFI_IMAGE_DOS_HEADER
*DosHdr
;
590 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
597 // Coff file start with a DOS header.
599 CoffOffset
= sizeof(EFI_IMAGE_DOS_HEADER
) + 0x40;
600 NtHdrOffset
= CoffOffset
;
601 switch (Ehdr
->e_machine
) {
604 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS32
);
608 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS64
);
611 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN
)Ehdr
->e_machine
);
612 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS32
);
616 TableOffset
= CoffOffset
;
617 CoffOffset
+= CoffNbrSections
* sizeof(EFI_IMAGE_SECTION_HEADER
);
620 // First text sections.
622 CoffOffset
= CoffAlign(CoffOffset
);
623 TextOffset
= CoffOffset
;
624 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
625 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
626 if (IsTextShdr(shdr
)) {
627 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
628 // the alignment field is valid
629 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
630 // if the section address is aligned we must align PE/COFF
631 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
632 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
633 // ARM RVCT tools have behavior outside of the ELF specification to try
634 // and make images smaller. If sh_addr is not aligned to sh_addralign
635 // then the section needs to preserve sh_addr MOD sh_addralign.
636 // Normally doing nothing here works great.
637 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
641 /* Relocate entry. */
642 if ((Ehdr
->e_entry
>= shdr
->sh_addr
) &&
643 (Ehdr
->e_entry
< shdr
->sh_addr
+ shdr
->sh_size
)) {
644 CoffEntry
= CoffOffset
+ Ehdr
->e_entry
- shdr
->sh_addr
;
646 CoffSectionsOffset
[i
] = CoffOffset
;
647 CoffOffset
+= shdr
->sh_size
;
651 if (Ehdr
->e_machine
!= EM_ARM
) {
652 CoffOffset
= CoffAlign(CoffOffset
);
656 // Then data sections.
658 DataOffset
= CoffOffset
;
659 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
660 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
661 if (IsDataShdr(shdr
)) {
662 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
663 // the alignment field is valid
664 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
665 // if the section address is aligned we must align PE/COFF
666 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
667 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
668 // ARM RVCT tools have behavior outside of the ELF specification to try
669 // and make images smaller. If sh_addr is not aligned to sh_addralign
670 // then the section needs to preserve sh_addr MOD sh_addralign.
671 // Normally doing nothing here works great.
672 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
676 CoffSectionsOffset
[i
] = CoffOffset
;
677 CoffOffset
+= shdr
->sh_size
;
680 CoffOffset
= CoffAlign(CoffOffset
);
682 RelocOffset
= CoffOffset
;
685 // Allocate base Coff file. Will be expanded later for relocations.
687 CoffFile
= (UINT8
*)malloc(CoffOffset
);
688 memset(CoffFile
, 0, CoffOffset
);
693 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)CoffFile
;
694 DosHdr
->e_magic
= EFI_IMAGE_DOS_SIGNATURE
;
695 DosHdr
->e_lfanew
= NtHdrOffset
;
697 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
699 NtHdr
->Pe32
.Signature
= EFI_IMAGE_NT_SIGNATURE
;
701 switch (Ehdr
->e_machine
) {
703 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IA32
;
704 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
707 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_X64
;
708 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
711 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IPF
;
712 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
715 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_ARMT
;
716 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
719 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN
)Ehdr
->e_machine
);
720 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IA32
;
721 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
724 NtHdr
->Pe32
.FileHeader
.NumberOfSections
= CoffNbrSections
;
725 NtHdr
->Pe32
.FileHeader
.TimeDateStamp
= (UINT32
) time(NULL
);
726 NtHdr
->Pe32
.FileHeader
.PointerToSymbolTable
= 0;
727 NtHdr
->Pe32
.FileHeader
.NumberOfSymbols
= 0;
728 NtHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
= sizeof(NtHdr
->Pe32
.OptionalHeader
);
729 NtHdr
->Pe32
.FileHeader
.Characteristics
= EFI_IMAGE_FILE_EXECUTABLE_IMAGE
730 | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED
731 | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED
732 | EFI_IMAGE_FILE_32BIT_MACHINE
;
734 NtHdr
->Pe32
.OptionalHeader
.SizeOfCode
= DataOffset
- TextOffset
;
735 NtHdr
->Pe32
.OptionalHeader
.SizeOfInitializedData
= RelocOffset
- DataOffset
;
736 NtHdr
->Pe32
.OptionalHeader
.SizeOfUninitializedData
= 0;
737 NtHdr
->Pe32
.OptionalHeader
.AddressOfEntryPoint
= CoffEntry
;
739 NtHdr
->Pe32
.OptionalHeader
.BaseOfCode
= TextOffset
;
741 NtHdr
->Pe32
.OptionalHeader
.BaseOfData
= DataOffset
;
742 NtHdr
->Pe32
.OptionalHeader
.ImageBase
= 0;
743 NtHdr
->Pe32
.OptionalHeader
.SectionAlignment
= CoffAlignment
;
744 NtHdr
->Pe32
.OptionalHeader
.FileAlignment
= CoffAlignment
;
745 NtHdr
->Pe32
.OptionalHeader
.SizeOfImage
= 0;
747 NtHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
= TextOffset
;
748 NtHdr
->Pe32
.OptionalHeader
.NumberOfRvaAndSizes
= EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES
;
753 if ((DataOffset
- TextOffset
) > 0) {
754 CreateSectionHeader (".text", TextOffset
, DataOffset
- TextOffset
,
755 EFI_IMAGE_SCN_CNT_CODE
756 | EFI_IMAGE_SCN_MEM_EXECUTE
757 | EFI_IMAGE_SCN_MEM_READ
);
759 // Don't make a section of size 0.
760 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
763 if ((RelocOffset
- TextOffset
) > 0) {
764 CreateSectionHeader (".data", DataOffset
, RelocOffset
- DataOffset
,
765 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
766 | EFI_IMAGE_SCN_MEM_WRITE
767 | EFI_IMAGE_SCN_MEM_READ
);
769 // Don't make a section of size 0.
770 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
776 int (*Filter
)(Elf_Shdr
*)
784 // First: copy sections.
786 for (Idx
= 0; Idx
< Ehdr
->e_shnum
; Idx
++) {
787 Elf_Shdr
*Shdr
= GetShdrByIndex(Idx
);
788 if ((*Filter
)(Shdr
)) {
789 switch (Shdr
->sh_type
) {
792 memcpy(CoffFile
+ CoffSectionsOffset
[Idx
],
793 (UINT8
*)Ehdr
+ Shdr
->sh_offset
,
798 memset(CoffFile
+ CoffSectionsOffset
[Idx
], 0, Shdr
->sh_size
);
803 // Ignore for unkown section type.
805 VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName
, (unsigned)Shdr
->sh_type
);
812 // Second: apply relocations.
814 for (Idx
= 0; Idx
< Ehdr
->e_shnum
; Idx
++) {
815 Elf_Shdr
*RelShdr
= GetShdrByIndex(Idx
);
816 if (RelShdr
->sh_type
!= SHT_REL
)
818 SecShdr
= GetShdrByIndex(RelShdr
->sh_info
);
819 SecOffset
= CoffSectionsOffset
[RelShdr
->sh_info
];
820 if (RelShdr
->sh_type
== SHT_REL
&& (*Filter
)(SecShdr
)) {
822 Elf_Shdr
*SymtabShdr
= GetShdrByIndex(RelShdr
->sh_link
);
823 UINT8
*Symtab
= (UINT8
*)Ehdr
+ SymtabShdr
->sh_offset
;
825 for (RelIdx
= 0; RelIdx
< RelShdr
->sh_size
; RelIdx
+= RelShdr
->sh_entsize
) {
826 Elf_Rel
*Rel
= (Elf_Rel
*)((UINT8
*)Ehdr
+ RelShdr
->sh_offset
+ RelIdx
);
827 Elf_Sym
*Sym
= (Elf_Sym
*)(Symtab
+ ELF_R_SYM(Rel
->r_info
) * SymtabShdr
->sh_entsize
);
831 if (Sym
->st_shndx
== SHN_UNDEF
832 || Sym
->st_shndx
== SHN_ABS
833 || Sym
->st_shndx
> Ehdr
->e_shnum
) {
834 Error (NULL
, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName
);
836 SymShdr
= GetShdrByIndex(Sym
->st_shndx
);
839 // Note: r_offset in a memory address.
840 // Convert it to a pointer in the coff file.
842 Targ
= CoffFile
+ SecOffset
+ (Rel
->r_offset
- SecShdr
->sh_addr
);
844 if (Ehdr
->e_machine
== EM_386
) {
845 switch (ELF_R_TYPE(Rel
->r_info
)) {
850 // Absolute relocation.
852 *(UINT32
*)Targ
= *(UINT32
*)Targ
- SymShdr
->sh_addr
853 + CoffSectionsOffset
[Sym
->st_shndx
];
857 // Relative relocation: Symbol - Ip + Addend
859 *(UINT32
*)Targ
= *(UINT32
*)Targ
860 + (CoffSectionsOffset
[Sym
->st_shndx
] - SymShdr
->sh_addr
)
861 - (SecOffset
- SecShdr
->sh_addr
);
864 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, (unsigned) ELF_R_TYPE(Rel
->r_info
));
866 } else if (Ehdr
->e_machine
== EM_ARM
) {
867 switch (ELF32_R_TYPE(Rel
->r_info
)) {
868 case R_ARM_RBASE
: // No relocation - no action required
869 case R_ARM_PC24
: // PC-relative relocations don't require modification
870 case R_ARM_XPC25
: // PC-relative relocations don't require modification
875 // Absolute relocation.
877 *(UINT32
*)Targ
= *(UINT32
*)Targ
- SymShdr
->sh_addr
+ CoffSectionsOffset
[Sym
->st_shndx
];
880 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, (unsigned) ELF32_R_TYPE(Rel
->r_info
));
895 CoffBaseRel
->SizeOfBlock
+= 2;
905 if (CoffBaseRel
== NULL
906 || CoffBaseRel
->VirtualAddress
!= (Offset
& ~0xfff)) {
907 if (CoffBaseRel
!= NULL
) {
909 // Add a null entry (is it required ?)
911 CoffAddFixupEntry (0);
913 // Pad for alignment.
915 if (CoffOffset
% 4 != 0)
916 CoffAddFixupEntry (0);
921 CoffOffset
+ sizeof(EFI_IMAGE_BASE_RELOCATION
) + 2*0x1000);
922 memset(CoffFile
+ CoffOffset
, 0,
923 sizeof(EFI_IMAGE_BASE_RELOCATION
) + 2*0x1000);
925 CoffBaseRel
= (EFI_IMAGE_BASE_RELOCATION
*)(CoffFile
+ CoffOffset
);
926 CoffBaseRel
->VirtualAddress
= Offset
& ~0xfff;
927 CoffBaseRel
->SizeOfBlock
= sizeof(EFI_IMAGE_BASE_RELOCATION
);
929 CoffEntryRel
= (UINT16
*)(CoffBaseRel
+ 1);
930 CoffOffset
+= sizeof(EFI_IMAGE_BASE_RELOCATION
);
936 CoffAddFixupEntry((UINT16
) ((Type
<< 12) | (Offset
& 0xfff)));
945 if (num
>= Ehdr
->e_phnum
) {
949 return (Elf32_Phdr
*)((UINT8
*)gPhdrBase
+ num
* Ehdr
->e_phentsize
);
959 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
960 EFI_IMAGE_DATA_DIRECTORY
*Dir
;
961 BOOLEAN FoundRelocations
;
964 UINTN RelElementSize
;
969 Elf32_Phdr
*DynamicSegment
;
970 Elf32_Phdr
*TargetSegment
;
972 for (Index
= 0, FoundRelocations
= FALSE
; Index
< Ehdr
->e_shnum
; Index
++) {
973 Elf_Shdr
*RelShdr
= GetShdrByIndex(Index
);
974 if (RelShdr
->sh_type
== SHT_REL
) {
975 Elf_Shdr
*SecShdr
= GetShdrByIndex(RelShdr
->sh_info
);
976 if (IsTextShdr(SecShdr
) || IsDataShdr(SecShdr
)) {
978 FoundRelocations
= TRUE
;
979 for (RelIdx
= 0; RelIdx
< RelShdr
->sh_size
; RelIdx
+= RelShdr
->sh_entsize
) {
980 Elf_Rel
*Rel
= (Elf_Rel
*)
981 ((UINT8
*)Ehdr
+ RelShdr
->sh_offset
+ RelIdx
);
983 if (Ehdr
->e_machine
== EM_386
) {
984 switch (ELF_R_TYPE(Rel
->r_info
)) {
989 CoffAddFixup(CoffSectionsOffset
[RelShdr
->sh_info
]
990 + (Rel
->r_offset
- SecShdr
->sh_addr
),
991 EFI_IMAGE_REL_BASED_HIGHLOW
);
994 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, (unsigned) ELF_R_TYPE(Rel
->r_info
));
996 } else if (Ehdr
->e_machine
== EM_ARM
) {
997 switch (ELF32_R_TYPE(Rel
->r_info
)) {
1005 CoffSectionsOffset
[RelShdr
->sh_info
]
1006 + (Rel
->r_offset
- SecShdr
->sh_addr
),
1007 EFI_IMAGE_REL_BASED_HIGHLOW
1011 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, (unsigned) ELF32_R_TYPE(Rel
->r_info
));
1014 Error (NULL
, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) Ehdr
->e_machine
);
1021 if (!FoundRelocations
&& (Ehdr
->e_machine
== EM_ARM
)) {
1022 /* Try again, but look for PT_DYNAMIC instead of SHT_REL */
1024 for (Index
= 0; Index
< Ehdr
->e_phnum
; Index
++) {
1029 DynamicSegment
= GetPhdrByIndex (Index
);
1031 if (DynamicSegment
->p_type
== PT_DYNAMIC
) {
1032 Dyn
= (Elf32_Dyn
*) ((UINT8
*)Ehdr
+ DynamicSegment
->p_offset
);
1034 while (Dyn
->d_tag
!= DT_NULL
) {
1035 switch (Dyn
->d_tag
) {
1037 RelOffset
= Dyn
->d_un
.d_val
;
1041 RelSize
= Dyn
->d_un
.d_val
;
1045 RelElementSize
= Dyn
->d_un
.d_val
;
1050 if (( RelOffset
== 0 ) || ( RelSize
== 0 ) || ( RelElementSize
== 0 )) {
1051 Error (NULL
, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName
);
1054 for (K
= 0; K
< RelSize
; K
+= RelElementSize
) {
1056 Rel
= (Elf32_Rel
*) ((UINT8
*) Ehdr
+ DynamicSegment
->p_offset
+ RelOffset
+ K
);
1058 switch (ELF32_R_TYPE (Rel
->r_info
)) {
1062 TargetSegment
= GetPhdrByIndex (ELF32_R_SYM (Rel
->r_info
) - 1);
1064 // Note: r_offset in a memory address. Convert it to a pointer in the coff file.
1065 Targ
= CoffFile
+ CoffSectionsOffset
[ ELF32_R_SYM( Rel
->r_info
) ] + Rel
->r_offset
- TargetSegment
->p_vaddr
;
1067 *(UINT32
*)Targ
= *(UINT32
*)Targ
+ CoffSectionsOffset
[ELF32_R_SYM( Rel
->r_info
)];
1069 CoffAddFixup (CoffSectionsOffset
[ELF32_R_SYM (Rel
->r_info
)] + (Rel
->r_offset
- TargetSegment
->p_vaddr
), EFI_IMAGE_REL_BASED_HIGHLOW
);
1072 Error (NULL
, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type.", mInImageName
);
1081 // Pad by adding empty entries.
1083 while (CoffOffset
& (CoffAlignment
- 1)) {
1084 CoffAddFixupEntry(0);
1088 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1089 Dir
= &NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1090 Dir
->Size
= CoffOffset
- RelocOffset
;
1091 if (Dir
->Size
== 0) {
1092 // If no relocations, null out the directory entry and don't add the .reloc section
1093 Dir
->VirtualAddress
= 0;
1094 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
1096 Dir
->VirtualAddress
= RelocOffset
;
1097 CreateSectionHeader (".reloc", RelocOffset
, CoffOffset
- RelocOffset
,
1098 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
1099 | EFI_IMAGE_SCN_MEM_DISCARDABLE
1100 | EFI_IMAGE_SCN_MEM_READ
);
1112 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1113 EFI_IMAGE_DATA_DIRECTORY
*DataDir
;
1114 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*Dir
;
1115 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
*Nb10
;
1117 Len
= strlen(mInImageName
) + 1;
1118 DebugOffset
= CoffOffset
;
1120 CoffOffset
+= sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
)
1121 + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
)
1123 CoffOffset
= CoffAlign(CoffOffset
);
1125 CoffFile
= realloc(CoffFile
, CoffOffset
);
1126 memset(CoffFile
+ DebugOffset
, 0, CoffOffset
- DebugOffset
);
1128 Dir
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)(CoffFile
+ DebugOffset
);
1129 Dir
->Type
= EFI_IMAGE_DEBUG_TYPE_CODEVIEW
;
1130 Dir
->SizeOfData
= sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
) + Len
;
1131 Dir
->RVA
= DebugOffset
+ sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
1132 Dir
->FileOffset
= DebugOffset
+ sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
1134 Nb10
= (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
*)(Dir
+ 1);
1135 Nb10
->Signature
= CODEVIEW_SIGNATURE_NB10
;
1136 strcpy ((char *)(Nb10
+ 1), mInImageName
);
1139 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1140 DataDir
= &NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
];
1141 DataDir
->VirtualAddress
= DebugOffset
;
1142 DataDir
->Size
= CoffOffset
- DebugOffset
;
1143 if (DataDir
->Size
== 0) {
1144 // If no debug, null out the directory entry and don't add the .debug section
1145 DataDir
->VirtualAddress
= 0;
1146 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
1148 DataDir
->VirtualAddress
= DebugOffset
;
1149 CreateSectionHeader (".debug", DebugOffset
, CoffOffset
- DebugOffset
,
1150 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
1151 | EFI_IMAGE_SCN_MEM_DISCARDABLE
1152 | EFI_IMAGE_SCN_MEM_READ
);
1163 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1166 // Check header, read section table.
1168 Ehdr
= (Elf32_Ehdr
*)*FileBuffer
;
1169 if (!CheckElfHeader())
1172 VerboseMsg ("Check Efl Image Header");
1174 // Compute sections new address.
1179 VerboseMsg ("Compute sections new address.");
1182 // Write and relocate sections.
1184 WriteSections(IsTextShdr
);
1185 WriteSections(IsDataShdr
);
1186 VerboseMsg ("Write and relocate sections.");
1189 // Translate and write relocations.
1192 VerboseMsg ("Translate and write relocations.");
1195 // Write debug info.
1198 VerboseMsg ("Write debug info.");
1200 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1201 NtHdr
->Pe32
.OptionalHeader
.SizeOfImage
= CoffOffset
;
1207 *FileBuffer
= CoffFile
;
1208 *FileLength
= CoffOffset
;
1211 // Free memory space
1213 if (CoffSectionsOffset
!= NULL
) {
1214 free (CoffSectionsOffset
);
1220 IN CHAR8
*ImageName
,
1221 IN OUT UINT8
*FileBuffer
,
1222 IN EFI_IMAGE_SECTION_HEADER
*SectionHeader
,
1223 IN UINT32 SectionTotalNumber
1227 CHAR8 MapFileName
[_MAX_PATH
];
1228 CHAR8 Line
[MAX_LINE_LEN
];
1229 CHAR8 KeyWord
[MAX_LINE_LEN
];
1230 CHAR8 SectionName
[MAX_LINE_LEN
];
1231 UINT32 FunctionType
= 0;
1232 unsigned SectionOffset
= 0;
1233 unsigned SectionLength
= 0;
1234 unsigned SectionNumber
= 0;
1239 for (Index2
= 0; Index2
< SectionTotalNumber
; Index2
++) {
1240 if (stricmp ((char *)SectionHeader
[Index2
].Name
, ".zdata") == 0) {
1242 // try to zero the customized .zdata section, which is mapped to .xdata
1244 memset (FileBuffer
+ SectionHeader
[Index2
].PointerToRawData
, 0, SectionHeader
[Index2
].SizeOfRawData
);
1245 DebugMsg (NULL
, 0, 9, NULL
, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", (unsigned) SectionHeader
[Index2
].PointerToRawData
, (unsigned) SectionHeader
[Index2
].SizeOfRawData
);
1250 // Try to get PDB file name
1252 PdbPointer
= (CHAR8
*) PeCoffLoaderGetPdbPointer (FileBuffer
);
1253 if (PdbPointer
!= NULL
) {
1254 strcpy (MapFileName
, PdbPointer
);
1256 strcpy (MapFileName
, ImageName
);
1260 // Construct map file name
1262 Index
= strlen (MapFileName
) - 1;
1263 while (Index
>= 0 && MapFileName
[Index
] != '.') {
1268 // don't know how to costruct map file
1274 // fill map file postfix
1276 MapFileName
[Index
+ 1] = 'm';
1277 MapFileName
[Index
+ 2] = 'a';
1278 MapFileName
[Index
+ 3] = 'p';
1279 MapFileName
[Index
+ 4] = '\0';
1282 // try opening Map File
1284 fpMapFile
= fopen (MapFileName
, "r");
1285 if (fpMapFile
== NULL
) {
1287 // Can't open Map file. Maybe it doesn't exist.
1293 // Output Functions information into Fv Map file
1295 while (fgets (Line
, MAX_LINE_LEN
, fpMapFile
) != NULL
) {
1299 if (Line
[0] == 0x0a) {
1300 if (FunctionType
!= 0) {
1302 // read all section table data
1314 if (FunctionType
== 0) {
1315 sscanf (Line
, "%s", KeyWord
);
1316 if (stricmp (KeyWord
, "Start") == 0) {
1325 // Printf Function Information
1327 if (FunctionType
== 1) {
1328 sscanf (Line
, "%x:%x %xH %s", &SectionNumber
, &SectionOffset
, &SectionLength
, SectionName
);
1329 if (stricmp (SectionName
, ".xdata") == 0) {
1336 if (FunctionType
!= 2) {
1338 // no .xdata section is found
1345 // Zero .xdata Section data
1347 memset (FileBuffer
+ SectionHeader
[SectionNumber
-1].PointerToRawData
+ SectionOffset
, 0, SectionLength
);
1348 DebugMsg (NULL
, 0, 9, NULL
, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", (unsigned) SectionHeader
[SectionNumber
-1].PointerToRawData
+ SectionOffset
, SectionLength
);
1360 Routine Description:
1366 argc - Number of command line parameters.
1367 argv - Array of pointers to command line parameter strings.
1370 STATUS_SUCCESS - Utility exits successfully.
1371 STATUS_ERROR - Some error occurred during execution.
1376 UINT32 InputFileNum
;
1377 CHAR8
**InputFileName
;
1381 UINT32 OutImageType
;
1386 UINT32
*DataPointer
;
1387 UINT32
*OldDataPointer
;
1393 UINT32 MciAlignment
;
1395 UINT32 AllignedRelocSize
;
1398 UINT8
*OutputFileBuffer
;
1399 UINT32 OutputFileLength
;
1400 RUNTIME_FUNCTION
*RuntimeFunction
;
1401 UNWIND_INFO
*UnwindInfo
;
1403 BOOLEAN ReplaceFlag
;
1404 BOOLEAN KeepExceptionTableFlag
;
1405 BOOLEAN KeepZeroPendingFlag
;
1407 EFI_TE_IMAGE_HEADER TEImageHeader
;
1408 EFI_TE_IMAGE_HEADER
*TeHdr
;
1409 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1410 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1411 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1412 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32
;
1413 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64
;
1414 EFI_IMAGE_DOS_HEADER BackupDosHdr
;
1415 MICROCODE_IMAGE_HEADER
*MciHeader
;
1417 SetUtilityName (UTILITY_NAME
);
1420 // Assign to fix compile warning
1423 InputFileName
= NULL
;
1424 mInImageName
= NULL
;
1425 OutImageName
= NULL
;
1427 OutImageType
= FW_DUMMY_IMAGE
;
1429 Status
= STATUS_SUCCESS
;
1435 MciAlignment
= DEFAULT_MC_ALIGNMENT
;
1436 MciPadValue
= DEFAULT_MC_PAD_BYTE_VALUE
;
1440 ReplaceFlag
= FALSE
;
1442 OutputFileBuffer
= NULL
;
1443 OutputFileLength
= 0;
1446 KeepExceptionTableFlag
= FALSE
;
1447 KeepZeroPendingFlag
= FALSE
;
1450 Error (NULL
, 0, 1001, "Missing options", "No input options.");
1452 return STATUS_ERROR
;
1458 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
1461 return STATUS_SUCCESS
;
1464 if (stricmp (argv
[0], "--version") == 0) {
1466 return STATUS_SUCCESS
;
1470 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
1471 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1472 Error (NULL
, 0, 1003, "Invalid option value", "Output file name is missing for -o option");
1475 OutImageName
= argv
[1];
1481 if ((stricmp (argv
[0], "-e") == 0) || (stricmp (argv
[0], "--efiImage") == 0)) {
1482 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1483 Error (NULL
, 0, 1003, "Invalid option value", "Module Type is missing for -o option");
1486 ModuleType
= argv
[1];
1487 if (OutImageType
!= FW_TE_IMAGE
) {
1488 OutImageType
= FW_EFI_IMAGE
;
1495 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--stripped") == 0)) {
1496 OutImageType
= FW_RELOC_STRIPEED_IMAGE
;
1502 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--acpi") == 0)) {
1503 OutImageType
= FW_ACPI_IMAGE
;
1509 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--terse") == 0)) {
1510 OutImageType
= FW_TE_IMAGE
;
1516 if ((stricmp (argv
[0], "-u") == 0) || (stricmp (argv
[0], "--dump") == 0)) {
1517 OutImageType
= DUMP_TE_HEADER
;
1523 if ((stricmp (argv
[0], "-b") == 0) || (stricmp (argv
[0], "--exe2bin") == 0)) {
1524 OutImageType
= FW_BIN_IMAGE
;
1530 if ((stricmp (argv
[0], "-z") == 0) || (stricmp (argv
[0], "--zero") == 0)) {
1531 OutImageType
= FW_ZERO_DEBUG_IMAGE
;
1537 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--stamp") == 0)) {
1538 OutImageType
= FW_SET_STAMP_IMAGE
;
1539 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1540 Error (NULL
, 0, 1003, "Invalid option value", "time stamp is missing for -s option");
1543 TimeStamp
= argv
[1];
1549 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--replace") == 0)) {
1556 if (stricmp (argv
[0], "--keepexceptiontable") == 0) {
1557 KeepExceptionTableFlag
= TRUE
;
1563 if (stricmp (argv
[0], "--keepzeropending") == 0) {
1564 KeepZeroPendingFlag
= TRUE
;
1570 if ((stricmp (argv
[0], "-m") == 0) || (stricmp (argv
[0], "--mcifile") == 0)) {
1571 OutImageType
= FW_MCI_IMAGE
;
1577 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--join") == 0)) {
1578 OutImageType
= FW_MERGE_IMAGE
;
1584 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
1585 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1586 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1589 MciAlignment
= (UINT32
) Temp64
;
1595 if ((stricmp (argv
[0], "-p") == 0) || (stricmp (argv
[0], "--pad") == 0)) {
1596 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1597 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1600 MciPadValue
= (UINT8
) Temp64
;
1606 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
1607 SetPrintLevel (VERBOSE_LOG_LEVEL
);
1608 VerboseMsg ("Verbose output Mode Set!");
1614 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1615 SetPrintLevel (KEY_LOG_LEVEL
);
1616 KeyMsg ("Quiet output Mode Set!");
1622 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
1623 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
1624 if (EFI_ERROR (Status
)) {
1625 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1629 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel
);
1632 SetPrintLevel (LogLevel
);
1633 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
1639 if (argv
[0][0] == '-') {
1640 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
1644 // Get Input file name
1646 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
1647 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
1648 if (InputFileName
== NULL
) {
1649 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1653 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1654 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1656 // InputFileName buffer too small, need to realloc
1658 InputFileName
= (CHAR8
**) realloc (
1660 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1663 if (InputFileName
== NULL
) {
1664 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1668 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1671 InputFileName
[InputFileNum
++] = argv
[0];
1676 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1678 if (OutImageType
== FW_DUMMY_IMAGE
) {
1679 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!");
1681 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.");
1687 // check input files
1689 if (InputFileNum
== 0) {
1690 Error (NULL
, 0, 1001, "Missing option", "Input files");
1695 // Combine MciBinary files to one file
1697 if ((OutImageType
== FW_MERGE_IMAGE
) && ReplaceFlag
) {
1698 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");
1705 mInImageName
= InputFileName
[InputFileNum
- 1];
1706 VerboseMsg ("the input file name is %s", mInImageName
);
1709 // Action will be taken for the input file.
1711 switch (OutImageType
) {
1713 VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType
);
1716 VerboseMsg ("Create Te Image based on the input PE image.");
1719 VerboseMsg ("Get acpi table data from the input PE image.");
1721 case FW_RELOC_STRIPEED_IMAGE
:
1722 VerboseMsg ("Remove relocation section from Pe or Te image.");
1725 VerboseMsg ("Convert the input EXE to the output BIN file.");
1727 case FW_ZERO_DEBUG_IMAGE
:
1728 VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");
1730 case FW_SET_STAMP_IMAGE
:
1731 VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp
);
1733 case DUMP_TE_HEADER
:
1734 VerboseMsg ("Dump the TE header information of the input TE image.");
1737 VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");
1739 case FW_MERGE_IMAGE
:
1740 VerboseMsg ("Combine the input multi microcode bin files to one bin file.");
1747 VerboseMsg ("Overwrite the input file with the output content.");
1751 // Open output file and Write image into the output file.
1753 if (OutImageName
!= NULL
) {
1754 fpOut
= fopen (OutImageName
, "rb");
1755 if (fpOut
!= NULL
) {
1756 OutputFileLength
= _filelength (fileno (fpOut
));
1757 OutputFileBuffer
= malloc (OutputFileLength
);
1758 if (OutputFileBuffer
== NULL
) {
1759 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1764 fread (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
1767 fpOut
= fopen (OutImageName
, "wb");
1769 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1772 VerboseMsg ("Output file name is %s", OutImageName
);
1773 } else if (!ReplaceFlag
) {
1774 if (OutImageType
== DUMP_TE_HEADER
) {
1777 Error (NULL
, 0, 1001, "Missing option", "output file");
1783 // Combine MciBinary files to one file
1785 if (OutImageType
== FW_MERGE_IMAGE
) {
1786 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1787 fpIn
= fopen (InputFileName
[Index
], "rb");
1789 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1793 FileLength
= _filelength (fileno (fpIn
));
1794 FileBuffer
= malloc (FileLength
);
1795 if (FileBuffer
== NULL
) {
1796 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1801 fread (FileBuffer
, 1, FileLength
, fpIn
);
1804 // write input file to out file
1806 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
1808 // write pad value to out file.
1810 while (FileLength
++ % MciAlignment
!= 0) {
1811 fwrite (&MciPadValue
, 1, 1, fpOut
);
1814 // free allocated memory space
1820 // Done successfully
1826 // Convert MicroCode.txt file to MicroCode.bin file
1828 if (OutImageType
== FW_MCI_IMAGE
) {
1829 fpIn
= fopen (mInImageName
, "r");
1831 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1836 // The first pass is to determine
1837 // how much data is in the file so we can allocate a working buffer.
1841 Status
= MicrocodeReadData (fpIn
, &Data
);
1842 if (Status
== STATUS_SUCCESS
) {
1843 FileLength
+= sizeof (Data
);
1845 if (Status
== STATUS_IGNORE
) {
1846 Status
= STATUS_SUCCESS
;
1848 } while (Status
== STATUS_SUCCESS
);
1850 // Error if no data.
1852 if (FileLength
== 0) {
1853 Error (NULL
, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName
);
1856 if (FileLength
< sizeof (MICROCODE_IMAGE_HEADER
)) {
1857 Error (NULL
, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName
);
1862 // Allocate a buffer for the data
1864 FileBuffer
= malloc (FileLength
);
1865 if (FileBuffer
== NULL
) {
1866 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1870 // Re-read the file, storing the data into our buffer
1872 fseek (fpIn
, 0, SEEK_SET
);
1873 DataPointer
= (UINT32
*) FileBuffer
;
1874 OldDataPointer
= DataPointer
;
1876 OldDataPointer
= DataPointer
;
1877 Status
= MicrocodeReadData (fpIn
, DataPointer
++);
1878 if (Status
== STATUS_IGNORE
) {
1879 DataPointer
= OldDataPointer
;
1880 Status
= STATUS_SUCCESS
;
1882 } while (Status
== STATUS_SUCCESS
);
1884 // close input file after read data
1889 // Can't do much checking on the header because, per the spec, the
1890 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
1891 // and the TotalSize field is invalid (actually missing). Thus we can't
1892 // even verify the Reserved fields are 0.
1894 MciHeader
= (MICROCODE_IMAGE_HEADER
*) FileBuffer
;
1895 if (MciHeader
->DataSize
== 0) {
1898 Index
= MciHeader
->TotalSize
;
1901 if (Index
!= FileLength
) {
1902 Error (NULL
, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName
, (unsigned) FileLength
, (unsigned) Index
);
1907 // Checksum the contents
1909 DataPointer
= (UINT32
*) FileBuffer
;
1912 while (Index
< FileLength
) {
1913 CheckSum
+= *DataPointer
;
1915 Index
+= sizeof (*DataPointer
);
1917 if (CheckSum
!= 0) {
1918 Error (NULL
, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum
, mInImageName
);
1922 // Open the output file and write the buffer contents
1924 if (fpOut
!= NULL
) {
1925 if (fwrite (FileBuffer
, FileLength
, 1, fpOut
) != 1) {
1926 Error (NULL
, 0, 0002, "Error writing file", OutImageName
);
1932 fpInOut
= fopen (mInImageName
, "wb");
1933 if (fpInOut
!= NULL
) {
1934 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1937 if (fwrite (FileBuffer
, FileLength
, 1, fpInOut
) != 1) {
1938 Error (NULL
, 0, 0002, "Error writing file", mInImageName
);
1942 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
1944 // Convert Mci.TXT to Mci.bin file successfully
1950 // Open input file and read file data into file buffer.
1952 fpIn
= fopen (mInImageName
, "rb");
1954 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1958 FileLength
= _filelength (fileno (fpIn
));
1959 FileBuffer
= malloc (FileLength
);
1960 if (FileBuffer
== NULL
) {
1961 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1966 fread (FileBuffer
, 1, FileLength
, fpIn
);
1969 DebugMsg (NULL
, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) FileLength
);
1975 fpInOut
= fopen (mInImageName
, "wb");
1977 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1982 // Dump TeImage Header into output file.
1984 if (OutImageType
== DUMP_TE_HEADER
) {
1985 memcpy (&TEImageHeader
, FileBuffer
, sizeof (TEImageHeader
));
1986 if (TEImageHeader
.Signature
!= EFI_TE_IMAGE_HEADER_SIGNATURE
) {
1987 Error (NULL
, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName
);
1990 if (fpInOut
!= NULL
) {
1991 fprintf (fpInOut
, "Dump of file %s\n\n", mInImageName
);
1992 fprintf (fpInOut
, "TE IMAGE HEADER VALUES\n");
1993 fprintf (fpInOut
, "%17X machine\n", TEImageHeader
.Machine
);
1994 fprintf (fpInOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
1995 fprintf (fpInOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
1996 fprintf (fpInOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
1997 fprintf (fpInOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
1998 fprintf (fpInOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
1999 fprintf (fpInOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
2000 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
2001 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
2004 if (fpOut
!= NULL
) {
2005 fprintf (fpOut
, "Dump of file %s\n\n", mInImageName
);
2006 fprintf (fpOut
, "TE IMAGE HEADER VALUES\n");
2007 fprintf (fpOut
, "%17X machine\n", TEImageHeader
.Machine
);
2008 fprintf (fpOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
2009 fprintf (fpOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
2010 fprintf (fpOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
2011 fprintf (fpOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
2012 fprintf (fpOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
2013 fprintf (fpOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
2014 fprintf (fpOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
2015 fprintf (fpOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
2021 // Following code to convert dll to efi image or te image.
2022 // Get new image type
2024 if ((OutImageType
== FW_EFI_IMAGE
) || (OutImageType
== FW_TE_IMAGE
)) {
2025 if (ModuleType
== NULL
) {
2026 if (OutImageType
== FW_EFI_IMAGE
) {
2027 Error (NULL
, 0, 1001, "Missing option", "EFI_FILETYPE");
2029 } else if (OutImageType
== FW_TE_IMAGE
) {
2031 // Default TE Image Type is Boot service driver
2033 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2034 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2037 if (stricmp (ModuleType
, "BASE") == 0 ||
2038 stricmp (ModuleType
, "SEC") == 0 ||
2039 stricmp (ModuleType
, "SECURITY_CORE") == 0 ||
2040 stricmp (ModuleType
, "PEI_CORE") == 0 ||
2041 stricmp (ModuleType
, "PEIM") == 0 ||
2042 stricmp (ModuleType
, "COMBINED_PEIM_DRIVER") == 0 ||
2043 stricmp (ModuleType
, "PIC_PEIM") == 0 ||
2044 stricmp (ModuleType
, "RELOCATABLE_PEIM") == 0 ||
2045 stricmp (ModuleType
, "DXE_CORE") == 0 ||
2046 stricmp (ModuleType
, "BS_DRIVER") == 0 ||
2047 stricmp (ModuleType
, "DXE_DRIVER") == 0 ||
2048 stricmp (ModuleType
, "DXE_SMM_DRIVER") == 0 ||
2049 stricmp (ModuleType
, "UEFI_DRIVER") == 0 ||
2050 stricmp (ModuleType
, "SMM_DRIVER") == 0 ||
2051 stricmp (ModuleType
, "SMM_CORE") == 0) {
2052 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2053 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2055 } else if (stricmp (ModuleType
, "UEFI_APPLICATION") == 0 ||
2056 stricmp (ModuleType
, "APPLICATION") == 0) {
2057 Type
= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
;
2058 VerboseMsg ("Efi Image subsystem type is efi application.");
2060 } else if (stricmp (ModuleType
, "DXE_RUNTIME_DRIVER") == 0 ||
2061 stricmp (ModuleType
, "RT_DRIVER") == 0) {
2062 Type
= EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
;
2063 VerboseMsg ("Efi Image subsystem type is efi runtime driver.");
2065 } else if (stricmp (ModuleType
, "DXE_SAL_DRIVER") == 0 ||
2066 stricmp (ModuleType
, "SAL_RT_DRIVER") == 0) {
2067 Type
= EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
;
2068 VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");
2071 Error (NULL
, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType
);
2078 // Convert EFL image to PeImage
2080 if (IsElfHeader(FileBuffer
)) {
2081 VerboseMsg ("Convert the input ELF Image to Pe Image");
2082 ConvertElf(&FileBuffer
, &FileLength
);
2086 // Remove reloc section from PE or TE image
2088 if (OutImageType
== FW_RELOC_STRIPEED_IMAGE
) {
2092 TeHdr
= (EFI_TE_IMAGE_HEADER
*) FileBuffer
;
2093 if (TeHdr
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2094 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (TeHdr
+ 1);
2095 for (Index
= 0; Index
< TeHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2096 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2098 // Check the reloc section is in the end of image.
2100 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) ==
2101 (FileLength
+ TeHdr
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
))) {
2103 // Remove .reloc section and update TeImage Header
2105 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2106 SectionHeader
->SizeOfRawData
= 0;
2107 SectionHeader
->Misc
.VirtualSize
= 0;
2108 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2109 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2118 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2119 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2120 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2121 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2122 Error (NULL
, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName
);
2127 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2128 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2129 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2133 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2134 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2135 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2137 // Check the reloc section is in the end of image.
2139 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) == FileLength
) {
2141 // Remove .reloc section and update PeImage Header
2143 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2145 PeHdr
->Pe32
.FileHeader
.Characteristics
|= EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2146 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2147 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2148 Optional32
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2149 Optional32
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2150 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2151 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2152 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2155 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2156 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2157 Optional64
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2158 Optional64
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2159 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2160 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2161 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2164 SectionHeader
->Misc
.VirtualSize
= 0;
2165 SectionHeader
->SizeOfRawData
= 0;
2177 // Read the dos & pe hdrs of the image
2179 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2180 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2181 // NO DOS header, check for PE/COFF header
2182 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2183 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2184 Error (NULL
, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName
);
2190 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2191 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2192 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2197 if (PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_ARM
) {
2198 // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
2199 // so patch back to the offical UEFI value.
2200 PeHdr
->Pe32
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_ARMT
;
2204 // Extract bin data from Pe image.
2206 if (OutImageType
== FW_BIN_IMAGE
) {
2207 if (FileLength
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
2208 Error (NULL
, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName
);
2212 // Output bin data from exe file
2214 if (fpOut
!= NULL
) {
2215 fwrite (FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, 1, FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, fpOut
);
2217 if (fpInOut
!= NULL
) {
2218 fwrite (FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, 1, FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, fpInOut
);
2220 VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
));
2225 // Zero Debug Information of Pe Image
2227 if (OutImageType
== FW_ZERO_DEBUG_IMAGE
) {
2228 Status
= ZeroDebugData (FileBuffer
, TRUE
);
2229 if (EFI_ERROR (Status
)) {
2230 Error (NULL
, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status
);
2234 if (fpOut
!= NULL
) {
2235 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2237 if (fpInOut
!= NULL
) {
2238 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2240 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2245 // Set Time Stamp of Pe Image
2247 if (OutImageType
== FW_SET_STAMP_IMAGE
) {
2248 Status
= SetStamp (FileBuffer
, TimeStamp
);
2249 if (EFI_ERROR (Status
)) {
2253 if (fpOut
!= NULL
) {
2254 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2256 if (fpInOut
!= NULL
) {
2257 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2259 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2264 // Extract acpi data from pe image.
2266 if (OutImageType
== FW_ACPI_IMAGE
) {
2267 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2268 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2269 if (strcmp ((char *)SectionHeader
->Name
, ".data") == 0 || strcmp ((char *)SectionHeader
->Name
, ".sdata") == 0) {
2273 if (SectionHeader
->Misc
.VirtualSize
< SectionHeader
->SizeOfRawData
) {
2274 FileLength
= SectionHeader
->Misc
.VirtualSize
;
2276 FileLength
= SectionHeader
->SizeOfRawData
;
2279 if (CheckAcpiTable (FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
) != STATUS_SUCCESS
) {
2280 Error (NULL
, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName
);
2285 // Output Apci data to file
2287 if (fpOut
!= NULL
) {
2288 fwrite (FileBuffer
+ SectionHeader
->PointerToRawData
, 1, FileLength
, fpOut
);
2290 if (fpInOut
!= NULL
) {
2291 fwrite (FileBuffer
+ SectionHeader
->PointerToRawData
, 1, FileLength
, fpInOut
);
2293 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2297 Error (NULL
, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName
);
2301 // Zero all unused fields of the DOS header
2303 if (DosHdr
!= NULL
) {
2304 memcpy (&BackupDosHdr
, DosHdr
, sizeof (EFI_IMAGE_DOS_HEADER
));
2305 memset (DosHdr
, 0, sizeof (EFI_IMAGE_DOS_HEADER
));
2306 DosHdr
->e_magic
= BackupDosHdr
.e_magic
;
2307 DosHdr
->e_lfanew
= BackupDosHdr
.e_lfanew
;
2309 for (Index
= sizeof (EFI_IMAGE_DOS_HEADER
); Index
< (UINT32
) DosHdr
->e_lfanew
; Index
++) {
2310 FileBuffer
[Index
] = (UINT8
) DosHdr
->e_cp
;
2315 // Initialize TeImage Header
2317 memset (&TEImageHeader
, 0, sizeof (EFI_TE_IMAGE_HEADER
));
2318 TEImageHeader
.Signature
= EFI_TE_IMAGE_HEADER_SIGNATURE
;
2319 TEImageHeader
.Machine
= PeHdr
->Pe32
.FileHeader
.Machine
;
2320 TEImageHeader
.NumberOfSections
= (UINT8
) PeHdr
->Pe32
.FileHeader
.NumberOfSections
;
2321 TEImageHeader
.StrippedSize
= (UINT16
) ((UINTN
) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
) - (UINTN
) FileBuffer
);
2322 TEImageHeader
.Subsystem
= (UINT8
) Type
;
2325 // Patch the PE header
2327 PeHdr
->Pe32
.OptionalHeader
.Subsystem
= (UINT16
) Type
;
2329 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2330 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2331 Optional32
->MajorLinkerVersion
= 0;
2332 Optional32
->MinorLinkerVersion
= 0;
2333 Optional32
->MajorOperatingSystemVersion
= 0;
2334 Optional32
->MinorOperatingSystemVersion
= 0;
2335 Optional32
->MajorImageVersion
= 0;
2336 Optional32
->MinorImageVersion
= 0;
2337 Optional32
->MajorSubsystemVersion
= 0;
2338 Optional32
->MinorSubsystemVersion
= 0;
2339 Optional32
->Win32VersionValue
= 0;
2340 Optional32
->CheckSum
= 0;
2341 Optional32
->SizeOfStackReserve
= 0;
2342 Optional32
->SizeOfStackCommit
= 0;
2343 Optional32
->SizeOfHeapReserve
= 0;
2344 Optional32
->SizeOfHeapCommit
= 0;
2346 TEImageHeader
.AddressOfEntryPoint
= Optional32
->AddressOfEntryPoint
;
2347 TEImageHeader
.BaseOfCode
= Optional32
->BaseOfCode
;
2348 TEImageHeader
.ImageBase
= (UINT64
) (Optional32
->ImageBase
);
2350 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2351 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2352 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2355 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2356 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2357 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2361 // Zero .pdata section data.
2363 if (!KeepExceptionTableFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2364 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2365 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2366 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2367 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2368 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2370 // Zero .pdata Section data
2372 memset (FileBuffer
+ SectionHeader
->PointerToRawData
, 0, SectionHeader
->SizeOfRawData
);
2374 // Zero .pdata Section header name
2376 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2378 // Zero Execption Table
2380 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2381 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2382 DebugMsg (NULL
, 0, 9, "Zero the .pdata section for PE image", NULL
);
2389 // Strip zero padding at the end of the .reloc section
2391 if (!KeepZeroPendingFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2392 if (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2393 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2394 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2396 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2398 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2399 SectionHeader
->Misc
.VirtualSize
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2400 AllignedRelocSize
= (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional32
->FileAlignment
- 1) & (~(Optional32
->FileAlignment
- 1));
2402 // Check to see if there is zero padding at the end of the base relocations
2404 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2406 // Check to see if the base relocations are at the end of the file
2408 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional32
->SizeOfImage
) {
2410 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2412 Optional32
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2413 Optional32
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2414 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2415 FileLength
= Optional32
->SizeOfImage
;
2416 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
));
2423 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2424 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2425 Optional64
->MajorLinkerVersion
= 0;
2426 Optional64
->MinorLinkerVersion
= 0;
2427 Optional64
->MajorOperatingSystemVersion
= 0;
2428 Optional64
->MinorOperatingSystemVersion
= 0;
2429 Optional64
->MajorImageVersion
= 0;
2430 Optional64
->MinorImageVersion
= 0;
2431 Optional64
->MajorSubsystemVersion
= 0;
2432 Optional64
->MinorSubsystemVersion
= 0;
2433 Optional64
->Win32VersionValue
= 0;
2434 Optional64
->CheckSum
= 0;
2435 Optional64
->SizeOfStackReserve
= 0;
2436 Optional64
->SizeOfStackCommit
= 0;
2437 Optional64
->SizeOfHeapReserve
= 0;
2438 Optional64
->SizeOfHeapCommit
= 0;
2440 TEImageHeader
.AddressOfEntryPoint
= Optional64
->AddressOfEntryPoint
;
2441 TEImageHeader
.BaseOfCode
= Optional64
->BaseOfCode
;
2442 TEImageHeader
.ImageBase
= (UINT64
) (Optional64
->ImageBase
);
2444 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2445 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2446 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2449 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2450 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2451 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2455 // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
2456 // For Itaninum and X64 Image, remove .pdata section.
2458 if ((!KeepExceptionTableFlag
&& PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_X64
) || PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
) {
2459 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2460 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2461 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2462 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2463 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2464 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2466 // Zero .pdata Section header name
2468 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2470 RuntimeFunction
= (RUNTIME_FUNCTION
*)(FileBuffer
+ SectionHeader
->PointerToRawData
);
2471 for (Index1
= 0; Index1
< Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
/ sizeof (RUNTIME_FUNCTION
); Index1
++, RuntimeFunction
++) {
2472 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2473 for (Index2
= 0; Index2
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index2
++, SectionHeader
++) {
2474 if (RuntimeFunction
->UnwindInfoAddress
> SectionHeader
->VirtualAddress
&& RuntimeFunction
->UnwindInfoAddress
< (SectionHeader
->VirtualAddress
+ SectionHeader
->SizeOfRawData
)) {
2475 UnwindInfo
= (UNWIND_INFO
*)(FileBuffer
+ SectionHeader
->PointerToRawData
+ (RuntimeFunction
->UnwindInfoAddress
- SectionHeader
->VirtualAddress
));
2476 if (UnwindInfo
->Version
== 1) {
2477 memset (UnwindInfo
+ 1, 0, UnwindInfo
->CountOfUnwindCodes
* sizeof (UINT16
));
2478 memset (UnwindInfo
, 0, sizeof (UNWIND_INFO
));
2482 memset (RuntimeFunction
, 0, sizeof (RUNTIME_FUNCTION
));
2485 // Zero Execption Table
2487 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2488 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2489 DebugMsg (NULL
, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL
);
2497 // Strip zero padding at the end of the .reloc section
2499 if (!KeepZeroPendingFlag
&& Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2500 if (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2501 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2502 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2504 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2506 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2507 SectionHeader
->Misc
.VirtualSize
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2508 AllignedRelocSize
= (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional64
->FileAlignment
- 1) & (~(Optional64
->FileAlignment
- 1));
2510 // Check to see if there is zero padding at the end of the base relocations
2512 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2514 // Check to see if the base relocations are at the end of the file
2516 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional64
->SizeOfImage
) {
2518 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2520 Optional64
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2521 Optional64
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2522 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2523 FileLength
= Optional64
->SizeOfImage
;
2524 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
));
2532 Error (NULL
, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr
->Pe32
.OptionalHeader
.Magic
, mInImageName
);
2536 if (((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) == 0) && \
2537 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
== 0) && \
2538 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
== 0)) {
2540 // PeImage can be loaded into memory, but it has no relocation section.
2541 // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
2543 if (Optional32
!= NULL
) {
2544 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
2545 } else if (Optional64
!= NULL
) {
2546 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
2551 // Zero ExceptionTable Xdata
2553 if (!KeepExceptionTableFlag
) {
2554 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2555 ZeroXdataSection(mInImageName
, FileBuffer
, SectionHeader
, PeHdr
->Pe32
.FileHeader
.NumberOfSections
);
2559 // Zero Time/Data field
2561 ZeroDebugData (FileBuffer
, FALSE
);
2563 if (OutImageType
== FW_TE_IMAGE
) {
2564 if ((PeHdr
->Pe32
.FileHeader
.NumberOfSections
&~0xFF) || (Type
&~0xFF)) {
2566 // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
2568 Error (NULL
, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName
);
2572 if ((PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
)) {
2574 // TeImage has the same section alignment and file alignment.
2576 Error (NULL
, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName
);
2580 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",
2581 TEImageHeader
.Machine
, TEImageHeader
.NumberOfSections
, TEImageHeader
.StrippedSize
, (unsigned) TEImageHeader
.AddressOfEntryPoint
, (unsigned) TEImageHeader
.BaseOfCode
, (unsigned long long) TEImageHeader
.ImageBase
);
2583 // Update Image to TeImage
2585 if (fpOut
!= NULL
) {
2586 fwrite (&TEImageHeader
, 1, sizeof (EFI_TE_IMAGE_HEADER
), fpOut
);
2587 fwrite (FileBuffer
+ TEImageHeader
.StrippedSize
, 1, FileLength
- TEImageHeader
.StrippedSize
, fpOut
);
2589 if (fpInOut
!= NULL
) {
2590 fwrite (&TEImageHeader
, 1, sizeof (EFI_TE_IMAGE_HEADER
), fpInOut
);
2591 fwrite (FileBuffer
+ TEImageHeader
.StrippedSize
, 1, FileLength
- TEImageHeader
.StrippedSize
, fpInOut
);
2593 VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength
- TEImageHeader
.StrippedSize
));
2598 // Update Image to EfiImage
2600 if (fpOut
!= NULL
) {
2601 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2603 if (fpInOut
!= NULL
) {
2604 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2606 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2609 if (fpInOut
!= NULL
) {
2610 if (GetUtilityStatus () != STATUS_SUCCESS
) {
2612 // when file updates failed, original file is still recoveried.
2614 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2617 // Write converted data into fpInOut file and close input file.
2622 if (FileBuffer
!= NULL
) {
2626 if (InputFileName
!= NULL
) {
2627 free (InputFileName
);
2630 if (fpOut
!= NULL
) {
2632 // Write converted data into fpOut file and close output file.
2635 if (GetUtilityStatus () != STATUS_SUCCESS
) {
2636 if (OutputFileBuffer
== NULL
) {
2637 remove (OutImageName
);
2639 fpOut
= fopen (OutImageName
, "wb");
2640 fwrite (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
2642 free (OutputFileBuffer
);
2647 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
2649 return GetUtilityStatus ();
2655 IN OUT UINT8
*FileBuffer
,
2656 BOOLEAN ZeroDebugFlag
2660 Routine Description:
2662 Zero debug information in PeImage.
2666 FileBuffer - Pointer to PeImage.
2667 ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp
2671 EFI_ABORTED - PeImage is invalid.
2672 EFI_SUCCESS - Zero debug data successfully.
2677 UINT32 DebugDirectoryEntryRva
;
2678 UINT32 DebugDirectoryEntryFileOffset
;
2679 UINT32 ExportDirectoryEntryRva
;
2680 UINT32 ExportDirectoryEntryFileOffset
;
2681 UINT32 ResourceDirectoryEntryRva
;
2682 UINT32 ResourceDirectoryEntryFileOffset
;
2683 EFI_IMAGE_DOS_HEADER
*DosHdr
;
2684 EFI_IMAGE_FILE_HEADER
*FileHdr
;
2685 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
2686 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
2687 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
2688 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
2689 UINT32
*NewTimeStamp
;
2694 DebugDirectoryEntryRva
= 0;
2695 ExportDirectoryEntryRva
= 0;
2696 ResourceDirectoryEntryRva
= 0;
2697 DebugDirectoryEntryFileOffset
= 0;
2698 ExportDirectoryEntryFileOffset
= 0;
2699 ResourceDirectoryEntryFileOffset
= 0;
2700 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2701 FileHdr
= (EFI_IMAGE_FILE_HEADER
*) (FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2704 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2705 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2706 // NO DOS header, must start with PE/COFF header
2707 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
2709 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2713 // Get Debug, Export and Resource EntryTable RVA address.
2714 // Resource Directory entry need to review.
2716 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
2717 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2718 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2719 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2720 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2721 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2723 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2724 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2725 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2727 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2728 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2729 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2730 if (ZeroDebugFlag
) {
2731 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
2732 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
2736 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2737 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2738 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2739 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2740 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2742 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2743 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2744 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2746 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2747 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2748 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2749 if (ZeroDebugFlag
) {
2750 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
2751 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
2757 // Get DirectoryEntryTable file offset.
2759 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2760 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2761 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2762 DebugDirectoryEntryFileOffset
=
2763 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2765 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2766 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2767 ExportDirectoryEntryFileOffset
=
2768 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2770 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2771 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2772 ResourceDirectoryEntryFileOffset
=
2773 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2778 //Zero Debug Data and TimeStamp
2780 FileHdr
->TimeDateStamp
= 0;
2782 if (ExportDirectoryEntryFileOffset
!= 0) {
2783 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
2787 if (ResourceDirectoryEntryFileOffset
!= 0) {
2788 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
2792 if (DebugDirectoryEntryFileOffset
!= 0) {
2793 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
);
2794 DebugEntry
->TimeDateStamp
= 0;
2795 if (ZeroDebugFlag
) {
2796 memset (FileBuffer
+ DebugEntry
->FileOffset
, 0, DebugEntry
->SizeOfData
);
2797 memset (DebugEntry
, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
2807 IN OUT UINT8
*FileBuffer
,
2812 Routine Description:
2814 Set new time stamp into PeImage FileHdr and Directory table:
2815 Debug, Export and Resource.
2819 FileBuffer - Pointer to PeImage.
2820 TimeStamp - Time stamp string.
2824 EFI_INVALID_PARAMETER - TimeStamp format is not recognized.
2825 EFI_SUCCESS - Set new time stamp in this image successfully.
2833 UINT32 DebugDirectoryEntryRva
;
2834 UINT32 DebugDirectoryEntryFileOffset
;
2835 UINT32 ExportDirectoryEntryRva
;
2836 UINT32 ExportDirectoryEntryFileOffset
;
2837 UINT32 ResourceDirectoryEntryRva
;
2838 UINT32 ResourceDirectoryEntryFileOffset
;
2839 EFI_IMAGE_DOS_HEADER
*DosHdr
;
2840 EFI_IMAGE_FILE_HEADER
*FileHdr
;
2841 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
2842 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
2843 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
2844 UINT32
*NewTimeStamp
;
2849 DebugDirectoryEntryRva
= 0;
2850 DebugDirectoryEntryFileOffset
= 0;
2851 ExportDirectoryEntryRva
= 0;
2852 ExportDirectoryEntryFileOffset
= 0;
2853 ResourceDirectoryEntryRva
= 0;
2854 ResourceDirectoryEntryFileOffset
= 0;
2856 // Get time and date that will be set.
2858 if (TimeStamp
== NULL
) {
2859 Error (NULL
, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");
2860 return EFI_INVALID_PARAMETER
;
2863 // compare the value with "NOW", if yes, current system time is set.
2865 if (stricmp (TimeStamp
, "NOW") == 0) {
2867 // get system current time and date
2872 // Check Time Format strictly yyyy-mm-dd 00:00:00
2874 for (Index
= 0; TimeStamp
[Index
] != '\0' && Index
< 20; Index
++) {
2875 if (Index
== 4 || Index
== 7) {
2876 if (TimeStamp
[Index
] == '-') {
2879 } else if (Index
== 13 || Index
== 16) {
2880 if (TimeStamp
[Index
] == ':') {
2883 } else if (Index
== 10 && TimeStamp
[Index
] == ' ') {
2885 } else if ((TimeStamp
[Index
] < '0') || (TimeStamp
[Index
] > '9')) {
2890 if (Index
< 19 || TimeStamp
[19] != '\0') {
2891 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
2892 return EFI_INVALID_PARAMETER
;
2896 // get the date and time from TimeStamp
2898 if (sscanf (TimeStamp
, "%d-%d-%d %d:%d:%d",
2906 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
2907 return EFI_INVALID_PARAMETER
;
2911 // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
2913 if (stime
.tm_mon
<= 0 || stime
.tm_mday
<=0) {
2914 Error (NULL
, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp
);
2915 return EFI_INVALID_PARAMETER
;
2920 // in struct, Year (current year minus 1900)
2921 // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
2924 // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
2926 if (stime
.tm_year
>= 1970 && stime
.tm_year
<= 2038) {
2928 // convert 1970 -> 70, 2000 -> 100, ...
2930 stime
.tm_year
-= 1900;
2932 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
2933 return EFI_INVALID_PARAMETER
;
2937 // convert the date and time to time_t format
2939 newtime
= mktime (&stime
);
2940 if (newtime
== (time_t) - 1) {
2941 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
2942 return EFI_INVALID_PARAMETER
;
2946 ptime
= localtime (&newtime
);
2947 DebugMsg (NULL
, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",
2948 ptime
->tm_year
+ 1900, ptime
->tm_mon
+ 1, ptime
->tm_mday
, ptime
->tm_hour
, ptime
->tm_min
, ptime
->tm_sec
);
2950 // Set new time and data into PeImage.
2952 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2953 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2954 // NO DOS header, must start with PE/COFF header
2955 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
2957 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2961 // Get Debug, Export and Resource EntryTable RVA address.
2962 // Resource Directory entry need to review.
2964 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
2965 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2966 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2967 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2968 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2969 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2971 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2972 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2973 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2975 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2976 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2977 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2980 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2981 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2982 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2983 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2984 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2986 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2987 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2988 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2990 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2991 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2992 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2997 // Get DirectoryEntryTable file offset.
2999 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
3000 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3001 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3002 DebugDirectoryEntryFileOffset
=
3003 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3005 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3006 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3007 ExportDirectoryEntryFileOffset
=
3008 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3010 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3011 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3012 ResourceDirectoryEntryFileOffset
=
3013 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3020 FileHdr
->TimeDateStamp
= (UINT32
) newtime
;
3022 if (ExportDirectoryEntryRva
!= 0) {
3023 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
3024 *NewTimeStamp
= (UINT32
) newtime
;
3027 if (ResourceDirectoryEntryRva
!= 0) {
3028 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
3029 *NewTimeStamp
= (UINT32
) newtime
;
3032 if (DebugDirectoryEntryRva
!= 0) {
3033 NewTimeStamp
= (UINT32
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
+ sizeof (UINT32
));
3034 *NewTimeStamp
= (UINT32
) newtime
;
3048 Routine Description:
3049 Read a 32-bit microcode data value from a text file and convert to raw binary form.
3052 InFptr - file pointer to input text file
3053 Data - pointer to where to return the data parsed
3056 STATUS_SUCCESS - no errors or warnings, Data contains valid information
3057 STATUS_ERROR - errors were encountered
3061 CHAR8 Line
[MAX_LINE_LEN
];
3063 unsigned ScannedData
= 0;
3065 Line
[MAX_LINE_LEN
- 1] = 0;
3067 if (fgets (Line
, MAX_LINE_LEN
, InFptr
) == NULL
) {
3068 return STATUS_ERROR
;
3071 // If it was a binary file, then it may have overwritten our null terminator
3073 if (Line
[MAX_LINE_LEN
- 1] != 0) {
3074 return STATUS_ERROR
;
3080 for (cptr
= Line
; *cptr
&& isspace(*cptr
); cptr
++) {
3083 // Skip Blank Lines and Comment Lines
3084 if ((strlen(cptr
) != 0) && (*cptr
!= ';')) {
3090 // dd 000000001h ; comment
3095 if ((tolower(cptr
[0]) == 'd') && (tolower(cptr
[1]) == 'd') && isspace (cptr
[2])) {
3097 // Skip blanks and look for a hex digit
3100 for (; *cptr
&& isspace(*cptr
); cptr
++) {
3102 if (isxdigit (*cptr
)) {
3103 if (sscanf (cptr
, "%X", &ScannedData
) != 1) {
3104 return STATUS_ERROR
;
3107 *Data
= (UINT32
) ScannedData
;
3108 return STATUS_SUCCESS
;
3111 return STATUS_ERROR
;