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
80 #define FW_HII_PACKAGE_LIST_BINIMAGE 11
82 #define DUMP_TE_HEADER 0x11
84 #define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
85 #define DEFAULT_MC_ALIGNMENT 16
91 #define STATUS_IGNORE 0xA
93 // Structure definition for a microcode header
101 UINT32 LoaderVersion
;
103 UINT32 DataSize
; // if 0, then TotalSize = 2048, and TotalSize field is invalid
104 UINT32 TotalSize
; // number of bytes
106 } MICROCODE_IMAGE_HEADER
;
108 static EFI_GUID mZeroGuid
= {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
110 static const char *gHiiPackageRCFileHeader
[] = {
112 "// DO NOT EDIT -- auto-generated file",
117 STATIC CHAR8
*mInImageName
;
122 IN OUT UINT8
*FileBuffer
,
129 IN OUT UINT8
*FileBuffer
,
149 Print out version information for this utility.
161 fprintf (stdout
, "%s Version %d.%d\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
);
188 fprintf (stdout
, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME
);
191 // Copyright declaration
193 fprintf (stdout
, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");
198 fprintf (stdout
, "Options:\n");
199 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
200 File will be created to store the ouput content.\n");
201 fprintf (stdout
, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\
202 Create Efi Image. EFI_FILETYPE is one of BASE,SMM_CORE,\n\
203 PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\
204 SEC, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER,\n\
205 DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER,\n\
206 PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\
207 APPLICATION, SAL_RT_DRIVER to support all module types\n\
208 It can only be used together with --keepexceptiontable,\n\
209 --keepzeropending, -r, -o option.It is a action option.\n\
210 If it is combined with other action options, the later\n\
211 input action option will override the previous one.\n");
212 fprintf (stdout
, " -c, --acpi Create Acpi table.\n\
213 It can't be combined with other action options\n\
214 except for -o, -r option. It is a action option.\n\
215 If it is combined with other action options, the later\n\
216 input action option will override the previous one.\n");
217 fprintf (stdout
, " -t, --terse Create Te Image.\n\
218 It can only be used together with --keepexceptiontable,\n\
219 --keepzeropending, -r, -o option.It is a action option.\n\
220 If it is combined with other action options, the later\n\
221 input action option will override the previous one.\n");
222 fprintf (stdout
, " -u, --dump Dump TeImage Header.\n\
223 It can't be combined with other action options\n\
224 except for -o, -r option. It is a action option.\n\
225 If it is combined with other action options, the later\n\
226 input action option will override the previous one.\n");
227 fprintf (stdout
, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\
228 It also zeros the time stamp fields.\n\
229 This option can be used to compare the binary efi image.\n\
230 It can't be combined with other action options\n\
231 except for -o, -r option. It is a action option.\n\
232 If it is combined with other action options, the later\n\
233 input action option will override the previous one.\n");
234 fprintf (stdout
, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\
235 It can't be combined with other action options\n\
236 except for -o, -r option. It is a action option.\n\
237 If it is combined with other action options, the later\n\
238 input action option will override the previous one.\n");;
239 fprintf (stdout
, " -l, --stripped Strip off the relocation info from PE or TE image.\n\
240 It can't be combined with other action options\n\
241 except for -o, -r option. It is a action option.\n\
242 If it is combined with other action options, the later\n\
243 input action option will override the previous one.\n");
244 fprintf (stdout
, " -s timedate, --stamp timedate\n\
245 timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\
246 is set to NOW, current system time is used. The support\n\
247 date scope is 1970-1-1 8:0:0 ~ 2038-1-19 3:14:07\n\
248 It can't be combined with other action options\n\
249 except for -o, -r option. It is a action option.\n\
250 If it is combined with other action options, the later\n\
251 input action option will override the previous one.\n");
252 fprintf (stdout
, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\
253 It can't be combined with other action options\n\
254 except for -o option. It is a action option.\n\
255 If it is combined with other action options, the later\n\
256 input action option will override the previous one.\n");
257 fprintf (stdout
, " -j, --join Combine multi microcode bin files to one file.\n\
258 It can be specified with -a, -p, -o option.\n\
259 No other options can be combined with it.\n\
260 If it is combined with other action options, the later\n\
261 input action option will override the previous one.\n");
262 fprintf (stdout
, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\
263 This option is only used together with -j option.\n");
264 fprintf (stdout
, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\
265 This option is only used together with -j option.\n");
266 fprintf (stdout
, " --keepexceptiontable Don't clear exception table.\n\
267 This option can be used together with -e or -t.\n\
268 It doesn't work for other options.\n");
269 fprintf (stdout
, " --keepzeropending Don't strip zero pending of .reloc.\n\
270 This option can be used together with -e or -t.\n\
271 It doesn't work for other options.\n");
272 fprintf (stdout
, " -r, --replace Overwrite the input file with the output content.\n\
273 If more input files are specified,\n\
274 the last input file will be as the output file.\n");
275 fprintf (stdout
, " -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\
276 Guid is used to specify hii package list guid.\n\
277 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\
278 If not specified, the first Form FormSet guid is used.\n");
279 fprintf (stdout
, " --hiipackage Combine all input binary hii pacakges into \n\
280 a single package list as the text resource data(RC).\n\
281 It can't be combined with other action options\n\
282 except for -o option. It is a action option.\n\
283 If it is combined with other action options, the later\n\
284 input action option will override the previous one.\n");
285 fprintf (stdout
, " --hiibinpackage Combine all input binary hii pacakges into \n\
286 a single package list as the binary resource section.\n\
287 It can't be combined with other action options\n\
288 except for -o option. It is a action option.\n\
289 If it is combined with other action options, the later\n\
290 input action option will override the previous one.\n");
291 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
292 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
293 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
294 fprintf (stdout
, " --version Show program's version number and exit\n");
295 fprintf (stdout
, " -h, --help Show this help message and exit\n");
312 AcpiTable Buffer for AcpiSection
313 Length AcpiSection Length
322 EFI_ACPI_DESCRIPTION_HEADER
*AcpiHeader
;
323 EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs
;
324 UINT32 ExpectedLength
;
326 AcpiHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTable
;
329 // Generic check for AcpiTable length.
331 if (AcpiHeader
->Length
> Length
) {
332 Error (NULL
, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL
);
337 // Currently, we only check must-have tables: FADT, FACS, DSDT,
338 // and some important tables: MADT, MCFG.
340 switch (AcpiHeader
->Signature
) {
343 // "FACP" Fixed ACPI Description Table
345 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
:
346 switch (AcpiHeader
->Revision
) {
347 case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
348 ExpectedLength
= sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
);
350 case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
351 ExpectedLength
= sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
);
353 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
354 ExpectedLength
= sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
);
357 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
) {
358 ExpectedLength
= AcpiHeader
->Length
;
361 Error (NULL
, 0, 3000, "Invalid", "FACP revision check failed.");
364 if (ExpectedLength
!= AcpiHeader
->Length
) {
365 Error (NULL
, 0, 3000, "Invalid", "FACP length check failed.");
371 // "FACS" Firmware ACPI Control Structure
373 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE
:
374 Facs
= (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)AcpiTable
;
375 if (Facs
->Version
> EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) {
378 if ((Facs
->Version
!= EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
379 (Facs
->Version
!= EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
380 (Facs
->Version
!= EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
)){
381 Error (NULL
, 0, 3000, "Invalid", "FACS version check failed.");
384 if ((Facs
->Length
!= sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
385 (Facs
->Length
!= sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
386 (Facs
->Length
!= sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
))) {
387 Error (NULL
, 0, 3000, "Invalid", "FACS length check failed.");
393 // "DSDT" Differentiated System Description Table
395 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
396 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION
) {
399 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
)) {
400 Error (NULL
, 0, 3000, "Invalid", "DSDT length check failed.");
406 // "APIC" Multiple APIC Description Table
408 case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE
:
409 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) {
412 if ((AcpiHeader
->Revision
!= EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
413 (AcpiHeader
->Revision
!= EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
414 (AcpiHeader
->Revision
!= EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
)) {
415 Error (NULL
, 0, 3000, "Invalid", "APIC revision check failed.");
418 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT32
) + sizeof(UINT32
)) {
419 Error (NULL
, 0, 3000, "Invalid", "APIC length check failed.");
425 // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
427 case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE
:
428 if (AcpiHeader
->Revision
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
431 if (AcpiHeader
->Revision
!= EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
432 Error (NULL
, 0, 3000, "Invalid", "MCFG revision check failed.");
435 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT64
)) {
436 Error (NULL
, 0, 3000, "Invalid", "MCFG length check failed.");
442 // Other table pass check
448 return STATUS_SUCCESS
;
457 return (FileBuffer
[EI_MAG0
] == ELFMAG0
458 && FileBuffer
[EI_MAG1
] == ELFMAG1
459 && FileBuffer
[EI_MAG2
] == ELFMAG2
460 && FileBuffer
[EI_MAG3
] == ELFMAG3
);
463 typedef Elf32_Shdr Elf_Shdr
;
464 typedef Elf32_Ehdr Elf_Ehdr
;
465 typedef Elf32_Rel Elf_Rel
;
466 typedef Elf32_Sym Elf_Sym
;
467 typedef Elf32_Phdr Elf_Phdr
;
468 typedef Elf32_Dyn Elf_Dyn
;
470 #define ELFCLASS ELFCLASS32
471 #define ELF_R_TYPE(r) ELF32_R_TYPE(r)
472 #define ELF_R_SYM(r) ELF32_R_SYM(r)
473 #define ELF_HII_SECTION_NAME ".hii"
475 // Well known ELF structures.
482 // PE section alignment.
484 const UINT32 CoffAlignment
= 0x20;
485 const UINT16 CoffNbrSections
= 5;
488 // Current offset in coff file.
493 // Result Coff file in memory.
495 UINT8
*CoffFile
= NULL
;
497 // ELF sections to offset in Coff file.
499 UINT32
*CoffSectionsOffset
= NULL
;
502 // Offset in Coff file of headers and sections.
508 UINT32 HiiRsrcOffset
;
511 EFI_IMAGE_BASE_RELOCATION
*CoffBaseRel
;
512 UINT16
*CoffEntryRel
;
519 return (Offset
+ CoffAlignment
- 1) & ~(CoffAlignment
- 1);
527 if (Num
>= Ehdr
->e_shnum
)
529 return (Elf_Shdr
*)((UINT8
*)ShdrBase
+ Num
* Ehdr
->e_shentsize
);
538 // Note: Magic has already been tested.
540 if (Ehdr
->e_ident
[EI_CLASS
] != ELFCLASS
) {
541 Error (NULL
, 0, 3000, "Unsupported", "%s needs to be ported for 64-bit ELF.", mInImageName
);
544 if (Ehdr
->e_ident
[EI_DATA
] != ELFDATA2LSB
) {
545 Error (NULL
, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");
548 if ((Ehdr
->e_type
!= ET_EXEC
) && (Ehdr
->e_type
!= ET_DYN
)) {
549 Error (NULL
, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");
552 if (!((Ehdr
->e_machine
== EM_386
) || (Ehdr
->e_machine
== EM_ARM
))) {
553 Error (NULL
, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM");
556 if (Ehdr
->e_version
!= EV_CURRENT
) {
557 Error (NULL
, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) Ehdr
->e_version
, EV_CURRENT
);
562 // Find the section header table
564 ShdrBase
= (Elf_Shdr
*)((UINT8
*)Ehdr
+ Ehdr
->e_shoff
);
565 gPhdrBase
= (Elf_Phdr
*)((UINT8
*)Ehdr
+ Ehdr
->e_phoff
);
567 CoffSectionsOffset
= (UINT32
*)malloc(Ehdr
->e_shnum
* sizeof (UINT32
));
569 memset(CoffSectionsOffset
, 0, Ehdr
->e_shnum
* sizeof(UINT32
));
578 return (Shdr
->sh_flags
& (SHF_WRITE
| SHF_ALLOC
)) == SHF_ALLOC
;
586 Elf_Shdr
*Namedr
= GetShdrByIndex(Ehdr
->e_shstrndx
);
588 if (strcmp((CHAR8
*)Ehdr
+ Namedr
->sh_offset
+ Shdr
->sh_name
, ELF_HII_SECTION_NAME
) == 0) {
600 if (IsHiiRsrcShdr(Shdr
)) {
603 return (Shdr
->sh_flags
& (SHF_WRITE
| SHF_ALLOC
)) == (SHF_ALLOC
| SHF_WRITE
);
614 EFI_IMAGE_SECTION_HEADER
*Hdr
;
615 Hdr
= (EFI_IMAGE_SECTION_HEADER
*)(CoffFile
+ TableOffset
);
617 strcpy((char *)Hdr
->Name
, Name
);
618 Hdr
->Misc
.VirtualSize
= Size
;
619 Hdr
->VirtualAddress
= Offset
;
620 Hdr
->SizeOfRawData
= Size
;
621 Hdr
->PointerToRawData
= Offset
;
622 Hdr
->PointerToRelocations
= 0;
623 Hdr
->PointerToLinenumbers
= 0;
624 Hdr
->NumberOfRelocations
= 0;
625 Hdr
->NumberOfLinenumbers
= 0;
626 Hdr
->Characteristics
= Flags
;
628 TableOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
632 SetHiiResourceHeader (
638 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
639 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*ResourceDirectoryEntry
;
640 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
641 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
644 // Fill Resource section entry
646 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
);
647 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
648 for (Index
= 0; Index
< ResourceDirectory
->NumberOfNamedEntries
; Index
++) {
649 if (ResourceDirectoryEntry
->u1
.s
.NameIsString
) {
650 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiBinData
+ ResourceDirectoryEntry
->u1
.s
.NameOffset
);
652 if (ResourceDirectoryString
->Length
== 3 &&
653 ResourceDirectoryString
->String
[0] == L
'H' &&
654 ResourceDirectoryString
->String
[1] == L
'I' &&
655 ResourceDirectoryString
->String
[2] == L
'I') {
657 // Resource Type "HII" found
659 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
661 // Move to next level - resource Name
663 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
664 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
666 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
668 // Move to next level - resource Language
670 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
671 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
676 // Now it ought to be resource Data and update its OffsetToData value
678 if (!ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
679 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.OffsetToData
);
680 ResourceDataEntry
->OffsetToData
= ResourceDataEntry
->OffsetToData
+ OffsetToFile
;
685 ResourceDirectoryEntry
++;
697 EFI_IMAGE_DOS_HEADER
*DosHdr
;
698 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
705 // Coff file start with a DOS header.
707 CoffOffset
= sizeof(EFI_IMAGE_DOS_HEADER
) + 0x40;
708 NtHdrOffset
= CoffOffset
;
709 switch (Ehdr
->e_machine
) {
712 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS32
);
716 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS64
);
719 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN
)Ehdr
->e_machine
);
720 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS32
);
724 TableOffset
= CoffOffset
;
725 CoffOffset
+= CoffNbrSections
* sizeof(EFI_IMAGE_SECTION_HEADER
);
728 // First text sections.
730 CoffOffset
= CoffAlign(CoffOffset
);
731 TextOffset
= CoffOffset
;
732 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
733 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
734 if (IsTextShdr(shdr
)) {
735 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
736 // the alignment field is valid
737 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
738 // if the section address is aligned we must align PE/COFF
739 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
740 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
741 // ARM RVCT tools have behavior outside of the ELF specification to try
742 // and make images smaller. If sh_addr is not aligned to sh_addralign
743 // then the section needs to preserve sh_addr MOD sh_addralign.
744 // Normally doing nothing here works great.
745 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
749 /* Relocate entry. */
750 if ((Ehdr
->e_entry
>= shdr
->sh_addr
) &&
751 (Ehdr
->e_entry
< shdr
->sh_addr
+ shdr
->sh_size
)) {
752 CoffEntry
= CoffOffset
+ Ehdr
->e_entry
- shdr
->sh_addr
;
754 CoffSectionsOffset
[i
] = CoffOffset
;
755 CoffOffset
+= shdr
->sh_size
;
759 if (Ehdr
->e_machine
!= EM_ARM
) {
760 CoffOffset
= CoffAlign(CoffOffset
);
764 // Then data sections.
766 DataOffset
= CoffOffset
;
767 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
768 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
769 if (IsDataShdr(shdr
)) {
770 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
771 // the alignment field is valid
772 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
773 // if the section address is aligned we must align PE/COFF
774 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
775 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
776 // ARM RVCT tools have behavior outside of the ELF specification to try
777 // and make images smaller. If sh_addr is not aligned to sh_addralign
778 // then the section needs to preserve sh_addr MOD sh_addralign.
779 // Normally doing nothing here works great.
780 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
783 CoffSectionsOffset
[i
] = CoffOffset
;
784 CoffOffset
+= shdr
->sh_size
;
787 CoffOffset
= CoffAlign(CoffOffset
);
790 // The HII resource sections.
792 HiiRsrcOffset
= CoffOffset
;
793 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
794 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
795 if (IsHiiRsrcShdr(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.");
809 if (shdr
->sh_size
!= 0) {
810 CoffSectionsOffset
[i
] = CoffOffset
;
811 CoffOffset
+= shdr
->sh_size
;
812 CoffOffset
= CoffAlign(CoffOffset
);
813 SetHiiResourceHeader ((UINT8
*) Ehdr
+ shdr
->sh_offset
, HiiRsrcOffset
);
819 RelocOffset
= CoffOffset
;
822 // Allocate base Coff file. Will be expanded later for relocations.
824 CoffFile
= (UINT8
*)malloc(CoffOffset
);
825 memset(CoffFile
, 0, CoffOffset
);
830 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)CoffFile
;
831 DosHdr
->e_magic
= EFI_IMAGE_DOS_SIGNATURE
;
832 DosHdr
->e_lfanew
= NtHdrOffset
;
834 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
836 NtHdr
->Pe32
.Signature
= EFI_IMAGE_NT_SIGNATURE
;
838 switch (Ehdr
->e_machine
) {
840 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IA32
;
841 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
844 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_X64
;
845 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
848 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IPF
;
849 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
852 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_ARMT
;
853 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
856 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN
)Ehdr
->e_machine
);
857 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IA32
;
858 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
861 NtHdr
->Pe32
.FileHeader
.NumberOfSections
= CoffNbrSections
;
862 NtHdr
->Pe32
.FileHeader
.TimeDateStamp
= (UINT32
) time(NULL
);
863 NtHdr
->Pe32
.FileHeader
.PointerToSymbolTable
= 0;
864 NtHdr
->Pe32
.FileHeader
.NumberOfSymbols
= 0;
865 NtHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
= sizeof(NtHdr
->Pe32
.OptionalHeader
);
866 NtHdr
->Pe32
.FileHeader
.Characteristics
= EFI_IMAGE_FILE_EXECUTABLE_IMAGE
867 | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED
868 | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED
869 | EFI_IMAGE_FILE_32BIT_MACHINE
;
871 NtHdr
->Pe32
.OptionalHeader
.SizeOfCode
= DataOffset
- TextOffset
;
872 NtHdr
->Pe32
.OptionalHeader
.SizeOfInitializedData
= RelocOffset
- DataOffset
;
873 NtHdr
->Pe32
.OptionalHeader
.SizeOfUninitializedData
= 0;
874 NtHdr
->Pe32
.OptionalHeader
.AddressOfEntryPoint
= CoffEntry
;
876 NtHdr
->Pe32
.OptionalHeader
.BaseOfCode
= TextOffset
;
878 NtHdr
->Pe32
.OptionalHeader
.BaseOfData
= DataOffset
;
879 NtHdr
->Pe32
.OptionalHeader
.ImageBase
= 0;
880 NtHdr
->Pe32
.OptionalHeader
.SectionAlignment
= CoffAlignment
;
881 NtHdr
->Pe32
.OptionalHeader
.FileAlignment
= CoffAlignment
;
882 NtHdr
->Pe32
.OptionalHeader
.SizeOfImage
= 0;
884 NtHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
= TextOffset
;
885 NtHdr
->Pe32
.OptionalHeader
.NumberOfRvaAndSizes
= EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES
;
890 if ((DataOffset
- TextOffset
) > 0) {
891 CreateSectionHeader (".text", TextOffset
, DataOffset
- TextOffset
,
892 EFI_IMAGE_SCN_CNT_CODE
893 | EFI_IMAGE_SCN_MEM_EXECUTE
894 | EFI_IMAGE_SCN_MEM_READ
);
896 // Don't make a section of size 0.
897 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
900 if ((HiiRsrcOffset
- DataOffset
) > 0) {
901 CreateSectionHeader (".data", DataOffset
, HiiRsrcOffset
- DataOffset
,
902 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
903 | EFI_IMAGE_SCN_MEM_WRITE
904 | EFI_IMAGE_SCN_MEM_READ
);
906 // Don't make a section of size 0.
907 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
910 if ((RelocOffset
- HiiRsrcOffset
) > 0) {
911 CreateSectionHeader (".rsrc", HiiRsrcOffset
, RelocOffset
- HiiRsrcOffset
,
912 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
913 | EFI_IMAGE_SCN_MEM_READ
);
915 NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= RelocOffset
- HiiRsrcOffset
;
916 NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= HiiRsrcOffset
;
918 // Don't make a section of size 0.
919 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
926 int (*Filter
)(Elf_Shdr
*)
934 // First: copy sections.
936 for (Idx
= 0; Idx
< Ehdr
->e_shnum
; Idx
++) {
937 Elf_Shdr
*Shdr
= GetShdrByIndex(Idx
);
938 if ((*Filter
)(Shdr
)) {
939 switch (Shdr
->sh_type
) {
942 memcpy(CoffFile
+ CoffSectionsOffset
[Idx
],
943 (UINT8
*)Ehdr
+ Shdr
->sh_offset
,
948 memset(CoffFile
+ CoffSectionsOffset
[Idx
], 0, Shdr
->sh_size
);
953 // Ignore for unkown section type.
955 VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName
, (unsigned)Shdr
->sh_type
);
962 // Second: apply relocations.
964 for (Idx
= 0; Idx
< Ehdr
->e_shnum
; Idx
++) {
965 Elf_Shdr
*RelShdr
= GetShdrByIndex(Idx
);
966 if (RelShdr
->sh_type
!= SHT_REL
)
968 SecShdr
= GetShdrByIndex(RelShdr
->sh_info
);
969 SecOffset
= CoffSectionsOffset
[RelShdr
->sh_info
];
970 if (RelShdr
->sh_type
== SHT_REL
&& (*Filter
)(SecShdr
)) {
972 Elf_Shdr
*SymtabShdr
= GetShdrByIndex(RelShdr
->sh_link
);
973 UINT8
*Symtab
= (UINT8
*)Ehdr
+ SymtabShdr
->sh_offset
;
975 for (RelIdx
= 0; RelIdx
< RelShdr
->sh_size
; RelIdx
+= RelShdr
->sh_entsize
) {
976 Elf_Rel
*Rel
= (Elf_Rel
*)((UINT8
*)Ehdr
+ RelShdr
->sh_offset
+ RelIdx
);
977 Elf_Sym
*Sym
= (Elf_Sym
*)(Symtab
+ ELF_R_SYM(Rel
->r_info
) * SymtabShdr
->sh_entsize
);
981 if (Sym
->st_shndx
== SHN_UNDEF
982 || Sym
->st_shndx
== SHN_ABS
983 || Sym
->st_shndx
> Ehdr
->e_shnum
) {
984 Error (NULL
, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName
);
986 SymShdr
= GetShdrByIndex(Sym
->st_shndx
);
989 // Note: r_offset in a memory address.
990 // Convert it to a pointer in the coff file.
992 Targ
= CoffFile
+ SecOffset
+ (Rel
->r_offset
- SecShdr
->sh_addr
);
994 if (Ehdr
->e_machine
== EM_386
) {
995 switch (ELF_R_TYPE(Rel
->r_info
)) {
1000 // Absolute relocation.
1002 *(UINT32
*)Targ
= *(UINT32
*)Targ
- SymShdr
->sh_addr
1003 + CoffSectionsOffset
[Sym
->st_shndx
];
1007 // Relative relocation: Symbol - Ip + Addend
1009 *(UINT32
*)Targ
= *(UINT32
*)Targ
1010 + (CoffSectionsOffset
[Sym
->st_shndx
] - SymShdr
->sh_addr
)
1011 - (SecOffset
- SecShdr
->sh_addr
);
1014 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, (unsigned) ELF_R_TYPE(Rel
->r_info
));
1016 } else if (Ehdr
->e_machine
== EM_ARM
) {
1017 switch (ELF32_R_TYPE(Rel
->r_info
)) {
1018 case R_ARM_RBASE
: // No relocation - no action required
1019 case R_ARM_PC24
: // PC-relative relocations don't require modification
1020 case R_ARM_XPC25
: // PC-relative relocations don't require modification
1025 // Absolute relocation.
1027 *(UINT32
*)Targ
= *(UINT32
*)Targ
- SymShdr
->sh_addr
+ CoffSectionsOffset
[Sym
->st_shndx
];
1030 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, (unsigned) ELF32_R_TYPE(Rel
->r_info
));
1043 *CoffEntryRel
= Val
;
1045 CoffBaseRel
->SizeOfBlock
+= 2;
1055 if (CoffBaseRel
== NULL
1056 || CoffBaseRel
->VirtualAddress
!= (Offset
& ~0xfff)) {
1057 if (CoffBaseRel
!= NULL
) {
1059 // Add a null entry (is it required ?)
1061 CoffAddFixupEntry (0);
1063 // Pad for alignment.
1065 if (CoffOffset
% 4 != 0)
1066 CoffAddFixupEntry (0);
1071 CoffOffset
+ sizeof(EFI_IMAGE_BASE_RELOCATION
) + 2*0x1000);
1072 memset(CoffFile
+ CoffOffset
, 0,
1073 sizeof(EFI_IMAGE_BASE_RELOCATION
) + 2*0x1000);
1075 CoffBaseRel
= (EFI_IMAGE_BASE_RELOCATION
*)(CoffFile
+ CoffOffset
);
1076 CoffBaseRel
->VirtualAddress
= Offset
& ~0xfff;
1077 CoffBaseRel
->SizeOfBlock
= sizeof(EFI_IMAGE_BASE_RELOCATION
);
1079 CoffEntryRel
= (UINT16
*)(CoffBaseRel
+ 1);
1080 CoffOffset
+= sizeof(EFI_IMAGE_BASE_RELOCATION
);
1086 CoffAddFixupEntry((UINT16
) ((Type
<< 12) | (Offset
& 0xfff)));
1095 if (num
>= Ehdr
->e_phnum
) {
1099 return (Elf32_Phdr
*)((UINT8
*)gPhdrBase
+ num
* Ehdr
->e_phentsize
);
1109 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1110 EFI_IMAGE_DATA_DIRECTORY
*Dir
;
1111 BOOLEAN FoundRelocations
;
1114 UINTN RelElementSize
;
1119 Elf32_Phdr
*DynamicSegment
;
1120 Elf32_Phdr
*TargetSegment
;
1122 for (Index
= 0, FoundRelocations
= FALSE
; Index
< Ehdr
->e_shnum
; Index
++) {
1123 Elf_Shdr
*RelShdr
= GetShdrByIndex(Index
);
1124 if (RelShdr
->sh_type
== SHT_REL
) {
1125 Elf_Shdr
*SecShdr
= GetShdrByIndex(RelShdr
->sh_info
);
1126 if (IsTextShdr(SecShdr
) || IsDataShdr(SecShdr
)) {
1128 FoundRelocations
= TRUE
;
1129 for (RelIdx
= 0; RelIdx
< RelShdr
->sh_size
; RelIdx
+= RelShdr
->sh_entsize
) {
1130 Elf_Rel
*Rel
= (Elf_Rel
*)
1131 ((UINT8
*)Ehdr
+ RelShdr
->sh_offset
+ RelIdx
);
1133 if (Ehdr
->e_machine
== EM_386
) {
1134 switch (ELF_R_TYPE(Rel
->r_info
)) {
1139 CoffAddFixup(CoffSectionsOffset
[RelShdr
->sh_info
]
1140 + (Rel
->r_offset
- SecShdr
->sh_addr
),
1141 EFI_IMAGE_REL_BASED_HIGHLOW
);
1144 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, (unsigned) ELF_R_TYPE(Rel
->r_info
));
1146 } else if (Ehdr
->e_machine
== EM_ARM
) {
1147 switch (ELF32_R_TYPE(Rel
->r_info
)) {
1155 CoffSectionsOffset
[RelShdr
->sh_info
]
1156 + (Rel
->r_offset
- SecShdr
->sh_addr
),
1157 EFI_IMAGE_REL_BASED_HIGHLOW
1161 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, (unsigned) ELF32_R_TYPE(Rel
->r_info
));
1164 Error (NULL
, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) Ehdr
->e_machine
);
1171 if (!FoundRelocations
&& (Ehdr
->e_machine
== EM_ARM
)) {
1172 /* Try again, but look for PT_DYNAMIC instead of SHT_REL */
1174 for (Index
= 0; Index
< Ehdr
->e_phnum
; Index
++) {
1179 DynamicSegment
= GetPhdrByIndex (Index
);
1181 if (DynamicSegment
->p_type
== PT_DYNAMIC
) {
1182 Dyn
= (Elf32_Dyn
*) ((UINT8
*)Ehdr
+ DynamicSegment
->p_offset
);
1184 while (Dyn
->d_tag
!= DT_NULL
) {
1185 switch (Dyn
->d_tag
) {
1187 RelOffset
= Dyn
->d_un
.d_val
;
1191 RelSize
= Dyn
->d_un
.d_val
;
1195 RelElementSize
= Dyn
->d_un
.d_val
;
1200 if (( RelOffset
== 0 ) || ( RelSize
== 0 ) || ( RelElementSize
== 0 )) {
1201 Error (NULL
, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName
);
1204 for (K
= 0; K
< RelSize
; K
+= RelElementSize
) {
1206 Rel
= (Elf32_Rel
*) ((UINT8
*) Ehdr
+ DynamicSegment
->p_offset
+ RelOffset
+ K
);
1208 switch (ELF32_R_TYPE (Rel
->r_info
)) {
1212 TargetSegment
= GetPhdrByIndex (ELF32_R_SYM (Rel
->r_info
) - 1);
1214 // Note: r_offset in a memory address. Convert it to a pointer in the coff file.
1215 Targ
= CoffFile
+ CoffSectionsOffset
[ ELF32_R_SYM( Rel
->r_info
) ] + Rel
->r_offset
- TargetSegment
->p_vaddr
;
1217 *(UINT32
*)Targ
= *(UINT32
*)Targ
+ CoffSectionsOffset
[ELF32_R_SYM( Rel
->r_info
)];
1219 CoffAddFixup (CoffSectionsOffset
[ELF32_R_SYM (Rel
->r_info
)] + (Rel
->r_offset
- TargetSegment
->p_vaddr
), EFI_IMAGE_REL_BASED_HIGHLOW
);
1222 Error (NULL
, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type.", mInImageName
);
1231 // Pad by adding empty entries.
1233 while (CoffOffset
& (CoffAlignment
- 1)) {
1234 CoffAddFixupEntry(0);
1238 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1239 Dir
= &NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1240 Dir
->Size
= CoffOffset
- RelocOffset
;
1241 if (Dir
->Size
== 0) {
1242 // If no relocations, null out the directory entry and don't add the .reloc section
1243 Dir
->VirtualAddress
= 0;
1244 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
1246 Dir
->VirtualAddress
= RelocOffset
;
1247 CreateSectionHeader (".reloc", RelocOffset
, CoffOffset
- RelocOffset
,
1248 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
1249 | EFI_IMAGE_SCN_MEM_DISCARDABLE
1250 | EFI_IMAGE_SCN_MEM_READ
);
1262 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1263 EFI_IMAGE_DATA_DIRECTORY
*DataDir
;
1264 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*Dir
;
1265 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
*Nb10
;
1267 Len
= strlen(mInImageName
) + 1;
1268 DebugOffset
= CoffOffset
;
1270 CoffOffset
+= sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
)
1271 + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
)
1273 CoffOffset
= CoffAlign(CoffOffset
);
1275 CoffFile
= realloc(CoffFile
, CoffOffset
);
1276 memset(CoffFile
+ DebugOffset
, 0, CoffOffset
- DebugOffset
);
1278 Dir
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)(CoffFile
+ DebugOffset
);
1279 Dir
->Type
= EFI_IMAGE_DEBUG_TYPE_CODEVIEW
;
1280 Dir
->SizeOfData
= sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
) + Len
;
1281 Dir
->RVA
= DebugOffset
+ sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
1282 Dir
->FileOffset
= DebugOffset
+ sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
1284 Nb10
= (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
*)(Dir
+ 1);
1285 Nb10
->Signature
= CODEVIEW_SIGNATURE_NB10
;
1286 strcpy ((char *)(Nb10
+ 1), mInImageName
);
1289 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1290 DataDir
= &NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
];
1291 DataDir
->VirtualAddress
= DebugOffset
;
1292 DataDir
->Size
= CoffOffset
- DebugOffset
;
1293 if (DataDir
->Size
== 0) {
1294 // If no debug, null out the directory entry and don't add the .debug section
1295 DataDir
->VirtualAddress
= 0;
1296 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
1298 DataDir
->VirtualAddress
= DebugOffset
;
1299 CreateSectionHeader (".debug", DebugOffset
, CoffOffset
- DebugOffset
,
1300 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
1301 | EFI_IMAGE_SCN_MEM_DISCARDABLE
1302 | EFI_IMAGE_SCN_MEM_READ
);
1313 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1316 // Check header, read section table.
1318 Ehdr
= (Elf32_Ehdr
*)*FileBuffer
;
1319 if (!CheckElfHeader())
1322 VerboseMsg ("Check Efl Image Header");
1324 // Compute sections new address.
1329 VerboseMsg ("Compute sections new address.");
1332 // Write and relocate sections.
1334 WriteSections(IsTextShdr
);
1335 WriteSections(IsDataShdr
);
1336 WriteSections(IsHiiRsrcShdr
);
1337 VerboseMsg ("Write and relocate sections.");
1340 // Translate and write relocations.
1343 VerboseMsg ("Translate and write relocations.");
1346 // Write debug info.
1349 VerboseMsg ("Write debug info.");
1351 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1352 NtHdr
->Pe32
.OptionalHeader
.SizeOfImage
= CoffOffset
;
1358 *FileBuffer
= CoffFile
;
1359 *FileLength
= CoffOffset
;
1362 // Free memory space
1364 if (CoffSectionsOffset
!= NULL
) {
1365 free (CoffSectionsOffset
);
1370 EFI_IMAGE_OPTIONAL_HEADER_UNION
*
1375 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1376 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1379 // Read the dos & pe hdrs of the image
1381 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Data
;
1382 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
1383 // NO DOS header, check for PE/COFF header
1384 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(Data
);
1385 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1390 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(((UINT8
*)Data
) + DosHdr
->e_lfanew
);
1391 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1400 PeCoffConvertImageToXip (
1405 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1406 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NewPeHdr
;
1407 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1408 UINTN TotalNecessaryFileSize
;
1413 UINTN FirstSectionOffset
;
1414 BOOLEAN ConversionNeeded
;
1416 PeHdr
= GetPeCoffHeader ((void *) *FileBuffer
);
1417 if (PeHdr
== NULL
) {
1421 if (PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
) {
1423 // The only reason to expand zero fill sections is to make them compatible with XIP images.
1424 // If SectionAlignment is not equal to FileAlginment then it is not an XIP type image.
1430 // Calculate size of XIP file, and determine if the conversion is needed.
1432 ConversionNeeded
= FALSE
;
1434 FirstSectionOffset
= *FileLength
;
1435 TotalNecessaryFileSize
= 0;
1436 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
1437 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1438 SectionSize
= MAX (SectionHeader
->Misc
.VirtualSize
, SectionHeader
->SizeOfRawData
);
1439 TotalNecessaryFileSize
+= SectionSize
;
1440 if (SectionSize
> 0) {
1441 FirstSectionOffset
= MIN (FirstSectionOffset
, SectionHeader
->VirtualAddress
);
1442 XipLength
= MAX (XipLength
, SectionHeader
->VirtualAddress
+ SectionSize
);
1443 if (SectionHeader
->VirtualAddress
!= SectionHeader
->PointerToRawData
) {
1444 ConversionNeeded
= TRUE
;
1447 if (SectionHeader
->Misc
.VirtualSize
> SectionHeader
->SizeOfRawData
) {
1448 ConversionNeeded
= TRUE
;
1452 if (FirstSectionOffset
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
1454 // If one of the sections should be loaded to an offset overlapping with
1455 // the executable header, then it cannot be made into an XIP image.
1457 VerboseMsg ("PE/COFF conversion to XIP is impossible due to overlap");
1458 VerboseMsg ("of section data with the executable header.");
1462 if (FirstSectionOffset
== *FileLength
) {
1464 // If we never found a section with a non-zero size, then we
1465 // skip the conversion.
1470 TotalNecessaryFileSize
+= FirstSectionOffset
;
1472 if (!ConversionNeeded
) {
1476 if (XipLength
> (2 * TotalNecessaryFileSize
)) {
1477 VerboseMsg ("PE/COFF conversion to XIP appears to be larger than necessary.");
1478 VerboseMsg ("The image linking process may have left unused memory ranges.");
1481 if (PeHdr
->Pe32
.FileHeader
.PointerToSymbolTable
!= 0) {
1483 // This field is obsolete and should be zero
1485 PeHdr
->Pe32
.FileHeader
.PointerToSymbolTable
= 0;
1489 // Allocate the extra space that we need to grow the image
1491 XipFile
= malloc (XipLength
);
1492 memset (XipFile
, 0, XipLength
);
1495 // Copy the file headers
1497 memcpy (XipFile
, *FileBuffer
, PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
);
1499 NewPeHdr
= GetPeCoffHeader ((void *)XipFile
);
1500 if (NewPeHdr
== NULL
) {
1506 // Copy the section data over to the appropriate XIP offsets
1508 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(NewPeHdr
->Pe32
.OptionalHeader
) + NewPeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
1509 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1510 if (SectionHeader
->SizeOfRawData
> 0) {
1512 XipFile
+ SectionHeader
->VirtualAddress
,
1513 *FileBuffer
+ SectionHeader
->PointerToRawData
,
1514 SectionHeader
->SizeOfRawData
1517 SectionHeader
->SizeOfRawData
= SectionHeader
->Misc
.VirtualSize
;
1518 SectionHeader
->PointerToRawData
= SectionHeader
->VirtualAddress
;
1522 *FileLength
= XipLength
;
1523 *FileBuffer
= XipFile
;
1527 CreateHiiResouceSectionHeader (
1528 UINT32
*pSectionHeaderSize
,
1533 Routine Description:
1535 Create COFF resource section header
1539 pSectionHeaderSize - Pointer to section header size.
1540 HiiDataSize - Size of the total HII data in section.
1543 The created section header buffer.
1547 UINT32 HiiSectionHeaderSize
;
1548 UINT32 HiiSectionOffset
;
1549 UINT8
*HiiSectionHeader
;
1550 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
1551 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*TypeResourceDirectoryEntry
;
1552 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*NameResourceDirectoryEntry
;
1553 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*LanguageResourceDirectoryEntry
;
1554 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
1555 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
1558 // Calculate the total size for the resource header (include Type, Name and Language)
1559 // then allocate memory for the resource header.
1561 HiiSectionHeaderSize
= 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
))
1562 + 3 * (sizeof (UINT16
) + 3 * sizeof (CHAR16
))
1563 + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
1564 HiiSectionHeader
= malloc (HiiSectionHeaderSize
);
1565 memset (HiiSectionHeader
, 0, HiiSectionHeaderSize
);
1567 HiiSectionOffset
= 0;
1569 // Create Type entry
1571 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1572 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
1573 ResourceDirectory
->NumberOfNamedEntries
= 1;
1574 TypeResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1575 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
1576 TypeResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
1577 TypeResourceDirectoryEntry
->u2
.s
.DataIsDirectory
= 1;
1578 TypeResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
= HiiSectionOffset
;
1580 // Create Name entry
1582 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1583 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
1584 ResourceDirectory
->NumberOfNamedEntries
= 1;
1585 NameResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1586 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
1587 NameResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
1588 NameResourceDirectoryEntry
->u2
.s
.DataIsDirectory
= 1;
1589 NameResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
= HiiSectionOffset
;
1591 // Create Language entry
1593 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1594 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
1595 ResourceDirectory
->NumberOfNamedEntries
= 1;
1596 LanguageResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1597 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
1598 LanguageResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
1600 // Create string entry for Type
1602 TypeResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
1603 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
1604 ResourceDirectoryString
->Length
= 3;
1605 ResourceDirectoryString
->String
[0] = L
'H';
1606 ResourceDirectoryString
->String
[1] = L
'I';
1607 ResourceDirectoryString
->String
[2] = L
'I';
1608 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
1610 // Create string entry for Name
1612 NameResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
1613 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
1614 ResourceDirectoryString
->Length
= 3;
1615 ResourceDirectoryString
->String
[0] = L
'E';
1616 ResourceDirectoryString
->String
[1] = L
'F';
1617 ResourceDirectoryString
->String
[2] = L
'I';
1618 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
1620 // Create string entry for Language
1622 LanguageResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
1623 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
1624 ResourceDirectoryString
->Length
= 3;
1625 ResourceDirectoryString
->String
[0] = L
'B';
1626 ResourceDirectoryString
->String
[1] = L
'I';
1627 ResourceDirectoryString
->String
[2] = L
'N';
1628 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
1632 LanguageResourceDirectoryEntry
->u2
.OffsetToData
= HiiSectionOffset
;
1633 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1634 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
1635 ResourceDataEntry
->OffsetToData
= HiiSectionOffset
;
1636 ResourceDataEntry
->Size
= HiiDataSize
;
1638 *pSectionHeaderSize
= HiiSectionHeaderSize
;
1639 return HiiSectionHeader
;
1649 Routine Description:
1655 argc - Number of command line parameters.
1656 argv - Array of pointers to command line parameter strings.
1659 STATUS_SUCCESS - Utility exits successfully.
1660 STATUS_ERROR - Some error occurred during execution.
1665 UINT32 InputFileNum
;
1666 CHAR8
**InputFileName
;
1670 UINT32 OutImageType
;
1675 UINT32
*DataPointer
;
1676 UINT32
*OldDataPointer
;
1682 UINT32 MciAlignment
;
1684 UINT32 AllignedRelocSize
;
1687 UINT8
*OutputFileBuffer
;
1688 UINT32 OutputFileLength
;
1689 RUNTIME_FUNCTION
*RuntimeFunction
;
1690 UNWIND_INFO
*UnwindInfo
;
1692 BOOLEAN ReplaceFlag
;
1693 BOOLEAN KeepExceptionTableFlag
;
1694 BOOLEAN KeepZeroPendingFlag
;
1696 EFI_TE_IMAGE_HEADER TEImageHeader
;
1697 EFI_TE_IMAGE_HEADER
*TeHdr
;
1698 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1699 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1700 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1701 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32
;
1702 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64
;
1703 EFI_IMAGE_DOS_HEADER BackupDosHdr
;
1704 MICROCODE_IMAGE_HEADER
*MciHeader
;
1705 UINT8
*HiiPackageListBuffer
;
1706 UINT8
*HiiPackageDataPointer
;
1707 EFI_GUID HiiPackageListGuid
;
1708 EFI_HII_PACKAGE_LIST_HEADER HiiPackageListHeader
;
1709 EFI_HII_PACKAGE_HEADER HiiPackageHeader
;
1710 EFI_IFR_FORM_SET IfrFormSet
;
1711 UINT8 NumberOfFormPacakge
;
1712 EFI_HII_PACKAGE_HEADER EndPackage
;
1713 UINT32 HiiSectionHeaderSize
;
1714 UINT8
*HiiSectionHeader
;
1716 SetUtilityName (UTILITY_NAME
);
1719 // Assign to fix compile warning
1722 InputFileName
= NULL
;
1723 mInImageName
= NULL
;
1724 OutImageName
= NULL
;
1726 OutImageType
= FW_DUMMY_IMAGE
;
1728 Status
= STATUS_SUCCESS
;
1734 MciAlignment
= DEFAULT_MC_ALIGNMENT
;
1735 MciPadValue
= DEFAULT_MC_PAD_BYTE_VALUE
;
1739 ReplaceFlag
= FALSE
;
1741 OutputFileBuffer
= NULL
;
1742 OutputFileLength
= 0;
1745 KeepExceptionTableFlag
= FALSE
;
1746 KeepZeroPendingFlag
= FALSE
;
1747 NumberOfFormPacakge
= 0;
1748 HiiPackageListBuffer
= NULL
;
1749 HiiPackageDataPointer
= NULL
;
1750 EndPackage
.Length
= sizeof (EFI_HII_PACKAGE_HEADER
);
1751 EndPackage
.Type
= EFI_HII_PACKAGE_END
;
1752 memset (&HiiPackageListGuid
, 0, sizeof (HiiPackageListGuid
));
1753 HiiSectionHeaderSize
= 0;
1754 HiiSectionHeader
= NULL
;
1757 Error (NULL
, 0, 1001, "Missing options", "No input options.");
1759 return STATUS_ERROR
;
1765 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
1768 return STATUS_SUCCESS
;
1771 if (stricmp (argv
[0], "--version") == 0) {
1773 return STATUS_SUCCESS
;
1777 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
1778 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1779 Error (NULL
, 0, 1003, "Invalid option value", "Output file name is missing for -o option");
1782 OutImageName
= argv
[1];
1788 if ((stricmp (argv
[0], "-e") == 0) || (stricmp (argv
[0], "--efiImage") == 0)) {
1789 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1790 Error (NULL
, 0, 1003, "Invalid option value", "Module Type is missing for -o option");
1793 ModuleType
= argv
[1];
1794 if (OutImageType
!= FW_TE_IMAGE
) {
1795 OutImageType
= FW_EFI_IMAGE
;
1802 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--stripped") == 0)) {
1803 OutImageType
= FW_RELOC_STRIPEED_IMAGE
;
1809 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--acpi") == 0)) {
1810 OutImageType
= FW_ACPI_IMAGE
;
1816 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--terse") == 0)) {
1817 OutImageType
= FW_TE_IMAGE
;
1823 if ((stricmp (argv
[0], "-u") == 0) || (stricmp (argv
[0], "--dump") == 0)) {
1824 OutImageType
= DUMP_TE_HEADER
;
1830 if ((stricmp (argv
[0], "-b") == 0) || (stricmp (argv
[0], "--exe2bin") == 0)) {
1831 OutImageType
= FW_BIN_IMAGE
;
1837 if ((stricmp (argv
[0], "-z") == 0) || (stricmp (argv
[0], "--zero") == 0)) {
1838 OutImageType
= FW_ZERO_DEBUG_IMAGE
;
1844 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--stamp") == 0)) {
1845 OutImageType
= FW_SET_STAMP_IMAGE
;
1846 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1847 Error (NULL
, 0, 1003, "Invalid option value", "time stamp is missing for -s option");
1850 TimeStamp
= argv
[1];
1856 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--replace") == 0)) {
1863 if (stricmp (argv
[0], "--keepexceptiontable") == 0) {
1864 KeepExceptionTableFlag
= TRUE
;
1870 if (stricmp (argv
[0], "--keepzeropending") == 0) {
1871 KeepZeroPendingFlag
= TRUE
;
1877 if ((stricmp (argv
[0], "-m") == 0) || (stricmp (argv
[0], "--mcifile") == 0)) {
1878 OutImageType
= FW_MCI_IMAGE
;
1884 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--join") == 0)) {
1885 OutImageType
= FW_MERGE_IMAGE
;
1891 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
1892 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1893 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1896 MciAlignment
= (UINT32
) Temp64
;
1902 if ((stricmp (argv
[0], "-p") == 0) || (stricmp (argv
[0], "--pad") == 0)) {
1903 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1904 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1907 MciPadValue
= (UINT8
) Temp64
;
1913 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
1914 SetPrintLevel (VERBOSE_LOG_LEVEL
);
1915 VerboseMsg ("Verbose output Mode Set!");
1921 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1922 SetPrintLevel (KEY_LOG_LEVEL
);
1923 KeyMsg ("Quiet output Mode Set!");
1929 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
1930 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
1931 if (EFI_ERROR (Status
)) {
1932 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1936 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel
);
1939 SetPrintLevel (LogLevel
);
1940 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
1946 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--hiiguid") == 0)) {
1947 Status
= StringToGuid (argv
[1], &HiiPackageListGuid
);
1948 if (EFI_ERROR (Status
)) {
1949 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1957 if (stricmp (argv
[0], "--hiipackage") == 0) {
1958 OutImageType
= FW_HII_PACKAGE_LIST_RCIMAGE
;
1964 if (stricmp (argv
[0], "--hiibinpackage") == 0) {
1965 OutImageType
= FW_HII_PACKAGE_LIST_BINIMAGE
;
1971 if (argv
[0][0] == '-') {
1972 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
1976 // Get Input file name
1978 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
1979 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
1980 if (InputFileName
== NULL
) {
1981 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1985 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1986 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1988 // InputFileName buffer too small, need to realloc
1990 InputFileName
= (CHAR8
**) realloc (
1992 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1995 if (InputFileName
== NULL
) {
1996 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2000 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
2003 InputFileName
[InputFileNum
++] = argv
[0];
2008 VerboseMsg ("%s tool start.", UTILITY_NAME
);
2010 if (OutImageType
== FW_DUMMY_IMAGE
) {
2011 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!");
2013 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.");
2019 // check input files
2021 if (InputFileNum
== 0) {
2022 Error (NULL
, 0, 1001, "Missing option", "Input files");
2027 // Combine MciBinary files to one file
2029 if ((OutImageType
== FW_MERGE_IMAGE
) && ReplaceFlag
) {
2030 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");
2035 // Combine HiiBinary packages to a single package list
2037 if ((OutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) && ReplaceFlag
) {
2038 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option.");
2042 if ((OutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) && ReplaceFlag
) {
2043 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiibinpackage merge files option.");
2050 mInImageName
= InputFileName
[InputFileNum
- 1];
2051 VerboseMsg ("the input file name is %s", mInImageName
);
2054 // Action will be taken for the input file.
2056 switch (OutImageType
) {
2058 VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType
);
2061 VerboseMsg ("Create Te Image based on the input PE image.");
2064 VerboseMsg ("Get acpi table data from the input PE image.");
2066 case FW_RELOC_STRIPEED_IMAGE
:
2067 VerboseMsg ("Remove relocation section from Pe or Te image.");
2070 VerboseMsg ("Convert the input EXE to the output BIN file.");
2072 case FW_ZERO_DEBUG_IMAGE
:
2073 VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");
2075 case FW_SET_STAMP_IMAGE
:
2076 VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp
);
2078 case DUMP_TE_HEADER
:
2079 VerboseMsg ("Dump the TE header information of the input TE image.");
2082 VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");
2084 case FW_MERGE_IMAGE
:
2085 VerboseMsg ("Combine the input multi microcode bin files to one bin file.");
2087 case FW_HII_PACKAGE_LIST_RCIMAGE
:
2088 VerboseMsg ("Combine the input multi hii bin packages to one text pacakge list RC file.");
2090 case FW_HII_PACKAGE_LIST_BINIMAGE
:
2091 VerboseMsg ("Combine the input multi hii bin packages to one binary pacakge list file.");
2098 VerboseMsg ("Overwrite the input file with the output content.");
2102 // Open output file and Write image into the output file.
2104 if (OutImageName
!= NULL
) {
2105 fpOut
= fopen (OutImageName
, "rb");
2106 if (fpOut
!= NULL
) {
2107 OutputFileLength
= _filelength (fileno (fpOut
));
2108 OutputFileBuffer
= malloc (OutputFileLength
);
2109 if (OutputFileBuffer
== NULL
) {
2110 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2115 fread (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
2118 fpOut
= fopen (OutImageName
, "wb");
2120 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
2123 VerboseMsg ("Output file name is %s", OutImageName
);
2124 } else if (!ReplaceFlag
) {
2125 if (OutImageType
== DUMP_TE_HEADER
) {
2128 Error (NULL
, 0, 1001, "Missing option", "output file");
2134 // Combine multi binary HII package files.
2136 if (OutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
|| OutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) {
2138 // Get hii package list lenght
2140 HiiPackageListHeader
.PackageLength
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
2141 for (Index
= 0; Index
< InputFileNum
; Index
++) {
2142 fpIn
= fopen (InputFileName
[Index
], "rb");
2144 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
2147 FileLength
= _filelength (fileno (fpIn
));
2148 fread (&HiiPackageHeader
, 1, sizeof (HiiPackageHeader
), fpIn
);
2149 if (HiiPackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) {
2150 if (HiiPackageHeader
.Length
!= FileLength
) {
2151 Error (NULL
, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName
[Index
]);
2155 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
2156 fread (&IfrFormSet
, 1, sizeof (IfrFormSet
), fpIn
);
2157 memcpy (&HiiPackageListGuid
, &IfrFormSet
.Guid
, sizeof (EFI_GUID
));
2159 NumberOfFormPacakge
++;
2161 HiiPackageListHeader
.PackageLength
+= FileLength
;
2164 HiiPackageListHeader
.PackageLength
+= sizeof (EndPackage
);
2166 // Check whether hii packages are valid
2168 if (NumberOfFormPacakge
> 1) {
2169 Error (NULL
, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package");
2172 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
2173 Error (NULL
, 0, 3000, "Invalid", "HII pacakge list guid is not specified!");
2176 memcpy (&HiiPackageListHeader
.PackageListGuid
, &HiiPackageListGuid
, sizeof (EFI_GUID
));
2178 // read hii packages
2180 HiiPackageListBuffer
= malloc (HiiPackageListHeader
.PackageLength
);
2181 if (HiiPackageListBuffer
== NULL
) {
2182 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2185 memcpy (HiiPackageListBuffer
, &HiiPackageListHeader
, sizeof (HiiPackageListHeader
));
2186 HiiPackageDataPointer
= HiiPackageListBuffer
+ sizeof (HiiPackageListHeader
);
2187 for (Index
= 0; Index
< InputFileNum
; Index
++) {
2188 fpIn
= fopen (InputFileName
[Index
], "rb");
2190 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
2191 free (HiiPackageListBuffer
);
2195 FileLength
= _filelength (fileno (fpIn
));
2196 fread (HiiPackageDataPointer
, 1, FileLength
, fpIn
);
2198 HiiPackageDataPointer
= HiiPackageDataPointer
+ FileLength
;
2200 memcpy (HiiPackageDataPointer
, &EndPackage
, sizeof (EndPackage
));
2203 // write the hii package into the binary package list file with the resource section header
2205 if (OutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) {
2207 // Create the resource section header
2209 HiiSectionHeader
= CreateHiiResouceSectionHeader (&HiiSectionHeaderSize
, HiiPackageListHeader
.PackageLength
);
2211 // Wrtie section header and HiiData into File.
2213 fwrite (HiiSectionHeader
, 1, HiiSectionHeaderSize
, fpOut
);
2214 fwrite (HiiPackageListBuffer
, 1, HiiPackageListHeader
.PackageLength
, fpOut
);
2216 // Free allocated resources.
2218 free (HiiSectionHeader
);
2219 free (HiiPackageListBuffer
);
2221 // Done successfully
2227 // write the hii package into the text package list rc file.
2229 if (OutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) {
2230 for (Index
= 0; gHiiPackageRCFileHeader
[Index
] != NULL
; Index
++) {
2231 fprintf (fpOut
, "%s\n", gHiiPackageRCFileHeader
[Index
]);
2233 fprintf (fpOut
, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX
, HII_RESOURCE_SECTION_NAME
);
2235 HiiPackageDataPointer
= HiiPackageListBuffer
;
2236 for (Index
= 0; Index
+ 2 < HiiPackageListHeader
.PackageLength
; Index
+= 2) {
2237 if (Index
% 16 == 0) {
2238 fprintf (fpOut
, "\n ");
2240 fprintf (fpOut
, " 0x%04X,", *(UINT16
*) HiiPackageDataPointer
);
2241 HiiPackageDataPointer
+= 2;
2244 if (Index
% 16 == 0) {
2245 fprintf (fpOut
, "\n ");
2247 if ((Index
+ 2) == HiiPackageListHeader
.PackageLength
) {
2248 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT16
*) HiiPackageDataPointer
);
2250 if ((Index
+ 1) == HiiPackageListHeader
.PackageLength
) {
2251 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT8
*) HiiPackageDataPointer
);
2253 free (HiiPackageListBuffer
);
2255 // Done successfully
2262 // Combine MciBinary files to one file
2264 if (OutImageType
== FW_MERGE_IMAGE
) {
2265 for (Index
= 0; Index
< InputFileNum
; Index
++) {
2266 fpIn
= fopen (InputFileName
[Index
], "rb");
2268 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
2272 FileLength
= _filelength (fileno (fpIn
));
2273 FileBuffer
= malloc (FileLength
);
2274 if (FileBuffer
== NULL
) {
2275 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2280 fread (FileBuffer
, 1, FileLength
, fpIn
);
2283 // write input file to out file
2285 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2287 // write pad value to out file.
2289 while (FileLength
++ % MciAlignment
!= 0) {
2290 fwrite (&MciPadValue
, 1, 1, fpOut
);
2293 // free allocated memory space
2299 // Done successfully
2305 // Convert MicroCode.txt file to MicroCode.bin file
2307 if (OutImageType
== FW_MCI_IMAGE
) {
2308 fpIn
= fopen (mInImageName
, "r");
2310 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2315 // The first pass is to determine
2316 // how much data is in the file so we can allocate a working buffer.
2320 Status
= MicrocodeReadData (fpIn
, &Data
);
2321 if (Status
== STATUS_SUCCESS
) {
2322 FileLength
+= sizeof (Data
);
2324 if (Status
== STATUS_IGNORE
) {
2325 Status
= STATUS_SUCCESS
;
2327 } while (Status
== STATUS_SUCCESS
);
2329 // Error if no data.
2331 if (FileLength
== 0) {
2332 Error (NULL
, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName
);
2335 if (FileLength
< sizeof (MICROCODE_IMAGE_HEADER
)) {
2336 Error (NULL
, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName
);
2341 // Allocate a buffer for the data
2343 FileBuffer
= malloc (FileLength
);
2344 if (FileBuffer
== NULL
) {
2345 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2349 // Re-read the file, storing the data into our buffer
2351 fseek (fpIn
, 0, SEEK_SET
);
2352 DataPointer
= (UINT32
*) FileBuffer
;
2353 OldDataPointer
= DataPointer
;
2355 OldDataPointer
= DataPointer
;
2356 Status
= MicrocodeReadData (fpIn
, DataPointer
++);
2357 if (Status
== STATUS_IGNORE
) {
2358 DataPointer
= OldDataPointer
;
2359 Status
= STATUS_SUCCESS
;
2361 } while (Status
== STATUS_SUCCESS
);
2363 // close input file after read data
2368 // Can't do much checking on the header because, per the spec, the
2369 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
2370 // and the TotalSize field is invalid (actually missing). Thus we can't
2371 // even verify the Reserved fields are 0.
2373 MciHeader
= (MICROCODE_IMAGE_HEADER
*) FileBuffer
;
2374 if (MciHeader
->DataSize
== 0) {
2377 Index
= MciHeader
->TotalSize
;
2380 if (Index
!= FileLength
) {
2381 Error (NULL
, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName
, (unsigned) FileLength
, (unsigned) Index
);
2386 // Checksum the contents
2388 DataPointer
= (UINT32
*) FileBuffer
;
2391 while (Index
< FileLength
) {
2392 CheckSum
+= *DataPointer
;
2394 Index
+= sizeof (*DataPointer
);
2396 if (CheckSum
!= 0) {
2397 Error (NULL
, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum
, mInImageName
);
2401 // Open the output file and write the buffer contents
2403 if (fpOut
!= NULL
) {
2404 if (fwrite (FileBuffer
, FileLength
, 1, fpOut
) != 1) {
2405 Error (NULL
, 0, 0002, "Error writing file", OutImageName
);
2411 fpInOut
= fopen (mInImageName
, "wb");
2412 if (fpInOut
!= NULL
) {
2413 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2416 if (fwrite (FileBuffer
, FileLength
, 1, fpInOut
) != 1) {
2417 Error (NULL
, 0, 0002, "Error writing file", mInImageName
);
2421 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2423 // Convert Mci.TXT to Mci.bin file successfully
2429 // Open input file and read file data into file buffer.
2431 fpIn
= fopen (mInImageName
, "rb");
2433 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2437 FileLength
= _filelength (fileno (fpIn
));
2438 FileBuffer
= malloc (FileLength
);
2439 if (FileBuffer
== NULL
) {
2440 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2445 fread (FileBuffer
, 1, FileLength
, fpIn
);
2448 DebugMsg (NULL
, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) FileLength
);
2454 fpInOut
= fopen (mInImageName
, "wb");
2456 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2461 // Dump TeImage Header into output file.
2463 if (OutImageType
== DUMP_TE_HEADER
) {
2464 memcpy (&TEImageHeader
, FileBuffer
, sizeof (TEImageHeader
));
2465 if (TEImageHeader
.Signature
!= EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2466 Error (NULL
, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName
);
2469 if (fpInOut
!= NULL
) {
2470 fprintf (fpInOut
, "Dump of file %s\n\n", mInImageName
);
2471 fprintf (fpInOut
, "TE IMAGE HEADER VALUES\n");
2472 fprintf (fpInOut
, "%17X machine\n", TEImageHeader
.Machine
);
2473 fprintf (fpInOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
2474 fprintf (fpInOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
2475 fprintf (fpInOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
2476 fprintf (fpInOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
2477 fprintf (fpInOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
2478 fprintf (fpInOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
2479 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
2480 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
2483 if (fpOut
!= NULL
) {
2484 fprintf (fpOut
, "Dump of file %s\n\n", mInImageName
);
2485 fprintf (fpOut
, "TE IMAGE HEADER VALUES\n");
2486 fprintf (fpOut
, "%17X machine\n", TEImageHeader
.Machine
);
2487 fprintf (fpOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
2488 fprintf (fpOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
2489 fprintf (fpOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
2490 fprintf (fpOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
2491 fprintf (fpOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
2492 fprintf (fpOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
2493 fprintf (fpOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
2494 fprintf (fpOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
2500 // Following code to convert dll to efi image or te image.
2501 // Get new image type
2503 if ((OutImageType
== FW_EFI_IMAGE
) || (OutImageType
== FW_TE_IMAGE
)) {
2504 if (ModuleType
== NULL
) {
2505 if (OutImageType
== FW_EFI_IMAGE
) {
2506 Error (NULL
, 0, 1001, "Missing option", "EFI_FILETYPE");
2508 } else if (OutImageType
== FW_TE_IMAGE
) {
2510 // Default TE Image Type is Boot service driver
2512 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2513 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2516 if (stricmp (ModuleType
, "BASE") == 0 ||
2517 stricmp (ModuleType
, "SEC") == 0 ||
2518 stricmp (ModuleType
, "SECURITY_CORE") == 0 ||
2519 stricmp (ModuleType
, "PEI_CORE") == 0 ||
2520 stricmp (ModuleType
, "PEIM") == 0 ||
2521 stricmp (ModuleType
, "COMBINED_PEIM_DRIVER") == 0 ||
2522 stricmp (ModuleType
, "PIC_PEIM") == 0 ||
2523 stricmp (ModuleType
, "RELOCATABLE_PEIM") == 0 ||
2524 stricmp (ModuleType
, "DXE_CORE") == 0 ||
2525 stricmp (ModuleType
, "BS_DRIVER") == 0 ||
2526 stricmp (ModuleType
, "DXE_DRIVER") == 0 ||
2527 stricmp (ModuleType
, "DXE_SMM_DRIVER") == 0 ||
2528 stricmp (ModuleType
, "UEFI_DRIVER") == 0 ||
2529 stricmp (ModuleType
, "SMM_CORE") == 0) {
2530 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2531 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2533 } else if (stricmp (ModuleType
, "UEFI_APPLICATION") == 0 ||
2534 stricmp (ModuleType
, "APPLICATION") == 0) {
2535 Type
= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
;
2536 VerboseMsg ("Efi Image subsystem type is efi application.");
2538 } else if (stricmp (ModuleType
, "DXE_RUNTIME_DRIVER") == 0 ||
2539 stricmp (ModuleType
, "RT_DRIVER") == 0) {
2540 Type
= EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
;
2541 VerboseMsg ("Efi Image subsystem type is efi runtime driver.");
2543 } else if (stricmp (ModuleType
, "DXE_SAL_DRIVER") == 0 ||
2544 stricmp (ModuleType
, "SAL_RT_DRIVER") == 0) {
2545 Type
= EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
;
2546 VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");
2549 Error (NULL
, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType
);
2556 // Convert EFL image to PeImage
2558 if (IsElfHeader(FileBuffer
)) {
2559 VerboseMsg ("Convert the input ELF Image to Pe Image");
2560 ConvertElf(&FileBuffer
, &FileLength
);
2564 // Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP
2565 // XIP == eXecute In Place
2567 PeCoffConvertImageToXip (&FileBuffer
, &FileLength
);
2570 // Remove reloc section from PE or TE image
2572 if (OutImageType
== FW_RELOC_STRIPEED_IMAGE
) {
2576 TeHdr
= (EFI_TE_IMAGE_HEADER
*) FileBuffer
;
2577 if (TeHdr
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2578 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (TeHdr
+ 1);
2579 for (Index
= 0; Index
< TeHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2580 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2582 // Check the reloc section is in the end of image.
2584 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) ==
2585 (FileLength
+ TeHdr
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
))) {
2587 // Remove .reloc section and update TeImage Header
2589 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2590 SectionHeader
->SizeOfRawData
= 0;
2591 SectionHeader
->Misc
.VirtualSize
= 0;
2592 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2593 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2602 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2603 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2604 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2605 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2606 Error (NULL
, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName
);
2611 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2612 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2613 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
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
++) {
2619 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2621 // Check the reloc section is in the end of image.
2623 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) == FileLength
) {
2625 // Remove .reloc section and update PeImage Header
2627 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2629 PeHdr
->Pe32
.FileHeader
.Characteristics
|= EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2630 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2631 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2632 Optional32
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2633 Optional32
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2634 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2635 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2636 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2639 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2640 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2641 Optional64
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2642 Optional64
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2643 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2644 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2645 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2648 SectionHeader
->Misc
.VirtualSize
= 0;
2649 SectionHeader
->SizeOfRawData
= 0;
2661 // Read the dos & pe hdrs of the image
2663 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2664 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2665 // NO DOS header, check for PE/COFF header
2666 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2667 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2668 Error (NULL
, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName
);
2674 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2675 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2676 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2681 if (PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_ARM
) {
2682 // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
2683 // so patch back to the offical UEFI value.
2684 PeHdr
->Pe32
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_ARMT
;
2688 // Extract bin data from Pe image.
2690 if (OutImageType
== FW_BIN_IMAGE
) {
2691 if (FileLength
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
2692 Error (NULL
, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName
);
2696 // Output bin data from exe file
2698 if (fpOut
!= NULL
) {
2699 fwrite (FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, 1, FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, fpOut
);
2701 if (fpInOut
!= NULL
) {
2702 fwrite (FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, 1, FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, fpInOut
);
2704 VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
));
2709 // Zero Debug Information of Pe Image
2711 if (OutImageType
== FW_ZERO_DEBUG_IMAGE
) {
2712 Status
= ZeroDebugData (FileBuffer
, TRUE
);
2713 if (EFI_ERROR (Status
)) {
2714 Error (NULL
, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status
);
2718 if (fpOut
!= NULL
) {
2719 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2721 if (fpInOut
!= NULL
) {
2722 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2724 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2729 // Set Time Stamp of Pe Image
2731 if (OutImageType
== FW_SET_STAMP_IMAGE
) {
2732 Status
= SetStamp (FileBuffer
, TimeStamp
);
2733 if (EFI_ERROR (Status
)) {
2737 if (fpOut
!= NULL
) {
2738 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2740 if (fpInOut
!= NULL
) {
2741 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2743 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2748 // Extract acpi data from pe image.
2750 if (OutImageType
== FW_ACPI_IMAGE
) {
2751 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2752 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2753 if (strcmp ((char *)SectionHeader
->Name
, ".data") == 0 || strcmp ((char *)SectionHeader
->Name
, ".sdata") == 0) {
2757 if (SectionHeader
->Misc
.VirtualSize
< SectionHeader
->SizeOfRawData
) {
2758 FileLength
= SectionHeader
->Misc
.VirtualSize
;
2760 FileLength
= SectionHeader
->SizeOfRawData
;
2763 if (CheckAcpiTable (FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
) != STATUS_SUCCESS
) {
2764 Error (NULL
, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName
);
2769 // Output Apci data to file
2771 if (fpOut
!= NULL
) {
2772 fwrite (FileBuffer
+ SectionHeader
->PointerToRawData
, 1, FileLength
, fpOut
);
2774 if (fpInOut
!= NULL
) {
2775 fwrite (FileBuffer
+ SectionHeader
->PointerToRawData
, 1, FileLength
, fpInOut
);
2777 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2781 Error (NULL
, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName
);
2785 // Zero all unused fields of the DOS header
2787 if (DosHdr
!= NULL
) {
2788 memcpy (&BackupDosHdr
, DosHdr
, sizeof (EFI_IMAGE_DOS_HEADER
));
2789 memset (DosHdr
, 0, sizeof (EFI_IMAGE_DOS_HEADER
));
2790 DosHdr
->e_magic
= BackupDosHdr
.e_magic
;
2791 DosHdr
->e_lfanew
= BackupDosHdr
.e_lfanew
;
2793 for (Index
= sizeof (EFI_IMAGE_DOS_HEADER
); Index
< (UINT32
) DosHdr
->e_lfanew
; Index
++) {
2794 FileBuffer
[Index
] = (UINT8
) DosHdr
->e_cp
;
2799 // Initialize TeImage Header
2801 memset (&TEImageHeader
, 0, sizeof (EFI_TE_IMAGE_HEADER
));
2802 TEImageHeader
.Signature
= EFI_TE_IMAGE_HEADER_SIGNATURE
;
2803 TEImageHeader
.Machine
= PeHdr
->Pe32
.FileHeader
.Machine
;
2804 TEImageHeader
.NumberOfSections
= (UINT8
) PeHdr
->Pe32
.FileHeader
.NumberOfSections
;
2805 TEImageHeader
.StrippedSize
= (UINT16
) ((UINTN
) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
) - (UINTN
) FileBuffer
);
2806 TEImageHeader
.Subsystem
= (UINT8
) Type
;
2809 // Patch the PE header
2811 PeHdr
->Pe32
.OptionalHeader
.Subsystem
= (UINT16
) Type
;
2813 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2814 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2815 Optional32
->MajorLinkerVersion
= 0;
2816 Optional32
->MinorLinkerVersion
= 0;
2817 Optional32
->MajorOperatingSystemVersion
= 0;
2818 Optional32
->MinorOperatingSystemVersion
= 0;
2819 Optional32
->MajorImageVersion
= 0;
2820 Optional32
->MinorImageVersion
= 0;
2821 Optional32
->MajorSubsystemVersion
= 0;
2822 Optional32
->MinorSubsystemVersion
= 0;
2823 Optional32
->Win32VersionValue
= 0;
2824 Optional32
->CheckSum
= 0;
2825 Optional32
->SizeOfStackReserve
= 0;
2826 Optional32
->SizeOfStackCommit
= 0;
2827 Optional32
->SizeOfHeapReserve
= 0;
2828 Optional32
->SizeOfHeapCommit
= 0;
2830 TEImageHeader
.AddressOfEntryPoint
= Optional32
->AddressOfEntryPoint
;
2831 TEImageHeader
.BaseOfCode
= Optional32
->BaseOfCode
;
2832 TEImageHeader
.ImageBase
= (UINT64
) (Optional32
->ImageBase
);
2834 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2835 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2836 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2839 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2840 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2841 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2845 // Zero .pdata section data.
2847 if (!KeepExceptionTableFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2848 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2849 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2850 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2851 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2852 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2854 // Zero .pdata Section data
2856 memset (FileBuffer
+ SectionHeader
->PointerToRawData
, 0, SectionHeader
->SizeOfRawData
);
2858 // Zero .pdata Section header name
2860 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2862 // Zero Execption Table
2864 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2865 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2866 DebugMsg (NULL
, 0, 9, "Zero the .pdata section for PE image", NULL
);
2873 // Strip zero padding at the end of the .reloc section
2875 if (!KeepZeroPendingFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2876 if (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2877 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2878 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2880 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2882 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2883 SectionHeader
->Misc
.VirtualSize
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2884 AllignedRelocSize
= (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional32
->FileAlignment
- 1) & (~(Optional32
->FileAlignment
- 1));
2886 // Check to see if there is zero padding at the end of the base relocations
2888 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2890 // Check to see if the base relocations are at the end of the file
2892 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional32
->SizeOfImage
) {
2894 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2896 Optional32
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2897 Optional32
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2898 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2899 FileLength
= Optional32
->SizeOfImage
;
2900 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
));
2907 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2908 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2909 Optional64
->MajorLinkerVersion
= 0;
2910 Optional64
->MinorLinkerVersion
= 0;
2911 Optional64
->MajorOperatingSystemVersion
= 0;
2912 Optional64
->MinorOperatingSystemVersion
= 0;
2913 Optional64
->MajorImageVersion
= 0;
2914 Optional64
->MinorImageVersion
= 0;
2915 Optional64
->MajorSubsystemVersion
= 0;
2916 Optional64
->MinorSubsystemVersion
= 0;
2917 Optional64
->Win32VersionValue
= 0;
2918 Optional64
->CheckSum
= 0;
2919 Optional64
->SizeOfStackReserve
= 0;
2920 Optional64
->SizeOfStackCommit
= 0;
2921 Optional64
->SizeOfHeapReserve
= 0;
2922 Optional64
->SizeOfHeapCommit
= 0;
2924 TEImageHeader
.AddressOfEntryPoint
= Optional64
->AddressOfEntryPoint
;
2925 TEImageHeader
.BaseOfCode
= Optional64
->BaseOfCode
;
2926 TEImageHeader
.ImageBase
= (UINT64
) (Optional64
->ImageBase
);
2928 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2929 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2930 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2933 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2934 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2935 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2939 // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
2940 // For Itaninum and X64 Image, remove .pdata section.
2942 if ((!KeepExceptionTableFlag
&& PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_X64
) || PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
) {
2943 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2944 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2945 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2946 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2947 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2948 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2950 // Zero .pdata Section header name
2952 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2954 RuntimeFunction
= (RUNTIME_FUNCTION
*)(FileBuffer
+ SectionHeader
->PointerToRawData
);
2955 for (Index1
= 0; Index1
< Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
/ sizeof (RUNTIME_FUNCTION
); Index1
++, RuntimeFunction
++) {
2956 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2957 for (Index2
= 0; Index2
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index2
++, SectionHeader
++) {
2958 if (RuntimeFunction
->UnwindInfoAddress
>= SectionHeader
->VirtualAddress
&& RuntimeFunction
->UnwindInfoAddress
< (SectionHeader
->VirtualAddress
+ SectionHeader
->SizeOfRawData
)) {
2959 UnwindInfo
= (UNWIND_INFO
*)(FileBuffer
+ SectionHeader
->PointerToRawData
+ (RuntimeFunction
->UnwindInfoAddress
- SectionHeader
->VirtualAddress
));
2960 if (UnwindInfo
->Version
== 1) {
2961 memset (UnwindInfo
+ 1, 0, UnwindInfo
->CountOfUnwindCodes
* sizeof (UINT16
));
2962 memset (UnwindInfo
, 0, sizeof (UNWIND_INFO
));
2967 memset (RuntimeFunction
, 0, sizeof (RUNTIME_FUNCTION
));
2970 // Zero Execption Table
2972 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2973 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2974 DebugMsg (NULL
, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL
);
2982 // Strip zero padding at the end of the .reloc section
2984 if (!KeepZeroPendingFlag
&& Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2985 if (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2986 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2987 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2989 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2991 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2992 SectionHeader
->Misc
.VirtualSize
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2993 AllignedRelocSize
= (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional64
->FileAlignment
- 1) & (~(Optional64
->FileAlignment
- 1));
2995 // Check to see if there is zero padding at the end of the base relocations
2997 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2999 // Check to see if the base relocations are at the end of the file
3001 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional64
->SizeOfImage
) {
3003 // All the required conditions are met to strip the zero padding of the end of the base relocations section
3005 Optional64
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
3006 Optional64
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
3007 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
3008 FileLength
= Optional64
->SizeOfImage
;
3009 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
));
3017 Error (NULL
, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr
->Pe32
.OptionalHeader
.Magic
, mInImageName
);
3021 if (((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) == 0) && \
3022 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
== 0) && \
3023 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
== 0)) {
3025 // PeImage can be loaded into memory, but it has no relocation section.
3026 // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
3028 if (Optional32
!= NULL
) {
3029 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
3030 } else if (Optional64
!= NULL
) {
3031 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
3036 // Fill HII section data
3038 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3039 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++) {
3040 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".hii") == 0) {
3042 // Update resource section header offset
3044 SetHiiResourceHeader ((UINT8
*) FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, SectionHeader
[Index
].VirtualAddress
);
3046 // Update resource section name
3048 strcpy((char *) SectionHeader
[Index
].Name
, ".rsrc");
3050 // Update resource data directory.
3052 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
3053 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
3054 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= SectionHeader
[Index
].VirtualAddress
;
3055 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= SectionHeader
[Index
].Misc
.VirtualSize
;
3056 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
3057 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
3058 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= SectionHeader
[Index
].VirtualAddress
;
3059 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= SectionHeader
[Index
].Misc
.VirtualSize
;
3066 // Zero ExceptionTable Xdata
3068 if (!KeepExceptionTableFlag
) {
3069 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3070 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++) {
3071 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".xdata") == 0) {
3073 // zero .xdata section
3075 memset (FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, 0, SectionHeader
[Index
].SizeOfRawData
);
3076 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
);
3083 // Zero Time/Data field
3085 ZeroDebugData (FileBuffer
, FALSE
);
3087 if (OutImageType
== FW_TE_IMAGE
) {
3088 if ((PeHdr
->Pe32
.FileHeader
.NumberOfSections
&~0xFF) || (Type
&~0xFF)) {
3090 // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
3092 Error (NULL
, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName
);
3096 if ((PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
)) {
3098 // TeImage has the same section alignment and file alignment.
3100 Error (NULL
, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName
);
3104 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",
3105 TEImageHeader
.Machine
, TEImageHeader
.NumberOfSections
, TEImageHeader
.StrippedSize
, (unsigned) TEImageHeader
.AddressOfEntryPoint
, (unsigned) TEImageHeader
.BaseOfCode
, (unsigned long long) TEImageHeader
.ImageBase
);
3107 // Update Image to TeImage
3109 if (fpOut
!= NULL
) {
3110 fwrite (&TEImageHeader
, 1, sizeof (EFI_TE_IMAGE_HEADER
), fpOut
);
3111 fwrite (FileBuffer
+ TEImageHeader
.StrippedSize
, 1, FileLength
- TEImageHeader
.StrippedSize
, fpOut
);
3113 if (fpInOut
!= NULL
) {
3114 fwrite (&TEImageHeader
, 1, sizeof (EFI_TE_IMAGE_HEADER
), fpInOut
);
3115 fwrite (FileBuffer
+ TEImageHeader
.StrippedSize
, 1, FileLength
- TEImageHeader
.StrippedSize
, fpInOut
);
3117 VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength
- TEImageHeader
.StrippedSize
));
3122 // Update Image to EfiImage
3124 if (fpOut
!= NULL
) {
3125 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
3127 if (fpInOut
!= NULL
) {
3128 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
3130 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
3133 if (fpInOut
!= NULL
) {
3134 if (GetUtilityStatus () != STATUS_SUCCESS
) {
3136 // when file updates failed, original file is still recoveried.
3138 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
3141 // Write converted data into fpInOut file and close input file.
3146 if (FileBuffer
!= NULL
) {
3150 if (InputFileName
!= NULL
) {
3151 free (InputFileName
);
3154 if (fpOut
!= NULL
) {
3156 // Write converted data into fpOut file and close output file.
3159 if (GetUtilityStatus () != STATUS_SUCCESS
) {
3160 if (OutputFileBuffer
== NULL
) {
3161 remove (OutImageName
);
3163 fpOut
= fopen (OutImageName
, "wb");
3164 fwrite (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
3166 free (OutputFileBuffer
);
3171 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
3173 return GetUtilityStatus ();
3179 IN OUT UINT8
*FileBuffer
,
3180 BOOLEAN ZeroDebugFlag
3184 Routine Description:
3186 Zero debug information in PeImage.
3190 FileBuffer - Pointer to PeImage.
3191 ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp
3195 EFI_ABORTED - PeImage is invalid.
3196 EFI_SUCCESS - Zero debug data successfully.
3201 UINT32 DebugDirectoryEntryRva
;
3202 UINT32 DebugDirectoryEntryFileOffset
;
3203 UINT32 ExportDirectoryEntryRva
;
3204 UINT32 ExportDirectoryEntryFileOffset
;
3205 UINT32 ResourceDirectoryEntryRva
;
3206 UINT32 ResourceDirectoryEntryFileOffset
;
3207 EFI_IMAGE_DOS_HEADER
*DosHdr
;
3208 EFI_IMAGE_FILE_HEADER
*FileHdr
;
3209 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
3210 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
3211 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
3212 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
3213 UINT32
*NewTimeStamp
;
3218 DebugDirectoryEntryRva
= 0;
3219 ExportDirectoryEntryRva
= 0;
3220 ResourceDirectoryEntryRva
= 0;
3221 DebugDirectoryEntryFileOffset
= 0;
3222 ExportDirectoryEntryFileOffset
= 0;
3223 ResourceDirectoryEntryFileOffset
= 0;
3224 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
3225 FileHdr
= (EFI_IMAGE_FILE_HEADER
*) (FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
3228 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
3229 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
3230 // NO DOS header, must start with PE/COFF header
3231 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
3233 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
3237 // Get Debug, Export and Resource EntryTable RVA address.
3238 // Resource Directory entry need to review.
3240 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
3241 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3242 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3243 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3244 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3245 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3247 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3248 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3249 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3251 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3252 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3253 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3254 if (ZeroDebugFlag
) {
3255 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
3256 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
3260 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3261 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3262 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3263 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3264 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3266 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3267 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3268 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3270 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3271 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3272 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3273 if (ZeroDebugFlag
) {
3274 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
3275 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
3281 // Get DirectoryEntryTable file offset.
3283 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
3284 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3285 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3286 DebugDirectoryEntryFileOffset
=
3287 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3289 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3290 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3291 ExportDirectoryEntryFileOffset
=
3292 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3294 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3295 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3296 ResourceDirectoryEntryFileOffset
=
3297 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3302 //Zero Debug Data and TimeStamp
3304 FileHdr
->TimeDateStamp
= 0;
3306 if (ExportDirectoryEntryFileOffset
!= 0) {
3307 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
3311 if (ResourceDirectoryEntryFileOffset
!= 0) {
3312 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
3316 if (DebugDirectoryEntryFileOffset
!= 0) {
3317 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
);
3318 DebugEntry
->TimeDateStamp
= 0;
3319 if (ZeroDebugFlag
) {
3320 memset (FileBuffer
+ DebugEntry
->FileOffset
, 0, DebugEntry
->SizeOfData
);
3321 memset (DebugEntry
, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
3331 IN OUT UINT8
*FileBuffer
,
3336 Routine Description:
3338 Set new time stamp into PeImage FileHdr and Directory table:
3339 Debug, Export and Resource.
3343 FileBuffer - Pointer to PeImage.
3344 TimeStamp - Time stamp string.
3348 EFI_INVALID_PARAMETER - TimeStamp format is not recognized.
3349 EFI_SUCCESS - Set new time stamp in this image successfully.
3357 UINT32 DebugDirectoryEntryRva
;
3358 UINT32 DebugDirectoryEntryFileOffset
;
3359 UINT32 ExportDirectoryEntryRva
;
3360 UINT32 ExportDirectoryEntryFileOffset
;
3361 UINT32 ResourceDirectoryEntryRva
;
3362 UINT32 ResourceDirectoryEntryFileOffset
;
3363 EFI_IMAGE_DOS_HEADER
*DosHdr
;
3364 EFI_IMAGE_FILE_HEADER
*FileHdr
;
3365 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
3366 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
3367 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
3368 UINT32
*NewTimeStamp
;
3373 DebugDirectoryEntryRva
= 0;
3374 DebugDirectoryEntryFileOffset
= 0;
3375 ExportDirectoryEntryRva
= 0;
3376 ExportDirectoryEntryFileOffset
= 0;
3377 ResourceDirectoryEntryRva
= 0;
3378 ResourceDirectoryEntryFileOffset
= 0;
3380 // Get time and date that will be set.
3382 if (TimeStamp
== NULL
) {
3383 Error (NULL
, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");
3384 return EFI_INVALID_PARAMETER
;
3387 // compare the value with "NOW", if yes, current system time is set.
3389 if (stricmp (TimeStamp
, "NOW") == 0) {
3391 // get system current time and date
3396 // Check Time Format strictly yyyy-mm-dd 00:00:00
3398 for (Index
= 0; TimeStamp
[Index
] != '\0' && Index
< 20; Index
++) {
3399 if (Index
== 4 || Index
== 7) {
3400 if (TimeStamp
[Index
] == '-') {
3403 } else if (Index
== 13 || Index
== 16) {
3404 if (TimeStamp
[Index
] == ':') {
3407 } else if (Index
== 10 && TimeStamp
[Index
] == ' ') {
3409 } else if ((TimeStamp
[Index
] < '0') || (TimeStamp
[Index
] > '9')) {
3414 if (Index
< 19 || TimeStamp
[19] != '\0') {
3415 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
3416 return EFI_INVALID_PARAMETER
;
3420 // get the date and time from TimeStamp
3422 if (sscanf (TimeStamp
, "%d-%d-%d %d:%d:%d",
3430 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
3431 return EFI_INVALID_PARAMETER
;
3435 // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
3437 if (stime
.tm_mon
<= 0 || stime
.tm_mday
<=0) {
3438 Error (NULL
, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp
);
3439 return EFI_INVALID_PARAMETER
;
3444 // in struct, Year (current year minus 1900)
3445 // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
3448 // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
3450 if (stime
.tm_year
>= 1970 && stime
.tm_year
<= 2038) {
3452 // convert 1970 -> 70, 2000 -> 100, ...
3454 stime
.tm_year
-= 1900;
3456 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
3457 return EFI_INVALID_PARAMETER
;
3461 // convert the date and time to time_t format
3463 newtime
= mktime (&stime
);
3464 if (newtime
== (time_t) - 1) {
3465 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
3466 return EFI_INVALID_PARAMETER
;
3470 ptime
= localtime (&newtime
);
3471 DebugMsg (NULL
, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",
3472 ptime
->tm_year
+ 1900, ptime
->tm_mon
+ 1, ptime
->tm_mday
, ptime
->tm_hour
, ptime
->tm_min
, ptime
->tm_sec
);
3474 // Set new time and data into PeImage.
3476 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
3477 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
3478 // NO DOS header, must start with PE/COFF header
3479 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
3481 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
3485 // Get Debug, Export and Resource EntryTable RVA address.
3486 // Resource Directory entry need to review.
3488 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
3489 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3490 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3491 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3492 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3493 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3495 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3496 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3497 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3499 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3500 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3501 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3504 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3505 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3506 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3507 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3508 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3510 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3511 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3512 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3514 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3515 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3516 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3521 // Get DirectoryEntryTable file offset.
3523 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
3524 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3525 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3526 DebugDirectoryEntryFileOffset
=
3527 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3529 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3530 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3531 ExportDirectoryEntryFileOffset
=
3532 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3534 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3535 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3536 ResourceDirectoryEntryFileOffset
=
3537 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3544 FileHdr
->TimeDateStamp
= (UINT32
) newtime
;
3546 if (ExportDirectoryEntryRva
!= 0) {
3547 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
3548 *NewTimeStamp
= (UINT32
) newtime
;
3551 if (ResourceDirectoryEntryRva
!= 0) {
3552 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
3553 *NewTimeStamp
= (UINT32
) newtime
;
3556 if (DebugDirectoryEntryRva
!= 0) {
3557 NewTimeStamp
= (UINT32
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
+ sizeof (UINT32
));
3558 *NewTimeStamp
= (UINT32
) newtime
;
3572 Routine Description:
3573 Read a 32-bit microcode data value from a text file and convert to raw binary form.
3576 InFptr - file pointer to input text file
3577 Data - pointer to where to return the data parsed
3580 STATUS_SUCCESS - no errors or warnings, Data contains valid information
3581 STATUS_ERROR - errors were encountered
3585 CHAR8 Line
[MAX_LINE_LEN
];
3587 unsigned ScannedData
= 0;
3589 Line
[MAX_LINE_LEN
- 1] = 0;
3591 if (fgets (Line
, MAX_LINE_LEN
, InFptr
) == NULL
) {
3592 return STATUS_ERROR
;
3595 // If it was a binary file, then it may have overwritten our null terminator
3597 if (Line
[MAX_LINE_LEN
- 1] != 0) {
3598 return STATUS_ERROR
;
3604 for (cptr
= Line
; *cptr
&& isspace((int)*cptr
); cptr
++) {
3607 // Skip Blank Lines and Comment Lines
3608 if ((strlen(cptr
) != 0) && (*cptr
!= ';')) {
3614 // dd 000000001h ; comment
3619 if ((tolower((int)cptr
[0]) == 'd') && (tolower((int)cptr
[1]) == 'd') && isspace ((int)cptr
[2])) {
3621 // Skip blanks and look for a hex digit
3624 for (; *cptr
&& isspace((int)*cptr
); cptr
++) {
3626 if (isxdigit ((int)*cptr
)) {
3627 if (sscanf (cptr
, "%X", &ScannedData
) != 1) {
3628 return STATUS_ERROR
;
3631 *Data
= (UINT32
) ScannedData
;
3632 return STATUS_SUCCESS
;
3635 return STATUS_ERROR
;