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"
33 #include <Common/UefiBaseTypes.h>
34 #include <IndustryStandard/PeImage.h>
37 // Acpi Table definition
39 #include <IndustryStandard/Acpi.h>
40 #include <IndustryStandard/Acpi1_0.h>
41 #include <IndustryStandard/Acpi2_0.h>
42 #include <IndustryStandard/Acpi3_0.h>
43 #include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
45 #include "CommonLib.h"
46 #include "EfiUtilityMsgs.h"
48 #include "elf_common.h"
54 // Version of this utility
56 #define UTILITY_NAME "GenFw"
57 #define UTILITY_MAJOR_VERSION 0
58 #define UTILITY_MINOR_VERSION 2
61 // Action for this tool.
63 #define FW_DUMMY_IMAGE 0
64 #define FW_EFI_IMAGE 1
66 #define FW_ACPI_IMAGE 3
67 #define FW_BIN_IMAGE 4
68 #define FW_ZERO_DEBUG_IMAGE 5
69 #define FW_SET_STAMP_IMAGE 6
70 #define FW_MCI_IMAGE 7
71 #define FW_MERGE_IMAGE 8
72 #define FW_RELOC_STRIPEED_IMAGE 9
74 #define DUMP_TE_HEADER 0x11
76 #define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
77 #define DEFAULT_MC_ALIGNMENT 16
83 #define STATUS_IGNORE 0xA
85 // Structure definition for a microcode header
95 UINT32 DataSize
; // if 0, then TotalSize = 2048, and TotalSize field is invalid
96 UINT32 TotalSize
; // number of bytes
98 } MICROCODE_IMAGE_HEADER
;
100 STATIC CHAR8
*mInImageName
;
105 IN OUT UINT8
*FileBuffer
,
112 IN OUT UINT8
*FileBuffer
,
132 Print out version information for this utility.
144 fprintf (stdout
, "%s Version %d.%d\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
);
171 fprintf (stdout
, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME
);
174 // Copyright declaration
176 fprintf (stdout
, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");
181 fprintf (stdout
, "Options:\n");
182 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
183 File will be created to store the ouput content.\n");
184 fprintf (stdout
, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\
185 Create Efi Image. EFI_FILETYPE is one of BASE, SEC,\n\
186 PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\
187 DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER, \n\
188 DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER, \n\
189 PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\
190 APPLICATION, SAL_RT_DRIVER to support all module types\n\
191 It can only be used together with --keepexceptiontable,\n\
192 --keepzeropending, -r, -o option.It is a action option.\n\
193 If it is combined with other action options, the later\n\
194 input action option will override the previous one.\n");
195 fprintf (stdout
, " -c, --acpi Create Acpi table.\n\
196 It can't be combined with other action options\n\
197 except for -o, -r option. It is a action option.\n\
198 If it is combined with other action options, the later\n\
199 input action option will override the previous one.\n");
200 fprintf (stdout
, " -t, --terse Create Te Image.\n\
201 It can only be used together with --keepexceptiontable,\n\
202 --keepzeropending, -r, -o option.It is a action option.\n\
203 If it is combined with other action options, the later\n\
204 input action option will override the previous one.\n");
205 fprintf (stdout
, " -u, --dump Dump TeImage Header.\n\
206 It can't be combined with other action options\n\
207 except for -o, -r option. It is a action option.\n\
208 If it is combined with other action options, the later\n\
209 input action option will override the previous one.\n");
210 fprintf (stdout
, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\
211 It also zeros the time stamp fields.\n\
212 This option can be used to compare the binary efi image.\n\
213 It can't be combined with other action options\n\
214 except for -o, -r option. It is a action option.\n\
215 If it is combined with other action options, the later\n\
216 input action option will override the previous one.\n");
217 fprintf (stdout
, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\
218 It can't be combined with other action options\n\
219 except for -o, -r 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
, " -l, --stripped Relocation info stripped from the input PE or TE image.\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
, " -s timedate, --stamp timedate\n\
228 timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\
229 is set to NOW, current system time is used. The support\n\
230 date scope is 1970-1-1 8:0:0 ~ 2038-1-19 3:14:07\n\
231 It can't be combined with other action options\n\
232 except for -o, -r option. It is a action option.\n\
233 If it is combined with other action options, the later\n\
234 input action option will override the previous one.\n");
235 fprintf (stdout
, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\
236 It can't be combined with other action options\n\
237 except for -o option. It is a action option.\n\
238 If it is combined with other action options, the later\n\
239 input action option will override the previous one.\n");
240 fprintf (stdout
, " -j, --join Combine multi microcode bin files to one file.\n\
241 It can be specified with -a, -p, -o option.\n\
242 No other options can be combined with it.\n\
243 If it is combined with other action options, the later\n\
244 input action option will override the previous one.\n");
245 fprintf (stdout
, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\
246 This option is only used together with -j option.\n");
247 fprintf (stdout
, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\
248 This option is only used together with -j option.\n");
249 fprintf (stdout
, " --keepexceptiontable Don't clear exception table.\n\
250 This option can be used together with -e or -t.\n\
251 It doesn't work for other options.\n");
252 fprintf (stdout
, " --keepzeropending Don't strip zero pending of .reloc.\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
, " -r, --replace Overwrite the input file with the output content.\n\
256 If more input files are specified,\n\
257 the last input file will be as the output file.\n");
258 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
259 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
260 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
261 fprintf (stdout
, " --version Show program's version number and exit\n");
262 fprintf (stdout
, " -h, --help Show this help message and exit\n");
279 AcpiTable Buffer for AcpiSection
280 Length AcpiSection Length
289 EFI_ACPI_DESCRIPTION_HEADER
*AcpiHeader
;
290 EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs
;
291 UINT32 ExpectedLength
;
293 AcpiHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTable
;
296 // Generic check for AcpiTable length.
298 if (AcpiHeader
->Length
> Length
) {
299 Error (NULL
, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL
);
304 // Currently, we only check must-have tables: FADT, FACS, DSDT,
305 // and some important tables: MADT, MCFG.
307 switch (AcpiHeader
->Signature
) {
310 // "FACP" Fixed ACPI Description Table
312 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
:
313 switch (AcpiHeader
->Revision
) {
314 case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
315 ExpectedLength
= sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
);
317 case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
318 ExpectedLength
= sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
);
320 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
321 ExpectedLength
= sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
);
324 Error (NULL
, 0, 3000, "Invalid", "FACP revision check failed.");
327 if (ExpectedLength
!= AcpiHeader
->Length
) {
328 Error (NULL
, 0, 3000, "Invalid", "FACP length check failed.");
334 // "FACS" Firmware ACPI Control Structure
336 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE
:
337 Facs
= (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)AcpiTable
;
338 if ((Facs
->Version
!= 0) &&
339 (Facs
->Version
!= EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
340 (Facs
->Version
!= EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
)){
341 Error (NULL
, 0, 3000, "Invalid", "FACS version check failed.");
344 if ((Facs
->Length
!= sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
345 (Facs
->Length
!= sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
346 (Facs
->Length
!= sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
))) {
347 Error (NULL
, 0, 3000, "Invalid", "FACS length check failed.");
353 // "DSDT" Differentiated System Description Table
355 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
356 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION
) {
357 Error (NULL
, 0, 3000, "Invalid", "DSDT revision check failed.");
360 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
)) {
361 Error (NULL
, 0, 3000, "Invalid", "DSDT length check failed.");
367 // "APIC" Multiple APIC Description Table
369 case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE
:
370 if ((AcpiHeader
->Revision
!= EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
371 (AcpiHeader
->Revision
!= EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
372 (AcpiHeader
->Revision
!= EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
)) {
373 Error (NULL
, 0, 3000, "Invalid", "APIC revision check failed.");
376 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT32
) + sizeof(UINT32
)) {
377 Error (NULL
, 0, 3000, "Invalid", "APIC length check failed.");
383 // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
385 case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE
:
386 if (AcpiHeader
->Revision
!= EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
387 Error (NULL
, 0, 3000, "Invalid", "MCFG revision check failed.");
390 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT64
)) {
391 Error (NULL
, 0, 3000, "Invalid", "MCFG length check failed.");
397 // Other table pass check
403 return STATUS_SUCCESS
;
412 return (FileBuffer
[EI_MAG0
] == ELFMAG0
413 && FileBuffer
[EI_MAG1
] == ELFMAG1
414 && FileBuffer
[EI_MAG2
] == ELFMAG2
415 && FileBuffer
[EI_MAG3
] == ELFMAG3
);
418 typedef Elf32_Shdr Elf_Shdr
;
419 typedef Elf32_Ehdr Elf_Ehdr
;
420 typedef Elf32_Rel Elf_Rel
;
421 typedef Elf32_Sym Elf_Sym
;
422 typedef Elf32_Phdr Elf_Phdr
;
423 typedef Elf32_Dyn Elf_Dyn
;
425 #define ELFCLASS ELFCLASS32
426 #define ELF_R_TYPE(r) ELF32_R_TYPE(r)
427 #define ELF_R_SYM(r) ELF32_R_SYM(r)
430 // Well known ELF structures.
437 // PE section alignment.
439 const UINT32 CoffAlignment
= 0x20;
440 const UINT32 CoffNbrSections
= 4;
443 // Current offset in coff file.
448 // Result Coff file in memory.
450 UINT8
*CoffFile
= NULL
;
452 // ELF sections to offset in Coff file.
454 UINT32
*CoffSectionsOffset
= NULL
;
457 // Offset in Coff file of headers and sections.
465 EFI_IMAGE_BASE_RELOCATION
*CoffBaseRel
;
466 UINT16
*CoffEntryRel
;
473 return (Offset
+ CoffAlignment
- 1) & ~(CoffAlignment
- 1);
481 if (Num
>= Ehdr
->e_shnum
)
483 return (Elf_Shdr
*)((UINT8
*)ShdrBase
+ Num
* Ehdr
->e_shentsize
);
492 // Note: Magic has already been tested.
494 if (Ehdr
->e_ident
[EI_CLASS
] != ELFCLASS
) {
495 Error (NULL
, 0, 3000, "Unsupported", "%s needs to be ported for 64-bit ELF.", mInImageName
);
498 if (Ehdr
->e_ident
[EI_DATA
] != ELFDATA2LSB
) {
499 Error (NULL
, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");
502 if ((Ehdr
->e_type
!= ET_EXEC
) && (Ehdr
->e_type
!= ET_DYN
)) {
503 Error (NULL
, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");
506 if (!((Ehdr
->e_machine
== EM_386
) || (Ehdr
->e_machine
== EM_ARM
))) {
507 Error (NULL
, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM");
510 if (Ehdr
->e_version
!= EV_CURRENT
) {
511 Error (NULL
, 0, 3000, "Unsupported", "ELF e_version (%d) not EV_CURRENT (%d)", Ehdr
->e_version
, EV_CURRENT
);
516 // Find the section header table
518 ShdrBase
= (Elf_Shdr
*)((UINT8
*)Ehdr
+ Ehdr
->e_shoff
);
519 gPhdrBase
= (Elf_Phdr
*)((UINT8
*)Ehdr
+ Ehdr
->e_phoff
);
521 CoffSectionsOffset
= (UINT32
*)malloc(Ehdr
->e_shnum
* sizeof (UINT32
));
523 memset(CoffSectionsOffset
, 0, Ehdr
->e_shnum
* sizeof(UINT32
));
532 return (Shdr
->sh_flags
& (SHF_WRITE
| SHF_ALLOC
)) == SHF_ALLOC
;
540 return (Shdr
->sh_flags
& (SHF_WRITE
| SHF_ALLOC
)) == (SHF_ALLOC
| SHF_WRITE
);
551 EFI_IMAGE_SECTION_HEADER
*Hdr
;
552 Hdr
= (EFI_IMAGE_SECTION_HEADER
*)(CoffFile
+ TableOffset
);
554 strcpy((char *)Hdr
->Name
, Name
);
555 Hdr
->Misc
.VirtualSize
= Size
;
556 Hdr
->VirtualAddress
= Offset
;
557 Hdr
->SizeOfRawData
= Size
;
558 Hdr
->PointerToRawData
= Offset
;
559 Hdr
->PointerToRelocations
= 0;
560 Hdr
->PointerToLinenumbers
= 0;
561 Hdr
->NumberOfRelocations
= 0;
562 Hdr
->NumberOfLinenumbers
= 0;
563 Hdr
->Characteristics
= Flags
;
565 TableOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
574 EFI_IMAGE_DOS_HEADER
*DosHdr
;
575 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
582 // Coff file start with a DOS header.
584 CoffOffset
= sizeof(EFI_IMAGE_DOS_HEADER
) + 0x40;
585 NtHdrOffset
= CoffOffset
;
586 switch (Ehdr
->e_machine
) {
589 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS32
);
593 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS64
);
596 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN
)Ehdr
->e_machine
);
597 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS32
);
601 TableOffset
= CoffOffset
;
602 CoffOffset
+= CoffNbrSections
* sizeof(EFI_IMAGE_SECTION_HEADER
);
605 // First text sections.
607 CoffOffset
= CoffAlign(CoffOffset
);
608 TextOffset
= CoffOffset
;
609 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
610 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
611 if (IsTextShdr(shdr
)) {
612 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
613 // the alignment field is valid
614 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
615 // if the section address is aligned we must align PE/COFF
616 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
617 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
618 // ARM RVCT tools have behavior outside of the ELF specification to try
619 // and make images smaller. If sh_addr is not aligned to sh_addralign
620 // then the section needs to preserve sh_addr MOD sh_addralign.
621 // Normally doing nothing here works great.
622 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
626 /* Relocate entry. */
627 if ((Ehdr
->e_entry
>= shdr
->sh_addr
) &&
628 (Ehdr
->e_entry
< shdr
->sh_addr
+ shdr
->sh_size
)) {
629 CoffEntry
= CoffOffset
+ Ehdr
->e_entry
- shdr
->sh_addr
;
631 CoffSectionsOffset
[i
] = CoffOffset
;
632 CoffOffset
+= shdr
->sh_size
;
636 if (Ehdr
->e_machine
!= EM_ARM
) {
637 CoffOffset
= CoffAlign(CoffOffset
);
641 // Then data sections.
643 DataOffset
= CoffOffset
;
644 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
645 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
646 if (IsDataShdr(shdr
)) {
647 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
648 // the alignment field is valid
649 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
650 // if the section address is aligned we must align PE/COFF
651 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
652 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
653 // ARM RVCT tools have behavior outside of the ELF specification to try
654 // and make images smaller. If sh_addr is not aligned to sh_addralign
655 // then the section needs to preserve sh_addr MOD sh_addralign.
656 // Normally doing nothing here works great.
657 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
661 CoffSectionsOffset
[i
] = CoffOffset
;
662 CoffOffset
+= shdr
->sh_size
;
665 CoffOffset
= CoffAlign(CoffOffset
);
667 RelocOffset
= CoffOffset
;
670 // Allocate base Coff file. Will be expanded later for relocations.
672 CoffFile
= (UINT8
*)malloc(CoffOffset
);
673 memset(CoffFile
, 0, CoffOffset
);
678 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)CoffFile
;
679 DosHdr
->e_magic
= EFI_IMAGE_DOS_SIGNATURE
;
680 DosHdr
->e_lfanew
= NtHdrOffset
;
682 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
684 NtHdr
->Pe32
.Signature
= EFI_IMAGE_NT_SIGNATURE
;
686 switch (Ehdr
->e_machine
) {
688 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IA32
;
689 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
692 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_X64
;
693 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
696 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IPF
;
697 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
700 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_ARMT
;
701 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
704 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN
)Ehdr
->e_machine
);
705 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IA32
;
706 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
709 NtHdr
->Pe32
.FileHeader
.NumberOfSections
= CoffNbrSections
;
710 NtHdr
->Pe32
.FileHeader
.TimeDateStamp
= time(NULL
);
711 NtHdr
->Pe32
.FileHeader
.PointerToSymbolTable
= 0;
712 NtHdr
->Pe32
.FileHeader
.NumberOfSymbols
= 0;
713 NtHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
= sizeof(NtHdr
->Pe32
.OptionalHeader
);
714 NtHdr
->Pe32
.FileHeader
.Characteristics
= EFI_IMAGE_FILE_EXECUTABLE_IMAGE
715 | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED
716 | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED
717 | EFI_IMAGE_FILE_32BIT_MACHINE
;
719 NtHdr
->Pe32
.OptionalHeader
.SizeOfCode
= DataOffset
- TextOffset
;
720 NtHdr
->Pe32
.OptionalHeader
.SizeOfInitializedData
= RelocOffset
- DataOffset
;
721 NtHdr
->Pe32
.OptionalHeader
.SizeOfUninitializedData
= 0;
722 NtHdr
->Pe32
.OptionalHeader
.AddressOfEntryPoint
= CoffEntry
;
724 NtHdr
->Pe32
.OptionalHeader
.BaseOfCode
= TextOffset
;
726 NtHdr
->Pe32
.OptionalHeader
.BaseOfData
= DataOffset
;
727 NtHdr
->Pe32
.OptionalHeader
.ImageBase
= 0;
728 NtHdr
->Pe32
.OptionalHeader
.SectionAlignment
= CoffAlignment
;
729 NtHdr
->Pe32
.OptionalHeader
.FileAlignment
= CoffAlignment
;
730 NtHdr
->Pe32
.OptionalHeader
.SizeOfImage
= 0;
732 NtHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
= TextOffset
;
733 NtHdr
->Pe32
.OptionalHeader
.NumberOfRvaAndSizes
= EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES
;
738 if ((DataOffset
- TextOffset
) > 0) {
739 CreateSectionHeader (".text", TextOffset
, DataOffset
- TextOffset
,
740 EFI_IMAGE_SCN_CNT_CODE
741 | EFI_IMAGE_SCN_MEM_EXECUTE
742 | EFI_IMAGE_SCN_MEM_READ
);
744 // Don't make a section of size 0.
745 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
748 if ((RelocOffset
- TextOffset
) > 0) {
749 CreateSectionHeader (".data", DataOffset
, RelocOffset
- DataOffset
,
750 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
751 | EFI_IMAGE_SCN_MEM_WRITE
752 | EFI_IMAGE_SCN_MEM_READ
);
754 // Don't make a section of size 0.
755 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
761 int (*Filter
)(Elf_Shdr
*)
769 // First: copy sections.
771 for (Idx
= 0; Idx
< Ehdr
->e_shnum
; Idx
++) {
772 Elf_Shdr
*Shdr
= GetShdrByIndex(Idx
);
773 if ((*Filter
)(Shdr
)) {
774 switch (Shdr
->sh_type
) {
777 memcpy(CoffFile
+ CoffSectionsOffset
[Idx
],
778 (UINT8
*)Ehdr
+ Shdr
->sh_offset
,
783 memset(CoffFile
+ CoffSectionsOffset
[Idx
], 0, Shdr
->sh_size
);
788 // Ignore for unkown section type.
790 VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName
, (UINTN
)Shdr
->sh_type
);
797 // Second: apply relocations.
799 for (Idx
= 0; Idx
< Ehdr
->e_shnum
; Idx
++) {
800 Elf_Shdr
*RelShdr
= GetShdrByIndex(Idx
);
801 if (RelShdr
->sh_type
!= SHT_REL
)
803 SecShdr
= GetShdrByIndex(RelShdr
->sh_info
);
804 SecOffset
= CoffSectionsOffset
[RelShdr
->sh_info
];
805 if (RelShdr
->sh_type
== SHT_REL
&& (*Filter
)(SecShdr
)) {
807 Elf_Shdr
*SymtabShdr
= GetShdrByIndex(RelShdr
->sh_link
);
808 UINT8
*Symtab
= (UINT8
*)Ehdr
+ SymtabShdr
->sh_offset
;
810 for (RelIdx
= 0; RelIdx
< RelShdr
->sh_size
; RelIdx
+= RelShdr
->sh_entsize
) {
811 Elf_Rel
*Rel
= (Elf_Rel
*)((UINT8
*)Ehdr
+ RelShdr
->sh_offset
+ RelIdx
);
812 Elf_Sym
*Sym
= (Elf_Sym
*)(Symtab
+ ELF_R_SYM(Rel
->r_info
) * SymtabShdr
->sh_entsize
);
816 if (Sym
->st_shndx
== SHN_UNDEF
817 || Sym
->st_shndx
== SHN_ABS
818 || Sym
->st_shndx
> Ehdr
->e_shnum
) {
819 Error (NULL
, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName
);
821 SymShdr
= GetShdrByIndex(Sym
->st_shndx
);
824 // Note: r_offset in a memory address.
825 // Convert it to a pointer in the coff file.
827 Targ
= CoffFile
+ SecOffset
+ (Rel
->r_offset
- SecShdr
->sh_addr
);
829 if (Ehdr
->e_machine
== EM_386
) {
830 switch (ELF_R_TYPE(Rel
->r_info
)) {
835 // Absolute relocation.
837 *(UINT32
*)Targ
= *(UINT32
*)Targ
- SymShdr
->sh_addr
838 + CoffSectionsOffset
[Sym
->st_shndx
];
842 // Relative relocation: Symbol - Ip + Addend
844 *(UINT32
*)Targ
= *(UINT32
*)Targ
845 + (CoffSectionsOffset
[Sym
->st_shndx
] - SymShdr
->sh_addr
)
846 - (SecOffset
- SecShdr
->sh_addr
);
849 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, ELF_R_TYPE(Rel
->r_info
));
851 } else if (Ehdr
->e_machine
== EM_ARM
) {
852 switch (ELF32_R_TYPE(Rel
->r_info
)) {
853 case R_ARM_RBASE
: // No relocation - no action required
854 case R_ARM_PC24
: // PC-relative relocations don't require modification
855 case R_ARM_XPC25
: // PC-relative relocations don't require modification
860 // Absolute relocation.
862 *(UINT32
*)Targ
= *(UINT32
*)Targ
- SymShdr
->sh_addr
+ CoffSectionsOffset
[Sym
->st_shndx
];
865 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, ELF32_R_TYPE(Rel
->r_info
));
880 CoffBaseRel
->SizeOfBlock
+= 2;
890 if (CoffBaseRel
== NULL
891 || CoffBaseRel
->VirtualAddress
!= (Offset
& ~0xfff)) {
892 if (CoffBaseRel
!= NULL
) {
894 // Add a null entry (is it required ?)
896 CoffAddFixupEntry (0);
898 // Pad for alignment.
900 if (CoffOffset
% 4 != 0)
901 CoffAddFixupEntry (0);
906 CoffOffset
+ sizeof(EFI_IMAGE_BASE_RELOCATION
) + 2*0x1000);
907 memset(CoffFile
+ CoffOffset
, 0,
908 sizeof(EFI_IMAGE_BASE_RELOCATION
) + 2*0x1000);
910 CoffBaseRel
= (EFI_IMAGE_BASE_RELOCATION
*)(CoffFile
+ CoffOffset
);
911 CoffBaseRel
->VirtualAddress
= Offset
& ~0xfff;
912 CoffBaseRel
->SizeOfBlock
= sizeof(EFI_IMAGE_BASE_RELOCATION
);
914 CoffEntryRel
= (UINT16
*)(CoffBaseRel
+ 1);
915 CoffOffset
+= sizeof(EFI_IMAGE_BASE_RELOCATION
);
921 CoffAddFixupEntry((Type
<< 12) | (Offset
& 0xfff));
930 if (num
>= Ehdr
->e_phnum
) {
934 return (Elf32_Phdr
*)((UINT8
*)gPhdrBase
+ num
* Ehdr
->e_phentsize
);
944 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
945 EFI_IMAGE_DATA_DIRECTORY
*Dir
;
946 BOOLEAN FoundRelocations
;
949 UINTN RelElementSize
;
954 Elf32_Phdr
*DynamicSegment
;
955 Elf32_Phdr
*TargetSegment
;
957 for (Index
= 0, FoundRelocations
= FALSE
; Index
< Ehdr
->e_shnum
; Index
++) {
958 Elf_Shdr
*RelShdr
= GetShdrByIndex(Index
);
959 if (RelShdr
->sh_type
== SHT_REL
) {
960 Elf_Shdr
*SecShdr
= GetShdrByIndex(RelShdr
->sh_info
);
961 if (IsTextShdr(SecShdr
) || IsDataShdr(SecShdr
)) {
963 FoundRelocations
= TRUE
;
964 for (RelIdx
= 0; RelIdx
< RelShdr
->sh_size
; RelIdx
+= RelShdr
->sh_entsize
) {
965 Elf_Rel
*Rel
= (Elf_Rel
*)
966 ((UINT8
*)Ehdr
+ RelShdr
->sh_offset
+ RelIdx
);
968 if (Ehdr
->e_machine
== EM_386
) {
969 switch (ELF_R_TYPE(Rel
->r_info
)) {
974 CoffAddFixup(CoffSectionsOffset
[RelShdr
->sh_info
]
975 + (Rel
->r_offset
- SecShdr
->sh_addr
),
976 EFI_IMAGE_REL_BASED_HIGHLOW
);
979 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, ELF_R_TYPE(Rel
->r_info
));
981 } else if (Ehdr
->e_machine
== EM_ARM
) {
982 switch (ELF32_R_TYPE(Rel
->r_info
)) {
990 CoffSectionsOffset
[RelShdr
->sh_info
]
991 + (Rel
->r_offset
- SecShdr
->sh_addr
),
992 EFI_IMAGE_REL_BASED_HIGHLOW
996 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, ELF32_R_TYPE(Rel
->r_info
));
999 Error (NULL
, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %d (processor type).", Ehdr
->e_machine
);
1006 if (!FoundRelocations
&& (Ehdr
->e_machine
== EM_ARM
)) {
1007 /* Try again, but look for PT_DYNAMIC instead of SHT_REL */
1009 for (Index
= 0; Index
< Ehdr
->e_phnum
; Index
++) {
1014 DynamicSegment
= GetPhdrByIndex (Index
);
1016 if (DynamicSegment
->p_type
== PT_DYNAMIC
) {
1017 Dyn
= (Elf32_Dyn
*) ((UINT8
*)Ehdr
+ DynamicSegment
->p_offset
);
1019 while (Dyn
->d_tag
!= DT_NULL
) {
1020 switch (Dyn
->d_tag
) {
1022 RelOffset
= Dyn
->d_un
.d_val
;
1026 RelSize
= Dyn
->d_un
.d_val
;
1030 RelElementSize
= Dyn
->d_un
.d_val
;
1035 if (( RelOffset
== 0 ) || ( RelSize
== 0 ) || ( RelElementSize
== 0 )) {
1036 Error (NULL
, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName
);
1039 for (K
= 0; K
< RelSize
; K
+= RelElementSize
) {
1041 Rel
= (Elf32_Rel
*) ((UINT8
*) Ehdr
+ DynamicSegment
->p_offset
+ RelOffset
+ K
);
1043 switch (ELF32_R_TYPE (Rel
->r_info
)) {
1047 TargetSegment
= GetPhdrByIndex (ELF32_R_SYM (Rel
->r_info
) - 1);
1049 // Note: r_offset in a memory address. Convert it to a pointer in the coff file.
1050 Targ
= CoffFile
+ CoffSectionsOffset
[ ELF32_R_SYM( Rel
->r_info
) ] + Rel
->r_offset
- TargetSegment
->p_vaddr
;
1052 *(UINT32
*)Targ
= *(UINT32
*)Targ
+ CoffSectionsOffset
[ELF32_R_SYM( Rel
->r_info
)];
1054 CoffAddFixup (CoffSectionsOffset
[ELF32_R_SYM (Rel
->r_info
)] + (Rel
->r_offset
- TargetSegment
->p_vaddr
), EFI_IMAGE_REL_BASED_HIGHLOW
);
1057 Error (NULL
, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type.", mInImageName
);
1066 // Pad by adding empty entries.
1068 while (CoffOffset
& (CoffAlignment
- 1)) {
1069 CoffAddFixupEntry(0);
1073 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1074 Dir
= &NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1075 Dir
->Size
= CoffOffset
- RelocOffset
;
1076 if (Dir
->Size
== 0) {
1077 // If no relocations, null out the directory entry and don't add the .reloc section
1078 Dir
->VirtualAddress
= 0;
1079 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
1081 Dir
->VirtualAddress
= RelocOffset
;
1082 CreateSectionHeader (".reloc", RelocOffset
, CoffOffset
- RelocOffset
,
1083 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
1084 | EFI_IMAGE_SCN_MEM_DISCARDABLE
1085 | EFI_IMAGE_SCN_MEM_READ
);
1097 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1098 EFI_IMAGE_DATA_DIRECTORY
*DataDir
;
1099 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*Dir
;
1100 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
*Nb10
;
1102 Len
= strlen(mInImageName
) + 1;
1103 DebugOffset
= CoffOffset
;
1105 CoffOffset
+= sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
)
1106 + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
)
1108 CoffOffset
= CoffAlign(CoffOffset
);
1110 CoffFile
= realloc(CoffFile
, CoffOffset
);
1111 memset(CoffFile
+ DebugOffset
, 0, CoffOffset
- DebugOffset
);
1113 Dir
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)(CoffFile
+ DebugOffset
);
1114 Dir
->Type
= EFI_IMAGE_DEBUG_TYPE_CODEVIEW
;
1115 Dir
->SizeOfData
= sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
) + Len
;
1116 Dir
->RVA
= DebugOffset
+ sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
1117 Dir
->FileOffset
= DebugOffset
+ sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
1119 Nb10
= (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
*)(Dir
+ 1);
1120 Nb10
->Signature
= CODEVIEW_SIGNATURE_NB10
;
1121 strcpy ((char *)(Nb10
+ 1), mInImageName
);
1124 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1125 DataDir
= &NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
];
1126 DataDir
->VirtualAddress
= DebugOffset
;
1127 DataDir
->Size
= CoffOffset
- DebugOffset
;
1128 if (DataDir
->Size
== 0) {
1129 // If no debug, null out the directory entry and don't add the .debug section
1130 DataDir
->VirtualAddress
= 0;
1131 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
1133 DataDir
->VirtualAddress
= DebugOffset
;
1134 CreateSectionHeader (".debug", DebugOffset
, CoffOffset
- DebugOffset
,
1135 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
1136 | EFI_IMAGE_SCN_MEM_DISCARDABLE
1137 | EFI_IMAGE_SCN_MEM_READ
);
1148 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1151 // Check header, read section table.
1153 Ehdr
= (Elf32_Ehdr
*)*FileBuffer
;
1154 if (!CheckElfHeader())
1157 VerboseMsg ("Check Efl Image Header");
1159 // Compute sections new address.
1164 VerboseMsg ("Compute sections new address.");
1167 // Write and relocate sections.
1169 WriteSections(IsTextShdr
);
1170 WriteSections(IsDataShdr
);
1171 VerboseMsg ("Write and relocate sections.");
1174 // Translate and write relocations.
1177 VerboseMsg ("Translate and write relocations.");
1180 // Write debug info.
1183 VerboseMsg ("Write debug info.");
1185 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1186 NtHdr
->Pe32
.OptionalHeader
.SizeOfImage
= CoffOffset
;
1192 *FileBuffer
= CoffFile
;
1193 *FileLength
= CoffOffset
;
1196 // Free memory space
1198 if (CoffSectionsOffset
!= NULL
) {
1199 free (CoffSectionsOffset
);
1205 IN CHAR8
*ImageName
,
1206 IN OUT UINT8
*FileBuffer
,
1207 IN EFI_IMAGE_SECTION_HEADER
*SectionHeader
,
1208 IN UINT32 SectionTotalNumber
1212 CHAR8 MapFileName
[_MAX_PATH
];
1213 CHAR8 Line
[MAX_LINE_LEN
];
1214 CHAR8 KeyWord
[MAX_LINE_LEN
];
1215 CHAR8 SectionName
[MAX_LINE_LEN
];
1216 UINT32 FunctionType
= 0;
1217 UINT32 SectionOffset
;
1218 UINT32 SectionLength
;
1219 UINT32 SectionNumber
;
1223 for (Index
= 0; Index
< SectionTotalNumber
; Index
++) {
1224 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".zdata") == 0) {
1226 // try to zero the customized .zdata section, which is mapped to .xdata
1228 memset (FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, 0, SectionHeader
[Index
].SizeOfRawData
);
1229 DebugMsg (NULL
, 0, 9, NULL
, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", SectionHeader
[Index
].PointerToRawData
, SectionHeader
[Index
].SizeOfRawData
);
1234 // Try to get PDB file name
1236 PdbPointer
= (CHAR8
*) PeCoffLoaderGetPdbPointer (FileBuffer
);
1237 if (PdbPointer
!= NULL
) {
1238 strcpy (MapFileName
, PdbPointer
);
1240 strcpy (MapFileName
, ImageName
);
1244 // Construct map file name
1246 Index
= strlen (MapFileName
) - 1;
1247 while (Index
>= 0 && MapFileName
[Index
] != '.') {
1252 // don't know how to costruct map file
1258 // fill map file postfix
1260 MapFileName
[Index
+ 1] = 'm';
1261 MapFileName
[Index
+ 2] = 'a';
1262 MapFileName
[Index
+ 3] = 'p';
1263 MapFileName
[Index
+ 4] = '\0';
1266 // try opening Map File
1268 fpMapFile
= fopen (MapFileName
, "r");
1269 if (fpMapFile
== NULL
) {
1271 // Can't open Map file. Maybe it doesn't exist.
1277 // Output Functions information into Fv Map file
1279 while (fgets (Line
, MAX_LINE_LEN
, fpMapFile
) != NULL
) {
1283 if (Line
[0] == 0x0a) {
1284 if (FunctionType
!= 0) {
1286 // read all section table data
1298 if (FunctionType
== 0) {
1299 sscanf (Line
, "%s", KeyWord
);
1300 if (stricmp (KeyWord
, "Start") == 0) {
1309 // Printf Function Information
1311 if (FunctionType
== 1) {
1312 sscanf (Line
, "%x:%x %xH %s", &SectionNumber
, &SectionOffset
, &SectionLength
, SectionName
);
1313 if (stricmp (SectionName
, ".xdata") == 0) {
1320 if (FunctionType
!= 2) {
1322 // no .xdata section is found
1329 // Zero .xdata Section data
1331 memset (FileBuffer
+ SectionHeader
[SectionNumber
-1].PointerToRawData
+ SectionOffset
, 0, SectionLength
);
1332 DebugMsg (NULL
, 0, 9, NULL
, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", SectionHeader
[SectionNumber
-1].PointerToRawData
+ SectionOffset
, SectionLength
);
1344 Routine Description:
1350 argc - Number of command line parameters.
1351 argv - Array of pointers to command line parameter strings.
1354 STATUS_SUCCESS - Utility exits successfully.
1355 STATUS_ERROR - Some error occurred during execution.
1360 UINT32 InputFileNum
;
1361 CHAR8
**InputFileName
;
1365 UINT32 OutImageType
;
1370 UINT32
*DataPointer
;
1371 UINT32
*OldDataPointer
;
1377 UINT32 MciAlignment
;
1379 UINT32 AllignedRelocSize
;
1382 UINT8
*OutputFileBuffer
;
1383 UINT32 OutputFileLength
;
1384 RUNTIME_FUNCTION
*RuntimeFunction
;
1385 UNWIND_INFO
*UnwindInfo
;
1387 BOOLEAN ReplaceFlag
;
1388 BOOLEAN KeepExceptionTableFlag
;
1389 BOOLEAN KeepZeroPendingFlag
;
1391 EFI_TE_IMAGE_HEADER TEImageHeader
;
1392 EFI_TE_IMAGE_HEADER
*TeHdr
;
1393 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1394 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1395 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1396 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32
;
1397 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64
;
1398 EFI_IMAGE_DOS_HEADER BackupDosHdr
;
1399 MICROCODE_IMAGE_HEADER
*MciHeader
;
1401 SetUtilityName (UTILITY_NAME
);
1404 // Assign to fix compile warning
1407 InputFileName
= NULL
;
1408 mInImageName
= NULL
;
1409 OutImageName
= NULL
;
1411 OutImageType
= FW_DUMMY_IMAGE
;
1413 Status
= STATUS_SUCCESS
;
1419 MciAlignment
= DEFAULT_MC_ALIGNMENT
;
1420 MciPadValue
= DEFAULT_MC_PAD_BYTE_VALUE
;
1424 ReplaceFlag
= FALSE
;
1426 OutputFileBuffer
= NULL
;
1427 OutputFileLength
= 0;
1430 KeepExceptionTableFlag
= FALSE
;
1431 KeepZeroPendingFlag
= FALSE
;
1434 Error (NULL
, 0, 1001, "Missing options", "No input options.");
1436 return STATUS_ERROR
;
1442 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
1445 return STATUS_SUCCESS
;
1448 if (stricmp (argv
[0], "--version") == 0) {
1450 return STATUS_SUCCESS
;
1454 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
1455 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1456 Error (NULL
, 0, 1003, "Invalid option value", "Output file name is missing for -o option");
1459 OutImageName
= argv
[1];
1465 if ((stricmp (argv
[0], "-e") == 0) || (stricmp (argv
[0], "--efiImage") == 0)) {
1466 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1467 Error (NULL
, 0, 1003, "Invalid option value", "Module Type is missing for -o option");
1470 ModuleType
= argv
[1];
1471 if (OutImageType
!= FW_TE_IMAGE
) {
1472 OutImageType
= FW_EFI_IMAGE
;
1479 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--stripped") == 0)) {
1480 OutImageType
= FW_RELOC_STRIPEED_IMAGE
;
1486 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--acpi") == 0)) {
1487 OutImageType
= FW_ACPI_IMAGE
;
1493 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--terse") == 0)) {
1494 OutImageType
= FW_TE_IMAGE
;
1500 if ((stricmp (argv
[0], "-u") == 0) || (stricmp (argv
[0], "--dump") == 0)) {
1501 OutImageType
= DUMP_TE_HEADER
;
1507 if ((stricmp (argv
[0], "-b") == 0) || (stricmp (argv
[0], "--exe2bin") == 0)) {
1508 OutImageType
= FW_BIN_IMAGE
;
1514 if ((stricmp (argv
[0], "-z") == 0) || (stricmp (argv
[0], "--zero") == 0)) {
1515 OutImageType
= FW_ZERO_DEBUG_IMAGE
;
1521 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--stamp") == 0)) {
1522 OutImageType
= FW_SET_STAMP_IMAGE
;
1523 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1524 Error (NULL
, 0, 1003, "Invalid option value", "time stamp is missing for -s option");
1527 TimeStamp
= argv
[1];
1533 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--replace") == 0)) {
1540 if (stricmp (argv
[0], "--keepexceptiontable") == 0) {
1541 KeepExceptionTableFlag
= TRUE
;
1547 if (stricmp (argv
[0], "--keepzeropending") == 0) {
1548 KeepZeroPendingFlag
= TRUE
;
1554 if ((stricmp (argv
[0], "-m") == 0) || (stricmp (argv
[0], "--mcifile") == 0)) {
1555 OutImageType
= FW_MCI_IMAGE
;
1561 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--join") == 0)) {
1562 OutImageType
= FW_MERGE_IMAGE
;
1568 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
1569 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1570 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1573 MciAlignment
= (UINT32
) Temp64
;
1579 if ((stricmp (argv
[0], "-p") == 0) || (stricmp (argv
[0], "--pad") == 0)) {
1580 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1581 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1584 MciPadValue
= (UINT8
) Temp64
;
1590 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
1591 SetPrintLevel (VERBOSE_LOG_LEVEL
);
1592 VerboseMsg ("Verbose output Mode Set!");
1598 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1599 SetPrintLevel (KEY_LOG_LEVEL
);
1600 KeyMsg ("Quiet output Mode Set!");
1606 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
1607 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
1608 if (EFI_ERROR (Status
)) {
1609 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1613 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", LogLevel
);
1616 SetPrintLevel (LogLevel
);
1617 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
1623 if (argv
[0][0] == '-') {
1624 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
1628 // Get Input file name
1630 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
1631 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
1632 if (InputFileName
== NULL
) {
1633 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1634 return EFI_OUT_OF_RESOURCES
;
1637 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1638 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1640 // InputFileName buffer too small, need to realloc
1642 InputFileName
= (CHAR8
**) realloc (
1644 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1647 if (InputFileName
== NULL
) {
1648 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1649 return EFI_OUT_OF_RESOURCES
;
1652 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1655 InputFileName
[InputFileNum
++] = argv
[0];
1660 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1662 if (OutImageType
== FW_DUMMY_IMAGE
) {
1663 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!");
1665 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.");
1671 // check input files
1673 if (InputFileNum
== 0) {
1674 Error (NULL
, 0, 1001, "Missing option", "Input files");
1679 // Combine MciBinary files to one file
1681 if ((OutImageType
== FW_MERGE_IMAGE
) && ReplaceFlag
) {
1682 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");
1689 mInImageName
= InputFileName
[InputFileNum
- 1];
1690 VerboseMsg ("the input file name is %s", mInImageName
);
1693 // Action will be taken for the input file.
1695 switch (OutImageType
) {
1697 VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType
);
1700 VerboseMsg ("Create Te Image based on the input PE image.");
1703 VerboseMsg ("Get acpi table data from the input PE image.");
1705 case FW_RELOC_STRIPEED_IMAGE
:
1706 VerboseMsg ("Remove relocation section from Pe or Te image.");
1709 VerboseMsg ("Convert the input EXE to the output BIN file.");
1711 case FW_ZERO_DEBUG_IMAGE
:
1712 VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");
1714 case FW_SET_STAMP_IMAGE
:
1715 VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp
);
1717 case DUMP_TE_HEADER
:
1718 VerboseMsg ("Dump the TE header information of the input TE image.");
1721 VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");
1723 case FW_MERGE_IMAGE
:
1724 VerboseMsg ("Combine the input multi microcode bin files to one bin file.");
1731 VerboseMsg ("Overwrite the input file with the output content.");
1735 // Open output file and Write image into the output file.
1737 if (OutImageName
!= NULL
) {
1738 fpOut
= fopen (OutImageName
, "rb");
1739 if (fpOut
!= NULL
) {
1740 OutputFileLength
= _filelength (fileno (fpOut
));
1741 OutputFileBuffer
= malloc (OutputFileLength
);
1742 if (OutputFileBuffer
== NULL
) {
1743 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1748 fread (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
1751 fpOut
= fopen (OutImageName
, "wb");
1753 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1756 VerboseMsg ("Output file name is %s", OutImageName
);
1757 } else if (!ReplaceFlag
) {
1758 if (OutImageType
== DUMP_TE_HEADER
) {
1761 Error (NULL
, 0, 1001, "Missing option", "output file");
1767 // Combine MciBinary files to one file
1769 if (OutImageType
== FW_MERGE_IMAGE
) {
1770 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1771 fpIn
= fopen (InputFileName
[Index
], "rb");
1773 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1777 FileLength
= _filelength (fileno (fpIn
));
1778 FileBuffer
= malloc (FileLength
);
1779 if (FileBuffer
== NULL
) {
1780 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1785 fread (FileBuffer
, 1, FileLength
, fpIn
);
1788 // write input file to out file
1790 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
1792 // write pad value to out file.
1794 while (FileLength
++ % MciAlignment
!= 0) {
1795 fwrite (&MciPadValue
, 1, 1, fpOut
);
1798 // free allocated memory space
1804 // Done successfully
1810 // Convert MicroCode.txt file to MicroCode.bin file
1812 if (OutImageType
== FW_MCI_IMAGE
) {
1813 fpIn
= fopen (mInImageName
, "r");
1815 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1820 // The first pass is to determine
1821 // how much data is in the file so we can allocate a working buffer.
1825 Status
= MicrocodeReadData (fpIn
, &Data
);
1826 if (Status
== STATUS_SUCCESS
) {
1827 FileLength
+= sizeof (Data
);
1829 if (Status
== STATUS_IGNORE
) {
1830 Status
= STATUS_SUCCESS
;
1832 } while (Status
== STATUS_SUCCESS
);
1834 // Error if no data.
1836 if (FileLength
== 0) {
1837 Error (NULL
, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName
);
1840 if (FileLength
< sizeof (MICROCODE_IMAGE_HEADER
)) {
1841 Error (NULL
, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName
);
1846 // Allocate a buffer for the data
1848 FileBuffer
= malloc (FileLength
);
1849 if (FileBuffer
== NULL
) {
1850 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1854 // Re-read the file, storing the data into our buffer
1856 fseek (fpIn
, 0, SEEK_SET
);
1857 DataPointer
= (UINT32
*) FileBuffer
;
1858 OldDataPointer
= DataPointer
;
1860 OldDataPointer
= DataPointer
;
1861 Status
= MicrocodeReadData (fpIn
, DataPointer
++);
1862 if (Status
== STATUS_IGNORE
) {
1863 DataPointer
= OldDataPointer
;
1864 Status
= STATUS_SUCCESS
;
1866 } while (Status
== STATUS_SUCCESS
);
1868 // close input file after read data
1873 // Can't do much checking on the header because, per the spec, the
1874 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
1875 // and the TotalSize field is invalid (actually missing). Thus we can't
1876 // even verify the Reserved fields are 0.
1878 MciHeader
= (MICROCODE_IMAGE_HEADER
*) FileBuffer
;
1879 if (MciHeader
->DataSize
== 0) {
1882 Index
= MciHeader
->TotalSize
;
1885 if (Index
!= FileLength
) {
1886 Error (NULL
, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName
, FileLength
, Index
);
1891 // Checksum the contents
1893 DataPointer
= (UINT32
*) FileBuffer
;
1896 while (Index
< FileLength
) {
1897 CheckSum
+= *DataPointer
;
1899 Index
+= sizeof (*DataPointer
);
1901 if (CheckSum
!= 0) {
1902 Error (NULL
, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", CheckSum
, mInImageName
);
1906 // Open the output file and write the buffer contents
1908 if (fpOut
!= NULL
) {
1909 if (fwrite (FileBuffer
, FileLength
, 1, fpOut
) != 1) {
1910 Error (NULL
, 0, 0002, "Error writing file", OutImageName
);
1916 fpInOut
= fopen (mInImageName
, "wb");
1917 if (fpInOut
!= NULL
) {
1918 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1921 if (fwrite (FileBuffer
, FileLength
, 1, fpInOut
) != 1) {
1922 Error (NULL
, 0, 0002, "Error writing file", mInImageName
);
1926 VerboseMsg ("the size of output file is %d bytes", FileLength
);
1928 // Convert Mci.TXT to Mci.bin file successfully
1934 // Open input file and read file data into file buffer.
1936 fpIn
= fopen (mInImageName
, "rb");
1938 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1942 FileLength
= _filelength (fileno (fpIn
));
1943 FileBuffer
= malloc (FileLength
);
1944 if (FileBuffer
== NULL
) {
1945 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1950 fread (FileBuffer
, 1, FileLength
, fpIn
);
1953 DebugMsg (NULL
, 0, 9, "input file info", "the input file size is %d bytes", FileLength
);
1959 fpInOut
= fopen (mInImageName
, "wb");
1961 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1966 // Dump TeImage Header into output file.
1968 if (OutImageType
== DUMP_TE_HEADER
) {
1969 memcpy (&TEImageHeader
, FileBuffer
, sizeof (TEImageHeader
));
1970 if (TEImageHeader
.Signature
!= EFI_TE_IMAGE_HEADER_SIGNATURE
) {
1971 Error (NULL
, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName
);
1974 if (fpInOut
!= NULL
) {
1975 fprintf (fpInOut
, "Dump of file %s\n\n", mInImageName
);
1976 fprintf (fpInOut
, "TE IMAGE HEADER VALUES\n");
1977 fprintf (fpInOut
, "%17X machine\n", TEImageHeader
.Machine
);
1978 fprintf (fpInOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
1979 fprintf (fpInOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
1980 fprintf (fpInOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
1981 fprintf (fpInOut
, "%17X entry point\n", TEImageHeader
.AddressOfEntryPoint
);
1982 fprintf (fpInOut
, "%17X base of code\n", TEImageHeader
.BaseOfCode
);
1983 fprintf (fpInOut
, "%17lX image base\n", (long unsigned int)TEImageHeader
.ImageBase
);
1984 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader
.DataDirectory
[0].VirtualAddress
, TEImageHeader
.DataDirectory
[0].Size
);
1985 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader
.DataDirectory
[1].VirtualAddress
, TEImageHeader
.DataDirectory
[1].Size
);
1988 if (fpOut
!= NULL
) {
1989 fprintf (fpOut
, "Dump of file %s\n\n", mInImageName
);
1990 fprintf (fpOut
, "TE IMAGE HEADER VALUES\n");
1991 fprintf (fpOut
, "%17X machine\n", TEImageHeader
.Machine
);
1992 fprintf (fpOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
1993 fprintf (fpOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
1994 fprintf (fpOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
1995 fprintf (fpOut
, "%17X entry point\n", TEImageHeader
.AddressOfEntryPoint
);
1996 fprintf (fpOut
, "%17X base of code\n", TEImageHeader
.BaseOfCode
);
1997 fprintf (fpOut
, "%17lX image base\n", (long unsigned int)TEImageHeader
.ImageBase
);
1998 fprintf (fpOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader
.DataDirectory
[0].VirtualAddress
, TEImageHeader
.DataDirectory
[0].Size
);
1999 fprintf (fpOut
, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader
.DataDirectory
[1].VirtualAddress
, TEImageHeader
.DataDirectory
[1].Size
);
2005 // Following code to convert dll to efi image or te image.
2006 // Get new image type
2008 if ((OutImageType
== FW_EFI_IMAGE
) || (OutImageType
== FW_TE_IMAGE
)) {
2009 if (ModuleType
== NULL
) {
2010 if (OutImageType
== FW_EFI_IMAGE
) {
2011 Error (NULL
, 0, 1001, "Missing option", "EFI_FILETYPE");
2013 } else if (OutImageType
== FW_TE_IMAGE
) {
2015 // Default TE Image Type is Boot service driver
2017 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2018 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2021 if (stricmp (ModuleType
, "BASE") == 0 ||
2022 stricmp (ModuleType
, "SEC") == 0 ||
2023 stricmp (ModuleType
, "SECURITY_CORE") == 0 ||
2024 stricmp (ModuleType
, "PEI_CORE") == 0 ||
2025 stricmp (ModuleType
, "PEIM") == 0 ||
2026 stricmp (ModuleType
, "COMBINED_PEIM_DRIVER") == 0 ||
2027 stricmp (ModuleType
, "PIC_PEIM") == 0 ||
2028 stricmp (ModuleType
, "RELOCATABLE_PEIM") == 0 ||
2029 stricmp (ModuleType
, "DXE_CORE") == 0 ||
2030 stricmp (ModuleType
, "BS_DRIVER") == 0 ||
2031 stricmp (ModuleType
, "DXE_DRIVER") == 0 ||
2032 stricmp (ModuleType
, "DXE_SMM_DRIVER") == 0 ||
2033 stricmp (ModuleType
, "UEFI_DRIVER") == 0 ||
2034 stricmp (ModuleType
, "SMM_DRIVER") == 0 ||
2035 stricmp (ModuleType
, "SMM_CORE") == 0) {
2036 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2037 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2039 } else if (stricmp (ModuleType
, "UEFI_APPLICATION") == 0 ||
2040 stricmp (ModuleType
, "APPLICATION") == 0) {
2041 Type
= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
;
2042 VerboseMsg ("Efi Image subsystem type is efi application.");
2044 } else if (stricmp (ModuleType
, "DXE_RUNTIME_DRIVER") == 0 ||
2045 stricmp (ModuleType
, "RT_DRIVER") == 0) {
2046 Type
= EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
;
2047 VerboseMsg ("Efi Image subsystem type is efi runtime driver.");
2049 } else if (stricmp (ModuleType
, "DXE_SAL_DRIVER") == 0 ||
2050 stricmp (ModuleType
, "SAL_RT_DRIVER") == 0) {
2051 Type
= EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
;
2052 VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");
2055 Error (NULL
, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType
);
2062 // Convert EFL image to PeImage
2064 if (IsElfHeader(FileBuffer
)) {
2065 VerboseMsg ("Convert the input ELF Image to Pe Image");
2066 ConvertElf(&FileBuffer
, &FileLength
);
2070 // Remove reloc section from PE or TE image
2072 if (OutImageType
== FW_RELOC_STRIPEED_IMAGE
) {
2076 TeHdr
= (EFI_TE_IMAGE_HEADER
*) FileBuffer
;
2077 if (TeHdr
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2078 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (TeHdr
+ 1);
2079 for (Index
= 0; Index
< TeHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2080 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2082 // Check the reloc section is in the end of image.
2084 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) ==
2085 (FileLength
+ TeHdr
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
))) {
2087 // Remove .reloc section and update TeImage Header
2089 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2090 SectionHeader
->SizeOfRawData
= 0;
2091 SectionHeader
->Misc
.VirtualSize
= 0;
2092 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2093 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2102 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2103 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2104 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2105 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2106 Error (NULL
, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName
);
2111 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2112 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2113 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2117 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2118 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2119 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2121 // Check the reloc section is in the end of image.
2123 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) == FileLength
) {
2125 // Remove .reloc section and update PeImage Header
2127 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2129 PeHdr
->Pe32
.FileHeader
.Characteristics
|= EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2130 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2131 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2132 Optional32
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2133 Optional32
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2134 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2135 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2136 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2139 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2140 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2141 Optional64
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2142 Optional64
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2143 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2144 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2145 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2148 SectionHeader
->Misc
.VirtualSize
= 0;
2149 SectionHeader
->SizeOfRawData
= 0;
2161 // Read the dos & pe hdrs of the image
2163 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2164 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2165 // NO DOS header, check for PE/COFF header
2166 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2167 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2168 Error (NULL
, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName
);
2174 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2175 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2176 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2181 if (PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_ARM
) {
2182 // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
2183 // so patch back to the offical UEFI value.
2184 PeHdr
->Pe32
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_ARMT
;
2188 // Extract bin data from Pe image.
2190 if (OutImageType
== FW_BIN_IMAGE
) {
2191 if (FileLength
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
2192 Error (NULL
, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName
);
2196 // Output bin data from exe file
2198 if (fpOut
!= NULL
) {
2199 fwrite (FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, 1, FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, fpOut
);
2201 if (fpInOut
!= NULL
) {
2202 fwrite (FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, 1, FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, fpInOut
);
2204 VerboseMsg ("the size of output file is %d bytes", FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
);
2209 // Zero Debug Information of Pe Image
2211 if (OutImageType
== FW_ZERO_DEBUG_IMAGE
) {
2212 Status
= ZeroDebugData (FileBuffer
, TRUE
);
2213 if (EFI_ERROR (Status
)) {
2214 Error (NULL
, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%lx", (UINTN
) Status
);
2218 if (fpOut
!= NULL
) {
2219 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2221 if (fpInOut
!= NULL
) {
2222 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2224 VerboseMsg ("the size of output file is %d bytes", FileLength
);
2229 // Set Time Stamp of Pe Image
2231 if (OutImageType
== FW_SET_STAMP_IMAGE
) {
2232 Status
= SetStamp (FileBuffer
, TimeStamp
);
2233 if (EFI_ERROR (Status
)) {
2237 if (fpOut
!= NULL
) {
2238 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2240 if (fpInOut
!= NULL
) {
2241 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2243 VerboseMsg ("the size of output file is %d bytes", FileLength
);
2248 // Extract acpi data from pe image.
2250 if (OutImageType
== FW_ACPI_IMAGE
) {
2251 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2252 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2253 if (strcmp ((char *)SectionHeader
->Name
, ".data") == 0 || strcmp ((char *)SectionHeader
->Name
, ".sdata") == 0) {
2257 if (SectionHeader
->Misc
.VirtualSize
< SectionHeader
->SizeOfRawData
) {
2258 FileLength
= SectionHeader
->Misc
.VirtualSize
;
2260 FileLength
= SectionHeader
->SizeOfRawData
;
2263 if (CheckAcpiTable (FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
) != STATUS_SUCCESS
) {
2264 Error (NULL
, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName
);
2269 // Output Apci data to file
2271 if (fpOut
!= NULL
) {
2272 fwrite (FileBuffer
+ SectionHeader
->PointerToRawData
, 1, FileLength
, fpOut
);
2274 if (fpInOut
!= NULL
) {
2275 fwrite (FileBuffer
+ SectionHeader
->PointerToRawData
, 1, FileLength
, fpInOut
);
2277 VerboseMsg ("the size of output file is %d bytes", FileLength
);
2281 Error (NULL
, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName
);
2285 // Zero all unused fields of the DOS header
2287 if (DosHdr
!= NULL
) {
2288 memcpy (&BackupDosHdr
, DosHdr
, sizeof (EFI_IMAGE_DOS_HEADER
));
2289 memset (DosHdr
, 0, sizeof (EFI_IMAGE_DOS_HEADER
));
2290 DosHdr
->e_magic
= BackupDosHdr
.e_magic
;
2291 DosHdr
->e_lfanew
= BackupDosHdr
.e_lfanew
;
2293 for (Index
= sizeof (EFI_IMAGE_DOS_HEADER
); Index
< (UINT32
) DosHdr
->e_lfanew
; Index
++) {
2294 FileBuffer
[Index
] = DosHdr
->e_cp
;
2299 // Initialize TeImage Header
2301 memset (&TEImageHeader
, 0, sizeof (EFI_TE_IMAGE_HEADER
));
2302 TEImageHeader
.Signature
= EFI_TE_IMAGE_HEADER_SIGNATURE
;
2303 TEImageHeader
.Machine
= PeHdr
->Pe32
.FileHeader
.Machine
;
2304 TEImageHeader
.NumberOfSections
= (UINT8
) PeHdr
->Pe32
.FileHeader
.NumberOfSections
;
2305 TEImageHeader
.StrippedSize
= (UINT16
) ((UINTN
) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
) - (UINTN
) FileBuffer
);
2306 TEImageHeader
.Subsystem
= (UINT8
) Type
;
2309 // Patch the PE header
2311 PeHdr
->Pe32
.OptionalHeader
.Subsystem
= (UINT16
) Type
;
2313 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2314 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2315 Optional32
->MajorLinkerVersion
= 0;
2316 Optional32
->MinorLinkerVersion
= 0;
2317 Optional32
->MajorOperatingSystemVersion
= 0;
2318 Optional32
->MinorOperatingSystemVersion
= 0;
2319 Optional32
->MajorImageVersion
= 0;
2320 Optional32
->MinorImageVersion
= 0;
2321 Optional32
->MajorSubsystemVersion
= 0;
2322 Optional32
->MinorSubsystemVersion
= 0;
2323 Optional32
->Win32VersionValue
= 0;
2324 Optional32
->CheckSum
= 0;
2325 Optional32
->SizeOfStackReserve
= 0;
2326 Optional32
->SizeOfStackCommit
= 0;
2327 Optional32
->SizeOfHeapReserve
= 0;
2328 Optional32
->SizeOfHeapCommit
= 0;
2330 TEImageHeader
.AddressOfEntryPoint
= Optional32
->AddressOfEntryPoint
;
2331 TEImageHeader
.BaseOfCode
= Optional32
->BaseOfCode
;
2332 TEImageHeader
.ImageBase
= (UINT64
) (Optional32
->ImageBase
);
2334 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2335 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2336 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2339 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2340 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2341 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2345 // Zero .pdata section data.
2347 if (!KeepExceptionTableFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2348 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2349 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2350 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2351 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2352 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2354 // Zero .pdata Section data
2356 memset (FileBuffer
+ SectionHeader
->PointerToRawData
, 0, SectionHeader
->SizeOfRawData
);
2358 // Zero .pdata Section header name
2360 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2362 // Zero Execption Table
2364 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2365 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2366 DebugMsg (NULL
, 0, 9, "Zero the .pdata section for PE image", NULL
);
2373 // Strip zero padding at the end of the .reloc section
2375 if (!KeepZeroPendingFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2376 if (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2377 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2378 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2380 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2382 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2383 SectionHeader
->Misc
.VirtualSize
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2384 AllignedRelocSize
= (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional32
->FileAlignment
- 1) & (~(Optional32
->FileAlignment
- 1));
2386 // Check to see if there is zero padding at the end of the base relocations
2388 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2390 // Check to see if the base relocations are at the end of the file
2392 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional32
->SizeOfImage
) {
2394 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2396 Optional32
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2397 Optional32
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2398 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2399 FileLength
= Optional32
->SizeOfImage
;
2400 DebugMsg (NULL
, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %d", SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2407 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2408 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2409 Optional64
->MajorLinkerVersion
= 0;
2410 Optional64
->MinorLinkerVersion
= 0;
2411 Optional64
->MajorOperatingSystemVersion
= 0;
2412 Optional64
->MinorOperatingSystemVersion
= 0;
2413 Optional64
->MajorImageVersion
= 0;
2414 Optional64
->MinorImageVersion
= 0;
2415 Optional64
->MajorSubsystemVersion
= 0;
2416 Optional64
->MinorSubsystemVersion
= 0;
2417 Optional64
->Win32VersionValue
= 0;
2418 Optional64
->CheckSum
= 0;
2419 Optional64
->SizeOfStackReserve
= 0;
2420 Optional64
->SizeOfStackCommit
= 0;
2421 Optional64
->SizeOfHeapReserve
= 0;
2422 Optional64
->SizeOfHeapCommit
= 0;
2424 TEImageHeader
.AddressOfEntryPoint
= Optional64
->AddressOfEntryPoint
;
2425 TEImageHeader
.BaseOfCode
= Optional64
->BaseOfCode
;
2426 TEImageHeader
.ImageBase
= (UINT64
) (Optional64
->ImageBase
);
2428 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2429 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2430 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2433 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2434 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2435 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2439 // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
2440 // For Itaninum and X64 Image, remove .pdata section.
2442 if ((!KeepExceptionTableFlag
&& PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_X64
) || PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
) {
2443 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2444 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2445 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2446 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2447 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2448 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2450 // Zero .pdata Section header name
2452 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2454 RuntimeFunction
= (RUNTIME_FUNCTION
*)(FileBuffer
+ SectionHeader
->PointerToRawData
);
2455 for (Index1
= 0; Index1
< Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
/ sizeof (RUNTIME_FUNCTION
); Index1
++, RuntimeFunction
++) {
2456 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2457 for (Index2
= 0; Index2
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index2
++, SectionHeader
++) {
2458 if (RuntimeFunction
->UnwindInfoAddress
> SectionHeader
->VirtualAddress
&& RuntimeFunction
->UnwindInfoAddress
< (SectionHeader
->VirtualAddress
+ SectionHeader
->SizeOfRawData
)) {
2459 UnwindInfo
= (UNWIND_INFO
*)(FileBuffer
+ SectionHeader
->PointerToRawData
+ (RuntimeFunction
->UnwindInfoAddress
- SectionHeader
->VirtualAddress
));
2460 if (UnwindInfo
->Version
== 1) {
2461 memset (UnwindInfo
+ 1, 0, UnwindInfo
->CountOfUnwindCodes
* sizeof (UINT16
));
2462 memset (UnwindInfo
, 0, sizeof (UNWIND_INFO
));
2466 memset (RuntimeFunction
, 0, sizeof (RUNTIME_FUNCTION
));
2469 // Zero Execption Table
2471 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2472 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2473 DebugMsg (NULL
, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL
);
2481 // Strip zero padding at the end of the .reloc section
2483 if (!KeepZeroPendingFlag
&& Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2484 if (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2485 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2486 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2488 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2490 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2491 SectionHeader
->Misc
.VirtualSize
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2492 AllignedRelocSize
= (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional64
->FileAlignment
- 1) & (~(Optional64
->FileAlignment
- 1));
2494 // Check to see if there is zero padding at the end of the base relocations
2496 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2498 // Check to see if the base relocations are at the end of the file
2500 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional64
->SizeOfImage
) {
2502 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2504 Optional64
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2505 Optional64
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2506 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2507 FileLength
= Optional64
->SizeOfImage
;
2508 DebugMsg (NULL
, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %d", SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2516 Error (NULL
, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr
->Pe32
.OptionalHeader
.Magic
, mInImageName
);
2520 if (((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) == 0) && \
2521 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
== 0) && \
2522 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
== 0)) {
2524 // PeImage can be loaded into memory, but it has no relocation section.
2525 // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
2527 if (Optional32
!= NULL
) {
2528 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
2529 } else if (Optional64
!= NULL
) {
2530 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
2535 // Zero ExceptionTable Xdata
2537 if (!KeepExceptionTableFlag
) {
2538 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2539 ZeroXdataSection(mInImageName
, FileBuffer
, SectionHeader
, PeHdr
->Pe32
.FileHeader
.NumberOfSections
);
2543 // Zero Time/Data field
2545 ZeroDebugData (FileBuffer
, FALSE
);
2547 if (OutImageType
== FW_TE_IMAGE
) {
2548 if ((PeHdr
->Pe32
.FileHeader
.NumberOfSections
&~0xFF) || (Type
&~0xFF)) {
2550 // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
2552 Error (NULL
, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName
);
2556 if ((PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
)) {
2558 // TeImage has the same section alignment and file alignment.
2560 Error (NULL
, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName
);
2564 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 %X",
2565 TEImageHeader
.Machine
, TEImageHeader
.NumberOfSections
, TEImageHeader
.StrippedSize
, TEImageHeader
.AddressOfEntryPoint
, TEImageHeader
.BaseOfCode
, TEImageHeader
.ImageBase
);
2567 // Update Image to TeImage
2569 if (fpOut
!= NULL
) {
2570 fwrite (&TEImageHeader
, 1, sizeof (EFI_TE_IMAGE_HEADER
), fpOut
);
2571 fwrite (FileBuffer
+ TEImageHeader
.StrippedSize
, 1, FileLength
- TEImageHeader
.StrippedSize
, fpOut
);
2573 if (fpInOut
!= NULL
) {
2574 fwrite (&TEImageHeader
, 1, sizeof (EFI_TE_IMAGE_HEADER
), fpInOut
);
2575 fwrite (FileBuffer
+ TEImageHeader
.StrippedSize
, 1, FileLength
- TEImageHeader
.StrippedSize
, fpInOut
);
2577 VerboseMsg ("the size of output file is %d bytes", FileLength
- TEImageHeader
.StrippedSize
);
2582 // Update Image to EfiImage
2584 if (fpOut
!= NULL
) {
2585 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2587 if (fpInOut
!= NULL
) {
2588 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2590 VerboseMsg ("the size of output file is %d bytes", FileLength
);
2593 if (fpInOut
!= NULL
) {
2594 if (GetUtilityStatus () != STATUS_SUCCESS
) {
2596 // when file updates failed, original file is still recoveried.
2598 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2601 // Write converted data into fpInOut file and close input file.
2606 if (FileBuffer
!= NULL
) {
2610 if (InputFileName
!= NULL
) {
2611 free (InputFileName
);
2614 if (fpOut
!= NULL
) {
2616 // Write converted data into fpOut file and close output file.
2619 if (GetUtilityStatus () != STATUS_SUCCESS
) {
2620 if (OutputFileBuffer
== NULL
) {
2621 remove (OutImageName
);
2623 fpOut
= fopen (OutImageName
, "wb");
2624 fwrite (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
2626 free (OutputFileBuffer
);
2631 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
2633 return GetUtilityStatus ();
2639 IN OUT UINT8
*FileBuffer
,
2640 BOOLEAN ZeroDebugFlag
2644 Routine Description:
2646 Zero debug information in PeImage.
2650 FileBuffer - Pointer to PeImage.
2651 ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp
2655 EFI_ABORTED - PeImage is invalid.
2656 EFI_SUCCESS - Zero debug data successfully.
2661 UINT32 DebugDirectoryEntryRva
;
2662 UINT32 DebugDirectoryEntryFileOffset
;
2663 UINT32 ExportDirectoryEntryRva
;
2664 UINT32 ExportDirectoryEntryFileOffset
;
2665 UINT32 ResourceDirectoryEntryRva
;
2666 UINT32 ResourceDirectoryEntryFileOffset
;
2667 EFI_IMAGE_DOS_HEADER
*DosHdr
;
2668 EFI_IMAGE_FILE_HEADER
*FileHdr
;
2669 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
2670 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
2671 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
2672 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
2673 UINT32
*NewTimeStamp
;
2678 DebugDirectoryEntryRva
= 0;
2679 ExportDirectoryEntryRva
= 0;
2680 ResourceDirectoryEntryRva
= 0;
2681 DebugDirectoryEntryFileOffset
= 0;
2682 ExportDirectoryEntryFileOffset
= 0;
2683 ResourceDirectoryEntryFileOffset
= 0;
2684 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2685 FileHdr
= (EFI_IMAGE_FILE_HEADER
*) (FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2688 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2689 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2690 // NO DOS header, must start with PE/COFF header
2691 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
2693 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2697 // Get Debug, Export and Resource EntryTable RVA address.
2698 // Resource Directory entry need to review.
2700 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
2701 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2702 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2703 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2704 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2705 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2707 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2708 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2709 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2711 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2712 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2713 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2714 if (ZeroDebugFlag
) {
2715 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
2716 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
2720 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2721 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2722 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2723 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2724 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2726 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2727 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2728 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2730 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2731 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2732 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2733 if (ZeroDebugFlag
) {
2734 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
2735 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
2741 // Get DirectoryEntryTable file offset.
2743 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2744 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2745 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2746 DebugDirectoryEntryFileOffset
=
2747 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2749 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2750 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2751 ExportDirectoryEntryFileOffset
=
2752 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2754 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2755 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2756 ResourceDirectoryEntryFileOffset
=
2757 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2762 //Zero Debug Data and TimeStamp
2764 FileHdr
->TimeDateStamp
= 0;
2766 if (ExportDirectoryEntryFileOffset
!= 0) {
2767 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
2771 if (ResourceDirectoryEntryFileOffset
!= 0) {
2772 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
2776 if (DebugDirectoryEntryFileOffset
!= 0) {
2777 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
);
2778 DebugEntry
->TimeDateStamp
= 0;
2779 if (ZeroDebugFlag
) {
2780 memset (FileBuffer
+ DebugEntry
->FileOffset
, 0, DebugEntry
->SizeOfData
);
2781 memset (DebugEntry
, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
2791 IN OUT UINT8
*FileBuffer
,
2796 Routine Description:
2798 Set new time stamp into PeImage FileHdr and Directory table:
2799 Debug, Export and Resource.
2803 FileBuffer - Pointer to PeImage.
2804 TimeStamp - Time stamp string.
2808 EFI_INVALID_PARAMETER - TimeStamp format is not recognized.
2809 EFI_SUCCESS - Set new time stamp in this image successfully.
2817 UINT32 DebugDirectoryEntryRva
;
2818 UINT32 DebugDirectoryEntryFileOffset
;
2819 UINT32 ExportDirectoryEntryRva
;
2820 UINT32 ExportDirectoryEntryFileOffset
;
2821 UINT32 ResourceDirectoryEntryRva
;
2822 UINT32 ResourceDirectoryEntryFileOffset
;
2823 EFI_IMAGE_DOS_HEADER
*DosHdr
;
2824 EFI_IMAGE_FILE_HEADER
*FileHdr
;
2825 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
2826 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
2827 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
2828 UINT32
*NewTimeStamp
;
2833 DebugDirectoryEntryRva
= 0;
2834 ExportDirectoryEntryRva
= 0;
2835 ResourceDirectoryEntryRva
= 0;
2837 // Get time and date that will be set.
2839 if (TimeStamp
== NULL
) {
2840 Error (NULL
, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");
2841 return EFI_INVALID_PARAMETER
;
2844 // compare the value with "NOW", if yes, current system time is set.
2846 if (stricmp (TimeStamp
, "NOW") == 0) {
2848 // get system current time and date
2853 // Check Time Format strictly yyyy-mm-dd 00:00:00
2855 for (Index
= 0; TimeStamp
[Index
] != '\0' && Index
< 20; Index
++) {
2856 if (Index
== 4 || Index
== 7) {
2857 if (TimeStamp
[Index
] == '-') {
2860 } else if (Index
== 13 || Index
== 16) {
2861 if (TimeStamp
[Index
] == ':') {
2864 } else if (Index
== 10 && TimeStamp
[Index
] == ' ') {
2866 } else if ((TimeStamp
[Index
] < '0') || (TimeStamp
[Index
] > '9')) {
2871 if (Index
< 19 || TimeStamp
[19] != '\0') {
2872 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
2873 return EFI_INVALID_PARAMETER
;
2877 // get the date and time from TimeStamp
2879 if (sscanf (TimeStamp
, "%d-%d-%d %d:%d:%d",
2887 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
2888 return EFI_INVALID_PARAMETER
;
2892 // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
2894 if (stime
.tm_mon
<= 0 || stime
.tm_mday
<=0) {
2895 Error (NULL
, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp
);
2896 return EFI_INVALID_PARAMETER
;
2901 // in struct, Year (current year minus 1900)
2902 // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
2905 // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
2907 if (stime
.tm_year
>= 1970 && stime
.tm_year
<= 2038) {
2909 // convert 1970 -> 70, 2000 -> 100, ...
2911 stime
.tm_year
-= 1900;
2913 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
2914 return EFI_INVALID_PARAMETER
;
2918 // convert the date and time to time_t format
2920 newtime
= mktime (&stime
);
2921 if (newtime
== (time_t) - 1) {
2922 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
2923 return EFI_INVALID_PARAMETER
;
2927 ptime
= localtime (&newtime
);
2928 DebugMsg (NULL
, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",
2929 ptime
->tm_year
+ 1900, ptime
->tm_mon
+ 1, ptime
->tm_mday
, ptime
->tm_hour
, ptime
->tm_min
, ptime
->tm_sec
);
2931 // Set new time and data into PeImage.
2933 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2934 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2935 // NO DOS header, must start with PE/COFF header
2936 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
2938 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2942 // Get Debug, Export and Resource EntryTable RVA address.
2943 // Resource Directory entry need to review.
2945 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
2946 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2947 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2948 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2949 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2950 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2952 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2953 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2954 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2956 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2957 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2958 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2961 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2962 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2963 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2964 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2965 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2967 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2968 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2969 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2971 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2972 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2973 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2978 // Get DirectoryEntryTable file offset.
2980 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2981 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2982 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2983 DebugDirectoryEntryFileOffset
=
2984 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2986 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2987 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2988 ExportDirectoryEntryFileOffset
=
2989 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2991 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2992 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2993 ResourceDirectoryEntryFileOffset
=
2994 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3001 FileHdr
->TimeDateStamp
= (UINT32
) newtime
;
3003 if (ExportDirectoryEntryRva
!= 0) {
3004 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
3005 *NewTimeStamp
= (UINT32
) newtime
;
3008 if (ResourceDirectoryEntryRva
!= 0) {
3009 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
3010 *NewTimeStamp
= (UINT32
) newtime
;
3013 if (DebugDirectoryEntryRva
!= 0) {
3014 NewTimeStamp
= (UINT32
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
+ sizeof (UINT32
));
3015 *NewTimeStamp
= (UINT32
) newtime
;
3029 Routine Description:
3030 Read a 32-bit microcode data value from a text file and convert to raw binary form.
3033 InFptr - file pointer to input text file
3034 Data - pointer to where to return the data parsed
3037 STATUS_SUCCESS - no errors or warnings, Data contains valid information
3038 STATUS_ERROR - errors were encountered
3042 CHAR8 Line
[MAX_LINE_LEN
];
3045 Line
[MAX_LINE_LEN
- 1] = 0;
3047 if (fgets (Line
, MAX_LINE_LEN
, InFptr
) == NULL
) {
3048 return STATUS_ERROR
;
3051 // If it was a binary file, then it may have overwritten our null terminator
3053 if (Line
[MAX_LINE_LEN
- 1] != 0) {
3054 return STATUS_ERROR
;
3060 for (cptr
= Line
; *cptr
&& isspace(*cptr
); cptr
++) {
3063 // Skip Blank Lines and Comment Lines
3064 if ((strlen(cptr
) != 0) && (*cptr
!= ';')) {
3070 // dd 000000001h ; comment
3075 if ((tolower(cptr
[0]) == 'd') && (tolower(cptr
[1]) == 'd') && isspace (cptr
[2])) {
3077 // Skip blanks and look for a hex digit
3080 for (; *cptr
&& isspace(*cptr
); cptr
++) {
3082 if (isxdigit (*cptr
)) {
3083 if (sscanf (cptr
, "%X", Data
) != 1) {
3084 return STATUS_ERROR
;
3087 return STATUS_SUCCESS
;
3090 return STATUS_ERROR
;