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 CoffOffset
+= sizeof(EFI_IMAGE_OPTIONAL_HEADER_UNION
);
587 TableOffset
= CoffOffset
;
588 CoffOffset
+= CoffNbrSections
* sizeof(EFI_IMAGE_SECTION_HEADER
);
591 // First text sections.
593 CoffOffset
= CoffAlign(CoffOffset
);
594 TextOffset
= CoffOffset
;
595 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
596 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
597 if (IsTextShdr(shdr
)) {
598 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
599 // the alignment field is valid
600 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
601 // if the section address is aligned we must align PE/COFF
602 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
603 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
604 // ARM RVCT tools have behavior outside of the ELF specification to try
605 // and make images smaller. If sh_addr is not aligned to sh_addralign
606 // then the section needs to preserve sh_addr MOD sh_addralign.
607 // Normally doing nothing here works great.
608 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
612 /* Relocate entry. */
613 if ((Ehdr
->e_entry
>= shdr
->sh_addr
) &&
614 (Ehdr
->e_entry
< shdr
->sh_addr
+ shdr
->sh_size
)) {
615 CoffEntry
= CoffOffset
+ Ehdr
->e_entry
- shdr
->sh_addr
;
617 CoffSectionsOffset
[i
] = CoffOffset
;
618 CoffOffset
+= shdr
->sh_size
;
622 if (Ehdr
->e_machine
!= EM_ARM
) {
623 CoffOffset
= CoffAlign(CoffOffset
);
627 // Then data sections.
629 DataOffset
= CoffOffset
;
630 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
631 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
632 if (IsDataShdr(shdr
)) {
633 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
634 // the alignment field is valid
635 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
636 // if the section address is aligned we must align PE/COFF
637 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
638 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
639 // ARM RVCT tools have behavior outside of the ELF specification to try
640 // and make images smaller. If sh_addr is not aligned to sh_addralign
641 // then the section needs to preserve sh_addr MOD sh_addralign.
642 // Normally doing nothing here works great.
643 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
647 CoffSectionsOffset
[i
] = CoffOffset
;
648 CoffOffset
+= shdr
->sh_size
;
651 CoffOffset
= CoffAlign(CoffOffset
);
653 RelocOffset
= CoffOffset
;
656 // Allocate base Coff file. Will be expanded later for relocations.
658 CoffFile
= (UINT8
*)malloc(CoffOffset
);
659 memset(CoffFile
, 0, CoffOffset
);
664 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)CoffFile
;
665 DosHdr
->e_magic
= EFI_IMAGE_DOS_SIGNATURE
;
666 DosHdr
->e_lfanew
= NtHdrOffset
;
668 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
670 NtHdr
->Pe32
.Signature
= EFI_IMAGE_NT_SIGNATURE
;
672 switch (Ehdr
->e_machine
) {
674 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IA32
;
675 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
678 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_X64
;
679 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
682 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IPF
;
683 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
686 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_ARMT
;
687 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
690 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN
)Ehdr
->e_machine
);
691 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IA32
;
692 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
695 NtHdr
->Pe32
.FileHeader
.NumberOfSections
= CoffNbrSections
;
696 NtHdr
->Pe32
.FileHeader
.TimeDateStamp
= time(NULL
);
697 NtHdr
->Pe32
.FileHeader
.PointerToSymbolTable
= 0;
698 NtHdr
->Pe32
.FileHeader
.NumberOfSymbols
= 0;
699 NtHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
= sizeof(NtHdr
->Pe32
.OptionalHeader
);
700 NtHdr
->Pe32
.FileHeader
.Characteristics
= EFI_IMAGE_FILE_EXECUTABLE_IMAGE
701 | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED
702 | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED
703 | EFI_IMAGE_FILE_32BIT_MACHINE
;
705 NtHdr
->Pe32
.OptionalHeader
.SizeOfCode
= DataOffset
- TextOffset
;
706 NtHdr
->Pe32
.OptionalHeader
.SizeOfInitializedData
= RelocOffset
- DataOffset
;
707 NtHdr
->Pe32
.OptionalHeader
.SizeOfUninitializedData
= 0;
708 NtHdr
->Pe32
.OptionalHeader
.AddressOfEntryPoint
= CoffEntry
;
710 NtHdr
->Pe32
.OptionalHeader
.BaseOfCode
= TextOffset
;
712 NtHdr
->Pe32
.OptionalHeader
.BaseOfData
= DataOffset
;
713 NtHdr
->Pe32
.OptionalHeader
.ImageBase
= 0;
714 NtHdr
->Pe32
.OptionalHeader
.SectionAlignment
= CoffAlignment
;
715 NtHdr
->Pe32
.OptionalHeader
.FileAlignment
= CoffAlignment
;
716 NtHdr
->Pe32
.OptionalHeader
.SizeOfImage
= 0;
718 NtHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
= TextOffset
;
719 NtHdr
->Pe32
.OptionalHeader
.NumberOfRvaAndSizes
= EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES
;
724 if ((DataOffset
- TextOffset
) > 0) {
725 CreateSectionHeader (".text", TextOffset
, DataOffset
- TextOffset
,
726 EFI_IMAGE_SCN_CNT_CODE
727 | EFI_IMAGE_SCN_MEM_EXECUTE
728 | EFI_IMAGE_SCN_MEM_READ
);
730 // Don't make a section of size 0.
731 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
734 if ((RelocOffset
- TextOffset
) > 0) {
735 CreateSectionHeader (".data", DataOffset
, RelocOffset
- DataOffset
,
736 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
737 | EFI_IMAGE_SCN_MEM_WRITE
738 | EFI_IMAGE_SCN_MEM_READ
);
740 // Don't make a section of size 0.
741 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
747 int (*Filter
)(Elf_Shdr
*)
755 // First: copy sections.
757 for (Idx
= 0; Idx
< Ehdr
->e_shnum
; Idx
++) {
758 Elf_Shdr
*Shdr
= GetShdrByIndex(Idx
);
759 if ((*Filter
)(Shdr
)) {
760 switch (Shdr
->sh_type
) {
763 memcpy(CoffFile
+ CoffSectionsOffset
[Idx
],
764 (UINT8
*)Ehdr
+ Shdr
->sh_offset
,
769 memset(CoffFile
+ CoffSectionsOffset
[Idx
], 0, Shdr
->sh_size
);
774 // Ignore for unkown section type.
776 VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName
, (UINTN
)Shdr
->sh_type
);
783 // Second: apply relocations.
785 for (Idx
= 0; Idx
< Ehdr
->e_shnum
; Idx
++) {
786 Elf_Shdr
*RelShdr
= GetShdrByIndex(Idx
);
787 if (RelShdr
->sh_type
!= SHT_REL
)
789 SecShdr
= GetShdrByIndex(RelShdr
->sh_info
);
790 SecOffset
= CoffSectionsOffset
[RelShdr
->sh_info
];
791 if (RelShdr
->sh_type
== SHT_REL
&& (*Filter
)(SecShdr
)) {
793 Elf_Shdr
*SymtabShdr
= GetShdrByIndex(RelShdr
->sh_link
);
794 UINT8
*Symtab
= (UINT8
*)Ehdr
+ SymtabShdr
->sh_offset
;
796 for (RelIdx
= 0; RelIdx
< RelShdr
->sh_size
; RelIdx
+= RelShdr
->sh_entsize
) {
797 Elf_Rel
*Rel
= (Elf_Rel
*)((UINT8
*)Ehdr
+ RelShdr
->sh_offset
+ RelIdx
);
798 Elf_Sym
*Sym
= (Elf_Sym
*)(Symtab
+ ELF_R_SYM(Rel
->r_info
) * SymtabShdr
->sh_entsize
);
802 if (Sym
->st_shndx
== SHN_UNDEF
803 || Sym
->st_shndx
== SHN_ABS
804 || Sym
->st_shndx
> Ehdr
->e_shnum
) {
805 Error (NULL
, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName
);
807 SymShdr
= GetShdrByIndex(Sym
->st_shndx
);
810 // Note: r_offset in a memory address.
811 // Convert it to a pointer in the coff file.
813 Targ
= CoffFile
+ SecOffset
+ (Rel
->r_offset
- SecShdr
->sh_addr
);
815 if (Ehdr
->e_machine
== EM_386
) {
816 switch (ELF_R_TYPE(Rel
->r_info
)) {
821 // Absolute relocation.
823 *(UINT32
*)Targ
= *(UINT32
*)Targ
- SymShdr
->sh_addr
824 + CoffSectionsOffset
[Sym
->st_shndx
];
828 // Relative relocation: Symbol - Ip + Addend
830 *(UINT32
*)Targ
= *(UINT32
*)Targ
831 + (CoffSectionsOffset
[Sym
->st_shndx
] - SymShdr
->sh_addr
)
832 - (SecOffset
- SecShdr
->sh_addr
);
835 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, ELF_R_TYPE(Rel
->r_info
));
837 } else if (Ehdr
->e_machine
== EM_ARM
) {
838 switch (ELF32_R_TYPE(Rel
->r_info
)) {
839 case R_ARM_RBASE
: // No relocation - no action required
840 case R_ARM_PC24
: // PC-relative relocations don't require modification
841 case R_ARM_XPC25
: // PC-relative relocations don't require modification
846 // Absolute relocation.
848 *(UINT32
*)Targ
= *(UINT32
*)Targ
- SymShdr
->sh_addr
+ CoffSectionsOffset
[Sym
->st_shndx
];
851 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, ELF32_R_TYPE(Rel
->r_info
));
866 CoffBaseRel
->SizeOfBlock
+= 2;
876 if (CoffBaseRel
== NULL
877 || CoffBaseRel
->VirtualAddress
!= (Offset
& ~0xfff)) {
878 if (CoffBaseRel
!= NULL
) {
880 // Add a null entry (is it required ?)
882 CoffAddFixupEntry (0);
884 // Pad for alignment.
886 if (CoffOffset
% 4 != 0)
887 CoffAddFixupEntry (0);
892 CoffOffset
+ sizeof(EFI_IMAGE_BASE_RELOCATION
) + 2*0x1000);
893 memset(CoffFile
+ CoffOffset
, 0,
894 sizeof(EFI_IMAGE_BASE_RELOCATION
) + 2*0x1000);
896 CoffBaseRel
= (EFI_IMAGE_BASE_RELOCATION
*)(CoffFile
+ CoffOffset
);
897 CoffBaseRel
->VirtualAddress
= Offset
& ~0xfff;
898 CoffBaseRel
->SizeOfBlock
= sizeof(EFI_IMAGE_BASE_RELOCATION
);
900 CoffEntryRel
= (UINT16
*)(CoffBaseRel
+ 1);
901 CoffOffset
+= sizeof(EFI_IMAGE_BASE_RELOCATION
);
907 CoffAddFixupEntry((Type
<< 12) | (Offset
& 0xfff));
916 if (num
>= Ehdr
->e_phnum
) {
920 return (Elf32_Phdr
*)((UINT8
*)gPhdrBase
+ num
* Ehdr
->e_phentsize
);
930 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
931 EFI_IMAGE_DATA_DIRECTORY
*Dir
;
932 BOOLEAN FoundRelocations
;
935 UINTN RelElementSize
;
940 Elf32_Phdr
*DynamicSegment
;
941 Elf32_Phdr
*TargetSegment
;
943 for (Index
= 0, FoundRelocations
= FALSE
; Index
< Ehdr
->e_shnum
; Index
++) {
944 Elf_Shdr
*RelShdr
= GetShdrByIndex(Index
);
945 if (RelShdr
->sh_type
== SHT_REL
) {
946 Elf_Shdr
*SecShdr
= GetShdrByIndex(RelShdr
->sh_info
);
947 if (IsTextShdr(SecShdr
) || IsDataShdr(SecShdr
)) {
949 FoundRelocations
= TRUE
;
950 for (RelIdx
= 0; RelIdx
< RelShdr
->sh_size
; RelIdx
+= RelShdr
->sh_entsize
) {
951 Elf_Rel
*Rel
= (Elf_Rel
*)
952 ((UINT8
*)Ehdr
+ RelShdr
->sh_offset
+ RelIdx
);
954 if (Ehdr
->e_machine
== EM_386
) {
955 switch (ELF_R_TYPE(Rel
->r_info
)) {
960 CoffAddFixup(CoffSectionsOffset
[RelShdr
->sh_info
]
961 + (Rel
->r_offset
- SecShdr
->sh_addr
),
962 EFI_IMAGE_REL_BASED_HIGHLOW
);
965 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, ELF_R_TYPE(Rel
->r_info
));
967 } else if (Ehdr
->e_machine
== EM_ARM
) {
968 switch (ELF32_R_TYPE(Rel
->r_info
)) {
976 CoffSectionsOffset
[RelShdr
->sh_info
]
977 + (Rel
->r_offset
- SecShdr
->sh_addr
),
978 EFI_IMAGE_REL_BASED_HIGHLOW
982 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, ELF32_R_TYPE(Rel
->r_info
));
985 Error (NULL
, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %d (processor type).", Ehdr
->e_machine
);
992 if (!FoundRelocations
&& (Ehdr
->e_machine
== EM_ARM
)) {
993 /* Try again, but look for PT_DYNAMIC instead of SHT_REL */
995 for (Index
= 0; Index
< Ehdr
->e_phnum
; Index
++) {
1000 DynamicSegment
= GetPhdrByIndex (Index
);
1002 if (DynamicSegment
->p_type
== PT_DYNAMIC
) {
1003 Dyn
= (Elf32_Dyn
*) ((UINT8
*)Ehdr
+ DynamicSegment
->p_offset
);
1005 while (Dyn
->d_tag
!= DT_NULL
) {
1006 switch (Dyn
->d_tag
) {
1008 RelOffset
= Dyn
->d_un
.d_val
;
1012 RelSize
= Dyn
->d_un
.d_val
;
1016 RelElementSize
= Dyn
->d_un
.d_val
;
1021 if (( RelOffset
== 0 ) || ( RelSize
== 0 ) || ( RelElementSize
== 0 )) {
1022 Error (NULL
, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName
);
1025 for (K
= 0; K
< RelSize
; K
+= RelElementSize
) {
1027 Rel
= (Elf32_Rel
*) ((UINT8
*) Ehdr
+ DynamicSegment
->p_offset
+ RelOffset
+ K
);
1029 switch (ELF32_R_TYPE (Rel
->r_info
)) {
1033 TargetSegment
= GetPhdrByIndex (ELF32_R_SYM (Rel
->r_info
) - 1);
1035 // Note: r_offset in a memory address. Convert it to a pointer in the coff file.
1036 Targ
= CoffFile
+ CoffSectionsOffset
[ ELF32_R_SYM( Rel
->r_info
) ] + Rel
->r_offset
- TargetSegment
->p_vaddr
;
1038 *(UINT32
*)Targ
= *(UINT32
*)Targ
+ CoffSectionsOffset
[ELF32_R_SYM( Rel
->r_info
)];
1040 CoffAddFixup (CoffSectionsOffset
[ELF32_R_SYM (Rel
->r_info
)] + (Rel
->r_offset
- TargetSegment
->p_vaddr
), EFI_IMAGE_REL_BASED_HIGHLOW
);
1043 Error (NULL
, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type.", mInImageName
);
1052 // Pad by adding empty entries.
1054 while (CoffOffset
& (CoffAlignment
- 1)) {
1055 CoffAddFixupEntry(0);
1059 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1060 Dir
= &NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1061 Dir
->Size
= CoffOffset
- RelocOffset
;
1062 if (Dir
->Size
== 0) {
1063 // If no relocations, null out the directory entry and don't add the .reloc section
1064 Dir
->VirtualAddress
= 0;
1065 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
1067 Dir
->VirtualAddress
= RelocOffset
;
1068 CreateSectionHeader (".reloc", RelocOffset
, CoffOffset
- RelocOffset
,
1069 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
1070 | EFI_IMAGE_SCN_MEM_DISCARDABLE
1071 | EFI_IMAGE_SCN_MEM_READ
);
1083 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1084 EFI_IMAGE_DATA_DIRECTORY
*DataDir
;
1085 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*Dir
;
1086 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
*Nb10
;
1088 Len
= strlen(mInImageName
) + 1;
1089 DebugOffset
= CoffOffset
;
1091 CoffOffset
+= sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
)
1092 + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
)
1094 CoffOffset
= CoffAlign(CoffOffset
);
1096 CoffFile
= realloc(CoffFile
, CoffOffset
);
1097 memset(CoffFile
+ DebugOffset
, 0, CoffOffset
- DebugOffset
);
1099 Dir
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)(CoffFile
+ DebugOffset
);
1100 Dir
->Type
= EFI_IMAGE_DEBUG_TYPE_CODEVIEW
;
1101 Dir
->SizeOfData
= sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
) + Len
;
1102 Dir
->RVA
= DebugOffset
+ sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
1103 Dir
->FileOffset
= DebugOffset
+ sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
1105 Nb10
= (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
*)(Dir
+ 1);
1106 Nb10
->Signature
= CODEVIEW_SIGNATURE_NB10
;
1107 strcpy ((char *)(Nb10
+ 1), mInImageName
);
1110 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1111 DataDir
= &NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
];
1112 DataDir
->VirtualAddress
= DebugOffset
;
1113 DataDir
->Size
= CoffOffset
- DebugOffset
;
1114 if (DataDir
->Size
== 0) {
1115 // If no debug, null out the directory entry and don't add the .debug section
1116 DataDir
->VirtualAddress
= 0;
1117 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
1119 DataDir
->VirtualAddress
= DebugOffset
;
1120 CreateSectionHeader (".debug", DebugOffset
, CoffOffset
- DebugOffset
,
1121 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
1122 | EFI_IMAGE_SCN_MEM_DISCARDABLE
1123 | EFI_IMAGE_SCN_MEM_READ
);
1134 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1137 // Check header, read section table.
1139 Ehdr
= (Elf32_Ehdr
*)*FileBuffer
;
1140 if (!CheckElfHeader())
1143 VerboseMsg ("Check Efl Image Header");
1145 // Compute sections new address.
1149 VerboseMsg ("Compute sections new address.");
1152 // Write and relocate sections.
1154 WriteSections(IsTextShdr
);
1155 WriteSections(IsDataShdr
);
1156 VerboseMsg ("Write and relocate sections.");
1159 // Translate and write relocations.
1162 VerboseMsg ("Translate and write relocations.");
1165 // Write debug info.
1168 VerboseMsg ("Write debug info.");
1170 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1171 NtHdr
->Pe32
.OptionalHeader
.SizeOfImage
= CoffOffset
;
1177 *FileBuffer
= CoffFile
;
1178 *FileLength
= CoffOffset
;
1181 // Free memory space
1183 if (CoffSectionsOffset
!= NULL
) {
1184 free (CoffSectionsOffset
);
1190 IN CHAR8
*ImageName
,
1191 IN OUT UINT8
*FileBuffer
,
1192 IN EFI_IMAGE_SECTION_HEADER
*SectionHeader
,
1193 IN UINT32 SectionTotalNumber
1197 CHAR8 MapFileName
[_MAX_PATH
];
1198 CHAR8 Line
[MAX_LINE_LEN
];
1199 CHAR8 KeyWord
[MAX_LINE_LEN
];
1200 CHAR8 SectionName
[MAX_LINE_LEN
];
1201 UINT32 FunctionType
= 0;
1202 UINT32 SectionOffset
;
1203 UINT32 SectionLength
;
1204 UINT32 SectionNumber
;
1208 for (Index
= 0; Index
< SectionTotalNumber
; Index
++) {
1209 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".zdata") == 0) {
1211 // try to zero the customized .zdata section, which is mapped to .xdata
1213 memset (FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, 0, SectionHeader
[Index
].SizeOfRawData
);
1214 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
);
1219 // Try to get PDB file name
1221 PdbPointer
= (CHAR8
*) PeCoffLoaderGetPdbPointer (FileBuffer
);
1222 if (PdbPointer
!= NULL
) {
1223 strcpy (MapFileName
, PdbPointer
);
1225 strcpy (MapFileName
, ImageName
);
1229 // Construct map file name
1231 Index
= strlen (MapFileName
) - 1;
1232 while (Index
>= 0 && MapFileName
[Index
] != '.') {
1237 // don't know how to costruct map file
1243 // fill map file postfix
1245 MapFileName
[Index
+ 1] = 'm';
1246 MapFileName
[Index
+ 2] = 'a';
1247 MapFileName
[Index
+ 3] = 'p';
1248 MapFileName
[Index
+ 4] = '\0';
1251 // try opening Map File
1253 fpMapFile
= fopen (MapFileName
, "r");
1254 if (fpMapFile
== NULL
) {
1256 // Can't open Map file. Maybe it doesn't exist.
1262 // Output Functions information into Fv Map file
1264 while (fgets (Line
, MAX_LINE_LEN
, fpMapFile
) != NULL
) {
1268 if (Line
[0] == 0x0a) {
1269 if (FunctionType
!= 0) {
1271 // read all section table data
1283 if (FunctionType
== 0) {
1284 sscanf (Line
, "%s", KeyWord
);
1285 if (stricmp (KeyWord
, "Start") == 0) {
1294 // Printf Function Information
1296 if (FunctionType
== 1) {
1297 sscanf (Line
, "%x:%x %xH %s", &SectionNumber
, &SectionOffset
, &SectionLength
, SectionName
);
1298 if (stricmp (SectionName
, ".xdata") == 0) {
1305 if (FunctionType
!= 2) {
1307 // no .xdata section is found
1314 // Zero .xdata Section data
1316 memset (FileBuffer
+ SectionHeader
[SectionNumber
-1].PointerToRawData
+ SectionOffset
, 0, SectionLength
);
1317 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
);
1329 Routine Description:
1335 argc - Number of command line parameters.
1336 argv - Array of pointers to command line parameter strings.
1339 STATUS_SUCCESS - Utility exits successfully.
1340 STATUS_ERROR - Some error occurred during execution.
1345 UINT32 InputFileNum
;
1346 CHAR8
**InputFileName
;
1350 UINT32 OutImageType
;
1355 UINT32
*DataPointer
;
1356 UINT32
*OldDataPointer
;
1362 UINT32 MciAlignment
;
1364 UINT32 AllignedRelocSize
;
1367 UINT8
*OutputFileBuffer
;
1368 UINT32 OutputFileLength
;
1369 RUNTIME_FUNCTION
*RuntimeFunction
;
1370 UNWIND_INFO
*UnwindInfo
;
1372 BOOLEAN ReplaceFlag
;
1373 BOOLEAN KeepExceptionTableFlag
;
1374 BOOLEAN KeepZeroPendingFlag
;
1376 EFI_TE_IMAGE_HEADER TEImageHeader
;
1377 EFI_TE_IMAGE_HEADER
*TeHdr
;
1378 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1379 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1380 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1381 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32
;
1382 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64
;
1383 EFI_IMAGE_DOS_HEADER BackupDosHdr
;
1384 MICROCODE_IMAGE_HEADER
*MciHeader
;
1386 SetUtilityName (UTILITY_NAME
);
1389 // Assign to fix compile warning
1392 InputFileName
= NULL
;
1393 mInImageName
= NULL
;
1394 OutImageName
= NULL
;
1396 OutImageType
= FW_DUMMY_IMAGE
;
1398 Status
= STATUS_SUCCESS
;
1404 MciAlignment
= DEFAULT_MC_ALIGNMENT
;
1405 MciPadValue
= DEFAULT_MC_PAD_BYTE_VALUE
;
1409 ReplaceFlag
= FALSE
;
1411 OutputFileBuffer
= NULL
;
1412 OutputFileLength
= 0;
1415 KeepExceptionTableFlag
= FALSE
;
1416 KeepZeroPendingFlag
= FALSE
;
1419 Error (NULL
, 0, 1001, "Missing options", "No input options.");
1421 return STATUS_ERROR
;
1427 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
1430 return STATUS_SUCCESS
;
1433 if (stricmp (argv
[0], "--version") == 0) {
1435 return STATUS_SUCCESS
;
1439 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
1440 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1441 Error (NULL
, 0, 1003, "Invalid option value", "Output file name is missing for -o option");
1444 OutImageName
= argv
[1];
1450 if ((stricmp (argv
[0], "-e") == 0) || (stricmp (argv
[0], "--efiImage") == 0)) {
1451 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1452 Error (NULL
, 0, 1003, "Invalid option value", "Module Type is missing for -o option");
1455 ModuleType
= argv
[1];
1456 if (OutImageType
!= FW_TE_IMAGE
) {
1457 OutImageType
= FW_EFI_IMAGE
;
1464 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--stripped") == 0)) {
1465 OutImageType
= FW_RELOC_STRIPEED_IMAGE
;
1471 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--acpi") == 0)) {
1472 OutImageType
= FW_ACPI_IMAGE
;
1478 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--terse") == 0)) {
1479 OutImageType
= FW_TE_IMAGE
;
1485 if ((stricmp (argv
[0], "-u") == 0) || (stricmp (argv
[0], "--dump") == 0)) {
1486 OutImageType
= DUMP_TE_HEADER
;
1492 if ((stricmp (argv
[0], "-b") == 0) || (stricmp (argv
[0], "--exe2bin") == 0)) {
1493 OutImageType
= FW_BIN_IMAGE
;
1499 if ((stricmp (argv
[0], "-z") == 0) || (stricmp (argv
[0], "--zero") == 0)) {
1500 OutImageType
= FW_ZERO_DEBUG_IMAGE
;
1506 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--stamp") == 0)) {
1507 OutImageType
= FW_SET_STAMP_IMAGE
;
1508 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1509 Error (NULL
, 0, 1003, "Invalid option value", "time stamp is missing for -s option");
1512 TimeStamp
= argv
[1];
1518 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--replace") == 0)) {
1525 if (stricmp (argv
[0], "--keepexceptiontable") == 0) {
1526 KeepExceptionTableFlag
= TRUE
;
1532 if (stricmp (argv
[0], "--keepzeropending") == 0) {
1533 KeepZeroPendingFlag
= TRUE
;
1539 if ((stricmp (argv
[0], "-m") == 0) || (stricmp (argv
[0], "--mcifile") == 0)) {
1540 OutImageType
= FW_MCI_IMAGE
;
1546 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--join") == 0)) {
1547 OutImageType
= FW_MERGE_IMAGE
;
1553 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
1554 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1555 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1558 MciAlignment
= (UINT32
) Temp64
;
1564 if ((stricmp (argv
[0], "-p") == 0) || (stricmp (argv
[0], "--pad") == 0)) {
1565 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1566 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1569 MciPadValue
= (UINT8
) Temp64
;
1575 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
1576 SetPrintLevel (VERBOSE_LOG_LEVEL
);
1577 VerboseMsg ("Verbose output Mode Set!");
1583 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1584 SetPrintLevel (KEY_LOG_LEVEL
);
1585 KeyMsg ("Quiet output Mode Set!");
1591 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
1592 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
1593 if (EFI_ERROR (Status
)) {
1594 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1598 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", LogLevel
);
1601 SetPrintLevel (LogLevel
);
1602 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
1608 if (argv
[0][0] == '-') {
1609 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
1613 // Get Input file name
1615 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
1616 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
1617 if (InputFileName
== NULL
) {
1618 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1619 return EFI_OUT_OF_RESOURCES
;
1622 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1623 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1625 // InputFileName buffer too small, need to realloc
1627 InputFileName
= (CHAR8
**) realloc (
1629 (InputFileNum
+ 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
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1640 InputFileName
[InputFileNum
++] = argv
[0];
1645 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1647 if (OutImageType
== FW_DUMMY_IMAGE
) {
1648 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!");
1650 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.");
1656 // check input files
1658 if (InputFileNum
== 0) {
1659 Error (NULL
, 0, 1001, "Missing option", "Input files");
1664 // Combine MciBinary files to one file
1666 if ((OutImageType
== FW_MERGE_IMAGE
) && ReplaceFlag
) {
1667 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");
1674 mInImageName
= InputFileName
[InputFileNum
- 1];
1675 VerboseMsg ("the input file name is %s", mInImageName
);
1678 // Action will be taken for the input file.
1680 switch (OutImageType
) {
1682 VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType
);
1685 VerboseMsg ("Create Te Image based on the input PE image.");
1688 VerboseMsg ("Get acpi table data from the input PE image.");
1690 case FW_RELOC_STRIPEED_IMAGE
:
1691 VerboseMsg ("Remove relocation section from Pe or Te image.");
1694 VerboseMsg ("Convert the input EXE to the output BIN file.");
1696 case FW_ZERO_DEBUG_IMAGE
:
1697 VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");
1699 case FW_SET_STAMP_IMAGE
:
1700 VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp
);
1702 case DUMP_TE_HEADER
:
1703 VerboseMsg ("Dump the TE header information of the input TE image.");
1706 VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");
1708 case FW_MERGE_IMAGE
:
1709 VerboseMsg ("Combine the input multi microcode bin files to one bin file.");
1716 VerboseMsg ("Overwrite the input file with the output content.");
1720 // Open output file and Write image into the output file.
1722 if (OutImageName
!= NULL
) {
1723 fpOut
= fopen (OutImageName
, "rb");
1724 if (fpOut
!= NULL
) {
1725 OutputFileLength
= _filelength (fileno (fpOut
));
1726 OutputFileBuffer
= malloc (OutputFileLength
);
1727 if (OutputFileBuffer
== NULL
) {
1728 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1733 fread (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
1736 fpOut
= fopen (OutImageName
, "wb");
1738 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1741 VerboseMsg ("Output file name is %s", OutImageName
);
1742 } else if (!ReplaceFlag
) {
1743 if (OutImageType
== DUMP_TE_HEADER
) {
1746 Error (NULL
, 0, 1001, "Missing option", "output file");
1752 // Combine MciBinary files to one file
1754 if (OutImageType
== FW_MERGE_IMAGE
) {
1755 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1756 fpIn
= fopen (InputFileName
[Index
], "rb");
1758 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1762 FileLength
= _filelength (fileno (fpIn
));
1763 FileBuffer
= malloc (FileLength
);
1764 if (FileBuffer
== NULL
) {
1765 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1770 fread (FileBuffer
, 1, FileLength
, fpIn
);
1773 // write input file to out file
1775 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
1777 // write pad value to out file.
1779 while (FileLength
++ % MciAlignment
!= 0) {
1780 fwrite (&MciPadValue
, 1, 1, fpOut
);
1783 // free allocated memory space
1789 // Done successfully
1795 // Convert MicroCode.txt file to MicroCode.bin file
1797 if (OutImageType
== FW_MCI_IMAGE
) {
1798 fpIn
= fopen (mInImageName
, "r");
1800 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1805 // The first pass is to determine
1806 // how much data is in the file so we can allocate a working buffer.
1810 Status
= MicrocodeReadData (fpIn
, &Data
);
1811 if (Status
== STATUS_SUCCESS
) {
1812 FileLength
+= sizeof (Data
);
1814 if (Status
== STATUS_IGNORE
) {
1815 Status
= STATUS_SUCCESS
;
1817 } while (Status
== STATUS_SUCCESS
);
1819 // Error if no data.
1821 if (FileLength
== 0) {
1822 Error (NULL
, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName
);
1825 if (FileLength
< sizeof (MICROCODE_IMAGE_HEADER
)) {
1826 Error (NULL
, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName
);
1831 // Allocate a buffer for the data
1833 FileBuffer
= malloc (FileLength
);
1834 if (FileBuffer
== NULL
) {
1835 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1839 // Re-read the file, storing the data into our buffer
1841 fseek (fpIn
, 0, SEEK_SET
);
1842 DataPointer
= (UINT32
*) FileBuffer
;
1843 OldDataPointer
= DataPointer
;
1845 OldDataPointer
= DataPointer
;
1846 Status
= MicrocodeReadData (fpIn
, DataPointer
++);
1847 if (Status
== STATUS_IGNORE
) {
1848 DataPointer
= OldDataPointer
;
1849 Status
= STATUS_SUCCESS
;
1851 } while (Status
== STATUS_SUCCESS
);
1853 // close input file after read data
1858 // Can't do much checking on the header because, per the spec, the
1859 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
1860 // and the TotalSize field is invalid (actually missing). Thus we can't
1861 // even verify the Reserved fields are 0.
1863 MciHeader
= (MICROCODE_IMAGE_HEADER
*) FileBuffer
;
1864 if (MciHeader
->DataSize
== 0) {
1867 Index
= MciHeader
->TotalSize
;
1870 if (Index
!= FileLength
) {
1871 Error (NULL
, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName
, FileLength
, Index
);
1876 // Checksum the contents
1878 DataPointer
= (UINT32
*) FileBuffer
;
1881 while (Index
< FileLength
) {
1882 CheckSum
+= *DataPointer
;
1884 Index
+= sizeof (*DataPointer
);
1886 if (CheckSum
!= 0) {
1887 Error (NULL
, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", CheckSum
, mInImageName
);
1891 // Open the output file and write the buffer contents
1893 if (fpOut
!= NULL
) {
1894 if (fwrite (FileBuffer
, FileLength
, 1, fpOut
) != 1) {
1895 Error (NULL
, 0, 0002, "Error writing file", OutImageName
);
1901 fpInOut
= fopen (mInImageName
, "wb");
1902 if (fpInOut
!= NULL
) {
1903 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1906 if (fwrite (FileBuffer
, FileLength
, 1, fpInOut
) != 1) {
1907 Error (NULL
, 0, 0002, "Error writing file", mInImageName
);
1911 VerboseMsg ("the size of output file is %d bytes", FileLength
);
1913 // Convert Mci.TXT to Mci.bin file successfully
1919 // Open input file and read file data into file buffer.
1921 fpIn
= fopen (mInImageName
, "rb");
1923 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1927 FileLength
= _filelength (fileno (fpIn
));
1928 FileBuffer
= malloc (FileLength
);
1929 if (FileBuffer
== NULL
) {
1930 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1935 fread (FileBuffer
, 1, FileLength
, fpIn
);
1938 DebugMsg (NULL
, 0, 9, "input file info", "the input file size is %d bytes", FileLength
);
1944 fpInOut
= fopen (mInImageName
, "wb");
1946 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1951 // Dump TeImage Header into output file.
1953 if (OutImageType
== DUMP_TE_HEADER
) {
1954 memcpy (&TEImageHeader
, FileBuffer
, sizeof (TEImageHeader
));
1955 if (TEImageHeader
.Signature
!= EFI_TE_IMAGE_HEADER_SIGNATURE
) {
1956 Error (NULL
, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName
);
1959 if (fpInOut
!= NULL
) {
1960 fprintf (fpInOut
, "Dump of file %s\n\n", mInImageName
);
1961 fprintf (fpInOut
, "TE IMAGE HEADER VALUES\n");
1962 fprintf (fpInOut
, "%17X machine\n", TEImageHeader
.Machine
);
1963 fprintf (fpInOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
1964 fprintf (fpInOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
1965 fprintf (fpInOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
1966 fprintf (fpInOut
, "%17X entry point\n", TEImageHeader
.AddressOfEntryPoint
);
1967 fprintf (fpInOut
, "%17X base of code\n", TEImageHeader
.BaseOfCode
);
1968 fprintf (fpInOut
, "%17lX image base\n", (long unsigned int)TEImageHeader
.ImageBase
);
1969 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader
.DataDirectory
[0].VirtualAddress
, TEImageHeader
.DataDirectory
[0].Size
);
1970 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader
.DataDirectory
[1].VirtualAddress
, TEImageHeader
.DataDirectory
[1].Size
);
1973 if (fpOut
!= NULL
) {
1974 fprintf (fpOut
, "Dump of file %s\n\n", mInImageName
);
1975 fprintf (fpOut
, "TE IMAGE HEADER VALUES\n");
1976 fprintf (fpOut
, "%17X machine\n", TEImageHeader
.Machine
);
1977 fprintf (fpOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
1978 fprintf (fpOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
1979 fprintf (fpOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
1980 fprintf (fpOut
, "%17X entry point\n", TEImageHeader
.AddressOfEntryPoint
);
1981 fprintf (fpOut
, "%17X base of code\n", TEImageHeader
.BaseOfCode
);
1982 fprintf (fpOut
, "%17lX image base\n", (long unsigned int)TEImageHeader
.ImageBase
);
1983 fprintf (fpOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader
.DataDirectory
[0].VirtualAddress
, TEImageHeader
.DataDirectory
[0].Size
);
1984 fprintf (fpOut
, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader
.DataDirectory
[1].VirtualAddress
, TEImageHeader
.DataDirectory
[1].Size
);
1990 // Following code to convert dll to efi image or te image.
1991 // Get new image type
1993 if ((OutImageType
== FW_EFI_IMAGE
) || (OutImageType
== FW_TE_IMAGE
)) {
1994 if (ModuleType
== NULL
) {
1995 if (OutImageType
== FW_EFI_IMAGE
) {
1996 Error (NULL
, 0, 1001, "Missing option", "EFI_FILETYPE");
1998 } else if (OutImageType
== FW_TE_IMAGE
) {
2000 // Default TE Image Type is Boot service driver
2002 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2003 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2006 if (stricmp (ModuleType
, "BASE") == 0 ||
2007 stricmp (ModuleType
, "SEC") == 0 ||
2008 stricmp (ModuleType
, "SECURITY_CORE") == 0 ||
2009 stricmp (ModuleType
, "PEI_CORE") == 0 ||
2010 stricmp (ModuleType
, "PEIM") == 0 ||
2011 stricmp (ModuleType
, "COMBINED_PEIM_DRIVER") == 0 ||
2012 stricmp (ModuleType
, "PIC_PEIM") == 0 ||
2013 stricmp (ModuleType
, "RELOCATABLE_PEIM") == 0 ||
2014 stricmp (ModuleType
, "DXE_CORE") == 0 ||
2015 stricmp (ModuleType
, "BS_DRIVER") == 0 ||
2016 stricmp (ModuleType
, "DXE_DRIVER") == 0 ||
2017 stricmp (ModuleType
, "DXE_SMM_DRIVER") == 0 ||
2018 stricmp (ModuleType
, "UEFI_DRIVER") == 0 ||
2019 stricmp (ModuleType
, "SMM_DRIVER") == 0 ||
2020 stricmp (ModuleType
, "SMM_CORE") == 0) {
2021 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2022 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2024 } else if (stricmp (ModuleType
, "UEFI_APPLICATION") == 0 ||
2025 stricmp (ModuleType
, "APPLICATION") == 0) {
2026 Type
= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
;
2027 VerboseMsg ("Efi Image subsystem type is efi application.");
2029 } else if (stricmp (ModuleType
, "DXE_RUNTIME_DRIVER") == 0 ||
2030 stricmp (ModuleType
, "RT_DRIVER") == 0) {
2031 Type
= EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
;
2032 VerboseMsg ("Efi Image subsystem type is efi runtime driver.");
2034 } else if (stricmp (ModuleType
, "DXE_SAL_DRIVER") == 0 ||
2035 stricmp (ModuleType
, "SAL_RT_DRIVER") == 0) {
2036 Type
= EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
;
2037 VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");
2040 Error (NULL
, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType
);
2047 // Convert EFL image to PeImage
2049 if (IsElfHeader(FileBuffer
)) {
2050 VerboseMsg ("Convert the input ELF Image to Pe Image");
2051 ConvertElf(&FileBuffer
, &FileLength
);
2055 // Remove reloc section from PE or TE image
2057 if (OutImageType
== FW_RELOC_STRIPEED_IMAGE
) {
2061 TeHdr
= (EFI_TE_IMAGE_HEADER
*) FileBuffer
;
2062 if (TeHdr
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2063 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (TeHdr
+ 1);
2064 for (Index
= 0; Index
< TeHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2065 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2067 // Check the reloc section is in the end of image.
2069 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) ==
2070 (FileLength
+ TeHdr
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
))) {
2072 // Remove .reloc section and update TeImage Header
2074 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2075 SectionHeader
->SizeOfRawData
= 0;
2076 SectionHeader
->Misc
.VirtualSize
= 0;
2077 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2078 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2087 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2088 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2089 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2090 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2091 Error (NULL
, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName
);
2096 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2097 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2098 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2102 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2103 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2104 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2106 // Check the reloc section is in the end of image.
2108 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) == FileLength
) {
2110 // Remove .reloc section and update PeImage Header
2112 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2114 PeHdr
->Pe32
.FileHeader
.Characteristics
|= EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2115 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2116 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2117 Optional32
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2118 Optional32
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2119 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2120 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2121 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2124 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2125 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2126 Optional64
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2127 Optional64
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2128 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2129 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2130 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2133 SectionHeader
->Misc
.VirtualSize
= 0;
2134 SectionHeader
->SizeOfRawData
= 0;
2146 // Read the dos & pe hdrs of the image
2148 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2149 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2150 // NO DOS header, check for PE/COFF header
2151 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2152 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2153 Error (NULL
, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName
);
2159 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2160 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2161 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2166 if (PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_ARM
) {
2167 // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
2168 // so patch back to the offical UEFI value.
2169 PeHdr
->Pe32
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_ARMT
;
2173 // Extract bin data from Pe image.
2175 if (OutImageType
== FW_BIN_IMAGE
) {
2176 if (FileLength
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
2177 Error (NULL
, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName
);
2181 // Output bin data from exe file
2183 if (fpOut
!= NULL
) {
2184 fwrite (FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, 1, FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, fpOut
);
2186 if (fpInOut
!= NULL
) {
2187 fwrite (FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, 1, FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, fpInOut
);
2189 VerboseMsg ("the size of output file is %d bytes", FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
);
2194 // Zero Debug Information of Pe Image
2196 if (OutImageType
== FW_ZERO_DEBUG_IMAGE
) {
2197 Status
= ZeroDebugData (FileBuffer
, TRUE
);
2198 if (EFI_ERROR (Status
)) {
2199 Error (NULL
, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%lx", (UINTN
) Status
);
2203 if (fpOut
!= NULL
) {
2204 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2206 if (fpInOut
!= NULL
) {
2207 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2209 VerboseMsg ("the size of output file is %d bytes", FileLength
);
2214 // Set Time Stamp of Pe Image
2216 if (OutImageType
== FW_SET_STAMP_IMAGE
) {
2217 Status
= SetStamp (FileBuffer
, TimeStamp
);
2218 if (EFI_ERROR (Status
)) {
2222 if (fpOut
!= NULL
) {
2223 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2225 if (fpInOut
!= NULL
) {
2226 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2228 VerboseMsg ("the size of output file is %d bytes", FileLength
);
2233 // Extract acpi data from pe image.
2235 if (OutImageType
== FW_ACPI_IMAGE
) {
2236 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2237 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2238 if (strcmp ((char *)SectionHeader
->Name
, ".data") == 0 || strcmp ((char *)SectionHeader
->Name
, ".sdata") == 0) {
2242 if (SectionHeader
->Misc
.VirtualSize
< SectionHeader
->SizeOfRawData
) {
2243 FileLength
= SectionHeader
->Misc
.VirtualSize
;
2245 FileLength
= SectionHeader
->SizeOfRawData
;
2248 if (CheckAcpiTable (FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
) != STATUS_SUCCESS
) {
2249 Error (NULL
, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName
);
2254 // Output Apci data to file
2256 if (fpOut
!= NULL
) {
2257 fwrite (FileBuffer
+ SectionHeader
->PointerToRawData
, 1, FileLength
, fpOut
);
2259 if (fpInOut
!= NULL
) {
2260 fwrite (FileBuffer
+ SectionHeader
->PointerToRawData
, 1, FileLength
, fpInOut
);
2262 VerboseMsg ("the size of output file is %d bytes", FileLength
);
2266 Error (NULL
, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName
);
2270 // Zero all unused fields of the DOS header
2272 if (DosHdr
!= NULL
) {
2273 memcpy (&BackupDosHdr
, DosHdr
, sizeof (EFI_IMAGE_DOS_HEADER
));
2274 memset (DosHdr
, 0, sizeof (EFI_IMAGE_DOS_HEADER
));
2275 DosHdr
->e_magic
= BackupDosHdr
.e_magic
;
2276 DosHdr
->e_lfanew
= BackupDosHdr
.e_lfanew
;
2278 for (Index
= sizeof (EFI_IMAGE_DOS_HEADER
); Index
< (UINT32
) DosHdr
->e_lfanew
; Index
++) {
2279 FileBuffer
[Index
] = DosHdr
->e_cp
;
2284 // Initialize TeImage Header
2286 memset (&TEImageHeader
, 0, sizeof (EFI_TE_IMAGE_HEADER
));
2287 TEImageHeader
.Signature
= EFI_TE_IMAGE_HEADER_SIGNATURE
;
2288 TEImageHeader
.Machine
= PeHdr
->Pe32
.FileHeader
.Machine
;
2289 TEImageHeader
.NumberOfSections
= (UINT8
) PeHdr
->Pe32
.FileHeader
.NumberOfSections
;
2290 TEImageHeader
.StrippedSize
= (UINT16
) ((UINTN
) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
) - (UINTN
) FileBuffer
);
2291 TEImageHeader
.Subsystem
= (UINT8
) Type
;
2294 // Patch the PE header
2296 PeHdr
->Pe32
.OptionalHeader
.Subsystem
= (UINT16
) Type
;
2298 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2299 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2300 Optional32
->MajorLinkerVersion
= 0;
2301 Optional32
->MinorLinkerVersion
= 0;
2302 Optional32
->MajorOperatingSystemVersion
= 0;
2303 Optional32
->MinorOperatingSystemVersion
= 0;
2304 Optional32
->MajorImageVersion
= 0;
2305 Optional32
->MinorImageVersion
= 0;
2306 Optional32
->MajorSubsystemVersion
= 0;
2307 Optional32
->MinorSubsystemVersion
= 0;
2308 Optional32
->Win32VersionValue
= 0;
2309 Optional32
->CheckSum
= 0;
2310 Optional32
->SizeOfStackReserve
= 0;
2311 Optional32
->SizeOfStackCommit
= 0;
2312 Optional32
->SizeOfHeapReserve
= 0;
2313 Optional32
->SizeOfHeapCommit
= 0;
2315 TEImageHeader
.AddressOfEntryPoint
= Optional32
->AddressOfEntryPoint
;
2316 TEImageHeader
.BaseOfCode
= Optional32
->BaseOfCode
;
2317 TEImageHeader
.ImageBase
= (UINT64
) (Optional32
->ImageBase
);
2319 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2320 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2321 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2324 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2325 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2326 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2330 // Zero .pdata section data.
2332 if (!KeepExceptionTableFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2333 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2334 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2335 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2336 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2337 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2339 // Zero .pdata Section data
2341 memset (FileBuffer
+ SectionHeader
->PointerToRawData
, 0, SectionHeader
->SizeOfRawData
);
2343 // Zero .pdata Section header name
2345 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2347 // Zero Execption Table
2349 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2350 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2351 DebugMsg (NULL
, 0, 9, "Zero the .pdata section for PE image", NULL
);
2358 // Strip zero padding at the end of the .reloc section
2360 if (!KeepZeroPendingFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2361 if (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2362 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2363 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2365 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2367 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2368 SectionHeader
->Misc
.VirtualSize
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2369 AllignedRelocSize
= (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional32
->FileAlignment
- 1) & (~(Optional32
->FileAlignment
- 1));
2371 // Check to see if there is zero padding at the end of the base relocations
2373 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2375 // Check to see if the base relocations are at the end of the file
2377 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional32
->SizeOfImage
) {
2379 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2381 Optional32
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2382 Optional32
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2383 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2384 FileLength
= Optional32
->SizeOfImage
;
2385 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
);
2392 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2393 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2394 Optional64
->MajorLinkerVersion
= 0;
2395 Optional64
->MinorLinkerVersion
= 0;
2396 Optional64
->MajorOperatingSystemVersion
= 0;
2397 Optional64
->MinorOperatingSystemVersion
= 0;
2398 Optional64
->MajorImageVersion
= 0;
2399 Optional64
->MinorImageVersion
= 0;
2400 Optional64
->MajorSubsystemVersion
= 0;
2401 Optional64
->MinorSubsystemVersion
= 0;
2402 Optional64
->Win32VersionValue
= 0;
2403 Optional64
->CheckSum
= 0;
2404 Optional64
->SizeOfStackReserve
= 0;
2405 Optional64
->SizeOfStackCommit
= 0;
2406 Optional64
->SizeOfHeapReserve
= 0;
2407 Optional64
->SizeOfHeapCommit
= 0;
2409 TEImageHeader
.AddressOfEntryPoint
= Optional64
->AddressOfEntryPoint
;
2410 TEImageHeader
.BaseOfCode
= Optional64
->BaseOfCode
;
2411 TEImageHeader
.ImageBase
= (UINT64
) (Optional64
->ImageBase
);
2413 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2414 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2415 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2418 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2419 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2420 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2424 // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
2425 // For Itaninum and X64 Image, remove .pdata section.
2427 if ((!KeepExceptionTableFlag
&& PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_X64
) || PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
) {
2428 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2429 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2430 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2431 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2432 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2433 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2435 // Zero .pdata Section header name
2437 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2439 RuntimeFunction
= (RUNTIME_FUNCTION
*)(FileBuffer
+ SectionHeader
->PointerToRawData
);
2440 for (Index1
= 0; Index1
< Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
/ sizeof (RUNTIME_FUNCTION
); Index1
++, RuntimeFunction
++) {
2441 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2442 for (Index2
= 0; Index2
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index2
++, SectionHeader
++) {
2443 if (RuntimeFunction
->UnwindInfoAddress
> SectionHeader
->VirtualAddress
&& RuntimeFunction
->UnwindInfoAddress
< (SectionHeader
->VirtualAddress
+ SectionHeader
->SizeOfRawData
)) {
2444 UnwindInfo
= (UNWIND_INFO
*)(FileBuffer
+ SectionHeader
->PointerToRawData
+ (RuntimeFunction
->UnwindInfoAddress
- SectionHeader
->VirtualAddress
));
2445 if (UnwindInfo
->Version
== 1) {
2446 memset (UnwindInfo
+ 1, 0, UnwindInfo
->CountOfUnwindCodes
* sizeof (UINT16
));
2447 memset (UnwindInfo
, 0, sizeof (UNWIND_INFO
));
2451 memset (RuntimeFunction
, 0, sizeof (RUNTIME_FUNCTION
));
2454 // Zero Execption Table
2456 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2457 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2458 DebugMsg (NULL
, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL
);
2466 // Strip zero padding at the end of the .reloc section
2468 if (!KeepZeroPendingFlag
&& Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2469 if (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2470 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2471 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2473 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2475 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2476 SectionHeader
->Misc
.VirtualSize
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2477 AllignedRelocSize
= (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional64
->FileAlignment
- 1) & (~(Optional64
->FileAlignment
- 1));
2479 // Check to see if there is zero padding at the end of the base relocations
2481 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2483 // Check to see if the base relocations are at the end of the file
2485 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional64
->SizeOfImage
) {
2487 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2489 Optional64
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2490 Optional64
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2491 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2492 FileLength
= Optional64
->SizeOfImage
;
2493 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
);
2501 Error (NULL
, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr
->Pe32
.OptionalHeader
.Magic
, mInImageName
);
2505 if (((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) == 0) && \
2506 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
== 0) && \
2507 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
== 0)) {
2509 // PeImage can be loaded into memory, but it has no relocation section.
2510 // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
2512 if (Optional32
!= NULL
) {
2513 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
2514 } else if (Optional64
!= NULL
) {
2515 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
2520 // Zero ExceptionTable Xdata
2522 if (!KeepExceptionTableFlag
) {
2523 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2524 ZeroXdataSection(mInImageName
, FileBuffer
, SectionHeader
, PeHdr
->Pe32
.FileHeader
.NumberOfSections
);
2528 // Zero Time/Data field
2530 ZeroDebugData (FileBuffer
, FALSE
);
2532 if (OutImageType
== FW_TE_IMAGE
) {
2533 if ((PeHdr
->Pe32
.FileHeader
.NumberOfSections
&~0xFF) || (Type
&~0xFF)) {
2535 // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
2537 Error (NULL
, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName
);
2541 if ((PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
)) {
2543 // TeImage has the same section alignment and file alignment.
2545 Error (NULL
, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName
);
2549 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",
2550 TEImageHeader
.Machine
, TEImageHeader
.NumberOfSections
, TEImageHeader
.StrippedSize
, TEImageHeader
.AddressOfEntryPoint
, TEImageHeader
.BaseOfCode
, TEImageHeader
.ImageBase
);
2552 // Update Image to TeImage
2554 if (fpOut
!= NULL
) {
2555 fwrite (&TEImageHeader
, 1, sizeof (EFI_TE_IMAGE_HEADER
), fpOut
);
2556 fwrite (FileBuffer
+ TEImageHeader
.StrippedSize
, 1, FileLength
- TEImageHeader
.StrippedSize
, fpOut
);
2558 if (fpInOut
!= NULL
) {
2559 fwrite (&TEImageHeader
, 1, sizeof (EFI_TE_IMAGE_HEADER
), fpInOut
);
2560 fwrite (FileBuffer
+ TEImageHeader
.StrippedSize
, 1, FileLength
- TEImageHeader
.StrippedSize
, fpInOut
);
2562 VerboseMsg ("the size of output file is %d bytes", FileLength
- TEImageHeader
.StrippedSize
);
2567 // Update Image to EfiImage
2569 if (fpOut
!= NULL
) {
2570 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2572 if (fpInOut
!= NULL
) {
2573 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2575 VerboseMsg ("the size of output file is %d bytes", FileLength
);
2578 if (fpInOut
!= NULL
) {
2579 if (GetUtilityStatus () != STATUS_SUCCESS
) {
2581 // when file updates failed, original file is still recoveried.
2583 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2586 // Write converted data into fpInOut file and close input file.
2591 if (FileBuffer
!= NULL
) {
2595 if (InputFileName
!= NULL
) {
2596 free (InputFileName
);
2599 if (fpOut
!= NULL
) {
2601 // Write converted data into fpOut file and close output file.
2604 if (GetUtilityStatus () != STATUS_SUCCESS
) {
2605 if (OutputFileBuffer
== NULL
) {
2606 remove (OutImageName
);
2608 fpOut
= fopen (OutImageName
, "wb");
2609 fwrite (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
2611 free (OutputFileBuffer
);
2616 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
2618 return GetUtilityStatus ();
2624 IN OUT UINT8
*FileBuffer
,
2625 BOOLEAN ZeroDebugFlag
2629 Routine Description:
2631 Zero debug information in PeImage.
2635 FileBuffer - Pointer to PeImage.
2636 ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp
2640 EFI_ABORTED - PeImage is invalid.
2641 EFI_SUCCESS - Zero debug data successfully.
2646 UINT32 DebugDirectoryEntryRva
;
2647 UINT32 DebugDirectoryEntryFileOffset
;
2648 UINT32 ExportDirectoryEntryRva
;
2649 UINT32 ExportDirectoryEntryFileOffset
;
2650 UINT32 ResourceDirectoryEntryRva
;
2651 UINT32 ResourceDirectoryEntryFileOffset
;
2652 EFI_IMAGE_DOS_HEADER
*DosHdr
;
2653 EFI_IMAGE_FILE_HEADER
*FileHdr
;
2654 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
2655 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
2656 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
2657 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
2658 UINT32
*NewTimeStamp
;
2663 DebugDirectoryEntryRva
= 0;
2664 ExportDirectoryEntryRva
= 0;
2665 ResourceDirectoryEntryRva
= 0;
2666 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2667 FileHdr
= (EFI_IMAGE_FILE_HEADER
*) (FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2670 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2671 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2672 // NO DOS header, must start with PE/COFF header
2673 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
2675 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2679 // Get Debug, Export and Resource EntryTable RVA address.
2680 // Resource Directory entry need to review.
2682 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
2683 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2684 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2685 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2686 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2687 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2689 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2690 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2691 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2693 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2694 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2695 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2696 if (ZeroDebugFlag
) {
2697 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
2698 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
2702 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2703 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2704 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2705 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2706 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2708 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2709 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2710 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2712 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2713 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2714 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2715 if (ZeroDebugFlag
) {
2716 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
2717 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
2723 // Get DirectoryEntryTable file offset.
2725 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2726 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2727 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2728 DebugDirectoryEntryFileOffset
=
2729 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2731 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2732 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2733 ExportDirectoryEntryFileOffset
=
2734 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2736 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2737 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2738 ResourceDirectoryEntryFileOffset
=
2739 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2744 //Zero Debug Data and TimeStamp
2746 FileHdr
->TimeDateStamp
= 0;
2748 if (ExportDirectoryEntryRva
!= 0) {
2749 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
2753 if (ResourceDirectoryEntryRva
!= 0) {
2754 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
2758 if (DebugDirectoryEntryRva
!= 0) {
2759 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
);
2760 DebugEntry
->TimeDateStamp
= 0;
2761 if (ZeroDebugFlag
) {
2762 memset (FileBuffer
+ DebugEntry
->FileOffset
, 0, DebugEntry
->SizeOfData
);
2763 memset (DebugEntry
, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
2773 IN OUT UINT8
*FileBuffer
,
2778 Routine Description:
2780 Set new time stamp into PeImage FileHdr and Directory table:
2781 Debug, Export and Resource.
2785 FileBuffer - Pointer to PeImage.
2786 TimeStamp - Time stamp string.
2790 EFI_INVALID_PARAMETER - TimeStamp format is not recognized.
2791 EFI_SUCCESS - Set new time stamp in this image successfully.
2799 UINT32 DebugDirectoryEntryRva
;
2800 UINT32 DebugDirectoryEntryFileOffset
;
2801 UINT32 ExportDirectoryEntryRva
;
2802 UINT32 ExportDirectoryEntryFileOffset
;
2803 UINT32 ResourceDirectoryEntryRva
;
2804 UINT32 ResourceDirectoryEntryFileOffset
;
2805 EFI_IMAGE_DOS_HEADER
*DosHdr
;
2806 EFI_IMAGE_FILE_HEADER
*FileHdr
;
2807 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
2808 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
2809 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
2810 UINT32
*NewTimeStamp
;
2815 DebugDirectoryEntryRva
= 0;
2816 ExportDirectoryEntryRva
= 0;
2817 ResourceDirectoryEntryRva
= 0;
2819 // Get time and date that will be set.
2821 if (TimeStamp
== NULL
) {
2822 Error (NULL
, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");
2823 return EFI_INVALID_PARAMETER
;
2826 // compare the value with "NOW", if yes, current system time is set.
2828 if (stricmp (TimeStamp
, "NOW") == 0) {
2830 // get system current time and date
2835 // Check Time Format strictly yyyy-mm-dd 00:00:00
2837 for (Index
= 0; TimeStamp
[Index
] != '\0' && Index
< 20; Index
++) {
2838 if (Index
== 4 || Index
== 7) {
2839 if (TimeStamp
[Index
] == '-') {
2842 } else if (Index
== 13 || Index
== 16) {
2843 if (TimeStamp
[Index
] == ':') {
2846 } else if (Index
== 10 && TimeStamp
[Index
] == ' ') {
2848 } else if ((TimeStamp
[Index
] < '0') || (TimeStamp
[Index
] > '9')) {
2853 if (Index
< 19 || TimeStamp
[19] != '\0') {
2854 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
2855 return EFI_INVALID_PARAMETER
;
2859 // get the date and time from TimeStamp
2861 if (sscanf (TimeStamp
, "%d-%d-%d %d:%d:%d",
2869 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
2870 return EFI_INVALID_PARAMETER
;
2874 // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
2876 if (stime
.tm_mon
<= 0 || stime
.tm_mday
<=0) {
2877 Error (NULL
, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp
);
2878 return EFI_INVALID_PARAMETER
;
2883 // in struct, Year (current year minus 1900)
2884 // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
2887 // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
2889 if (stime
.tm_year
>= 1970 && stime
.tm_year
<= 2038) {
2891 // convert 1970 -> 70, 2000 -> 100, ...
2893 stime
.tm_year
-= 1900;
2895 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
2896 return EFI_INVALID_PARAMETER
;
2900 // convert the date and time to time_t format
2902 newtime
= mktime (&stime
);
2903 if (newtime
== (time_t) - 1) {
2904 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
2905 return EFI_INVALID_PARAMETER
;
2909 ptime
= localtime (&newtime
);
2910 DebugMsg (NULL
, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",
2911 ptime
->tm_year
+ 1900, ptime
->tm_mon
+ 1, ptime
->tm_mday
, ptime
->tm_hour
, ptime
->tm_min
, ptime
->tm_sec
);
2913 // Set new time and data into PeImage.
2915 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2916 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2917 // NO DOS header, must start with PE/COFF header
2918 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
2920 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2924 // Get Debug, Export and Resource EntryTable RVA address.
2925 // Resource Directory entry need to review.
2927 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
2928 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2929 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2930 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2931 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2932 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2934 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2935 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2936 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2938 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2939 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2940 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2943 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2944 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2945 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2946 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2947 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2949 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2950 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2951 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2953 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2954 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2955 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2960 // Get DirectoryEntryTable file offset.
2962 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2963 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2964 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2965 DebugDirectoryEntryFileOffset
=
2966 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2968 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2969 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2970 ExportDirectoryEntryFileOffset
=
2971 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2973 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2974 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2975 ResourceDirectoryEntryFileOffset
=
2976 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2983 FileHdr
->TimeDateStamp
= (UINT32
) newtime
;
2985 if (ExportDirectoryEntryRva
!= 0) {
2986 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
2987 *NewTimeStamp
= (UINT32
) newtime
;
2990 if (ResourceDirectoryEntryRva
!= 0) {
2991 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
2992 *NewTimeStamp
= (UINT32
) newtime
;
2995 if (DebugDirectoryEntryRva
!= 0) {
2996 NewTimeStamp
= (UINT32
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
+ sizeof (UINT32
));
2997 *NewTimeStamp
= (UINT32
) newtime
;
3011 Routine Description:
3012 Read a 32-bit microcode data value from a text file and convert to raw binary form.
3015 InFptr - file pointer to input text file
3016 Data - pointer to where to return the data parsed
3019 STATUS_SUCCESS - no errors or warnings, Data contains valid information
3020 STATUS_ERROR - errors were encountered
3024 CHAR8 Line
[MAX_LINE_LEN
];
3027 Line
[MAX_LINE_LEN
- 1] = 0;
3029 if (fgets (Line
, MAX_LINE_LEN
, InFptr
) == NULL
) {
3030 return STATUS_ERROR
;
3033 // If it was a binary file, then it may have overwritten our null terminator
3035 if (Line
[MAX_LINE_LEN
- 1] != 0) {
3036 return STATUS_ERROR
;
3042 for (cptr
= Line
; *cptr
&& isspace(*cptr
); cptr
++) {
3045 // Skip Blank Lines and Comment Lines
3046 if ((strlen(cptr
) != 0) && (*cptr
!= ';')) {
3052 // dd 000000001h ; comment
3057 if ((tolower(cptr
[0]) == 'd') && (tolower(cptr
[1]) == 'd') && isspace (cptr
[2])) {
3059 // Skip blanks and look for a hex digit
3062 for (; *cptr
&& isspace(*cptr
); cptr
++) {
3064 if (isxdigit (*cptr
)) {
3065 if (sscanf (cptr
, "%X", Data
) != 1) {
3066 return STATUS_ERROR
;
3069 return STATUS_SUCCESS
;
3072 return STATUS_ERROR
;