3 Copyright (c) 2004 - 2009, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Converts a pe32+ image to an FW, Te image type, or other specific image.
22 #include "WinNtInclude.h"
34 #include <Common/UefiBaseTypes.h>
35 #include <IndustryStandard/PeImage.h>
36 #include <Common/UefiInternalFormRepresentation.h>
39 // Acpi Table definition
41 #include <IndustryStandard/Acpi.h>
42 #include <IndustryStandard/Acpi1_0.h>
43 #include <IndustryStandard/Acpi2_0.h>
44 #include <IndustryStandard/Acpi3_0.h>
45 #include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
47 #include "CommonLib.h"
48 #include "PeCoffLib.h"
50 #include "EfiUtilityMsgs.h"
52 #include "elf_common.h"
58 // Version of this utility
60 #define UTILITY_NAME "GenFw"
61 #define UTILITY_MAJOR_VERSION 0
62 #define UTILITY_MINOR_VERSION 2
64 #define HII_RESOURCE_SECTION_INDEX 1
65 #define HII_RESOURCE_SECTION_NAME "HII"
67 // Action for this tool.
69 #define FW_DUMMY_IMAGE 0
70 #define FW_EFI_IMAGE 1
72 #define FW_ACPI_IMAGE 3
73 #define FW_BIN_IMAGE 4
74 #define FW_ZERO_DEBUG_IMAGE 5
75 #define FW_SET_STAMP_IMAGE 6
76 #define FW_MCI_IMAGE 7
77 #define FW_MERGE_IMAGE 8
78 #define FW_RELOC_STRIPEED_IMAGE 9
79 #define FW_HII_PACKAGE_LIST_RCIMAGE 10
81 #define DUMP_TE_HEADER 0x11
83 #define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
84 #define DEFAULT_MC_ALIGNMENT 16
90 #define STATUS_IGNORE 0xA
92 // Structure definition for a microcode header
100 UINT32 LoaderVersion
;
102 UINT32 DataSize
; // if 0, then TotalSize = 2048, and TotalSize field is invalid
103 UINT32 TotalSize
; // number of bytes
105 } MICROCODE_IMAGE_HEADER
;
107 static EFI_GUID mZeroGuid
= {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
109 static const char *gHiiPackageRCFileHeader
[] = {
111 "// DO NOT EDIT -- auto-generated file",
116 STATIC CHAR8
*mInImageName
;
121 IN OUT UINT8
*FileBuffer
,
128 IN OUT UINT8
*FileBuffer
,
148 Print out version information for this utility.
160 fprintf (stdout
, "%s Version %d.%d\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
);
187 fprintf (stdout
, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME
);
190 // Copyright declaration
192 fprintf (stdout
, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");
197 fprintf (stdout
, "Options:\n");
198 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
199 File will be created to store the ouput content.\n");
200 fprintf (stdout
, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\
201 Create Efi Image. EFI_FILETYPE is one of BASE, SEC,\n\
202 PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\
203 DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER, \n\
204 DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER, \n\
205 PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\
206 APPLICATION, SAL_RT_DRIVER to support all module types\n\
207 It can only be used together with --keepexceptiontable,\n\
208 --keepzeropending, -r, -o option.It is a action option.\n\
209 If it is combined with other action options, the later\n\
210 input action option will override the previous one.\n");
211 fprintf (stdout
, " -c, --acpi Create Acpi table.\n\
212 It can't be combined with other action options\n\
213 except for -o, -r option. It is a action option.\n\
214 If it is combined with other action options, the later\n\
215 input action option will override the previous one.\n");
216 fprintf (stdout
, " -t, --terse Create Te Image.\n\
217 It can only be used together with --keepexceptiontable,\n\
218 --keepzeropending, -r, -o option.It is a action option.\n\
219 If it is combined with other action options, the later\n\
220 input action option will override the previous one.\n");
221 fprintf (stdout
, " -u, --dump Dump TeImage Header.\n\
222 It can't be combined with other action options\n\
223 except for -o, -r option. It is a action option.\n\
224 If it is combined with other action options, the later\n\
225 input action option will override the previous one.\n");
226 fprintf (stdout
, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\
227 It also zeros the time stamp fields.\n\
228 This option can be used to compare the binary efi image.\n\
229 It can't be combined with other action options\n\
230 except for -o, -r option. It is a action option.\n\
231 If it is combined with other action options, the later\n\
232 input action option will override the previous one.\n");
233 fprintf (stdout
, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\
234 It can't be combined with other action options\n\
235 except for -o, -r option. It is a action option.\n\
236 If it is combined with other action options, the later\n\
237 input action option will override the previous one.\n");;
238 fprintf (stdout
, " -l, --stripped Relocation info stripped from the input PE or TE image.\n\
239 It can't be combined with other action options\n\
240 except for -o, -r option. It is a action option.\n\
241 If it is combined with other action options, the later\n\
242 input action option will override the previous one.\n");
243 fprintf (stdout
, " -s timedate, --stamp timedate\n\
244 timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\
245 is set to NOW, current system time is used. The support\n\
246 date scope is 1970-1-1 8:0:0 ~ 2038-1-19 3:14:07\n\
247 It can't be combined with other action options\n\
248 except for -o, -r option. It is a action option.\n\
249 If it is combined with other action options, the later\n\
250 input action option will override the previous one.\n");
251 fprintf (stdout
, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\
252 It can't be combined with other action options\n\
253 except for -o option. It is a action option.\n\
254 If it is combined with other action options, the later\n\
255 input action option will override the previous one.\n");
256 fprintf (stdout
, " -j, --join Combine multi microcode bin files to one file.\n\
257 It can be specified with -a, -p, -o option.\n\
258 No other options can be combined with it.\n\
259 If it is combined with other action options, the later\n\
260 input action option will override the previous one.\n");
261 fprintf (stdout
, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\
262 This option is only used together with -j option.\n");
263 fprintf (stdout
, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\
264 This option is only used together with -j option.\n");
265 fprintf (stdout
, " --keepexceptiontable Don't clear exception table.\n\
266 This option can be used together with -e or -t.\n\
267 It doesn't work for other options.\n");
268 fprintf (stdout
, " --keepzeropending Don't strip zero pending of .reloc.\n\
269 This option can be used together with -e or -t.\n\
270 It doesn't work for other options.\n");
271 fprintf (stdout
, " -r, --replace Overwrite the input file with the output content.\n\
272 If more input files are specified,\n\
273 the last input file will be as the output file.\n");
274 fprintf (stdout
, " -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\
275 HiiListPackageGuidGuid is from the module guid.\n\
276 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\
277 If not specified, the first Form FormSet guid is used.\n");
278 fprintf (stdout
, " --hiipackage Combine all input binary hii pacakges into \n\
279 a single package list as the text resource data(RC).\n\
280 It can't be combined with other action options\n\
281 except for -o option. It is a action option.\n\
282 If it is combined with other action options, the later\n\
283 input action option will override the previous one.\n");
284 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
285 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
286 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
287 fprintf (stdout
, " --version Show program's version number and exit\n");
288 fprintf (stdout
, " -h, --help Show this help message and exit\n");
305 AcpiTable Buffer for AcpiSection
306 Length AcpiSection Length
315 EFI_ACPI_DESCRIPTION_HEADER
*AcpiHeader
;
316 EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs
;
317 UINT32 ExpectedLength
;
319 AcpiHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTable
;
322 // Generic check for AcpiTable length.
324 if (AcpiHeader
->Length
> Length
) {
325 Error (NULL
, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL
);
330 // Currently, we only check must-have tables: FADT, FACS, DSDT,
331 // and some important tables: MADT, MCFG.
333 switch (AcpiHeader
->Signature
) {
336 // "FACP" Fixed ACPI Description Table
338 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
:
339 switch (AcpiHeader
->Revision
) {
340 case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
341 ExpectedLength
= sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
);
343 case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
344 ExpectedLength
= sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
);
346 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
347 ExpectedLength
= sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
);
350 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
) {
351 ExpectedLength
= AcpiHeader
->Length
;
354 Error (NULL
, 0, 3000, "Invalid", "FACP revision check failed.");
357 if (ExpectedLength
!= AcpiHeader
->Length
) {
358 Error (NULL
, 0, 3000, "Invalid", "FACP length check failed.");
364 // "FACS" Firmware ACPI Control Structure
366 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE
:
367 Facs
= (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)AcpiTable
;
368 if (Facs
->Version
> EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) {
371 if ((Facs
->Version
!= EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
372 (Facs
->Version
!= EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
373 (Facs
->Version
!= EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
)){
374 Error (NULL
, 0, 3000, "Invalid", "FACS version check failed.");
377 if ((Facs
->Length
!= sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
378 (Facs
->Length
!= sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
379 (Facs
->Length
!= sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
))) {
380 Error (NULL
, 0, 3000, "Invalid", "FACS length check failed.");
386 // "DSDT" Differentiated System Description Table
388 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
389 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION
) {
392 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
)) {
393 Error (NULL
, 0, 3000, "Invalid", "DSDT length check failed.");
399 // "APIC" Multiple APIC Description Table
401 case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE
:
402 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) {
405 if ((AcpiHeader
->Revision
!= EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
406 (AcpiHeader
->Revision
!= EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
407 (AcpiHeader
->Revision
!= EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
)) {
408 Error (NULL
, 0, 3000, "Invalid", "APIC revision check failed.");
411 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT32
) + sizeof(UINT32
)) {
412 Error (NULL
, 0, 3000, "Invalid", "APIC length check failed.");
418 // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
420 case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE
:
421 if (AcpiHeader
->Revision
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
424 if (AcpiHeader
->Revision
!= EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
425 Error (NULL
, 0, 3000, "Invalid", "MCFG revision check failed.");
428 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT64
)) {
429 Error (NULL
, 0, 3000, "Invalid", "MCFG length check failed.");
435 // Other table pass check
441 return STATUS_SUCCESS
;
450 return (FileBuffer
[EI_MAG0
] == ELFMAG0
451 && FileBuffer
[EI_MAG1
] == ELFMAG1
452 && FileBuffer
[EI_MAG2
] == ELFMAG2
453 && FileBuffer
[EI_MAG3
] == ELFMAG3
);
456 typedef Elf32_Shdr Elf_Shdr
;
457 typedef Elf32_Ehdr Elf_Ehdr
;
458 typedef Elf32_Rel Elf_Rel
;
459 typedef Elf32_Sym Elf_Sym
;
460 typedef Elf32_Phdr Elf_Phdr
;
461 typedef Elf32_Dyn Elf_Dyn
;
463 #define ELFCLASS ELFCLASS32
464 #define ELF_R_TYPE(r) ELF32_R_TYPE(r)
465 #define ELF_R_SYM(r) ELF32_R_SYM(r)
466 #define ELF_HII_SECTION_NAME ".hii"
468 // Well known ELF structures.
475 // PE section alignment.
477 const UINT32 CoffAlignment
= 0x20;
478 const UINT16 CoffNbrSections
= 5;
481 // Current offset in coff file.
486 // Result Coff file in memory.
488 UINT8
*CoffFile
= NULL
;
490 // ELF sections to offset in Coff file.
492 UINT32
*CoffSectionsOffset
= NULL
;
495 // Offset in Coff file of headers and sections.
501 UINT32 HiiRsrcOffset
;
507 UINT8
* HiiBinData
= NULL
;
508 UINT32 HiiBinSize
= 0;
510 EFI_IMAGE_BASE_RELOCATION
*CoffBaseRel
;
511 UINT16
*CoffEntryRel
;
518 return (Offset
+ CoffAlignment
- 1) & ~(CoffAlignment
- 1);
526 if (Num
>= Ehdr
->e_shnum
)
528 return (Elf_Shdr
*)((UINT8
*)ShdrBase
+ Num
* Ehdr
->e_shentsize
);
537 // Note: Magic has already been tested.
539 if (Ehdr
->e_ident
[EI_CLASS
] != ELFCLASS
) {
540 Error (NULL
, 0, 3000, "Unsupported", "%s needs to be ported for 64-bit ELF.", mInImageName
);
543 if (Ehdr
->e_ident
[EI_DATA
] != ELFDATA2LSB
) {
544 Error (NULL
, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");
547 if ((Ehdr
->e_type
!= ET_EXEC
) && (Ehdr
->e_type
!= ET_DYN
)) {
548 Error (NULL
, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");
551 if (!((Ehdr
->e_machine
== EM_386
) || (Ehdr
->e_machine
== EM_ARM
))) {
552 Error (NULL
, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM");
555 if (Ehdr
->e_version
!= EV_CURRENT
) {
556 Error (NULL
, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) Ehdr
->e_version
, EV_CURRENT
);
561 // Find the section header table
563 ShdrBase
= (Elf_Shdr
*)((UINT8
*)Ehdr
+ Ehdr
->e_shoff
);
564 gPhdrBase
= (Elf_Phdr
*)((UINT8
*)Ehdr
+ Ehdr
->e_phoff
);
566 CoffSectionsOffset
= (UINT32
*)malloc(Ehdr
->e_shnum
* sizeof (UINT32
));
568 memset(CoffSectionsOffset
, 0, Ehdr
->e_shnum
* sizeof(UINT32
));
577 return (Shdr
->sh_flags
& (SHF_WRITE
| SHF_ALLOC
)) == SHF_ALLOC
;
585 Elf_Shdr
*Namedr
= GetShdrByIndex(Ehdr
->e_shstrndx
);
587 if (strcmp((CHAR8
*)Ehdr
+ Namedr
->sh_offset
+ Shdr
->sh_name
, ELF_HII_SECTION_NAME
) == 0) {
599 if (IsHiiRsrcShdr(Shdr
)) {
602 return (Shdr
->sh_flags
& (SHF_WRITE
| SHF_ALLOC
)) == (SHF_ALLOC
| SHF_WRITE
);
613 EFI_IMAGE_SECTION_HEADER
*Hdr
;
614 Hdr
= (EFI_IMAGE_SECTION_HEADER
*)(CoffFile
+ TableOffset
);
616 strcpy((char *)Hdr
->Name
, Name
);
617 Hdr
->Misc
.VirtualSize
= Size
;
618 Hdr
->VirtualAddress
= Offset
;
619 Hdr
->SizeOfRawData
= Size
;
620 Hdr
->PointerToRawData
= Offset
;
621 Hdr
->PointerToRelocations
= 0;
622 Hdr
->PointerToLinenumbers
= 0;
623 Hdr
->NumberOfRelocations
= 0;
624 Hdr
->NumberOfLinenumbers
= 0;
625 Hdr
->Characteristics
= Flags
;
627 TableOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
640 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
641 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*ResourceDirectoryEntry
;
642 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
643 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
646 while (Index
< Size
&& *RcString
!= '\0' && *RcString
!= '{') {
651 if (*RcString
== '\0' || Index
== Size
) {
656 // Skip '{' character
657 // Skip space and ',' character
661 while (Index
< Size
&& *RcString
!= '\0' && (isspace (*RcString
) || *RcString
== ',')){
669 if (*RcString
== '}' || Index
== Size
) {
675 HiiBinData
= (UINT8
*) malloc (HiiBinSize
);
676 if (HiiBinData
== NULL
) {
679 memset (HiiBinData
, 0, HiiBinSize
);
681 // Fill Resource section entry
683 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
+ HiiBinOffset
);
684 HiiBinOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
685 ResourceDirectory
->NumberOfNamedEntries
= 1;
687 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiBinData
+ HiiBinOffset
);
688 HiiBinOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
689 ResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
690 ResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiBinOffset
;
692 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiBinData
+ HiiBinOffset
);
693 ResourceDirectoryString
->Length
= 3;
694 ResourceDirectoryString
->String
[0] =L
'H';
695 ResourceDirectoryString
->String
[1] =L
'I';
696 ResourceDirectoryString
->String
[2] =L
'I';
697 HiiBinOffset
= HiiBinOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
699 ResourceDirectoryEntry
->u2
.OffsetToData
= HiiBinOffset
;
700 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (HiiBinData
+ HiiBinOffset
);
701 HiiBinOffset
+= sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
702 ResourceDataEntry
->OffsetToData
= OffsetToFile
+ HiiBinOffset
;
704 while (sscanf (RcString
, "0x%X", &Data16
) != EOF
) {
706 // Convert the string data to the binary data.
708 *(UINT16
*)(HiiBinData
+ HiiBinOffset
) = (UINT16
) Data16
;
711 // Jump to the next data.
713 RcString
= RcString
+ 2 + 4;
714 Index
= Index
+ 2 + 4;
716 // Skip space and ',' character
718 while (Index
< Size
&& *RcString
!= '\0' && (isspace (*RcString
) || *RcString
== ',')){
725 if (*RcString
== '}'|| Index
== Size
) {
729 // Check BinBuffer size
731 if (HiiBinOffset
>= HiiBinSize
) {
732 HiiBinSize
+= 0x1000;
733 HiiBinData
= (UINT8
*) realloc (HiiBinData
, HiiBinSize
);
735 // Memory allocation is failure.
737 if (HiiBinData
== NULL
) {
744 if (HiiBinData
!= NULL
) {
745 HiiBinSize
= HiiBinOffset
;
746 ResourceDataEntry
->Size
= HiiBinSize
+ OffsetToFile
- ResourceDataEntry
->OffsetToData
;
758 EFI_IMAGE_DOS_HEADER
*DosHdr
;
759 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
766 // Coff file start with a DOS header.
768 CoffOffset
= sizeof(EFI_IMAGE_DOS_HEADER
) + 0x40;
769 NtHdrOffset
= CoffOffset
;
770 switch (Ehdr
->e_machine
) {
773 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS32
);
777 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS64
);
780 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN
)Ehdr
->e_machine
);
781 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS32
);
785 TableOffset
= CoffOffset
;
786 CoffOffset
+= CoffNbrSections
* sizeof(EFI_IMAGE_SECTION_HEADER
);
789 // First text sections.
791 CoffOffset
= CoffAlign(CoffOffset
);
792 TextOffset
= CoffOffset
;
793 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
794 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
795 if (IsTextShdr(shdr
)) {
796 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
797 // the alignment field is valid
798 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
799 // if the section address is aligned we must align PE/COFF
800 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
801 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
802 // ARM RVCT tools have behavior outside of the ELF specification to try
803 // and make images smaller. If sh_addr is not aligned to sh_addralign
804 // then the section needs to preserve sh_addr MOD sh_addralign.
805 // Normally doing nothing here works great.
806 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
810 /* Relocate entry. */
811 if ((Ehdr
->e_entry
>= shdr
->sh_addr
) &&
812 (Ehdr
->e_entry
< shdr
->sh_addr
+ shdr
->sh_size
)) {
813 CoffEntry
= CoffOffset
+ Ehdr
->e_entry
- shdr
->sh_addr
;
815 CoffSectionsOffset
[i
] = CoffOffset
;
816 CoffOffset
+= shdr
->sh_size
;
820 if (Ehdr
->e_machine
!= EM_ARM
) {
821 CoffOffset
= CoffAlign(CoffOffset
);
825 // Then data sections.
827 DataOffset
= CoffOffset
;
828 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
829 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
830 if (IsDataShdr(shdr
)) {
831 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
832 // the alignment field is valid
833 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
834 // if the section address is aligned we must align PE/COFF
835 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
836 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
837 // ARM RVCT tools have behavior outside of the ELF specification to try
838 // and make images smaller. If sh_addr is not aligned to sh_addralign
839 // then the section needs to preserve sh_addr MOD sh_addralign.
840 // Normally doing nothing here works great.
841 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
844 CoffSectionsOffset
[i
] = CoffOffset
;
845 CoffOffset
+= shdr
->sh_size
;
848 CoffOffset
= CoffAlign(CoffOffset
);
851 // The HII resource sections.
853 HiiRsrcOffset
= CoffOffset
;
854 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
855 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
856 if (IsHiiRsrcShdr(shdr
)) {
857 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
858 // the alignment field is valid
859 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
860 // if the section address is aligned we must align PE/COFF
861 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
862 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
863 // ARM RVCT tools have behavior outside of the ELF specification to try
864 // and make images smaller. If sh_addr is not aligned to sh_addralign
865 // then the section needs to preserve sh_addr MOD sh_addralign.
866 // Normally doing nothing here works great.
867 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
870 GetBinaryHiiData ((CHAR8
*)Ehdr
+ shdr
->sh_offset
, shdr
->sh_size
, HiiRsrcOffset
);
871 if (HiiBinSize
!= 0) {
872 CoffOffset
+= HiiBinSize
;
873 CoffOffset
= CoffAlign(CoffOffset
);
879 RelocOffset
= CoffOffset
;
882 // Allocate base Coff file. Will be expanded later for relocations.
884 CoffFile
= (UINT8
*)malloc(CoffOffset
);
885 memset(CoffFile
, 0, CoffOffset
);
890 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)CoffFile
;
891 DosHdr
->e_magic
= EFI_IMAGE_DOS_SIGNATURE
;
892 DosHdr
->e_lfanew
= NtHdrOffset
;
894 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
896 NtHdr
->Pe32
.Signature
= EFI_IMAGE_NT_SIGNATURE
;
898 switch (Ehdr
->e_machine
) {
900 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IA32
;
901 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
904 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_X64
;
905 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
908 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IPF
;
909 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
912 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_ARMT
;
913 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
916 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN
)Ehdr
->e_machine
);
917 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IA32
;
918 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
921 NtHdr
->Pe32
.FileHeader
.NumberOfSections
= CoffNbrSections
;
922 NtHdr
->Pe32
.FileHeader
.TimeDateStamp
= (UINT32
) time(NULL
);
923 NtHdr
->Pe32
.FileHeader
.PointerToSymbolTable
= 0;
924 NtHdr
->Pe32
.FileHeader
.NumberOfSymbols
= 0;
925 NtHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
= sizeof(NtHdr
->Pe32
.OptionalHeader
);
926 NtHdr
->Pe32
.FileHeader
.Characteristics
= EFI_IMAGE_FILE_EXECUTABLE_IMAGE
927 | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED
928 | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED
929 | EFI_IMAGE_FILE_32BIT_MACHINE
;
931 NtHdr
->Pe32
.OptionalHeader
.SizeOfCode
= DataOffset
- TextOffset
;
932 NtHdr
->Pe32
.OptionalHeader
.SizeOfInitializedData
= RelocOffset
- DataOffset
;
933 NtHdr
->Pe32
.OptionalHeader
.SizeOfUninitializedData
= 0;
934 NtHdr
->Pe32
.OptionalHeader
.AddressOfEntryPoint
= CoffEntry
;
936 NtHdr
->Pe32
.OptionalHeader
.BaseOfCode
= TextOffset
;
938 NtHdr
->Pe32
.OptionalHeader
.BaseOfData
= DataOffset
;
939 NtHdr
->Pe32
.OptionalHeader
.ImageBase
= 0;
940 NtHdr
->Pe32
.OptionalHeader
.SectionAlignment
= CoffAlignment
;
941 NtHdr
->Pe32
.OptionalHeader
.FileAlignment
= CoffAlignment
;
942 NtHdr
->Pe32
.OptionalHeader
.SizeOfImage
= 0;
944 NtHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
= TextOffset
;
945 NtHdr
->Pe32
.OptionalHeader
.NumberOfRvaAndSizes
= EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES
;
950 if ((DataOffset
- TextOffset
) > 0) {
951 CreateSectionHeader (".text", TextOffset
, DataOffset
- TextOffset
,
952 EFI_IMAGE_SCN_CNT_CODE
953 | EFI_IMAGE_SCN_MEM_EXECUTE
954 | EFI_IMAGE_SCN_MEM_READ
);
956 // Don't make a section of size 0.
957 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
960 if ((HiiRsrcOffset
- DataOffset
) > 0) {
961 CreateSectionHeader (".data", DataOffset
, HiiRsrcOffset
- DataOffset
,
962 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
963 | EFI_IMAGE_SCN_MEM_WRITE
964 | EFI_IMAGE_SCN_MEM_READ
);
966 // Don't make a section of size 0.
967 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
970 if ((RelocOffset
- HiiRsrcOffset
) > 0) {
971 CreateSectionHeader (".rsrc", HiiRsrcOffset
, RelocOffset
- HiiRsrcOffset
,
972 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
973 | EFI_IMAGE_SCN_MEM_READ
);
975 NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= HiiBinSize
;
976 NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= HiiRsrcOffset
;
978 memcpy(CoffFile
+ HiiRsrcOffset
, HiiBinData
, HiiBinSize
);
983 // Don't make a section of size 0.
984 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
991 int (*Filter
)(Elf_Shdr
*)
999 // First: copy sections.
1001 for (Idx
= 0; Idx
< Ehdr
->e_shnum
; Idx
++) {
1002 Elf_Shdr
*Shdr
= GetShdrByIndex(Idx
);
1003 if ((*Filter
)(Shdr
)) {
1004 switch (Shdr
->sh_type
) {
1007 memcpy(CoffFile
+ CoffSectionsOffset
[Idx
],
1008 (UINT8
*)Ehdr
+ Shdr
->sh_offset
,
1013 memset(CoffFile
+ CoffSectionsOffset
[Idx
], 0, Shdr
->sh_size
);
1018 // Ignore for unkown section type.
1020 VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName
, (unsigned)Shdr
->sh_type
);
1027 // Second: apply relocations.
1029 for (Idx
= 0; Idx
< Ehdr
->e_shnum
; Idx
++) {
1030 Elf_Shdr
*RelShdr
= GetShdrByIndex(Idx
);
1031 if (RelShdr
->sh_type
!= SHT_REL
)
1033 SecShdr
= GetShdrByIndex(RelShdr
->sh_info
);
1034 SecOffset
= CoffSectionsOffset
[RelShdr
->sh_info
];
1035 if (RelShdr
->sh_type
== SHT_REL
&& (*Filter
)(SecShdr
)) {
1037 Elf_Shdr
*SymtabShdr
= GetShdrByIndex(RelShdr
->sh_link
);
1038 UINT8
*Symtab
= (UINT8
*)Ehdr
+ SymtabShdr
->sh_offset
;
1040 for (RelIdx
= 0; RelIdx
< RelShdr
->sh_size
; RelIdx
+= RelShdr
->sh_entsize
) {
1041 Elf_Rel
*Rel
= (Elf_Rel
*)((UINT8
*)Ehdr
+ RelShdr
->sh_offset
+ RelIdx
);
1042 Elf_Sym
*Sym
= (Elf_Sym
*)(Symtab
+ ELF_R_SYM(Rel
->r_info
) * SymtabShdr
->sh_entsize
);
1046 if (Sym
->st_shndx
== SHN_UNDEF
1047 || Sym
->st_shndx
== SHN_ABS
1048 || Sym
->st_shndx
> Ehdr
->e_shnum
) {
1049 Error (NULL
, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName
);
1051 SymShdr
= GetShdrByIndex(Sym
->st_shndx
);
1054 // Note: r_offset in a memory address.
1055 // Convert it to a pointer in the coff file.
1057 Targ
= CoffFile
+ SecOffset
+ (Rel
->r_offset
- SecShdr
->sh_addr
);
1059 if (Ehdr
->e_machine
== EM_386
) {
1060 switch (ELF_R_TYPE(Rel
->r_info
)) {
1065 // Absolute relocation.
1067 *(UINT32
*)Targ
= *(UINT32
*)Targ
- SymShdr
->sh_addr
1068 + CoffSectionsOffset
[Sym
->st_shndx
];
1072 // Relative relocation: Symbol - Ip + Addend
1074 *(UINT32
*)Targ
= *(UINT32
*)Targ
1075 + (CoffSectionsOffset
[Sym
->st_shndx
] - SymShdr
->sh_addr
)
1076 - (SecOffset
- SecShdr
->sh_addr
);
1079 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, (unsigned) ELF_R_TYPE(Rel
->r_info
));
1081 } else if (Ehdr
->e_machine
== EM_ARM
) {
1082 switch (ELF32_R_TYPE(Rel
->r_info
)) {
1083 case R_ARM_RBASE
: // No relocation - no action required
1084 case R_ARM_PC24
: // PC-relative relocations don't require modification
1085 case R_ARM_XPC25
: // PC-relative relocations don't require modification
1090 // Absolute relocation.
1092 *(UINT32
*)Targ
= *(UINT32
*)Targ
- SymShdr
->sh_addr
+ CoffSectionsOffset
[Sym
->st_shndx
];
1095 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, (unsigned) ELF32_R_TYPE(Rel
->r_info
));
1108 *CoffEntryRel
= Val
;
1110 CoffBaseRel
->SizeOfBlock
+= 2;
1120 if (CoffBaseRel
== NULL
1121 || CoffBaseRel
->VirtualAddress
!= (Offset
& ~0xfff)) {
1122 if (CoffBaseRel
!= NULL
) {
1124 // Add a null entry (is it required ?)
1126 CoffAddFixupEntry (0);
1128 // Pad for alignment.
1130 if (CoffOffset
% 4 != 0)
1131 CoffAddFixupEntry (0);
1136 CoffOffset
+ sizeof(EFI_IMAGE_BASE_RELOCATION
) + 2*0x1000);
1137 memset(CoffFile
+ CoffOffset
, 0,
1138 sizeof(EFI_IMAGE_BASE_RELOCATION
) + 2*0x1000);
1140 CoffBaseRel
= (EFI_IMAGE_BASE_RELOCATION
*)(CoffFile
+ CoffOffset
);
1141 CoffBaseRel
->VirtualAddress
= Offset
& ~0xfff;
1142 CoffBaseRel
->SizeOfBlock
= sizeof(EFI_IMAGE_BASE_RELOCATION
);
1144 CoffEntryRel
= (UINT16
*)(CoffBaseRel
+ 1);
1145 CoffOffset
+= sizeof(EFI_IMAGE_BASE_RELOCATION
);
1151 CoffAddFixupEntry((UINT16
) ((Type
<< 12) | (Offset
& 0xfff)));
1160 if (num
>= Ehdr
->e_phnum
) {
1164 return (Elf32_Phdr
*)((UINT8
*)gPhdrBase
+ num
* Ehdr
->e_phentsize
);
1174 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1175 EFI_IMAGE_DATA_DIRECTORY
*Dir
;
1176 BOOLEAN FoundRelocations
;
1179 UINTN RelElementSize
;
1184 Elf32_Phdr
*DynamicSegment
;
1185 Elf32_Phdr
*TargetSegment
;
1187 for (Index
= 0, FoundRelocations
= FALSE
; Index
< Ehdr
->e_shnum
; Index
++) {
1188 Elf_Shdr
*RelShdr
= GetShdrByIndex(Index
);
1189 if (RelShdr
->sh_type
== SHT_REL
) {
1190 Elf_Shdr
*SecShdr
= GetShdrByIndex(RelShdr
->sh_info
);
1191 if (IsTextShdr(SecShdr
) || IsDataShdr(SecShdr
)) {
1193 FoundRelocations
= TRUE
;
1194 for (RelIdx
= 0; RelIdx
< RelShdr
->sh_size
; RelIdx
+= RelShdr
->sh_entsize
) {
1195 Elf_Rel
*Rel
= (Elf_Rel
*)
1196 ((UINT8
*)Ehdr
+ RelShdr
->sh_offset
+ RelIdx
);
1198 if (Ehdr
->e_machine
== EM_386
) {
1199 switch (ELF_R_TYPE(Rel
->r_info
)) {
1204 CoffAddFixup(CoffSectionsOffset
[RelShdr
->sh_info
]
1205 + (Rel
->r_offset
- SecShdr
->sh_addr
),
1206 EFI_IMAGE_REL_BASED_HIGHLOW
);
1209 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, (unsigned) ELF_R_TYPE(Rel
->r_info
));
1211 } else if (Ehdr
->e_machine
== EM_ARM
) {
1212 switch (ELF32_R_TYPE(Rel
->r_info
)) {
1220 CoffSectionsOffset
[RelShdr
->sh_info
]
1221 + (Rel
->r_offset
- SecShdr
->sh_addr
),
1222 EFI_IMAGE_REL_BASED_HIGHLOW
1226 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, (unsigned) ELF32_R_TYPE(Rel
->r_info
));
1229 Error (NULL
, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) Ehdr
->e_machine
);
1236 if (!FoundRelocations
&& (Ehdr
->e_machine
== EM_ARM
)) {
1237 /* Try again, but look for PT_DYNAMIC instead of SHT_REL */
1239 for (Index
= 0; Index
< Ehdr
->e_phnum
; Index
++) {
1244 DynamicSegment
= GetPhdrByIndex (Index
);
1246 if (DynamicSegment
->p_type
== PT_DYNAMIC
) {
1247 Dyn
= (Elf32_Dyn
*) ((UINT8
*)Ehdr
+ DynamicSegment
->p_offset
);
1249 while (Dyn
->d_tag
!= DT_NULL
) {
1250 switch (Dyn
->d_tag
) {
1252 RelOffset
= Dyn
->d_un
.d_val
;
1256 RelSize
= Dyn
->d_un
.d_val
;
1260 RelElementSize
= Dyn
->d_un
.d_val
;
1265 if (( RelOffset
== 0 ) || ( RelSize
== 0 ) || ( RelElementSize
== 0 )) {
1266 Error (NULL
, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName
);
1269 for (K
= 0; K
< RelSize
; K
+= RelElementSize
) {
1271 Rel
= (Elf32_Rel
*) ((UINT8
*) Ehdr
+ DynamicSegment
->p_offset
+ RelOffset
+ K
);
1273 switch (ELF32_R_TYPE (Rel
->r_info
)) {
1277 TargetSegment
= GetPhdrByIndex (ELF32_R_SYM (Rel
->r_info
) - 1);
1279 // Note: r_offset in a memory address. Convert it to a pointer in the coff file.
1280 Targ
= CoffFile
+ CoffSectionsOffset
[ ELF32_R_SYM( Rel
->r_info
) ] + Rel
->r_offset
- TargetSegment
->p_vaddr
;
1282 *(UINT32
*)Targ
= *(UINT32
*)Targ
+ CoffSectionsOffset
[ELF32_R_SYM( Rel
->r_info
)];
1284 CoffAddFixup (CoffSectionsOffset
[ELF32_R_SYM (Rel
->r_info
)] + (Rel
->r_offset
- TargetSegment
->p_vaddr
), EFI_IMAGE_REL_BASED_HIGHLOW
);
1287 Error (NULL
, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type.", mInImageName
);
1296 // Pad by adding empty entries.
1298 while (CoffOffset
& (CoffAlignment
- 1)) {
1299 CoffAddFixupEntry(0);
1303 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1304 Dir
= &NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1305 Dir
->Size
= CoffOffset
- RelocOffset
;
1306 if (Dir
->Size
== 0) {
1307 // If no relocations, null out the directory entry and don't add the .reloc section
1308 Dir
->VirtualAddress
= 0;
1309 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
1311 Dir
->VirtualAddress
= RelocOffset
;
1312 CreateSectionHeader (".reloc", RelocOffset
, CoffOffset
- RelocOffset
,
1313 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
1314 | EFI_IMAGE_SCN_MEM_DISCARDABLE
1315 | EFI_IMAGE_SCN_MEM_READ
);
1327 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1328 EFI_IMAGE_DATA_DIRECTORY
*DataDir
;
1329 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*Dir
;
1330 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
*Nb10
;
1332 Len
= strlen(mInImageName
) + 1;
1333 DebugOffset
= CoffOffset
;
1335 CoffOffset
+= sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
)
1336 + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
)
1338 CoffOffset
= CoffAlign(CoffOffset
);
1340 CoffFile
= realloc(CoffFile
, CoffOffset
);
1341 memset(CoffFile
+ DebugOffset
, 0, CoffOffset
- DebugOffset
);
1343 Dir
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)(CoffFile
+ DebugOffset
);
1344 Dir
->Type
= EFI_IMAGE_DEBUG_TYPE_CODEVIEW
;
1345 Dir
->SizeOfData
= sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
) + Len
;
1346 Dir
->RVA
= DebugOffset
+ sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
1347 Dir
->FileOffset
= DebugOffset
+ sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
1349 Nb10
= (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
*)(Dir
+ 1);
1350 Nb10
->Signature
= CODEVIEW_SIGNATURE_NB10
;
1351 strcpy ((char *)(Nb10
+ 1), mInImageName
);
1354 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1355 DataDir
= &NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
];
1356 DataDir
->VirtualAddress
= DebugOffset
;
1357 DataDir
->Size
= CoffOffset
- DebugOffset
;
1358 if (DataDir
->Size
== 0) {
1359 // If no debug, null out the directory entry and don't add the .debug section
1360 DataDir
->VirtualAddress
= 0;
1361 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
1363 DataDir
->VirtualAddress
= DebugOffset
;
1364 CreateSectionHeader (".debug", DebugOffset
, CoffOffset
- DebugOffset
,
1365 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
1366 | EFI_IMAGE_SCN_MEM_DISCARDABLE
1367 | EFI_IMAGE_SCN_MEM_READ
);
1378 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1381 // Check header, read section table.
1383 Ehdr
= (Elf32_Ehdr
*)*FileBuffer
;
1384 if (!CheckElfHeader())
1387 VerboseMsg ("Check Efl Image Header");
1389 // Compute sections new address.
1394 VerboseMsg ("Compute sections new address.");
1397 // Write and relocate sections.
1399 WriteSections(IsTextShdr
);
1400 WriteSections(IsDataShdr
);
1401 VerboseMsg ("Write and relocate sections.");
1404 // Translate and write relocations.
1407 VerboseMsg ("Translate and write relocations.");
1410 // Write debug info.
1413 VerboseMsg ("Write debug info.");
1415 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1416 NtHdr
->Pe32
.OptionalHeader
.SizeOfImage
= CoffOffset
;
1422 *FileBuffer
= CoffFile
;
1423 *FileLength
= CoffOffset
;
1426 // Free memory space
1428 if (CoffSectionsOffset
!= NULL
) {
1429 free (CoffSectionsOffset
);
1440 Routine Description:
1446 argc - Number of command line parameters.
1447 argv - Array of pointers to command line parameter strings.
1450 STATUS_SUCCESS - Utility exits successfully.
1451 STATUS_ERROR - Some error occurred during execution.
1456 UINT32 InputFileNum
;
1457 CHAR8
**InputFileName
;
1461 UINT32 OutImageType
;
1466 UINT32
*DataPointer
;
1467 UINT32
*OldDataPointer
;
1473 UINT32 MciAlignment
;
1475 UINT32 AllignedRelocSize
;
1478 UINT8
*OutputFileBuffer
;
1479 UINT32 OutputFileLength
;
1480 RUNTIME_FUNCTION
*RuntimeFunction
;
1481 UNWIND_INFO
*UnwindInfo
;
1483 BOOLEAN ReplaceFlag
;
1484 BOOLEAN KeepExceptionTableFlag
;
1485 BOOLEAN KeepZeroPendingFlag
;
1487 EFI_TE_IMAGE_HEADER TEImageHeader
;
1488 EFI_TE_IMAGE_HEADER
*TeHdr
;
1489 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1490 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1491 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1492 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32
;
1493 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64
;
1494 EFI_IMAGE_DOS_HEADER BackupDosHdr
;
1495 MICROCODE_IMAGE_HEADER
*MciHeader
;
1496 UINT8
*HiiPackageListBuffer
;
1497 UINT8
*HiiPackageDataPointer
;
1498 EFI_GUID HiiPackageListGuid
;
1499 EFI_HII_PACKAGE_LIST_HEADER HiiPackageListHeader
;
1500 EFI_HII_PACKAGE_HEADER HiiPackageHeader
;
1501 EFI_IFR_FORM_SET IfrFormSet
;
1502 UINT8 NumberOfFormPacakge
;
1503 EFI_HII_PACKAGE_HEADER EndPackage
;
1505 SetUtilityName (UTILITY_NAME
);
1508 // Assign to fix compile warning
1511 InputFileName
= NULL
;
1512 mInImageName
= NULL
;
1513 OutImageName
= NULL
;
1515 OutImageType
= FW_DUMMY_IMAGE
;
1517 Status
= STATUS_SUCCESS
;
1523 MciAlignment
= DEFAULT_MC_ALIGNMENT
;
1524 MciPadValue
= DEFAULT_MC_PAD_BYTE_VALUE
;
1528 ReplaceFlag
= FALSE
;
1530 OutputFileBuffer
= NULL
;
1531 OutputFileLength
= 0;
1534 KeepExceptionTableFlag
= FALSE
;
1535 KeepZeroPendingFlag
= FALSE
;
1536 NumberOfFormPacakge
= 0;
1537 HiiPackageListBuffer
= NULL
;
1538 HiiPackageDataPointer
= NULL
;
1539 EndPackage
.Length
= sizeof (EFI_HII_PACKAGE_HEADER
);
1540 EndPackage
.Type
= EFI_HII_PACKAGE_END
;
1541 memset (&HiiPackageListGuid
, 0, sizeof (HiiPackageListGuid
));
1544 Error (NULL
, 0, 1001, "Missing options", "No input options.");
1546 return STATUS_ERROR
;
1552 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
1555 return STATUS_SUCCESS
;
1558 if (stricmp (argv
[0], "--version") == 0) {
1560 return STATUS_SUCCESS
;
1564 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
1565 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1566 Error (NULL
, 0, 1003, "Invalid option value", "Output file name is missing for -o option");
1569 OutImageName
= argv
[1];
1575 if ((stricmp (argv
[0], "-e") == 0) || (stricmp (argv
[0], "--efiImage") == 0)) {
1576 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1577 Error (NULL
, 0, 1003, "Invalid option value", "Module Type is missing for -o option");
1580 ModuleType
= argv
[1];
1581 if (OutImageType
!= FW_TE_IMAGE
) {
1582 OutImageType
= FW_EFI_IMAGE
;
1589 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--stripped") == 0)) {
1590 OutImageType
= FW_RELOC_STRIPEED_IMAGE
;
1596 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--acpi") == 0)) {
1597 OutImageType
= FW_ACPI_IMAGE
;
1603 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--terse") == 0)) {
1604 OutImageType
= FW_TE_IMAGE
;
1610 if ((stricmp (argv
[0], "-u") == 0) || (stricmp (argv
[0], "--dump") == 0)) {
1611 OutImageType
= DUMP_TE_HEADER
;
1617 if ((stricmp (argv
[0], "-b") == 0) || (stricmp (argv
[0], "--exe2bin") == 0)) {
1618 OutImageType
= FW_BIN_IMAGE
;
1624 if ((stricmp (argv
[0], "-z") == 0) || (stricmp (argv
[0], "--zero") == 0)) {
1625 OutImageType
= FW_ZERO_DEBUG_IMAGE
;
1631 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--stamp") == 0)) {
1632 OutImageType
= FW_SET_STAMP_IMAGE
;
1633 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1634 Error (NULL
, 0, 1003, "Invalid option value", "time stamp is missing for -s option");
1637 TimeStamp
= argv
[1];
1643 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--replace") == 0)) {
1650 if (stricmp (argv
[0], "--keepexceptiontable") == 0) {
1651 KeepExceptionTableFlag
= TRUE
;
1657 if (stricmp (argv
[0], "--keepzeropending") == 0) {
1658 KeepZeroPendingFlag
= TRUE
;
1664 if ((stricmp (argv
[0], "-m") == 0) || (stricmp (argv
[0], "--mcifile") == 0)) {
1665 OutImageType
= FW_MCI_IMAGE
;
1671 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--join") == 0)) {
1672 OutImageType
= FW_MERGE_IMAGE
;
1678 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
1679 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1680 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1683 MciAlignment
= (UINT32
) Temp64
;
1689 if ((stricmp (argv
[0], "-p") == 0) || (stricmp (argv
[0], "--pad") == 0)) {
1690 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1691 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1694 MciPadValue
= (UINT8
) Temp64
;
1700 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
1701 SetPrintLevel (VERBOSE_LOG_LEVEL
);
1702 VerboseMsg ("Verbose output Mode Set!");
1708 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1709 SetPrintLevel (KEY_LOG_LEVEL
);
1710 KeyMsg ("Quiet output Mode Set!");
1716 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
1717 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
1718 if (EFI_ERROR (Status
)) {
1719 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1723 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel
);
1726 SetPrintLevel (LogLevel
);
1727 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
1733 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--hiiguid") == 0)) {
1734 Status
= StringToGuid (argv
[1], &HiiPackageListGuid
);
1735 if (EFI_ERROR (Status
)) {
1736 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1744 if (stricmp (argv
[0], "--hiipackage") == 0) {
1745 OutImageType
= FW_HII_PACKAGE_LIST_RCIMAGE
;
1751 if (argv
[0][0] == '-') {
1752 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
1756 // Get Input file name
1758 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
1759 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
1760 if (InputFileName
== NULL
) {
1761 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1765 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1766 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1768 // InputFileName buffer too small, need to realloc
1770 InputFileName
= (CHAR8
**) realloc (
1772 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1775 if (InputFileName
== NULL
) {
1776 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1780 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1783 InputFileName
[InputFileNum
++] = argv
[0];
1788 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1790 if (OutImageType
== FW_DUMMY_IMAGE
) {
1791 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!");
1793 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.");
1799 // check input files
1801 if (InputFileNum
== 0) {
1802 Error (NULL
, 0, 1001, "Missing option", "Input files");
1807 // Combine MciBinary files to one file
1809 if ((OutImageType
== FW_MERGE_IMAGE
) && ReplaceFlag
) {
1810 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");
1815 // Combine HiiBinary packages to a single package list
1817 if ((OutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) && ReplaceFlag
) {
1818 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option.");
1825 mInImageName
= InputFileName
[InputFileNum
- 1];
1826 VerboseMsg ("the input file name is %s", mInImageName
);
1829 // Action will be taken for the input file.
1831 switch (OutImageType
) {
1833 VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType
);
1836 VerboseMsg ("Create Te Image based on the input PE image.");
1839 VerboseMsg ("Get acpi table data from the input PE image.");
1841 case FW_RELOC_STRIPEED_IMAGE
:
1842 VerboseMsg ("Remove relocation section from Pe or Te image.");
1845 VerboseMsg ("Convert the input EXE to the output BIN file.");
1847 case FW_ZERO_DEBUG_IMAGE
:
1848 VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");
1850 case FW_SET_STAMP_IMAGE
:
1851 VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp
);
1853 case DUMP_TE_HEADER
:
1854 VerboseMsg ("Dump the TE header information of the input TE image.");
1857 VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");
1859 case FW_MERGE_IMAGE
:
1860 VerboseMsg ("Combine the input multi microcode bin files to one bin file.");
1862 case FW_HII_PACKAGE_LIST_RCIMAGE
:
1863 VerboseMsg ("Combine the input multi hii bin packages to one text pacakge list RC file.");
1870 VerboseMsg ("Overwrite the input file with the output content.");
1874 // Open output file and Write image into the output file.
1876 if (OutImageName
!= NULL
) {
1877 fpOut
= fopen (OutImageName
, "rb");
1878 if (fpOut
!= NULL
) {
1879 OutputFileLength
= _filelength (fileno (fpOut
));
1880 OutputFileBuffer
= malloc (OutputFileLength
);
1881 if (OutputFileBuffer
== NULL
) {
1882 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1887 fread (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
1890 fpOut
= fopen (OutImageName
, "wb");
1892 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1895 VerboseMsg ("Output file name is %s", OutImageName
);
1896 } else if (!ReplaceFlag
) {
1897 if (OutImageType
== DUMP_TE_HEADER
) {
1900 Error (NULL
, 0, 1001, "Missing option", "output file");
1906 // Combine multi binary HII package files to a single text package list RC file.
1908 if (OutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) {
1910 // Get hii package list lenght
1912 HiiPackageListHeader
.PackageLength
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1913 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1914 fpIn
= fopen (InputFileName
[Index
], "rb");
1916 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1919 FileLength
= _filelength (fileno (fpIn
));
1920 fread (&HiiPackageHeader
, 1, sizeof (HiiPackageHeader
), fpIn
);
1921 if (HiiPackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) {
1922 if (HiiPackageHeader
.Length
!= FileLength
) {
1923 Error (NULL
, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName
[Index
]);
1927 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
1928 fread (&IfrFormSet
, 1, sizeof (IfrFormSet
), fpIn
);
1929 memcpy (&HiiPackageListGuid
, &IfrFormSet
.Guid
, sizeof (EFI_GUID
));
1931 NumberOfFormPacakge
++;
1933 HiiPackageListHeader
.PackageLength
+= FileLength
;
1936 HiiPackageListHeader
.PackageLength
+= sizeof (EndPackage
);
1938 // Check whether hii packages are valid
1940 if (NumberOfFormPacakge
> 1) {
1941 Error (NULL
, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package");
1944 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
1945 Error (NULL
, 0, 3000, "Invalid", "HII pacakge list guid is not specified!");
1948 memcpy (&HiiPackageListHeader
.PackageListGuid
, &HiiPackageListGuid
, sizeof (EFI_GUID
));
1950 // read hii packages
1952 HiiPackageListBuffer
= malloc (HiiPackageListHeader
.PackageLength
);
1953 if (HiiPackageListBuffer
== NULL
) {
1954 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1957 memcpy (HiiPackageListBuffer
, &HiiPackageListHeader
, sizeof (HiiPackageListHeader
));
1958 HiiPackageDataPointer
= HiiPackageListBuffer
+ sizeof (HiiPackageListHeader
);
1959 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1960 fpIn
= fopen (InputFileName
[Index
], "rb");
1962 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1963 free (HiiPackageListBuffer
);
1967 FileLength
= _filelength (fileno (fpIn
));
1968 fread (HiiPackageDataPointer
, 1, FileLength
, fpIn
);
1970 HiiPackageDataPointer
= HiiPackageDataPointer
+ FileLength
;
1972 memcpy (HiiPackageDataPointer
, &EndPackage
, sizeof (EndPackage
));
1974 // write the hii package into the text package list rc file.
1976 for (Index
= 0; gHiiPackageRCFileHeader
[Index
] != NULL
; Index
++) {
1977 fprintf (fpOut
, "%s\n", gHiiPackageRCFileHeader
[Index
]);
1979 fprintf (fpOut
, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX
, HII_RESOURCE_SECTION_NAME
);
1981 HiiPackageDataPointer
= HiiPackageListBuffer
;
1982 for (Index
= 0; Index
+ 2 < HiiPackageListHeader
.PackageLength
; Index
+= 2) {
1983 if (Index
% 16 == 0) {
1984 fprintf (fpOut
, "\n ");
1986 fprintf (fpOut
, " 0x%04X,", *(UINT16
*) HiiPackageDataPointer
);
1987 HiiPackageDataPointer
+= 2;
1990 if (Index
% 16 == 0) {
1991 fprintf (fpOut
, "\n ");
1993 if ((Index
+ 2) == HiiPackageListHeader
.PackageLength
) {
1994 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT16
*) HiiPackageDataPointer
);
1996 if ((Index
+ 1) == HiiPackageListHeader
.PackageLength
) {
1997 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT8
*) HiiPackageDataPointer
);
1999 free (HiiPackageListBuffer
);
2001 // Done successfully
2007 // Combine MciBinary files to one file
2009 if (OutImageType
== FW_MERGE_IMAGE
) {
2010 for (Index
= 0; Index
< InputFileNum
; Index
++) {
2011 fpIn
= fopen (InputFileName
[Index
], "rb");
2013 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
2017 FileLength
= _filelength (fileno (fpIn
));
2018 FileBuffer
= malloc (FileLength
);
2019 if (FileBuffer
== NULL
) {
2020 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2025 fread (FileBuffer
, 1, FileLength
, fpIn
);
2028 // write input file to out file
2030 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2032 // write pad value to out file.
2034 while (FileLength
++ % MciAlignment
!= 0) {
2035 fwrite (&MciPadValue
, 1, 1, fpOut
);
2038 // free allocated memory space
2044 // Done successfully
2050 // Convert MicroCode.txt file to MicroCode.bin file
2052 if (OutImageType
== FW_MCI_IMAGE
) {
2053 fpIn
= fopen (mInImageName
, "r");
2055 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2060 // The first pass is to determine
2061 // how much data is in the file so we can allocate a working buffer.
2065 Status
= MicrocodeReadData (fpIn
, &Data
);
2066 if (Status
== STATUS_SUCCESS
) {
2067 FileLength
+= sizeof (Data
);
2069 if (Status
== STATUS_IGNORE
) {
2070 Status
= STATUS_SUCCESS
;
2072 } while (Status
== STATUS_SUCCESS
);
2074 // Error if no data.
2076 if (FileLength
== 0) {
2077 Error (NULL
, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName
);
2080 if (FileLength
< sizeof (MICROCODE_IMAGE_HEADER
)) {
2081 Error (NULL
, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName
);
2086 // Allocate a buffer for the data
2088 FileBuffer
= malloc (FileLength
);
2089 if (FileBuffer
== NULL
) {
2090 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2094 // Re-read the file, storing the data into our buffer
2096 fseek (fpIn
, 0, SEEK_SET
);
2097 DataPointer
= (UINT32
*) FileBuffer
;
2098 OldDataPointer
= DataPointer
;
2100 OldDataPointer
= DataPointer
;
2101 Status
= MicrocodeReadData (fpIn
, DataPointer
++);
2102 if (Status
== STATUS_IGNORE
) {
2103 DataPointer
= OldDataPointer
;
2104 Status
= STATUS_SUCCESS
;
2106 } while (Status
== STATUS_SUCCESS
);
2108 // close input file after read data
2113 // Can't do much checking on the header because, per the spec, the
2114 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
2115 // and the TotalSize field is invalid (actually missing). Thus we can't
2116 // even verify the Reserved fields are 0.
2118 MciHeader
= (MICROCODE_IMAGE_HEADER
*) FileBuffer
;
2119 if (MciHeader
->DataSize
== 0) {
2122 Index
= MciHeader
->TotalSize
;
2125 if (Index
!= FileLength
) {
2126 Error (NULL
, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName
, (unsigned) FileLength
, (unsigned) Index
);
2131 // Checksum the contents
2133 DataPointer
= (UINT32
*) FileBuffer
;
2136 while (Index
< FileLength
) {
2137 CheckSum
+= *DataPointer
;
2139 Index
+= sizeof (*DataPointer
);
2141 if (CheckSum
!= 0) {
2142 Error (NULL
, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum
, mInImageName
);
2146 // Open the output file and write the buffer contents
2148 if (fpOut
!= NULL
) {
2149 if (fwrite (FileBuffer
, FileLength
, 1, fpOut
) != 1) {
2150 Error (NULL
, 0, 0002, "Error writing file", OutImageName
);
2156 fpInOut
= fopen (mInImageName
, "wb");
2157 if (fpInOut
!= NULL
) {
2158 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2161 if (fwrite (FileBuffer
, FileLength
, 1, fpInOut
) != 1) {
2162 Error (NULL
, 0, 0002, "Error writing file", mInImageName
);
2166 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2168 // Convert Mci.TXT to Mci.bin file successfully
2174 // Open input file and read file data into file buffer.
2176 fpIn
= fopen (mInImageName
, "rb");
2178 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2182 FileLength
= _filelength (fileno (fpIn
));
2183 FileBuffer
= malloc (FileLength
);
2184 if (FileBuffer
== NULL
) {
2185 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2190 fread (FileBuffer
, 1, FileLength
, fpIn
);
2193 DebugMsg (NULL
, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) FileLength
);
2199 fpInOut
= fopen (mInImageName
, "wb");
2201 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2206 // Dump TeImage Header into output file.
2208 if (OutImageType
== DUMP_TE_HEADER
) {
2209 memcpy (&TEImageHeader
, FileBuffer
, sizeof (TEImageHeader
));
2210 if (TEImageHeader
.Signature
!= EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2211 Error (NULL
, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName
);
2214 if (fpInOut
!= NULL
) {
2215 fprintf (fpInOut
, "Dump of file %s\n\n", mInImageName
);
2216 fprintf (fpInOut
, "TE IMAGE HEADER VALUES\n");
2217 fprintf (fpInOut
, "%17X machine\n", TEImageHeader
.Machine
);
2218 fprintf (fpInOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
2219 fprintf (fpInOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
2220 fprintf (fpInOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
2221 fprintf (fpInOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
2222 fprintf (fpInOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
2223 fprintf (fpInOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
2224 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
2225 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
2228 if (fpOut
!= NULL
) {
2229 fprintf (fpOut
, "Dump of file %s\n\n", mInImageName
);
2230 fprintf (fpOut
, "TE IMAGE HEADER VALUES\n");
2231 fprintf (fpOut
, "%17X machine\n", TEImageHeader
.Machine
);
2232 fprintf (fpOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
2233 fprintf (fpOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
2234 fprintf (fpOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
2235 fprintf (fpOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
2236 fprintf (fpOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
2237 fprintf (fpOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
2238 fprintf (fpOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
2239 fprintf (fpOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
2245 // Following code to convert dll to efi image or te image.
2246 // Get new image type
2248 if ((OutImageType
== FW_EFI_IMAGE
) || (OutImageType
== FW_TE_IMAGE
)) {
2249 if (ModuleType
== NULL
) {
2250 if (OutImageType
== FW_EFI_IMAGE
) {
2251 Error (NULL
, 0, 1001, "Missing option", "EFI_FILETYPE");
2253 } else if (OutImageType
== FW_TE_IMAGE
) {
2255 // Default TE Image Type is Boot service driver
2257 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2258 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2261 if (stricmp (ModuleType
, "BASE") == 0 ||
2262 stricmp (ModuleType
, "SEC") == 0 ||
2263 stricmp (ModuleType
, "SECURITY_CORE") == 0 ||
2264 stricmp (ModuleType
, "PEI_CORE") == 0 ||
2265 stricmp (ModuleType
, "PEIM") == 0 ||
2266 stricmp (ModuleType
, "COMBINED_PEIM_DRIVER") == 0 ||
2267 stricmp (ModuleType
, "PIC_PEIM") == 0 ||
2268 stricmp (ModuleType
, "RELOCATABLE_PEIM") == 0 ||
2269 stricmp (ModuleType
, "DXE_CORE") == 0 ||
2270 stricmp (ModuleType
, "BS_DRIVER") == 0 ||
2271 stricmp (ModuleType
, "DXE_DRIVER") == 0 ||
2272 stricmp (ModuleType
, "DXE_SMM_DRIVER") == 0 ||
2273 stricmp (ModuleType
, "UEFI_DRIVER") == 0 ||
2274 stricmp (ModuleType
, "SMM_DRIVER") == 0 ||
2275 stricmp (ModuleType
, "SMM_CORE") == 0) {
2276 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2277 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2279 } else if (stricmp (ModuleType
, "UEFI_APPLICATION") == 0 ||
2280 stricmp (ModuleType
, "APPLICATION") == 0) {
2281 Type
= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
;
2282 VerboseMsg ("Efi Image subsystem type is efi application.");
2284 } else if (stricmp (ModuleType
, "DXE_RUNTIME_DRIVER") == 0 ||
2285 stricmp (ModuleType
, "RT_DRIVER") == 0) {
2286 Type
= EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
;
2287 VerboseMsg ("Efi Image subsystem type is efi runtime driver.");
2289 } else if (stricmp (ModuleType
, "DXE_SAL_DRIVER") == 0 ||
2290 stricmp (ModuleType
, "SAL_RT_DRIVER") == 0) {
2291 Type
= EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
;
2292 VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");
2295 Error (NULL
, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType
);
2302 // Convert EFL image to PeImage
2304 if (IsElfHeader(FileBuffer
)) {
2305 VerboseMsg ("Convert the input ELF Image to Pe Image");
2306 ConvertElf(&FileBuffer
, &FileLength
);
2310 // Remove reloc section from PE or TE image
2312 if (OutImageType
== FW_RELOC_STRIPEED_IMAGE
) {
2316 TeHdr
= (EFI_TE_IMAGE_HEADER
*) FileBuffer
;
2317 if (TeHdr
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2318 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (TeHdr
+ 1);
2319 for (Index
= 0; Index
< TeHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2320 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2322 // Check the reloc section is in the end of image.
2324 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) ==
2325 (FileLength
+ TeHdr
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
))) {
2327 // Remove .reloc section and update TeImage Header
2329 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2330 SectionHeader
->SizeOfRawData
= 0;
2331 SectionHeader
->Misc
.VirtualSize
= 0;
2332 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2333 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2342 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2343 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2344 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2345 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2346 Error (NULL
, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName
);
2351 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2352 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2353 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2357 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2358 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2359 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2361 // Check the reloc section is in the end of image.
2363 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) == FileLength
) {
2365 // Remove .reloc section and update PeImage Header
2367 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2369 PeHdr
->Pe32
.FileHeader
.Characteristics
|= EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2370 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2371 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2372 Optional32
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2373 Optional32
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2374 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2375 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2376 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2379 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2380 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2381 Optional64
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2382 Optional64
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2383 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2384 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2385 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2388 SectionHeader
->Misc
.VirtualSize
= 0;
2389 SectionHeader
->SizeOfRawData
= 0;
2401 // Read the dos & pe hdrs of the image
2403 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2404 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2405 // NO DOS header, check for PE/COFF header
2406 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2407 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2408 Error (NULL
, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName
);
2414 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2415 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2416 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2421 if (PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_ARM
) {
2422 // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
2423 // so patch back to the offical UEFI value.
2424 PeHdr
->Pe32
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_ARMT
;
2428 // Extract bin data from Pe image.
2430 if (OutImageType
== FW_BIN_IMAGE
) {
2431 if (FileLength
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
2432 Error (NULL
, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName
);
2436 // Output bin data from exe file
2438 if (fpOut
!= NULL
) {
2439 fwrite (FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, 1, FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, fpOut
);
2441 if (fpInOut
!= NULL
) {
2442 fwrite (FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, 1, FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, fpInOut
);
2444 VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
));
2449 // Zero Debug Information of Pe Image
2451 if (OutImageType
== FW_ZERO_DEBUG_IMAGE
) {
2452 Status
= ZeroDebugData (FileBuffer
, TRUE
);
2453 if (EFI_ERROR (Status
)) {
2454 Error (NULL
, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status
);
2458 if (fpOut
!= NULL
) {
2459 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2461 if (fpInOut
!= NULL
) {
2462 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2464 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2469 // Set Time Stamp of Pe Image
2471 if (OutImageType
== FW_SET_STAMP_IMAGE
) {
2472 Status
= SetStamp (FileBuffer
, TimeStamp
);
2473 if (EFI_ERROR (Status
)) {
2477 if (fpOut
!= NULL
) {
2478 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2480 if (fpInOut
!= NULL
) {
2481 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2483 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2488 // Extract acpi data from pe image.
2490 if (OutImageType
== FW_ACPI_IMAGE
) {
2491 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2492 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2493 if (strcmp ((char *)SectionHeader
->Name
, ".data") == 0 || strcmp ((char *)SectionHeader
->Name
, ".sdata") == 0) {
2497 if (SectionHeader
->Misc
.VirtualSize
< SectionHeader
->SizeOfRawData
) {
2498 FileLength
= SectionHeader
->Misc
.VirtualSize
;
2500 FileLength
= SectionHeader
->SizeOfRawData
;
2503 if (CheckAcpiTable (FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
) != STATUS_SUCCESS
) {
2504 Error (NULL
, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName
);
2509 // Output Apci data to file
2511 if (fpOut
!= NULL
) {
2512 fwrite (FileBuffer
+ SectionHeader
->PointerToRawData
, 1, FileLength
, fpOut
);
2514 if (fpInOut
!= NULL
) {
2515 fwrite (FileBuffer
+ SectionHeader
->PointerToRawData
, 1, FileLength
, fpInOut
);
2517 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2521 Error (NULL
, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName
);
2525 // Zero all unused fields of the DOS header
2527 if (DosHdr
!= NULL
) {
2528 memcpy (&BackupDosHdr
, DosHdr
, sizeof (EFI_IMAGE_DOS_HEADER
));
2529 memset (DosHdr
, 0, sizeof (EFI_IMAGE_DOS_HEADER
));
2530 DosHdr
->e_magic
= BackupDosHdr
.e_magic
;
2531 DosHdr
->e_lfanew
= BackupDosHdr
.e_lfanew
;
2533 for (Index
= sizeof (EFI_IMAGE_DOS_HEADER
); Index
< (UINT32
) DosHdr
->e_lfanew
; Index
++) {
2534 FileBuffer
[Index
] = (UINT8
) DosHdr
->e_cp
;
2539 // Initialize TeImage Header
2541 memset (&TEImageHeader
, 0, sizeof (EFI_TE_IMAGE_HEADER
));
2542 TEImageHeader
.Signature
= EFI_TE_IMAGE_HEADER_SIGNATURE
;
2543 TEImageHeader
.Machine
= PeHdr
->Pe32
.FileHeader
.Machine
;
2544 TEImageHeader
.NumberOfSections
= (UINT8
) PeHdr
->Pe32
.FileHeader
.NumberOfSections
;
2545 TEImageHeader
.StrippedSize
= (UINT16
) ((UINTN
) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
) - (UINTN
) FileBuffer
);
2546 TEImageHeader
.Subsystem
= (UINT8
) Type
;
2549 // Patch the PE header
2551 PeHdr
->Pe32
.OptionalHeader
.Subsystem
= (UINT16
) Type
;
2553 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2554 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2555 Optional32
->MajorLinkerVersion
= 0;
2556 Optional32
->MinorLinkerVersion
= 0;
2557 Optional32
->MajorOperatingSystemVersion
= 0;
2558 Optional32
->MinorOperatingSystemVersion
= 0;
2559 Optional32
->MajorImageVersion
= 0;
2560 Optional32
->MinorImageVersion
= 0;
2561 Optional32
->MajorSubsystemVersion
= 0;
2562 Optional32
->MinorSubsystemVersion
= 0;
2563 Optional32
->Win32VersionValue
= 0;
2564 Optional32
->CheckSum
= 0;
2565 Optional32
->SizeOfStackReserve
= 0;
2566 Optional32
->SizeOfStackCommit
= 0;
2567 Optional32
->SizeOfHeapReserve
= 0;
2568 Optional32
->SizeOfHeapCommit
= 0;
2570 TEImageHeader
.AddressOfEntryPoint
= Optional32
->AddressOfEntryPoint
;
2571 TEImageHeader
.BaseOfCode
= Optional32
->BaseOfCode
;
2572 TEImageHeader
.ImageBase
= (UINT64
) (Optional32
->ImageBase
);
2574 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2575 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2576 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2579 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2580 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2581 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2585 // Zero .pdata section data.
2587 if (!KeepExceptionTableFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2588 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2589 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2590 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2591 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2592 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2594 // Zero .pdata Section data
2596 memset (FileBuffer
+ SectionHeader
->PointerToRawData
, 0, SectionHeader
->SizeOfRawData
);
2598 // Zero .pdata Section header name
2600 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2602 // Zero Execption Table
2604 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2605 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2606 DebugMsg (NULL
, 0, 9, "Zero the .pdata section for PE image", NULL
);
2613 // Strip zero padding at the end of the .reloc section
2615 if (!KeepZeroPendingFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2616 if (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2617 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2618 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2620 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2622 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2623 SectionHeader
->Misc
.VirtualSize
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2624 AllignedRelocSize
= (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional32
->FileAlignment
- 1) & (~(Optional32
->FileAlignment
- 1));
2626 // Check to see if there is zero padding at the end of the base relocations
2628 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2630 // Check to see if the base relocations are at the end of the file
2632 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional32
->SizeOfImage
) {
2634 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2636 Optional32
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2637 Optional32
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2638 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2639 FileLength
= Optional32
->SizeOfImage
;
2640 DebugMsg (NULL
, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader
->SizeOfRawData
- AllignedRelocSize
));
2647 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2648 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2649 Optional64
->MajorLinkerVersion
= 0;
2650 Optional64
->MinorLinkerVersion
= 0;
2651 Optional64
->MajorOperatingSystemVersion
= 0;
2652 Optional64
->MinorOperatingSystemVersion
= 0;
2653 Optional64
->MajorImageVersion
= 0;
2654 Optional64
->MinorImageVersion
= 0;
2655 Optional64
->MajorSubsystemVersion
= 0;
2656 Optional64
->MinorSubsystemVersion
= 0;
2657 Optional64
->Win32VersionValue
= 0;
2658 Optional64
->CheckSum
= 0;
2659 Optional64
->SizeOfStackReserve
= 0;
2660 Optional64
->SizeOfStackCommit
= 0;
2661 Optional64
->SizeOfHeapReserve
= 0;
2662 Optional64
->SizeOfHeapCommit
= 0;
2664 TEImageHeader
.AddressOfEntryPoint
= Optional64
->AddressOfEntryPoint
;
2665 TEImageHeader
.BaseOfCode
= Optional64
->BaseOfCode
;
2666 TEImageHeader
.ImageBase
= (UINT64
) (Optional64
->ImageBase
);
2668 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2669 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2670 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2673 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2674 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2675 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2679 // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
2680 // For Itaninum and X64 Image, remove .pdata section.
2682 if ((!KeepExceptionTableFlag
&& PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_X64
) || PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
) {
2683 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2684 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2685 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2686 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2687 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2688 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2690 // Zero .pdata Section header name
2692 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2694 RuntimeFunction
= (RUNTIME_FUNCTION
*)(FileBuffer
+ SectionHeader
->PointerToRawData
);
2695 for (Index1
= 0; Index1
< Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
/ sizeof (RUNTIME_FUNCTION
); Index1
++, RuntimeFunction
++) {
2696 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2697 for (Index2
= 0; Index2
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index2
++, SectionHeader
++) {
2698 if (RuntimeFunction
->UnwindInfoAddress
>= SectionHeader
->VirtualAddress
&& RuntimeFunction
->UnwindInfoAddress
< (SectionHeader
->VirtualAddress
+ SectionHeader
->SizeOfRawData
)) {
2699 UnwindInfo
= (UNWIND_INFO
*)(FileBuffer
+ SectionHeader
->PointerToRawData
+ (RuntimeFunction
->UnwindInfoAddress
- SectionHeader
->VirtualAddress
));
2700 if (UnwindInfo
->Version
== 1) {
2701 memset (UnwindInfo
+ 1, 0, UnwindInfo
->CountOfUnwindCodes
* sizeof (UINT16
));
2702 memset (UnwindInfo
, 0, sizeof (UNWIND_INFO
));
2707 memset (RuntimeFunction
, 0, sizeof (RUNTIME_FUNCTION
));
2710 // Zero Execption Table
2712 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2713 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2714 DebugMsg (NULL
, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL
);
2722 // Strip zero padding at the end of the .reloc section
2724 if (!KeepZeroPendingFlag
&& Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2725 if (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2726 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2727 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2729 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2731 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2732 SectionHeader
->Misc
.VirtualSize
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2733 AllignedRelocSize
= (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional64
->FileAlignment
- 1) & (~(Optional64
->FileAlignment
- 1));
2735 // Check to see if there is zero padding at the end of the base relocations
2737 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2739 // Check to see if the base relocations are at the end of the file
2741 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional64
->SizeOfImage
) {
2743 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2745 Optional64
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2746 Optional64
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2747 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2748 FileLength
= Optional64
->SizeOfImage
;
2749 DebugMsg (NULL
, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader
->SizeOfRawData
- AllignedRelocSize
));
2757 Error (NULL
, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr
->Pe32
.OptionalHeader
.Magic
, mInImageName
);
2761 if (((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) == 0) && \
2762 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
== 0) && \
2763 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
== 0)) {
2765 // PeImage can be loaded into memory, but it has no relocation section.
2766 // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
2768 if (Optional32
!= NULL
) {
2769 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
2770 } else if (Optional64
!= NULL
) {
2771 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
2776 // Zero ExceptionTable Xdata
2778 if (!KeepExceptionTableFlag
) {
2779 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2780 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++) {
2781 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".xdata") == 0) {
2783 // zero .xdata section
2785 memset (FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, 0, SectionHeader
[Index
].SizeOfRawData
);
2786 DebugMsg (NULL
, 0, 9, NULL
, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", (unsigned) SectionHeader
[Index
].PointerToRawData
, (unsigned) SectionHeader
[Index
].SizeOfRawData
);
2793 // Zero Time/Data field
2795 ZeroDebugData (FileBuffer
, FALSE
);
2797 if (OutImageType
== FW_TE_IMAGE
) {
2798 if ((PeHdr
->Pe32
.FileHeader
.NumberOfSections
&~0xFF) || (Type
&~0xFF)) {
2800 // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
2802 Error (NULL
, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName
);
2806 if ((PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
)) {
2808 // TeImage has the same section alignment and file alignment.
2810 Error (NULL
, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName
);
2814 DebugMsg (NULL
, 0, 9, "TeImage Header Info", "Machine type is %X, Number of sections is %X, Stripped size is %X, EntryPoint is %X, BaseOfCode is %X, ImageBase is %llX",
2815 TEImageHeader
.Machine
, TEImageHeader
.NumberOfSections
, TEImageHeader
.StrippedSize
, (unsigned) TEImageHeader
.AddressOfEntryPoint
, (unsigned) TEImageHeader
.BaseOfCode
, (unsigned long long) TEImageHeader
.ImageBase
);
2817 // Update Image to TeImage
2819 if (fpOut
!= NULL
) {
2820 fwrite (&TEImageHeader
, 1, sizeof (EFI_TE_IMAGE_HEADER
), fpOut
);
2821 fwrite (FileBuffer
+ TEImageHeader
.StrippedSize
, 1, FileLength
- TEImageHeader
.StrippedSize
, fpOut
);
2823 if (fpInOut
!= NULL
) {
2824 fwrite (&TEImageHeader
, 1, sizeof (EFI_TE_IMAGE_HEADER
), fpInOut
);
2825 fwrite (FileBuffer
+ TEImageHeader
.StrippedSize
, 1, FileLength
- TEImageHeader
.StrippedSize
, fpInOut
);
2827 VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength
- TEImageHeader
.StrippedSize
));
2832 // Update Image to EfiImage
2834 if (fpOut
!= NULL
) {
2835 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2837 if (fpInOut
!= NULL
) {
2838 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2840 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2843 if (fpInOut
!= NULL
) {
2844 if (GetUtilityStatus () != STATUS_SUCCESS
) {
2846 // when file updates failed, original file is still recoveried.
2848 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2851 // Write converted data into fpInOut file and close input file.
2856 if (FileBuffer
!= NULL
) {
2860 if (InputFileName
!= NULL
) {
2861 free (InputFileName
);
2864 if (fpOut
!= NULL
) {
2866 // Write converted data into fpOut file and close output file.
2869 if (GetUtilityStatus () != STATUS_SUCCESS
) {
2870 if (OutputFileBuffer
== NULL
) {
2871 remove (OutImageName
);
2873 fpOut
= fopen (OutImageName
, "wb");
2874 fwrite (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
2876 free (OutputFileBuffer
);
2881 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
2883 return GetUtilityStatus ();
2889 IN OUT UINT8
*FileBuffer
,
2890 BOOLEAN ZeroDebugFlag
2894 Routine Description:
2896 Zero debug information in PeImage.
2900 FileBuffer - Pointer to PeImage.
2901 ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp
2905 EFI_ABORTED - PeImage is invalid.
2906 EFI_SUCCESS - Zero debug data successfully.
2911 UINT32 DebugDirectoryEntryRva
;
2912 UINT32 DebugDirectoryEntryFileOffset
;
2913 UINT32 ExportDirectoryEntryRva
;
2914 UINT32 ExportDirectoryEntryFileOffset
;
2915 UINT32 ResourceDirectoryEntryRva
;
2916 UINT32 ResourceDirectoryEntryFileOffset
;
2917 EFI_IMAGE_DOS_HEADER
*DosHdr
;
2918 EFI_IMAGE_FILE_HEADER
*FileHdr
;
2919 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
2920 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
2921 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
2922 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
2923 UINT32
*NewTimeStamp
;
2928 DebugDirectoryEntryRva
= 0;
2929 ExportDirectoryEntryRva
= 0;
2930 ResourceDirectoryEntryRva
= 0;
2931 DebugDirectoryEntryFileOffset
= 0;
2932 ExportDirectoryEntryFileOffset
= 0;
2933 ResourceDirectoryEntryFileOffset
= 0;
2934 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2935 FileHdr
= (EFI_IMAGE_FILE_HEADER
*) (FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2938 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2939 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2940 // NO DOS header, must start with PE/COFF header
2941 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
2943 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2947 // Get Debug, Export and Resource EntryTable RVA address.
2948 // Resource Directory entry need to review.
2950 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
2951 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2952 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2953 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2954 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2955 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2957 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2958 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2959 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2961 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2962 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2963 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2964 if (ZeroDebugFlag
) {
2965 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
2966 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
2970 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2971 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2972 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2973 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2974 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2976 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2977 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2978 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2980 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2981 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2982 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2983 if (ZeroDebugFlag
) {
2984 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
2985 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
2991 // Get DirectoryEntryTable file offset.
2993 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2994 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2995 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2996 DebugDirectoryEntryFileOffset
=
2997 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2999 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3000 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3001 ExportDirectoryEntryFileOffset
=
3002 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3004 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3005 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3006 ResourceDirectoryEntryFileOffset
=
3007 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3012 //Zero Debug Data and TimeStamp
3014 FileHdr
->TimeDateStamp
= 0;
3016 if (ExportDirectoryEntryFileOffset
!= 0) {
3017 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
3021 if (ResourceDirectoryEntryFileOffset
!= 0) {
3022 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
3026 if (DebugDirectoryEntryFileOffset
!= 0) {
3027 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
);
3028 DebugEntry
->TimeDateStamp
= 0;
3029 if (ZeroDebugFlag
) {
3030 memset (FileBuffer
+ DebugEntry
->FileOffset
, 0, DebugEntry
->SizeOfData
);
3031 memset (DebugEntry
, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
3041 IN OUT UINT8
*FileBuffer
,
3046 Routine Description:
3048 Set new time stamp into PeImage FileHdr and Directory table:
3049 Debug, Export and Resource.
3053 FileBuffer - Pointer to PeImage.
3054 TimeStamp - Time stamp string.
3058 EFI_INVALID_PARAMETER - TimeStamp format is not recognized.
3059 EFI_SUCCESS - Set new time stamp in this image successfully.
3067 UINT32 DebugDirectoryEntryRva
;
3068 UINT32 DebugDirectoryEntryFileOffset
;
3069 UINT32 ExportDirectoryEntryRva
;
3070 UINT32 ExportDirectoryEntryFileOffset
;
3071 UINT32 ResourceDirectoryEntryRva
;
3072 UINT32 ResourceDirectoryEntryFileOffset
;
3073 EFI_IMAGE_DOS_HEADER
*DosHdr
;
3074 EFI_IMAGE_FILE_HEADER
*FileHdr
;
3075 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
3076 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
3077 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
3078 UINT32
*NewTimeStamp
;
3083 DebugDirectoryEntryRva
= 0;
3084 DebugDirectoryEntryFileOffset
= 0;
3085 ExportDirectoryEntryRva
= 0;
3086 ExportDirectoryEntryFileOffset
= 0;
3087 ResourceDirectoryEntryRva
= 0;
3088 ResourceDirectoryEntryFileOffset
= 0;
3090 // Get time and date that will be set.
3092 if (TimeStamp
== NULL
) {
3093 Error (NULL
, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");
3094 return EFI_INVALID_PARAMETER
;
3097 // compare the value with "NOW", if yes, current system time is set.
3099 if (stricmp (TimeStamp
, "NOW") == 0) {
3101 // get system current time and date
3106 // Check Time Format strictly yyyy-mm-dd 00:00:00
3108 for (Index
= 0; TimeStamp
[Index
] != '\0' && Index
< 20; Index
++) {
3109 if (Index
== 4 || Index
== 7) {
3110 if (TimeStamp
[Index
] == '-') {
3113 } else if (Index
== 13 || Index
== 16) {
3114 if (TimeStamp
[Index
] == ':') {
3117 } else if (Index
== 10 && TimeStamp
[Index
] == ' ') {
3119 } else if ((TimeStamp
[Index
] < '0') || (TimeStamp
[Index
] > '9')) {
3124 if (Index
< 19 || TimeStamp
[19] != '\0') {
3125 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
3126 return EFI_INVALID_PARAMETER
;
3130 // get the date and time from TimeStamp
3132 if (sscanf (TimeStamp
, "%d-%d-%d %d:%d:%d",
3140 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
3141 return EFI_INVALID_PARAMETER
;
3145 // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
3147 if (stime
.tm_mon
<= 0 || stime
.tm_mday
<=0) {
3148 Error (NULL
, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp
);
3149 return EFI_INVALID_PARAMETER
;
3154 // in struct, Year (current year minus 1900)
3155 // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
3158 // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
3160 if (stime
.tm_year
>= 1970 && stime
.tm_year
<= 2038) {
3162 // convert 1970 -> 70, 2000 -> 100, ...
3164 stime
.tm_year
-= 1900;
3166 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
3167 return EFI_INVALID_PARAMETER
;
3171 // convert the date and time to time_t format
3173 newtime
= mktime (&stime
);
3174 if (newtime
== (time_t) - 1) {
3175 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
3176 return EFI_INVALID_PARAMETER
;
3180 ptime
= localtime (&newtime
);
3181 DebugMsg (NULL
, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",
3182 ptime
->tm_year
+ 1900, ptime
->tm_mon
+ 1, ptime
->tm_mday
, ptime
->tm_hour
, ptime
->tm_min
, ptime
->tm_sec
);
3184 // Set new time and data into PeImage.
3186 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
3187 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
3188 // NO DOS header, must start with PE/COFF header
3189 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
3191 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
3195 // Get Debug, Export and Resource EntryTable RVA address.
3196 // Resource Directory entry need to review.
3198 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
3199 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3200 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3201 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3202 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3203 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3205 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3206 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3207 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3209 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3210 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3211 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3214 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3215 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3216 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3217 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3218 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3220 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3221 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3222 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3224 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3225 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3226 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3231 // Get DirectoryEntryTable file offset.
3233 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
3234 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3235 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3236 DebugDirectoryEntryFileOffset
=
3237 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3239 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3240 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3241 ExportDirectoryEntryFileOffset
=
3242 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3244 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3245 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3246 ResourceDirectoryEntryFileOffset
=
3247 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3254 FileHdr
->TimeDateStamp
= (UINT32
) newtime
;
3256 if (ExportDirectoryEntryRva
!= 0) {
3257 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
3258 *NewTimeStamp
= (UINT32
) newtime
;
3261 if (ResourceDirectoryEntryRva
!= 0) {
3262 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
3263 *NewTimeStamp
= (UINT32
) newtime
;
3266 if (DebugDirectoryEntryRva
!= 0) {
3267 NewTimeStamp
= (UINT32
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
+ sizeof (UINT32
));
3268 *NewTimeStamp
= (UINT32
) newtime
;
3282 Routine Description:
3283 Read a 32-bit microcode data value from a text file and convert to raw binary form.
3286 InFptr - file pointer to input text file
3287 Data - pointer to where to return the data parsed
3290 STATUS_SUCCESS - no errors or warnings, Data contains valid information
3291 STATUS_ERROR - errors were encountered
3295 CHAR8 Line
[MAX_LINE_LEN
];
3297 unsigned ScannedData
= 0;
3299 Line
[MAX_LINE_LEN
- 1] = 0;
3301 if (fgets (Line
, MAX_LINE_LEN
, InFptr
) == NULL
) {
3302 return STATUS_ERROR
;
3305 // If it was a binary file, then it may have overwritten our null terminator
3307 if (Line
[MAX_LINE_LEN
- 1] != 0) {
3308 return STATUS_ERROR
;
3314 for (cptr
= Line
; *cptr
&& isspace(*cptr
); cptr
++) {
3317 // Skip Blank Lines and Comment Lines
3318 if ((strlen(cptr
) != 0) && (*cptr
!= ';')) {
3324 // dd 000000001h ; comment
3329 if ((tolower(cptr
[0]) == 'd') && (tolower(cptr
[1]) == 'd') && isspace (cptr
[2])) {
3331 // Skip blanks and look for a hex digit
3334 for (; *cptr
&& isspace(*cptr
); cptr
++) {
3336 if (isxdigit (*cptr
)) {
3337 if (sscanf (cptr
, "%X", &ScannedData
) != 1) {
3338 return STATUS_ERROR
;
3341 *Data
= (UINT32
) ScannedData
;
3342 return STATUS_SUCCESS
;
3345 return STATUS_ERROR
;