3 Copyright (c) 2004 - 2010, 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
81 #define FW_REBASE_IMAGE 12
82 #define FW_SET_ADDRESS_IMAGE 13
84 #define DUMP_TE_HEADER 0x11
86 #define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
87 #define DEFAULT_MC_ALIGNMENT 16
93 #define STATUS_IGNORE 0xA
95 // Structure definition for a microcode header
103 UINT32 LoaderVersion
;
105 UINT32 DataSize
; // if 0, then TotalSize = 2048, and TotalSize field is invalid
106 UINT32 TotalSize
; // number of bytes
108 } MICROCODE_IMAGE_HEADER
;
110 static EFI_GUID mZeroGuid
= {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
112 static const char *gHiiPackageRCFileHeader
[] = {
114 "// DO NOT EDIT -- auto-generated file",
119 STATIC CHAR8
*mInImageName
;
122 // Module image information
124 STATIC UINT32 mImageTimeStamp
= 0;
125 STATIC UINT32 mImageSize
= 0;
130 IN OUT UINT8
*FileBuffer
,
137 IN OUT UINT8
*FileBuffer
,
157 Print out version information for this utility.
169 fprintf (stdout
, "%s Version %d.%d\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
);
196 fprintf (stdout
, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME
);
199 // Copyright declaration
201 fprintf (stdout
, "Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.\n\n");
206 fprintf (stdout
, "Options:\n");
207 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
208 File will be created to store the ouput content.\n");
209 fprintf (stdout
, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\
210 Create Efi Image. EFI_FILETYPE is one of BASE,SMM_CORE,\n\
211 PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\
212 SEC, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER,\n\
213 DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER,\n\
214 PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\
215 APPLICATION, SAL_RT_DRIVER to support all module types\n\
216 It can only be used together with --keepexceptiontable,\n\
217 --keepzeropending, -r, -o option.It is a action option.\n\
218 If it is combined with other action options, the later\n\
219 input action option will override the previous one.\n");
220 fprintf (stdout
, " -c, --acpi Create Acpi table.\n\
221 It can't be combined with other action options\n\
222 except for -o, -r option. It is a action option.\n\
223 If it is combined with other action options, the later\n\
224 input action option will override the previous one.\n");
225 fprintf (stdout
, " -t, --terse Create Te Image.\n\
226 It can only be used together with --keepexceptiontable,\n\
227 --keepzeropending, -r, -o option.It is a action option.\n\
228 If it is combined with other action options, the later\n\
229 input action option will override the previous one.\n");
230 fprintf (stdout
, " -u, --dump Dump TeImage Header.\n\
231 It can't be combined with other action options\n\
232 except for -o, -r option. It is a action option.\n\
233 If it is combined with other action options, the later\n\
234 input action option will override the previous one.\n");
235 fprintf (stdout
, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\
236 It also zeros the time stamp fields.\n\
237 This option can be used to compare the binary efi image.\n\
238 It can't be combined with other action options\n\
239 except for -o, -r option. It is a action option.\n\
240 If it is combined with other action options, the later\n\
241 input action option will override the previous one.\n");
242 fprintf (stdout
, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\
243 It can't be combined with other action options\n\
244 except for -o, -r option. It is a action option.\n\
245 If it is combined with other action options, the later\n\
246 input action option will override the previous one.\n");;
247 fprintf (stdout
, " -l, --stripped Strip off the relocation info from PE or TE image.\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
, " -s timedate, --stamp timedate\n\
253 timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\
254 is set to NOW, current system time is used. The support\n\
255 date scope is 1970-01-01 00+timezone:00:00\n\
256 ~ 2038-01-19 03+timezone:14:07\n\
257 The scope is adjusted according to the different zones.\n\
258 It can't be combined with other action options\n\
259 except for -o, -r option. It is a action option.\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
, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\
263 It can't be combined with other action options\n\
264 except for -o option. It is a action option.\n\
265 If it is combined with other action options, the later\n\
266 input action option will override the previous one.\n");
267 fprintf (stdout
, " -j, --join Combine multi microcode bin files to one file.\n\
268 It can be specified with -a, -p, -o option.\n\
269 No other options can be combined with it.\n\
270 If it is combined with other action options, the later\n\
271 input action option will override the previous one.\n");
272 fprintf (stdout
, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\
273 This option is only used together with -j option.\n");
274 fprintf (stdout
, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\
275 This option is only used together with -j option.\n");
276 fprintf (stdout
, " --keepexceptiontable Don't clear exception table.\n\
277 This option can be used together with -e or -t.\n\
278 It doesn't work for other options.\n");
279 fprintf (stdout
, " --keepzeropending Don't strip zero pending of .reloc.\n\
280 This option can be used together with -e or -t.\n\
281 It doesn't work for other options.\n");
282 fprintf (stdout
, " -r, --replace Overwrite the input file with the output content.\n\
283 If more input files are specified,\n\
284 the last input file will be as the output file.\n");
285 fprintf (stdout
, " -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\
286 Guid is used to specify hii package list guid.\n\
287 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\
288 If not specified, the first Form FormSet guid is used.\n");
289 fprintf (stdout
, " --hiipackage Combine all input binary hii pacakges into \n\
290 a single package list as the text resource data(RC).\n\
291 It can't be combined with other action options\n\
292 except for -o option. It is a action option.\n\
293 If it is combined with other action options, the later\n\
294 input action option will override the previous one.\n");
295 fprintf (stdout
, " --hiibinpackage Combine all input binary hii pacakges into \n\
296 a single package list as the binary resource section.\n\
297 It can't be combined with other action options\n\
298 except for -o option. It is a action option.\n\
299 If it is combined with other action options, the later\n\
300 input action option will override the previous one.\n");
301 fprintf (stdout
, " --rebase NewAddress Rebase image to new base address. New address \n\
302 is also set to the first none code section header.\n\
303 It can't be combined with other action options\n\
304 except for -o or -r option. It is a action option.\n\
305 If it is combined with other action options, the later\n\
306 input action option will override the previous one.\n");
307 fprintf (stdout
, " --address NewAddress Set new address into the first none code \n\
308 section header of the input image.\n\
309 It can't be combined with other action options\n\
310 except for -o or -r option. It is a action option.\n\
311 If it is combined with other action options, the later\n\
312 input action option will override the previous one.\n");
313 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
314 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
315 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
316 fprintf (stdout
, " --version Show program's version number and exit\n");
317 fprintf (stdout
, " -h, --help Show this help message and exit\n");
334 AcpiTable Buffer for AcpiSection
335 Length AcpiSection Length
344 EFI_ACPI_DESCRIPTION_HEADER
*AcpiHeader
;
345 EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs
;
346 UINT32 ExpectedLength
;
348 AcpiHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTable
;
351 // Generic check for AcpiTable length.
353 if (AcpiHeader
->Length
> Length
) {
354 Error (NULL
, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL
);
359 // Currently, we only check must-have tables: FADT, FACS, DSDT,
360 // and some important tables: MADT, MCFG.
362 switch (AcpiHeader
->Signature
) {
365 // "FACP" Fixed ACPI Description Table
367 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
:
368 switch (AcpiHeader
->Revision
) {
369 case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
370 ExpectedLength
= sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
);
372 case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
373 ExpectedLength
= sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
);
375 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
376 ExpectedLength
= sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
);
379 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
) {
380 ExpectedLength
= AcpiHeader
->Length
;
383 Error (NULL
, 0, 3000, "Invalid", "FACP revision check failed.");
386 if (ExpectedLength
!= AcpiHeader
->Length
) {
387 Error (NULL
, 0, 3000, "Invalid", "FACP length check failed.");
393 // "FACS" Firmware ACPI Control Structure
395 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE
:
396 Facs
= (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)AcpiTable
;
397 if (Facs
->Version
> EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) {
400 if ((Facs
->Version
!= EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
401 (Facs
->Version
!= EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
402 (Facs
->Version
!= EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
)){
403 Error (NULL
, 0, 3000, "Invalid", "FACS version check failed.");
406 if ((Facs
->Length
!= sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
407 (Facs
->Length
!= sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
408 (Facs
->Length
!= sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
))) {
409 Error (NULL
, 0, 3000, "Invalid", "FACS length check failed.");
415 // "DSDT" Differentiated System Description Table
417 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
418 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION
) {
421 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
)) {
422 Error (NULL
, 0, 3000, "Invalid", "DSDT length check failed.");
428 // "APIC" Multiple APIC Description Table
430 case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE
:
431 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) {
434 if ((AcpiHeader
->Revision
!= EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
435 (AcpiHeader
->Revision
!= EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
436 (AcpiHeader
->Revision
!= EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
)) {
437 Error (NULL
, 0, 3000, "Invalid", "APIC revision check failed.");
440 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT32
) + sizeof(UINT32
)) {
441 Error (NULL
, 0, 3000, "Invalid", "APIC length check failed.");
447 // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
449 case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE
:
450 if (AcpiHeader
->Revision
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
453 if (AcpiHeader
->Revision
!= EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
454 Error (NULL
, 0, 3000, "Invalid", "MCFG revision check failed.");
457 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT64
)) {
458 Error (NULL
, 0, 3000, "Invalid", "MCFG length check failed.");
464 // Other table pass check
470 return STATUS_SUCCESS
;
479 return (FileBuffer
[EI_MAG0
] == ELFMAG0
480 && FileBuffer
[EI_MAG1
] == ELFMAG1
481 && FileBuffer
[EI_MAG2
] == ELFMAG2
482 && FileBuffer
[EI_MAG3
] == ELFMAG3
);
485 typedef Elf32_Shdr Elf_Shdr
;
486 typedef Elf32_Ehdr Elf_Ehdr
;
487 typedef Elf32_Rel Elf_Rel
;
488 typedef Elf32_Sym Elf_Sym
;
489 typedef Elf32_Phdr Elf_Phdr
;
490 typedef Elf32_Dyn Elf_Dyn
;
492 #define ELFCLASS ELFCLASS32
493 #define ELF_R_TYPE(r) ELF32_R_TYPE(r)
494 #define ELF_R_SYM(r) ELF32_R_SYM(r)
495 #define ELF_HII_SECTION_NAME ".hii"
497 // Well known ELF structures.
504 // PE section alignment.
506 const UINT32 CoffAlignment
= 0x20;
507 const UINT16 CoffNbrSections
= 5;
510 // Current offset in coff file.
515 // Result Coff file in memory.
517 UINT8
*CoffFile
= NULL
;
519 // ELF sections to offset in Coff file.
521 UINT32
*CoffSectionsOffset
= NULL
;
524 // Offset in Coff file of headers and sections.
530 UINT32 HiiRsrcOffset
;
533 EFI_IMAGE_BASE_RELOCATION
*CoffBaseRel
;
534 UINT16
*CoffEntryRel
;
541 return (Offset
+ CoffAlignment
- 1) & ~(CoffAlignment
- 1);
549 if (Num
>= Ehdr
->e_shnum
)
551 return (Elf_Shdr
*)((UINT8
*)ShdrBase
+ Num
* Ehdr
->e_shentsize
);
560 // Note: Magic has already been tested.
562 if (Ehdr
->e_ident
[EI_CLASS
] != ELFCLASS
) {
563 Error (NULL
, 0, 3000, "Unsupported", "%s needs to be ported for 64-bit ELF.", mInImageName
);
566 if (Ehdr
->e_ident
[EI_DATA
] != ELFDATA2LSB
) {
567 Error (NULL
, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");
570 if ((Ehdr
->e_type
!= ET_EXEC
) && (Ehdr
->e_type
!= ET_DYN
)) {
571 Error (NULL
, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");
574 if (!((Ehdr
->e_machine
== EM_386
) || (Ehdr
->e_machine
== EM_ARM
))) {
575 Error (NULL
, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM");
578 if (Ehdr
->e_version
!= EV_CURRENT
) {
579 Error (NULL
, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) Ehdr
->e_version
, EV_CURRENT
);
584 // Find the section header table
586 ShdrBase
= (Elf_Shdr
*)((UINT8
*)Ehdr
+ Ehdr
->e_shoff
);
587 gPhdrBase
= (Elf_Phdr
*)((UINT8
*)Ehdr
+ Ehdr
->e_phoff
);
589 CoffSectionsOffset
= (UINT32
*)malloc(Ehdr
->e_shnum
* sizeof (UINT32
));
591 memset(CoffSectionsOffset
, 0, Ehdr
->e_shnum
* sizeof(UINT32
));
600 return (Shdr
->sh_flags
& (SHF_WRITE
| SHF_ALLOC
)) == SHF_ALLOC
;
608 Elf_Shdr
*Namedr
= GetShdrByIndex(Ehdr
->e_shstrndx
);
610 if (strcmp((CHAR8
*)Ehdr
+ Namedr
->sh_offset
+ Shdr
->sh_name
, ELF_HII_SECTION_NAME
) == 0) {
622 if (IsHiiRsrcShdr(Shdr
)) {
625 return (Shdr
->sh_flags
& (SHF_WRITE
| SHF_ALLOC
)) == (SHF_ALLOC
| SHF_WRITE
);
636 EFI_IMAGE_SECTION_HEADER
*Hdr
;
637 Hdr
= (EFI_IMAGE_SECTION_HEADER
*)(CoffFile
+ TableOffset
);
639 strcpy((char *)Hdr
->Name
, Name
);
640 Hdr
->Misc
.VirtualSize
= Size
;
641 Hdr
->VirtualAddress
= Offset
;
642 Hdr
->SizeOfRawData
= Size
;
643 Hdr
->PointerToRawData
= Offset
;
644 Hdr
->PointerToRelocations
= 0;
645 Hdr
->PointerToLinenumbers
= 0;
646 Hdr
->NumberOfRelocations
= 0;
647 Hdr
->NumberOfLinenumbers
= 0;
648 Hdr
->Characteristics
= Flags
;
650 TableOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
654 SetHiiResourceHeader (
660 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
661 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*ResourceDirectoryEntry
;
662 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
663 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
666 // Fill Resource section entry
668 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
);
669 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
670 for (Index
= 0; Index
< ResourceDirectory
->NumberOfNamedEntries
; Index
++) {
671 if (ResourceDirectoryEntry
->u1
.s
.NameIsString
) {
672 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiBinData
+ ResourceDirectoryEntry
->u1
.s
.NameOffset
);
674 if (ResourceDirectoryString
->Length
== 3 &&
675 ResourceDirectoryString
->String
[0] == L
'H' &&
676 ResourceDirectoryString
->String
[1] == L
'I' &&
677 ResourceDirectoryString
->String
[2] == L
'I') {
679 // Resource Type "HII" found
681 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
683 // Move to next level - resource Name
685 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
686 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
688 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
690 // Move to next level - resource Language
692 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
693 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
698 // Now it ought to be resource Data and update its OffsetToData value
700 if (!ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
701 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.OffsetToData
);
702 ResourceDataEntry
->OffsetToData
= ResourceDataEntry
->OffsetToData
+ OffsetToFile
;
707 ResourceDirectoryEntry
++;
719 EFI_IMAGE_DOS_HEADER
*DosHdr
;
720 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
727 // Coff file start with a DOS header.
729 CoffOffset
= sizeof(EFI_IMAGE_DOS_HEADER
) + 0x40;
730 NtHdrOffset
= CoffOffset
;
731 switch (Ehdr
->e_machine
) {
734 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS32
);
738 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS64
);
741 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN
)Ehdr
->e_machine
);
742 CoffOffset
+= sizeof (EFI_IMAGE_NT_HEADERS32
);
746 TableOffset
= CoffOffset
;
747 CoffOffset
+= CoffNbrSections
* sizeof(EFI_IMAGE_SECTION_HEADER
);
750 // First text sections.
752 CoffOffset
= CoffAlign(CoffOffset
);
753 TextOffset
= CoffOffset
;
754 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
755 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
756 if (IsTextShdr(shdr
)) {
757 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
758 // the alignment field is valid
759 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
760 // if the section address is aligned we must align PE/COFF
761 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
762 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
763 // ARM RVCT tools have behavior outside of the ELF specification to try
764 // and make images smaller. If sh_addr is not aligned to sh_addralign
765 // then the section needs to preserve sh_addr MOD sh_addralign.
766 // Normally doing nothing here works great.
767 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
771 /* Relocate entry. */
772 if ((Ehdr
->e_entry
>= shdr
->sh_addr
) &&
773 (Ehdr
->e_entry
< shdr
->sh_addr
+ shdr
->sh_size
)) {
774 CoffEntry
= CoffOffset
+ Ehdr
->e_entry
- shdr
->sh_addr
;
776 CoffSectionsOffset
[i
] = CoffOffset
;
777 CoffOffset
+= shdr
->sh_size
;
781 if (Ehdr
->e_machine
!= EM_ARM
) {
782 CoffOffset
= CoffAlign(CoffOffset
);
786 // Then data sections.
788 DataOffset
= CoffOffset
;
789 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
790 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
791 if (IsDataShdr(shdr
)) {
792 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
793 // the alignment field is valid
794 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
795 // if the section address is aligned we must align PE/COFF
796 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
797 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
798 // ARM RVCT tools have behavior outside of the ELF specification to try
799 // and make images smaller. If sh_addr is not aligned to sh_addralign
800 // then the section needs to preserve sh_addr MOD sh_addralign.
801 // Normally doing nothing here works great.
802 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
805 CoffSectionsOffset
[i
] = CoffOffset
;
806 CoffOffset
+= shdr
->sh_size
;
809 CoffOffset
= CoffAlign(CoffOffset
);
812 // The HII resource sections.
814 HiiRsrcOffset
= CoffOffset
;
815 for (i
= 0; i
< Ehdr
->e_shnum
; i
++) {
816 Elf_Shdr
*shdr
= GetShdrByIndex(i
);
817 if (IsHiiRsrcShdr(shdr
)) {
818 if ((shdr
->sh_addralign
!= 0) && (shdr
->sh_addralign
!= 1)) {
819 // the alignment field is valid
820 if ((shdr
->sh_addr
& (shdr
->sh_addralign
- 1)) == 0) {
821 // if the section address is aligned we must align PE/COFF
822 CoffOffset
= (CoffOffset
+ shdr
->sh_addralign
- 1) & ~(shdr
->sh_addralign
- 1);
823 } else if ((shdr
->sh_addr
% shdr
->sh_addralign
) != (CoffOffset
% shdr
->sh_addralign
)) {
824 // ARM RVCT tools have behavior outside of the ELF specification to try
825 // and make images smaller. If sh_addr is not aligned to sh_addralign
826 // then the section needs to preserve sh_addr MOD sh_addralign.
827 // Normally doing nothing here works great.
828 Error (NULL
, 0, 3000, "Invalid", "Unsupported section alignment.");
831 if (shdr
->sh_size
!= 0) {
832 CoffSectionsOffset
[i
] = CoffOffset
;
833 CoffOffset
+= shdr
->sh_size
;
834 CoffOffset
= CoffAlign(CoffOffset
);
835 SetHiiResourceHeader ((UINT8
*) Ehdr
+ shdr
->sh_offset
, HiiRsrcOffset
);
841 RelocOffset
= CoffOffset
;
844 // Allocate base Coff file. Will be expanded later for relocations.
846 CoffFile
= (UINT8
*)malloc(CoffOffset
);
847 memset(CoffFile
, 0, CoffOffset
);
852 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)CoffFile
;
853 DosHdr
->e_magic
= EFI_IMAGE_DOS_SIGNATURE
;
854 DosHdr
->e_lfanew
= NtHdrOffset
;
856 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
858 NtHdr
->Pe32
.Signature
= EFI_IMAGE_NT_SIGNATURE
;
860 switch (Ehdr
->e_machine
) {
862 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IA32
;
863 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
866 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_X64
;
867 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
870 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IPF
;
871 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
874 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_ARMT
;
875 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
878 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN
)Ehdr
->e_machine
);
879 NtHdr
->Pe32
.FileHeader
.Machine
= EFI_IMAGE_MACHINE_IA32
;
880 NtHdr
->Pe32
.OptionalHeader
.Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
883 NtHdr
->Pe32
.FileHeader
.NumberOfSections
= CoffNbrSections
;
884 NtHdr
->Pe32
.FileHeader
.TimeDateStamp
= (UINT32
) time(NULL
);
885 mImageTimeStamp
= NtHdr
->Pe32
.FileHeader
.TimeDateStamp
;
886 NtHdr
->Pe32
.FileHeader
.PointerToSymbolTable
= 0;
887 NtHdr
->Pe32
.FileHeader
.NumberOfSymbols
= 0;
888 NtHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
= sizeof(NtHdr
->Pe32
.OptionalHeader
);
889 NtHdr
->Pe32
.FileHeader
.Characteristics
= EFI_IMAGE_FILE_EXECUTABLE_IMAGE
890 | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED
891 | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED
892 | EFI_IMAGE_FILE_32BIT_MACHINE
;
894 NtHdr
->Pe32
.OptionalHeader
.SizeOfCode
= DataOffset
- TextOffset
;
895 NtHdr
->Pe32
.OptionalHeader
.SizeOfInitializedData
= RelocOffset
- DataOffset
;
896 NtHdr
->Pe32
.OptionalHeader
.SizeOfUninitializedData
= 0;
897 NtHdr
->Pe32
.OptionalHeader
.AddressOfEntryPoint
= CoffEntry
;
899 NtHdr
->Pe32
.OptionalHeader
.BaseOfCode
= TextOffset
;
901 NtHdr
->Pe32
.OptionalHeader
.BaseOfData
= DataOffset
;
902 NtHdr
->Pe32
.OptionalHeader
.ImageBase
= 0;
903 NtHdr
->Pe32
.OptionalHeader
.SectionAlignment
= CoffAlignment
;
904 NtHdr
->Pe32
.OptionalHeader
.FileAlignment
= CoffAlignment
;
905 NtHdr
->Pe32
.OptionalHeader
.SizeOfImage
= 0;
907 NtHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
= TextOffset
;
908 NtHdr
->Pe32
.OptionalHeader
.NumberOfRvaAndSizes
= EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES
;
913 if ((DataOffset
- TextOffset
) > 0) {
914 CreateSectionHeader (".text", TextOffset
, DataOffset
- TextOffset
,
915 EFI_IMAGE_SCN_CNT_CODE
916 | EFI_IMAGE_SCN_MEM_EXECUTE
917 | EFI_IMAGE_SCN_MEM_READ
);
919 // Don't make a section of size 0.
920 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
923 if ((HiiRsrcOffset
- DataOffset
) > 0) {
924 CreateSectionHeader (".data", DataOffset
, HiiRsrcOffset
- DataOffset
,
925 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
926 | EFI_IMAGE_SCN_MEM_WRITE
927 | EFI_IMAGE_SCN_MEM_READ
);
929 // Don't make a section of size 0.
930 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
933 if ((RelocOffset
- HiiRsrcOffset
) > 0) {
934 CreateSectionHeader (".rsrc", HiiRsrcOffset
, RelocOffset
- HiiRsrcOffset
,
935 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
936 | EFI_IMAGE_SCN_MEM_READ
);
938 NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= RelocOffset
- HiiRsrcOffset
;
939 NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= HiiRsrcOffset
;
941 // Don't make a section of size 0.
942 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
949 int (*Filter
)(Elf_Shdr
*)
957 // First: copy sections.
959 for (Idx
= 0; Idx
< Ehdr
->e_shnum
; Idx
++) {
960 Elf_Shdr
*Shdr
= GetShdrByIndex(Idx
);
961 if ((*Filter
)(Shdr
)) {
962 switch (Shdr
->sh_type
) {
965 memcpy(CoffFile
+ CoffSectionsOffset
[Idx
],
966 (UINT8
*)Ehdr
+ Shdr
->sh_offset
,
971 memset(CoffFile
+ CoffSectionsOffset
[Idx
], 0, Shdr
->sh_size
);
976 // Ignore for unkown section type.
978 VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName
, (unsigned)Shdr
->sh_type
);
985 // Second: apply relocations.
987 for (Idx
= 0; Idx
< Ehdr
->e_shnum
; Idx
++) {
988 Elf_Shdr
*RelShdr
= GetShdrByIndex(Idx
);
989 if (RelShdr
->sh_type
!= SHT_REL
)
991 SecShdr
= GetShdrByIndex(RelShdr
->sh_info
);
992 SecOffset
= CoffSectionsOffset
[RelShdr
->sh_info
];
993 if (RelShdr
->sh_type
== SHT_REL
&& (*Filter
)(SecShdr
)) {
995 Elf_Shdr
*SymtabShdr
= GetShdrByIndex(RelShdr
->sh_link
);
996 UINT8
*Symtab
= (UINT8
*)Ehdr
+ SymtabShdr
->sh_offset
;
998 for (RelIdx
= 0; RelIdx
< RelShdr
->sh_size
; RelIdx
+= RelShdr
->sh_entsize
) {
999 Elf_Rel
*Rel
= (Elf_Rel
*)((UINT8
*)Ehdr
+ RelShdr
->sh_offset
+ RelIdx
);
1000 Elf_Sym
*Sym
= (Elf_Sym
*)(Symtab
+ ELF_R_SYM(Rel
->r_info
) * SymtabShdr
->sh_entsize
);
1004 if (Sym
->st_shndx
== SHN_UNDEF
1005 || Sym
->st_shndx
== SHN_ABS
1006 || Sym
->st_shndx
> Ehdr
->e_shnum
) {
1007 Error (NULL
, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName
);
1009 SymShdr
= GetShdrByIndex(Sym
->st_shndx
);
1012 // Note: r_offset in a memory address.
1013 // Convert it to a pointer in the coff file.
1015 Targ
= CoffFile
+ SecOffset
+ (Rel
->r_offset
- SecShdr
->sh_addr
);
1017 if (Ehdr
->e_machine
== EM_386
) {
1018 switch (ELF_R_TYPE(Rel
->r_info
)) {
1023 // Absolute relocation.
1025 *(UINT32
*)Targ
= *(UINT32
*)Targ
- SymShdr
->sh_addr
1026 + CoffSectionsOffset
[Sym
->st_shndx
];
1030 // Relative relocation: Symbol - Ip + Addend
1032 *(UINT32
*)Targ
= *(UINT32
*)Targ
1033 + (CoffSectionsOffset
[Sym
->st_shndx
] - SymShdr
->sh_addr
)
1034 - (SecOffset
- SecShdr
->sh_addr
);
1037 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, (unsigned) ELF_R_TYPE(Rel
->r_info
));
1039 } else if (Ehdr
->e_machine
== EM_ARM
) {
1040 switch (ELF32_R_TYPE(Rel
->r_info
)) {
1041 case R_ARM_RBASE
: // No relocation - no action required
1042 case R_ARM_PC24
: // PC-relative relocations don't require modification
1043 case R_ARM_XPC25
: // PC-relative relocations don't require modification
1048 // Absolute relocation.
1050 *(UINT32
*)Targ
= *(UINT32
*)Targ
- SymShdr
->sh_addr
+ CoffSectionsOffset
[Sym
->st_shndx
];
1053 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, (unsigned) ELF32_R_TYPE(Rel
->r_info
));
1066 *CoffEntryRel
= Val
;
1068 CoffBaseRel
->SizeOfBlock
+= 2;
1078 if (CoffBaseRel
== NULL
1079 || CoffBaseRel
->VirtualAddress
!= (Offset
& ~0xfff)) {
1080 if (CoffBaseRel
!= NULL
) {
1082 // Add a null entry (is it required ?)
1084 CoffAddFixupEntry (0);
1086 // Pad for alignment.
1088 if (CoffOffset
% 4 != 0)
1089 CoffAddFixupEntry (0);
1094 CoffOffset
+ sizeof(EFI_IMAGE_BASE_RELOCATION
) + 2*0x1000);
1095 memset(CoffFile
+ CoffOffset
, 0,
1096 sizeof(EFI_IMAGE_BASE_RELOCATION
) + 2*0x1000);
1098 CoffBaseRel
= (EFI_IMAGE_BASE_RELOCATION
*)(CoffFile
+ CoffOffset
);
1099 CoffBaseRel
->VirtualAddress
= Offset
& ~0xfff;
1100 CoffBaseRel
->SizeOfBlock
= sizeof(EFI_IMAGE_BASE_RELOCATION
);
1102 CoffEntryRel
= (UINT16
*)(CoffBaseRel
+ 1);
1103 CoffOffset
+= sizeof(EFI_IMAGE_BASE_RELOCATION
);
1109 CoffAddFixupEntry((UINT16
) ((Type
<< 12) | (Offset
& 0xfff)));
1118 if (num
>= Ehdr
->e_phnum
) {
1122 return (Elf32_Phdr
*)((UINT8
*)gPhdrBase
+ num
* Ehdr
->e_phentsize
);
1132 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1133 EFI_IMAGE_DATA_DIRECTORY
*Dir
;
1134 BOOLEAN FoundRelocations
;
1137 UINTN RelElementSize
;
1142 Elf32_Phdr
*DynamicSegment
;
1143 Elf32_Phdr
*TargetSegment
;
1145 for (Index
= 0, FoundRelocations
= FALSE
; Index
< Ehdr
->e_shnum
; Index
++) {
1146 Elf_Shdr
*RelShdr
= GetShdrByIndex(Index
);
1147 if (RelShdr
->sh_type
== SHT_REL
) {
1148 Elf_Shdr
*SecShdr
= GetShdrByIndex(RelShdr
->sh_info
);
1149 if (IsTextShdr(SecShdr
) || IsDataShdr(SecShdr
)) {
1151 FoundRelocations
= TRUE
;
1152 for (RelIdx
= 0; RelIdx
< RelShdr
->sh_size
; RelIdx
+= RelShdr
->sh_entsize
) {
1153 Elf_Rel
*Rel
= (Elf_Rel
*)
1154 ((UINT8
*)Ehdr
+ RelShdr
->sh_offset
+ RelIdx
);
1156 if (Ehdr
->e_machine
== EM_386
) {
1157 switch (ELF_R_TYPE(Rel
->r_info
)) {
1162 CoffAddFixup(CoffSectionsOffset
[RelShdr
->sh_info
]
1163 + (Rel
->r_offset
- SecShdr
->sh_addr
),
1164 EFI_IMAGE_REL_BASED_HIGHLOW
);
1167 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, (unsigned) ELF_R_TYPE(Rel
->r_info
));
1169 } else if (Ehdr
->e_machine
== EM_ARM
) {
1170 switch (ELF32_R_TYPE(Rel
->r_info
)) {
1178 CoffSectionsOffset
[RelShdr
->sh_info
]
1179 + (Rel
->r_offset
- SecShdr
->sh_addr
),
1180 EFI_IMAGE_REL_BASED_HIGHLOW
1184 Error (NULL
, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName
, (unsigned) ELF32_R_TYPE(Rel
->r_info
));
1187 Error (NULL
, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) Ehdr
->e_machine
);
1194 if (!FoundRelocations
&& (Ehdr
->e_machine
== EM_ARM
)) {
1195 /* Try again, but look for PT_DYNAMIC instead of SHT_REL */
1197 for (Index
= 0; Index
< Ehdr
->e_phnum
; Index
++) {
1202 DynamicSegment
= GetPhdrByIndex (Index
);
1204 if (DynamicSegment
->p_type
== PT_DYNAMIC
) {
1205 Dyn
= (Elf32_Dyn
*) ((UINT8
*)Ehdr
+ DynamicSegment
->p_offset
);
1207 while (Dyn
->d_tag
!= DT_NULL
) {
1208 switch (Dyn
->d_tag
) {
1210 RelOffset
= Dyn
->d_un
.d_val
;
1214 RelSize
= Dyn
->d_un
.d_val
;
1218 RelElementSize
= Dyn
->d_un
.d_val
;
1223 if (( RelOffset
== 0 ) || ( RelSize
== 0 ) || ( RelElementSize
== 0 )) {
1224 Error (NULL
, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName
);
1227 for (K
= 0; K
< RelSize
; K
+= RelElementSize
) {
1229 Rel
= (Elf32_Rel
*) ((UINT8
*) Ehdr
+ DynamicSegment
->p_offset
+ RelOffset
+ K
);
1231 switch (ELF32_R_TYPE (Rel
->r_info
)) {
1235 TargetSegment
= GetPhdrByIndex (ELF32_R_SYM (Rel
->r_info
) - 1);
1237 // Note: r_offset in a memory address. Convert it to a pointer in the coff file.
1238 Targ
= CoffFile
+ CoffSectionsOffset
[ ELF32_R_SYM( Rel
->r_info
) ] + Rel
->r_offset
- TargetSegment
->p_vaddr
;
1240 *(UINT32
*)Targ
= *(UINT32
*)Targ
+ CoffSectionsOffset
[ELF32_R_SYM( Rel
->r_info
)];
1242 CoffAddFixup (CoffSectionsOffset
[ELF32_R_SYM (Rel
->r_info
)] + (Rel
->r_offset
- TargetSegment
->p_vaddr
), EFI_IMAGE_REL_BASED_HIGHLOW
);
1245 Error (NULL
, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type.", mInImageName
);
1254 // Pad by adding empty entries.
1256 while (CoffOffset
& (CoffAlignment
- 1)) {
1257 CoffAddFixupEntry(0);
1261 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1262 Dir
= &NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1263 Dir
->Size
= CoffOffset
- RelocOffset
;
1264 if (Dir
->Size
== 0) {
1265 // If no relocations, null out the directory entry and don't add the .reloc section
1266 Dir
->VirtualAddress
= 0;
1267 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
1269 Dir
->VirtualAddress
= RelocOffset
;
1270 CreateSectionHeader (".reloc", RelocOffset
, CoffOffset
- RelocOffset
,
1271 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
1272 | EFI_IMAGE_SCN_MEM_DISCARDABLE
1273 | EFI_IMAGE_SCN_MEM_READ
);
1285 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1286 EFI_IMAGE_DATA_DIRECTORY
*DataDir
;
1287 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*Dir
;
1288 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
*Nb10
;
1290 Len
= strlen(mInImageName
) + 1;
1291 DebugOffset
= CoffOffset
;
1293 CoffOffset
+= sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
)
1294 + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
)
1296 CoffOffset
= CoffAlign(CoffOffset
);
1298 CoffFile
= realloc(CoffFile
, CoffOffset
);
1299 memset(CoffFile
+ DebugOffset
, 0, CoffOffset
- DebugOffset
);
1301 Dir
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)(CoffFile
+ DebugOffset
);
1302 Dir
->Type
= EFI_IMAGE_DEBUG_TYPE_CODEVIEW
;
1303 Dir
->SizeOfData
= sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
) + Len
;
1304 Dir
->RVA
= DebugOffset
+ sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
1305 Dir
->FileOffset
= DebugOffset
+ sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
1307 Nb10
= (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
*)(Dir
+ 1);
1308 Nb10
->Signature
= CODEVIEW_SIGNATURE_NB10
;
1309 strcpy ((char *)(Nb10
+ 1), mInImageName
);
1312 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1313 DataDir
= &NtHdr
->Pe32
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
];
1314 DataDir
->VirtualAddress
= DebugOffset
;
1315 DataDir
->Size
= CoffOffset
- DebugOffset
;
1316 if (DataDir
->Size
== 0) {
1317 // If no debug, null out the directory entry and don't add the .debug section
1318 DataDir
->VirtualAddress
= 0;
1319 NtHdr
->Pe32
.FileHeader
.NumberOfSections
--;
1321 DataDir
->VirtualAddress
= DebugOffset
;
1322 CreateSectionHeader (".debug", DebugOffset
, CoffOffset
- DebugOffset
,
1323 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
1324 | EFI_IMAGE_SCN_MEM_DISCARDABLE
1325 | EFI_IMAGE_SCN_MEM_READ
);
1336 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NtHdr
;
1339 // Check header, read section table.
1341 Ehdr
= (Elf32_Ehdr
*)*FileBuffer
;
1342 if (!CheckElfHeader())
1345 VerboseMsg ("Check Efl Image Header");
1347 // Compute sections new address.
1352 VerboseMsg ("Compute sections new address.");
1355 // Write and relocate sections.
1357 WriteSections(IsTextShdr
);
1358 WriteSections(IsDataShdr
);
1359 WriteSections(IsHiiRsrcShdr
);
1360 VerboseMsg ("Write and relocate sections.");
1363 // Translate and write relocations.
1366 VerboseMsg ("Translate and write relocations.");
1369 // Write debug info.
1372 VerboseMsg ("Write debug info.");
1374 NtHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(CoffFile
+ NtHdrOffset
);
1375 NtHdr
->Pe32
.OptionalHeader
.SizeOfImage
= CoffOffset
;
1381 *FileBuffer
= CoffFile
;
1382 *FileLength
= CoffOffset
;
1385 // Free memory space
1387 if (CoffSectionsOffset
!= NULL
) {
1388 free (CoffSectionsOffset
);
1393 EFI_IMAGE_OPTIONAL_HEADER_UNION
*
1398 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1399 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1402 // Read the dos & pe hdrs of the image
1404 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Data
;
1405 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
1406 // NO DOS header, check for PE/COFF header
1407 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(Data
);
1408 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1413 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(((UINT8
*)Data
) + DosHdr
->e_lfanew
);
1414 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1423 PeCoffConvertImageToXip (
1428 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1429 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NewPeHdr
;
1430 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1431 UINTN TotalNecessaryFileSize
;
1436 UINTN FirstSectionOffset
;
1437 BOOLEAN ConversionNeeded
;
1439 PeHdr
= GetPeCoffHeader ((void *) *FileBuffer
);
1440 if (PeHdr
== NULL
) {
1444 if (PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
) {
1446 // The only reason to expand zero fill sections is to make them compatible with XIP images.
1447 // If SectionAlignment is not equal to FileAlginment then it is not an XIP type image.
1453 // Calculate size of XIP file, and determine if the conversion is needed.
1455 ConversionNeeded
= FALSE
;
1457 FirstSectionOffset
= *FileLength
;
1458 TotalNecessaryFileSize
= 0;
1459 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
1460 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1461 SectionSize
= MAX (SectionHeader
->Misc
.VirtualSize
, SectionHeader
->SizeOfRawData
);
1462 TotalNecessaryFileSize
+= SectionSize
;
1463 if (SectionSize
> 0) {
1464 FirstSectionOffset
= MIN (FirstSectionOffset
, SectionHeader
->VirtualAddress
);
1465 XipLength
= MAX (XipLength
, SectionHeader
->VirtualAddress
+ SectionSize
);
1466 if (SectionHeader
->VirtualAddress
!= SectionHeader
->PointerToRawData
) {
1467 ConversionNeeded
= TRUE
;
1470 if (SectionHeader
->Misc
.VirtualSize
> SectionHeader
->SizeOfRawData
) {
1471 ConversionNeeded
= TRUE
;
1475 if (FirstSectionOffset
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
1477 // If one of the sections should be loaded to an offset overlapping with
1478 // the executable header, then it cannot be made into an XIP image.
1480 VerboseMsg ("PE/COFF conversion to XIP is impossible due to overlap");
1481 VerboseMsg ("of section data with the executable header.");
1485 if (FirstSectionOffset
== *FileLength
) {
1487 // If we never found a section with a non-zero size, then we
1488 // skip the conversion.
1493 TotalNecessaryFileSize
+= FirstSectionOffset
;
1495 if (!ConversionNeeded
) {
1499 if (XipLength
> (2 * TotalNecessaryFileSize
)) {
1500 VerboseMsg ("PE/COFF conversion to XIP appears to be larger than necessary.");
1501 VerboseMsg ("The image linking process may have left unused memory ranges.");
1504 if (PeHdr
->Pe32
.FileHeader
.PointerToSymbolTable
!= 0) {
1506 // This field is obsolete and should be zero
1508 PeHdr
->Pe32
.FileHeader
.PointerToSymbolTable
= 0;
1512 // Allocate the extra space that we need to grow the image
1514 XipFile
= malloc (XipLength
);
1515 memset (XipFile
, 0, XipLength
);
1518 // Copy the file headers
1520 memcpy (XipFile
, *FileBuffer
, PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
);
1522 NewPeHdr
= GetPeCoffHeader ((void *)XipFile
);
1523 if (NewPeHdr
== NULL
) {
1529 // Copy the section data over to the appropriate XIP offsets
1531 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(NewPeHdr
->Pe32
.OptionalHeader
) + NewPeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
1532 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1533 if (SectionHeader
->SizeOfRawData
> 0) {
1535 XipFile
+ SectionHeader
->VirtualAddress
,
1536 *FileBuffer
+ SectionHeader
->PointerToRawData
,
1537 SectionHeader
->SizeOfRawData
1540 SectionHeader
->SizeOfRawData
= SectionHeader
->Misc
.VirtualSize
;
1541 SectionHeader
->PointerToRawData
= SectionHeader
->VirtualAddress
;
1545 *FileLength
= XipLength
;
1546 *FileBuffer
= XipFile
;
1550 CreateHiiResouceSectionHeader (
1551 UINT32
*pSectionHeaderSize
,
1556 Routine Description:
1558 Create COFF resource section header
1562 pSectionHeaderSize - Pointer to section header size.
1563 HiiDataSize - Size of the total HII data in section.
1566 The created section header buffer.
1570 UINT32 HiiSectionHeaderSize
;
1571 UINT32 HiiSectionOffset
;
1572 UINT8
*HiiSectionHeader
;
1573 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
1574 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*TypeResourceDirectoryEntry
;
1575 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*NameResourceDirectoryEntry
;
1576 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*LanguageResourceDirectoryEntry
;
1577 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
1578 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
1581 // Calculate the total size for the resource header (include Type, Name and Language)
1582 // then allocate memory for the resource header.
1584 HiiSectionHeaderSize
= 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
))
1585 + 3 * (sizeof (UINT16
) + 3 * sizeof (CHAR16
))
1586 + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
1587 HiiSectionHeader
= malloc (HiiSectionHeaderSize
);
1588 memset (HiiSectionHeader
, 0, HiiSectionHeaderSize
);
1590 HiiSectionOffset
= 0;
1592 // Create Type entry
1594 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1595 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
1596 ResourceDirectory
->NumberOfNamedEntries
= 1;
1597 TypeResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1598 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
1599 TypeResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
1600 TypeResourceDirectoryEntry
->u2
.s
.DataIsDirectory
= 1;
1601 TypeResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
= HiiSectionOffset
;
1603 // Create Name entry
1605 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1606 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
1607 ResourceDirectory
->NumberOfNamedEntries
= 1;
1608 NameResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1609 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
1610 NameResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
1611 NameResourceDirectoryEntry
->u2
.s
.DataIsDirectory
= 1;
1612 NameResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
= HiiSectionOffset
;
1614 // Create Language entry
1616 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1617 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
1618 ResourceDirectory
->NumberOfNamedEntries
= 1;
1619 LanguageResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1620 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
1621 LanguageResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
1623 // Create string entry for Type
1625 TypeResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
1626 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
1627 ResourceDirectoryString
->Length
= 3;
1628 ResourceDirectoryString
->String
[0] = L
'H';
1629 ResourceDirectoryString
->String
[1] = L
'I';
1630 ResourceDirectoryString
->String
[2] = L
'I';
1631 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
1633 // Create string entry for Name
1635 NameResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
1636 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
1637 ResourceDirectoryString
->Length
= 3;
1638 ResourceDirectoryString
->String
[0] = L
'E';
1639 ResourceDirectoryString
->String
[1] = L
'F';
1640 ResourceDirectoryString
->String
[2] = L
'I';
1641 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
1643 // Create string entry for Language
1645 LanguageResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
1646 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
1647 ResourceDirectoryString
->Length
= 3;
1648 ResourceDirectoryString
->String
[0] = L
'B';
1649 ResourceDirectoryString
->String
[1] = L
'I';
1650 ResourceDirectoryString
->String
[2] = L
'N';
1651 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
1655 LanguageResourceDirectoryEntry
->u2
.OffsetToData
= HiiSectionOffset
;
1656 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
1657 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
1658 ResourceDataEntry
->OffsetToData
= HiiSectionOffset
;
1659 ResourceDataEntry
->Size
= HiiDataSize
;
1661 *pSectionHeaderSize
= HiiSectionHeaderSize
;
1662 return HiiSectionHeader
;
1667 IN VOID
*FileHandle
,
1668 IN UINTN FileOffset
,
1669 IN OUT UINT32
*ReadSize
,
1674 Routine Description:
1676 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1680 FileHandle - The handle to the PE/COFF file
1682 FileOffset - The offset, in bytes, into the file to read
1684 ReadSize - The number of bytes to read from the file starting at FileOffset
1686 Buffer - A pointer to the buffer to read the data into.
1690 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1694 CHAR8
*Destination8
;
1698 Destination8
= Buffer
;
1699 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
1702 *(Destination8
++) = *(Source8
++);
1709 SetAddressToSectionHeader (
1711 IN OUT UINT8
*FileBuffer
,
1712 IN UINT64 NewPe32BaseAddress
1716 Routine Description:
1718 Set new base address into the section header of PeImage
1722 FileName - Name of file
1723 FileBuffer - Pointer to PeImage.
1724 NewPe32BaseAddress - New Base Address for PE image.
1728 EFI_SUCCESS Set new base address into this image successfully.
1733 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1735 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1736 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1739 // Initialize context
1741 memset (&ImageContext
, 0, sizeof (ImageContext
));
1742 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1743 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1744 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1745 if (EFI_ERROR (Status
)) {
1746 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1750 if (ImageContext
.RelocationsStripped
) {
1751 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1756 // Get PeHeader pointer
1758 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1761 // Get section header list
1763 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1766 sizeof (EFI_IMAGE_FILE_HEADER
) +
1767 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1771 // Set base address into the first section header that doesn't point to code section.
1773 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1774 if ((SectionHeader
->Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
1775 *(UINT64
*) &SectionHeader
->PointerToRelocations
= NewPe32BaseAddress
;
1781 // No available section header is found.
1783 if (Index
== ImgHdr
->Pe32
.FileHeader
.NumberOfSections
) {
1784 return EFI_NOT_FOUND
;
1788 // BaseAddress is set to section header.
1796 IN OUT UINT8
*FileBuffer
,
1797 IN UINT64 NewPe32BaseAddress
1801 Routine Description:
1803 Set new base address into PeImage, and fix up PeImage based on new address.
1807 FileName - Name of file
1808 FileBuffer - Pointer to PeImage.
1809 NewPe32BaseAddress - New Base Address for PE image.
1813 EFI_INVALID_PARAMETER - BaseAddress is not valid.
1814 EFI_SUCCESS - Update PeImage is correctly.
1819 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1821 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1822 UINT8
*MemoryImagePointer
;
1823 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1826 // Initialize context
1828 memset (&ImageContext
, 0, sizeof (ImageContext
));
1829 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1830 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1831 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1832 if (EFI_ERROR (Status
)) {
1833 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1837 if (ImageContext
.RelocationsStripped
) {
1838 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1843 // Get PeHeader pointer
1845 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1848 // Load and Relocate Image Data
1850 MemoryImagePointer
= (UINT8
*) malloc ((UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1851 if (MemoryImagePointer
== NULL
) {
1852 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
1853 return EFI_OUT_OF_RESOURCES
;
1855 memset ((VOID
*) MemoryImagePointer
, 0, (UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1856 ImageContext
.ImageAddress
= ((UINTN
) MemoryImagePointer
+ ImageContext
.SectionAlignment
- 1) & (~((INT64
)ImageContext
.SectionAlignment
- 1));
1858 Status
= PeCoffLoaderLoadImage (&ImageContext
);
1859 if (EFI_ERROR (Status
)) {
1860 Error (NULL
, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName
);
1861 free ((VOID
*) MemoryImagePointer
);
1865 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
1866 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
1867 if (EFI_ERROR (Status
)) {
1868 Error (NULL
, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName
);
1869 free ((VOID
*) MemoryImagePointer
);
1874 // Copy Relocated data to raw image file.
1876 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1879 sizeof (EFI_IMAGE_FILE_HEADER
) +
1880 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1883 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1885 FileBuffer
+ SectionHeader
->PointerToRawData
,
1886 (VOID
*) (UINTN
) (ImageContext
.ImageAddress
+ SectionHeader
->VirtualAddress
),
1887 SectionHeader
->SizeOfRawData
1891 free ((VOID
*) MemoryImagePointer
);
1894 // Update Image Base Address
1896 if ((ImgHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) && (ImgHdr
->Pe32
.FileHeader
.Machine
!= IMAGE_FILE_MACHINE_IA64
)) {
1897 ImgHdr
->Pe32
.OptionalHeader
.ImageBase
= (UINT32
) NewPe32BaseAddress
;
1898 } else if (ImgHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1899 ImgHdr
->Pe32Plus
.OptionalHeader
.ImageBase
= NewPe32BaseAddress
;
1901 Error (NULL
, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
1902 ImgHdr
->Pe32
.OptionalHeader
.Magic
,
1909 // Set new base address into section header
1911 Status
= SetAddressToSectionHeader (FileName
, FileBuffer
, NewPe32BaseAddress
);
1923 Routine Description:
1929 argc - Number of command line parameters.
1930 argv - Array of pointers to command line parameter strings.
1933 STATUS_SUCCESS - Utility exits successfully.
1934 STATUS_ERROR - Some error occurred during execution.
1939 UINT32 InputFileNum
;
1940 CHAR8
**InputFileName
;
1944 UINT32 OutImageType
;
1949 UINT32
*DataPointer
;
1950 UINT32
*OldDataPointer
;
1956 UINT32 MciAlignment
;
1958 UINT32 AllignedRelocSize
;
1961 UINT8
*OutputFileBuffer
;
1962 UINT32 OutputFileLength
;
1963 UINT8
*InputFileBuffer
;
1964 UINT32 InputFileLength
;
1965 RUNTIME_FUNCTION
*RuntimeFunction
;
1966 UNWIND_INFO
*UnwindInfo
;
1968 BOOLEAN ReplaceFlag
;
1969 BOOLEAN KeepExceptionTableFlag
;
1970 BOOLEAN KeepZeroPendingFlag
;
1972 EFI_TE_IMAGE_HEADER TEImageHeader
;
1973 EFI_TE_IMAGE_HEADER
*TeHdr
;
1974 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1975 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1976 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1977 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32
;
1978 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64
;
1979 EFI_IMAGE_DOS_HEADER BackupDosHdr
;
1980 MICROCODE_IMAGE_HEADER
*MciHeader
;
1981 UINT8
*HiiPackageListBuffer
;
1982 UINT8
*HiiPackageDataPointer
;
1983 EFI_GUID HiiPackageListGuid
;
1984 EFI_HII_PACKAGE_LIST_HEADER HiiPackageListHeader
;
1985 EFI_HII_PACKAGE_HEADER HiiPackageHeader
;
1986 EFI_IFR_FORM_SET IfrFormSet
;
1987 UINT8 NumberOfFormPacakge
;
1988 EFI_HII_PACKAGE_HEADER EndPackage
;
1989 UINT32 HiiSectionHeaderSize
;
1990 UINT8
*HiiSectionHeader
;
1991 UINT64 NewBaseAddress
;
1992 BOOLEAN NegativeAddr
;
1994 CHAR8
*ReportFileName
;
1997 SetUtilityName (UTILITY_NAME
);
2000 // Assign to fix compile warning
2004 InputFileName
= NULL
;
2005 mInImageName
= NULL
;
2006 OutImageName
= NULL
;
2008 OutImageType
= FW_DUMMY_IMAGE
;
2010 Status
= STATUS_SUCCESS
;
2016 MciAlignment
= DEFAULT_MC_ALIGNMENT
;
2017 MciPadValue
= DEFAULT_MC_PAD_BYTE_VALUE
;
2021 ReplaceFlag
= FALSE
;
2023 OutputFileBuffer
= NULL
;
2024 OutputFileLength
= 0;
2025 InputFileBuffer
= NULL
;
2026 InputFileLength
= 0;
2029 KeepExceptionTableFlag
= FALSE
;
2030 KeepZeroPendingFlag
= FALSE
;
2031 NumberOfFormPacakge
= 0;
2032 HiiPackageListBuffer
= NULL
;
2033 HiiPackageDataPointer
= NULL
;
2034 EndPackage
.Length
= sizeof (EFI_HII_PACKAGE_HEADER
);
2035 EndPackage
.Type
= EFI_HII_PACKAGE_END
;
2036 memset (&HiiPackageListGuid
, 0, sizeof (HiiPackageListGuid
));
2037 HiiSectionHeaderSize
= 0;
2038 HiiSectionHeader
= NULL
;
2040 NegativeAddr
= FALSE
;
2043 Error (NULL
, 0, 1001, "Missing options", "No input options.");
2045 return STATUS_ERROR
;
2051 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
2054 return STATUS_SUCCESS
;
2057 if (stricmp (argv
[0], "--version") == 0) {
2059 return STATUS_SUCCESS
;
2063 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
2064 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
2065 Error (NULL
, 0, 1003, "Invalid option value", "Output file name is missing for -o option");
2068 OutImageName
= argv
[1];
2074 if ((stricmp (argv
[0], "-e") == 0) || (stricmp (argv
[0], "--efiImage") == 0)) {
2075 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
2076 Error (NULL
, 0, 1003, "Invalid option value", "Module Type is missing for -o option");
2079 ModuleType
= argv
[1];
2080 if (OutImageType
!= FW_TE_IMAGE
) {
2081 OutImageType
= FW_EFI_IMAGE
;
2088 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--stripped") == 0)) {
2089 OutImageType
= FW_RELOC_STRIPEED_IMAGE
;
2095 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--acpi") == 0)) {
2096 OutImageType
= FW_ACPI_IMAGE
;
2102 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--terse") == 0)) {
2103 OutImageType
= FW_TE_IMAGE
;
2109 if ((stricmp (argv
[0], "-u") == 0) || (stricmp (argv
[0], "--dump") == 0)) {
2110 OutImageType
= DUMP_TE_HEADER
;
2116 if ((stricmp (argv
[0], "-b") == 0) || (stricmp (argv
[0], "--exe2bin") == 0)) {
2117 OutImageType
= FW_BIN_IMAGE
;
2123 if ((stricmp (argv
[0], "-z") == 0) || (stricmp (argv
[0], "--zero") == 0)) {
2124 OutImageType
= FW_ZERO_DEBUG_IMAGE
;
2130 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--stamp") == 0)) {
2131 OutImageType
= FW_SET_STAMP_IMAGE
;
2132 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
2133 Error (NULL
, 0, 1003, "Invalid option value", "time stamp is missing for -s option");
2136 TimeStamp
= argv
[1];
2142 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--replace") == 0)) {
2149 if (stricmp (argv
[0], "--keepexceptiontable") == 0) {
2150 KeepExceptionTableFlag
= TRUE
;
2156 if (stricmp (argv
[0], "--keepzeropending") == 0) {
2157 KeepZeroPendingFlag
= TRUE
;
2163 if ((stricmp (argv
[0], "-m") == 0) || (stricmp (argv
[0], "--mcifile") == 0)) {
2164 OutImageType
= FW_MCI_IMAGE
;
2170 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--join") == 0)) {
2171 OutImageType
= FW_MERGE_IMAGE
;
2177 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
2178 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
2179 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
2182 MciAlignment
= (UINT32
) Temp64
;
2188 if ((stricmp (argv
[0], "--rebase") == 0)) {
2189 if (argv
[1][0] == '-') {
2190 NegativeAddr
= TRUE
;
2191 Status
= AsciiStringToUint64 (argv
[1] + 1, FALSE
, &Temp64
);
2193 NegativeAddr
= FALSE
;
2194 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
);
2196 if (Status
!= EFI_SUCCESS
) {
2197 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
2200 OutImageType
= FW_REBASE_IMAGE
;
2201 NewBaseAddress
= (UINT64
) Temp64
;
2207 if ((stricmp (argv
[0], "--address") == 0)) {
2208 if (argv
[1][0] == '-') {
2209 NegativeAddr
= TRUE
;
2210 Status
= AsciiStringToUint64 (argv
[1] + 1, FALSE
, &Temp64
);
2212 NegativeAddr
= FALSE
;
2213 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
);
2215 if (Status
!= EFI_SUCCESS
) {
2216 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
2219 OutImageType
= FW_SET_ADDRESS_IMAGE
;
2220 NewBaseAddress
= (UINT64
) Temp64
;
2226 if ((stricmp (argv
[0], "-p") == 0) || (stricmp (argv
[0], "--pad") == 0)) {
2227 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
2228 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
2231 MciPadValue
= (UINT8
) Temp64
;
2237 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
2238 SetPrintLevel (VERBOSE_LOG_LEVEL
);
2239 VerboseMsg ("Verbose output Mode Set!");
2245 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
2246 SetPrintLevel (KEY_LOG_LEVEL
);
2247 KeyMsg ("Quiet output Mode Set!");
2253 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
2254 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
2255 if (EFI_ERROR (Status
)) {
2256 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
2260 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel
);
2263 SetPrintLevel (LogLevel
);
2264 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
2270 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--hiiguid") == 0)) {
2271 Status
= StringToGuid (argv
[1], &HiiPackageListGuid
);
2272 if (EFI_ERROR (Status
)) {
2273 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
2281 if (stricmp (argv
[0], "--hiipackage") == 0) {
2282 OutImageType
= FW_HII_PACKAGE_LIST_RCIMAGE
;
2288 if (stricmp (argv
[0], "--hiibinpackage") == 0) {
2289 OutImageType
= FW_HII_PACKAGE_LIST_BINIMAGE
;
2295 if (argv
[0][0] == '-') {
2296 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
2300 // Get Input file name
2302 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
2303 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
2304 if (InputFileName
== NULL
) {
2305 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2309 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
2310 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
2312 // InputFileName buffer too small, need to realloc
2314 InputFileName
= (CHAR8
**) realloc (
2316 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
2319 if (InputFileName
== NULL
) {
2320 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2324 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
2327 InputFileName
[InputFileNum
++] = argv
[0];
2332 VerboseMsg ("%s tool start.", UTILITY_NAME
);
2334 if (OutImageType
== FW_DUMMY_IMAGE
) {
2335 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!");
2337 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.");
2343 // check input files
2345 if (InputFileNum
== 0) {
2346 Error (NULL
, 0, 1001, "Missing option", "Input files");
2351 // Combine MciBinary files to one file
2353 if ((OutImageType
== FW_MERGE_IMAGE
) && ReplaceFlag
) {
2354 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");
2359 // Combine HiiBinary packages to a single package list
2361 if ((OutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) && ReplaceFlag
) {
2362 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option.");
2366 if ((OutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) && ReplaceFlag
) {
2367 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiibinpackage merge files option.");
2374 mInImageName
= InputFileName
[InputFileNum
- 1];
2375 VerboseMsg ("the input file name is %s", mInImageName
);
2378 // Action will be taken for the input file.
2380 switch (OutImageType
) {
2382 VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType
);
2385 VerboseMsg ("Create Te Image based on the input PE image.");
2388 VerboseMsg ("Get acpi table data from the input PE image.");
2390 case FW_RELOC_STRIPEED_IMAGE
:
2391 VerboseMsg ("Remove relocation section from Pe or Te image.");
2394 VerboseMsg ("Convert the input EXE to the output BIN file.");
2396 case FW_ZERO_DEBUG_IMAGE
:
2397 VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");
2399 case FW_SET_STAMP_IMAGE
:
2400 VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp
);
2402 case DUMP_TE_HEADER
:
2403 VerboseMsg ("Dump the TE header information of the input TE image.");
2406 VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");
2408 case FW_MERGE_IMAGE
:
2409 VerboseMsg ("Combine the input multi microcode bin files to one bin file.");
2411 case FW_HII_PACKAGE_LIST_RCIMAGE
:
2412 VerboseMsg ("Combine the input multi hii bin packages to one text pacakge list RC file.");
2414 case FW_HII_PACKAGE_LIST_BINIMAGE
:
2415 VerboseMsg ("Combine the input multi hii bin packages to one binary pacakge list file.");
2417 case FW_REBASE_IMAGE
:
2418 VerboseMsg ("Rebase the input image to new base address.");
2420 case FW_SET_ADDRESS_IMAGE
:
2421 VerboseMsg ("Set the preferred address into the section header of the input image");
2428 VerboseMsg ("Overwrite the input file with the output content.");
2432 // Open output file and Write image into the output file.
2434 if (OutImageName
!= NULL
) {
2435 fpOut
= fopen (OutImageName
, "rb");
2436 if (fpOut
!= NULL
) {
2437 OutputFileLength
= _filelength (fileno (fpOut
));
2438 OutputFileBuffer
= malloc (OutputFileLength
);
2439 if (OutputFileBuffer
== NULL
) {
2440 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2445 fread (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
2449 VerboseMsg ("Output file name is %s", OutImageName
);
2450 } else if (!ReplaceFlag
&& OutImageType
!= DUMP_TE_HEADER
) {
2451 Error (NULL
, 0, 1001, "Missing option", "output file");
2456 // Open input file and read file data into file buffer.
2458 fpIn
= fopen (mInImageName
, "rb");
2460 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2463 InputFileLength
= _filelength (fileno (fpIn
));
2464 InputFileBuffer
= malloc (InputFileLength
);
2465 if (InputFileBuffer
== NULL
) {
2466 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2470 fread (InputFileBuffer
, 1, InputFileLength
, fpIn
);
2472 DebugMsg (NULL
, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) InputFileLength
);
2475 // Combine multi binary HII package files.
2477 if (OutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
|| OutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) {
2479 // Open output file handle.
2481 fpOut
= fopen (OutImageName
, "wb");
2483 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
2487 // Get hii package list lenght
2489 HiiPackageListHeader
.PackageLength
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
2490 for (Index
= 0; Index
< InputFileNum
; Index
++) {
2491 fpIn
= fopen (InputFileName
[Index
], "rb");
2493 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
2496 FileLength
= _filelength (fileno (fpIn
));
2497 fread (&HiiPackageHeader
, 1, sizeof (HiiPackageHeader
), fpIn
);
2498 if (HiiPackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) {
2499 if (HiiPackageHeader
.Length
!= FileLength
) {
2500 Error (NULL
, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName
[Index
]);
2504 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
2505 fread (&IfrFormSet
, 1, sizeof (IfrFormSet
), fpIn
);
2506 memcpy (&HiiPackageListGuid
, &IfrFormSet
.Guid
, sizeof (EFI_GUID
));
2508 NumberOfFormPacakge
++;
2510 HiiPackageListHeader
.PackageLength
+= FileLength
;
2513 HiiPackageListHeader
.PackageLength
+= sizeof (EndPackage
);
2515 // Check whether hii packages are valid
2517 if (NumberOfFormPacakge
> 1) {
2518 Error (NULL
, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package");
2521 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
2522 Error (NULL
, 0, 3000, "Invalid", "HII pacakge list guid is not specified!");
2525 memcpy (&HiiPackageListHeader
.PackageListGuid
, &HiiPackageListGuid
, sizeof (EFI_GUID
));
2527 // read hii packages
2529 HiiPackageListBuffer
= malloc (HiiPackageListHeader
.PackageLength
);
2530 if (HiiPackageListBuffer
== NULL
) {
2531 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2534 memcpy (HiiPackageListBuffer
, &HiiPackageListHeader
, sizeof (HiiPackageListHeader
));
2535 HiiPackageDataPointer
= HiiPackageListBuffer
+ sizeof (HiiPackageListHeader
);
2536 for (Index
= 0; Index
< InputFileNum
; Index
++) {
2537 fpIn
= fopen (InputFileName
[Index
], "rb");
2539 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
2540 free (HiiPackageListBuffer
);
2544 FileLength
= _filelength (fileno (fpIn
));
2545 fread (HiiPackageDataPointer
, 1, FileLength
, fpIn
);
2547 HiiPackageDataPointer
= HiiPackageDataPointer
+ FileLength
;
2549 memcpy (HiiPackageDataPointer
, &EndPackage
, sizeof (EndPackage
));
2552 // write the hii package into the binary package list file with the resource section header
2554 if (OutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) {
2556 // Create the resource section header
2558 HiiSectionHeader
= CreateHiiResouceSectionHeader (&HiiSectionHeaderSize
, HiiPackageListHeader
.PackageLength
);
2560 // Wrtie section header and HiiData into File.
2562 fwrite (HiiSectionHeader
, 1, HiiSectionHeaderSize
, fpOut
);
2563 fwrite (HiiPackageListBuffer
, 1, HiiPackageListHeader
.PackageLength
, fpOut
);
2565 // Free allocated resources.
2567 free (HiiSectionHeader
);
2568 free (HiiPackageListBuffer
);
2570 // Done successfully
2576 // write the hii package into the text package list rc file.
2578 if (OutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) {
2579 for (Index
= 0; gHiiPackageRCFileHeader
[Index
] != NULL
; Index
++) {
2580 fprintf (fpOut
, "%s\n", gHiiPackageRCFileHeader
[Index
]);
2582 fprintf (fpOut
, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX
, HII_RESOURCE_SECTION_NAME
);
2584 HiiPackageDataPointer
= HiiPackageListBuffer
;
2585 for (Index
= 0; Index
+ 2 < HiiPackageListHeader
.PackageLength
; Index
+= 2) {
2586 if (Index
% 16 == 0) {
2587 fprintf (fpOut
, "\n ");
2589 fprintf (fpOut
, " 0x%04X,", *(UINT16
*) HiiPackageDataPointer
);
2590 HiiPackageDataPointer
+= 2;
2593 if (Index
% 16 == 0) {
2594 fprintf (fpOut
, "\n ");
2596 if ((Index
+ 2) == HiiPackageListHeader
.PackageLength
) {
2597 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT16
*) HiiPackageDataPointer
);
2599 if ((Index
+ 1) == HiiPackageListHeader
.PackageLength
) {
2600 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT8
*) HiiPackageDataPointer
);
2602 free (HiiPackageListBuffer
);
2604 // Done successfully
2611 // Combine MciBinary files to one file
2613 if (OutImageType
== FW_MERGE_IMAGE
) {
2615 // Open output file handle.
2617 fpOut
= fopen (OutImageName
, "wb");
2619 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
2622 for (Index
= 0; Index
< InputFileNum
; Index
++) {
2623 fpIn
= fopen (InputFileName
[Index
], "rb");
2625 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
2629 FileLength
= _filelength (fileno (fpIn
));
2630 FileBuffer
= malloc (FileLength
);
2631 if (FileBuffer
== NULL
) {
2632 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2637 fread (FileBuffer
, 1, FileLength
, fpIn
);
2640 // write input file to out file
2642 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2644 // write pad value to out file.
2646 while (FileLength
++ % MciAlignment
!= 0) {
2647 fwrite (&MciPadValue
, 1, 1, fpOut
);
2650 // free allocated memory space
2656 // Done successfully
2662 // Convert MicroCode.txt file to MicroCode.bin file
2664 if (OutImageType
== FW_MCI_IMAGE
) {
2665 fpIn
= fopen (mInImageName
, "r");
2667 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2672 // The first pass is to determine
2673 // how much data is in the file so we can allocate a working buffer.
2677 Status
= MicrocodeReadData (fpIn
, &Data
);
2678 if (Status
== STATUS_SUCCESS
) {
2679 FileLength
+= sizeof (Data
);
2681 if (Status
== STATUS_IGNORE
) {
2682 Status
= STATUS_SUCCESS
;
2684 } while (Status
== STATUS_SUCCESS
);
2686 // Error if no data.
2688 if (FileLength
== 0) {
2689 Error (NULL
, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName
);
2692 if (FileLength
< sizeof (MICROCODE_IMAGE_HEADER
)) {
2693 Error (NULL
, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName
);
2698 // Allocate a buffer for the data
2700 FileBuffer
= malloc (FileLength
);
2701 if (FileBuffer
== NULL
) {
2702 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2706 // Re-read the file, storing the data into our buffer
2708 fseek (fpIn
, 0, SEEK_SET
);
2709 DataPointer
= (UINT32
*) FileBuffer
;
2710 OldDataPointer
= DataPointer
;
2712 OldDataPointer
= DataPointer
;
2713 Status
= MicrocodeReadData (fpIn
, DataPointer
++);
2714 if (Status
== STATUS_IGNORE
) {
2715 DataPointer
= OldDataPointer
;
2716 Status
= STATUS_SUCCESS
;
2718 } while (Status
== STATUS_SUCCESS
);
2720 // close input file after read data
2725 // Can't do much checking on the header because, per the spec, the
2726 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
2727 // and the TotalSize field is invalid (actually missing). Thus we can't
2728 // even verify the Reserved fields are 0.
2730 MciHeader
= (MICROCODE_IMAGE_HEADER
*) FileBuffer
;
2731 if (MciHeader
->DataSize
== 0) {
2734 Index
= MciHeader
->TotalSize
;
2737 if (Index
!= FileLength
) {
2738 Error (NULL
, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName
, (unsigned) FileLength
, (unsigned) Index
);
2743 // Checksum the contents
2745 DataPointer
= (UINT32
*) FileBuffer
;
2748 while (Index
< FileLength
) {
2749 CheckSum
+= *DataPointer
;
2751 Index
+= sizeof (*DataPointer
);
2753 if (CheckSum
!= 0) {
2754 Error (NULL
, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum
, mInImageName
);
2758 // Open the output file and write the buffer contents
2760 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2765 // Open input file and read file data into file buffer.
2767 FileLength
= InputFileLength
;
2768 FileBuffer
= malloc (FileLength
);
2769 if (FileBuffer
== NULL
) {
2770 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2773 memcpy (FileBuffer
, InputFileBuffer
, InputFileLength
);
2776 // Dump TeImage Header into output file.
2778 if (OutImageType
== DUMP_TE_HEADER
) {
2779 memcpy (&TEImageHeader
, FileBuffer
, sizeof (TEImageHeader
));
2780 if (TEImageHeader
.Signature
!= EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2781 Error (NULL
, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName
);
2785 // Open the output file handle.
2788 fpInOut
= fopen (mInImageName
, "wb");
2789 if (fpInOut
== NULL
) {
2790 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2794 if (OutImageName
!= NULL
) {
2795 fpOut
= fopen (OutImageName
, "wb");
2799 if (fpOut
== NULL
) {
2800 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
2804 if (fpInOut
!= NULL
) {
2805 fprintf (fpInOut
, "Dump of file %s\n\n", mInImageName
);
2806 fprintf (fpInOut
, "TE IMAGE HEADER VALUES\n");
2807 fprintf (fpInOut
, "%17X machine\n", TEImageHeader
.Machine
);
2808 fprintf (fpInOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
2809 fprintf (fpInOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
2810 fprintf (fpInOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
2811 fprintf (fpInOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
2812 fprintf (fpInOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
2813 fprintf (fpInOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
2814 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
2815 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
2817 if (fpOut
!= NULL
) {
2818 fprintf (fpOut
, "Dump of file %s\n\n", mInImageName
);
2819 fprintf (fpOut
, "TE IMAGE HEADER VALUES\n");
2820 fprintf (fpOut
, "%17X machine\n", TEImageHeader
.Machine
);
2821 fprintf (fpOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
2822 fprintf (fpOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
2823 fprintf (fpOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
2824 fprintf (fpOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
2825 fprintf (fpOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
2826 fprintf (fpOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
2827 fprintf (fpOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
2828 fprintf (fpOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
2834 // Following code to convert dll to efi image or te image.
2835 // Get new image type
2837 if ((OutImageType
== FW_EFI_IMAGE
) || (OutImageType
== FW_TE_IMAGE
)) {
2838 if (ModuleType
== NULL
) {
2839 if (OutImageType
== FW_EFI_IMAGE
) {
2840 Error (NULL
, 0, 1001, "Missing option", "EFI_FILETYPE");
2842 } else if (OutImageType
== FW_TE_IMAGE
) {
2844 // Default TE Image Type is Boot service driver
2846 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2847 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2850 if (stricmp (ModuleType
, "BASE") == 0 ||
2851 stricmp (ModuleType
, "SEC") == 0 ||
2852 stricmp (ModuleType
, "SECURITY_CORE") == 0 ||
2853 stricmp (ModuleType
, "PEI_CORE") == 0 ||
2854 stricmp (ModuleType
, "PEIM") == 0 ||
2855 stricmp (ModuleType
, "COMBINED_PEIM_DRIVER") == 0 ||
2856 stricmp (ModuleType
, "PIC_PEIM") == 0 ||
2857 stricmp (ModuleType
, "RELOCATABLE_PEIM") == 0 ||
2858 stricmp (ModuleType
, "DXE_CORE") == 0 ||
2859 stricmp (ModuleType
, "BS_DRIVER") == 0 ||
2860 stricmp (ModuleType
, "DXE_DRIVER") == 0 ||
2861 stricmp (ModuleType
, "DXE_SMM_DRIVER") == 0 ||
2862 stricmp (ModuleType
, "UEFI_DRIVER") == 0 ||
2863 stricmp (ModuleType
, "SMM_CORE") == 0) {
2864 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2865 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2867 } else if (stricmp (ModuleType
, "UEFI_APPLICATION") == 0 ||
2868 stricmp (ModuleType
, "APPLICATION") == 0) {
2869 Type
= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
;
2870 VerboseMsg ("Efi Image subsystem type is efi application.");
2872 } else if (stricmp (ModuleType
, "DXE_RUNTIME_DRIVER") == 0 ||
2873 stricmp (ModuleType
, "RT_DRIVER") == 0) {
2874 Type
= EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
;
2875 VerboseMsg ("Efi Image subsystem type is efi runtime driver.");
2877 } else if (stricmp (ModuleType
, "DXE_SAL_DRIVER") == 0 ||
2878 stricmp (ModuleType
, "SAL_RT_DRIVER") == 0) {
2879 Type
= EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
;
2880 VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");
2883 Error (NULL
, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType
);
2890 // Convert EFL image to PeImage
2892 if (IsElfHeader(FileBuffer
)) {
2893 VerboseMsg ("Convert the input ELF Image to Pe Image");
2894 ConvertElf(&FileBuffer
, &FileLength
);
2898 // Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP
2899 // XIP == eXecute In Place
2901 PeCoffConvertImageToXip (&FileBuffer
, &FileLength
);
2904 // Remove reloc section from PE or TE image
2906 if (OutImageType
== FW_RELOC_STRIPEED_IMAGE
) {
2910 TeHdr
= (EFI_TE_IMAGE_HEADER
*) FileBuffer
;
2911 if (TeHdr
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2912 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (TeHdr
+ 1);
2913 for (Index
= 0; Index
< TeHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2914 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2916 // Check the reloc section is in the end of image.
2918 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) ==
2919 (FileLength
+ TeHdr
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
))) {
2921 // Remove .reloc section and update TeImage Header
2923 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2924 SectionHeader
->SizeOfRawData
= 0;
2925 SectionHeader
->Misc
.VirtualSize
= 0;
2926 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2927 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2936 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2937 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2938 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2939 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2940 Error (NULL
, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName
);
2945 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2946 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2947 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2951 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2952 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2953 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2955 // Check the reloc section is in the end of image.
2957 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) == FileLength
) {
2959 // Remove .reloc section and update PeImage Header
2961 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2963 PeHdr
->Pe32
.FileHeader
.Characteristics
|= EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2964 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2965 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2966 Optional32
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2967 Optional32
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2968 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2969 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2970 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2973 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2974 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2975 Optional64
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2976 Optional64
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2977 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2978 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2979 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2982 SectionHeader
->Misc
.VirtualSize
= 0;
2983 SectionHeader
->SizeOfRawData
= 0;
2995 // Read the dos & pe hdrs of the image
2997 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2998 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2999 // NO DOS header, check for PE/COFF header
3000 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
3001 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
3002 Error (NULL
, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName
);
3008 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
3009 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
3010 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
3015 if (PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_ARM
) {
3016 // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
3017 // so patch back to the offical UEFI value.
3018 PeHdr
->Pe32
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_ARMT
;
3022 // Set new base address into image
3024 if (OutImageType
== FW_REBASE_IMAGE
|| OutImageType
== FW_SET_ADDRESS_IMAGE
) {
3025 if ((PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) && (PeHdr
->Pe32
.FileHeader
.Machine
!= IMAGE_FILE_MACHINE_IA64
)) {
3026 if (NewBaseAddress
>= 0x100000000ULL
) {
3027 Error (NULL
, 0, 3000, "Invalid", "New base address is larger than 4G for 32bit PE image");
3034 // Set Base Address to a negative value.
3036 NewBaseAddress
= (UINT64
) (0 - NewBaseAddress
);
3038 if (OutImageType
== FW_REBASE_IMAGE
) {
3039 Status
= RebaseImage (mInImageName
, FileBuffer
, NewBaseAddress
);
3041 Status
= SetAddressToSectionHeader (mInImageName
, FileBuffer
, NewBaseAddress
);
3043 if (EFI_ERROR (Status
)) {
3045 Error (NULL
, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address -0x%llx can't success", mInImageName
, 0 - NewBaseAddress
);
3047 Error (NULL
, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address 0x%llx can't success", mInImageName
, NewBaseAddress
);
3059 // Extract bin data from Pe image.
3061 if (OutImageType
== FW_BIN_IMAGE
) {
3062 if (FileLength
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
3063 Error (NULL
, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName
);
3067 // Output bin data from exe file
3069 FileLength
= FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
;
3070 memcpy (FileBuffer
, FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, FileLength
);
3071 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
3076 // Zero Debug Information of Pe Image
3078 if (OutImageType
== FW_ZERO_DEBUG_IMAGE
) {
3079 Status
= ZeroDebugData (FileBuffer
, TRUE
);
3080 if (EFI_ERROR (Status
)) {
3081 Error (NULL
, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status
);
3086 // Write the updated Image
3088 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
3093 // Set Time Stamp of Pe Image
3095 if (OutImageType
== FW_SET_STAMP_IMAGE
) {
3096 Status
= SetStamp (FileBuffer
, TimeStamp
);
3097 if (EFI_ERROR (Status
)) {
3102 // Write the updated Image
3104 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
3109 // Extract acpi data from pe image.
3111 if (OutImageType
== FW_ACPI_IMAGE
) {
3112 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3113 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
3114 if (strcmp ((char *)SectionHeader
->Name
, ".data") == 0 || strcmp ((char *)SectionHeader
->Name
, ".sdata") == 0) {
3118 if (SectionHeader
->Misc
.VirtualSize
< SectionHeader
->SizeOfRawData
) {
3119 FileLength
= SectionHeader
->Misc
.VirtualSize
;
3121 FileLength
= SectionHeader
->SizeOfRawData
;
3124 if (CheckAcpiTable (FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
) != STATUS_SUCCESS
) {
3125 Error (NULL
, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName
);
3130 // Output Apci data to file
3132 memcpy (FileBuffer
, FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
);
3133 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
3137 Error (NULL
, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName
);
3141 // Zero all unused fields of the DOS header
3143 if (DosHdr
!= NULL
) {
3144 memcpy (&BackupDosHdr
, DosHdr
, sizeof (EFI_IMAGE_DOS_HEADER
));
3145 memset (DosHdr
, 0, sizeof (EFI_IMAGE_DOS_HEADER
));
3146 DosHdr
->e_magic
= BackupDosHdr
.e_magic
;
3147 DosHdr
->e_lfanew
= BackupDosHdr
.e_lfanew
;
3149 for (Index
= sizeof (EFI_IMAGE_DOS_HEADER
); Index
< (UINT32
) DosHdr
->e_lfanew
; Index
++) {
3150 FileBuffer
[Index
] = (UINT8
) DosHdr
->e_cp
;
3155 // Initialize TeImage Header
3157 memset (&TEImageHeader
, 0, sizeof (EFI_TE_IMAGE_HEADER
));
3158 TEImageHeader
.Signature
= EFI_TE_IMAGE_HEADER_SIGNATURE
;
3159 TEImageHeader
.Machine
= PeHdr
->Pe32
.FileHeader
.Machine
;
3160 TEImageHeader
.NumberOfSections
= (UINT8
) PeHdr
->Pe32
.FileHeader
.NumberOfSections
;
3161 TEImageHeader
.StrippedSize
= (UINT16
) ((UINTN
) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
) - (UINTN
) FileBuffer
);
3162 TEImageHeader
.Subsystem
= (UINT8
) Type
;
3165 // Patch the PE header
3167 PeHdr
->Pe32
.OptionalHeader
.Subsystem
= (UINT16
) Type
;
3169 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
3170 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
3171 Optional32
->MajorLinkerVersion
= 0;
3172 Optional32
->MinorLinkerVersion
= 0;
3173 Optional32
->MajorOperatingSystemVersion
= 0;
3174 Optional32
->MinorOperatingSystemVersion
= 0;
3175 Optional32
->MajorImageVersion
= 0;
3176 Optional32
->MinorImageVersion
= 0;
3177 Optional32
->MajorSubsystemVersion
= 0;
3178 Optional32
->MinorSubsystemVersion
= 0;
3179 Optional32
->Win32VersionValue
= 0;
3180 Optional32
->CheckSum
= 0;
3181 Optional32
->SizeOfStackReserve
= 0;
3182 Optional32
->SizeOfStackCommit
= 0;
3183 Optional32
->SizeOfHeapReserve
= 0;
3184 Optional32
->SizeOfHeapCommit
= 0;
3186 TEImageHeader
.AddressOfEntryPoint
= Optional32
->AddressOfEntryPoint
;
3187 TEImageHeader
.BaseOfCode
= Optional32
->BaseOfCode
;
3188 TEImageHeader
.ImageBase
= (UINT64
) (Optional32
->ImageBase
);
3190 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
3191 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
3192 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
3195 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
3196 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3197 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
3201 // Zero .pdata section data.
3203 if (!KeepExceptionTableFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
3204 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
3205 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
3206 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3207 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
3208 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
3210 // Zero .pdata Section data
3212 memset (FileBuffer
+ SectionHeader
->PointerToRawData
, 0, SectionHeader
->SizeOfRawData
);
3214 // Zero .pdata Section header name
3216 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
3218 // Zero Execption Table
3220 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
3221 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
3222 DebugMsg (NULL
, 0, 9, "Zero the .pdata section for PE image", NULL
);
3229 // Strip zero padding at the end of the .reloc section
3231 if (!KeepZeroPendingFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
3232 if (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
3233 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3234 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
3236 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
3238 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
3239 SectionHeader
->Misc
.VirtualSize
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
3240 AllignedRelocSize
= (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional32
->FileAlignment
- 1) & (~(Optional32
->FileAlignment
- 1));
3242 // Check to see if there is zero padding at the end of the base relocations
3244 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
3246 // Check to see if the base relocations are at the end of the file
3248 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional32
->SizeOfImage
) {
3250 // All the required conditions are met to strip the zero padding of the end of the base relocations section
3252 Optional32
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
3253 Optional32
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
3254 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
3255 FileLength
= Optional32
->SizeOfImage
;
3256 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
));
3263 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
3264 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
3265 Optional64
->MajorLinkerVersion
= 0;
3266 Optional64
->MinorLinkerVersion
= 0;
3267 Optional64
->MajorOperatingSystemVersion
= 0;
3268 Optional64
->MinorOperatingSystemVersion
= 0;
3269 Optional64
->MajorImageVersion
= 0;
3270 Optional64
->MinorImageVersion
= 0;
3271 Optional64
->MajorSubsystemVersion
= 0;
3272 Optional64
->MinorSubsystemVersion
= 0;
3273 Optional64
->Win32VersionValue
= 0;
3274 Optional64
->CheckSum
= 0;
3275 Optional64
->SizeOfStackReserve
= 0;
3276 Optional64
->SizeOfStackCommit
= 0;
3277 Optional64
->SizeOfHeapReserve
= 0;
3278 Optional64
->SizeOfHeapCommit
= 0;
3280 TEImageHeader
.AddressOfEntryPoint
= Optional64
->AddressOfEntryPoint
;
3281 TEImageHeader
.BaseOfCode
= Optional64
->BaseOfCode
;
3282 TEImageHeader
.ImageBase
= (UINT64
) (Optional64
->ImageBase
);
3284 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
3285 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
3286 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
3289 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
3290 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3291 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
3295 // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
3296 // For Itaninum and X64 Image, remove .pdata section.
3298 if ((!KeepExceptionTableFlag
&& PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_X64
) || PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
) {
3299 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
3300 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
3301 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
3302 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3303 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
3304 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
3306 // Zero .pdata Section header name
3308 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
3310 RuntimeFunction
= (RUNTIME_FUNCTION
*)(FileBuffer
+ SectionHeader
->PointerToRawData
);
3311 for (Index1
= 0; Index1
< Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
/ sizeof (RUNTIME_FUNCTION
); Index1
++, RuntimeFunction
++) {
3312 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3313 for (Index2
= 0; Index2
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index2
++, SectionHeader
++) {
3314 if (RuntimeFunction
->UnwindInfoAddress
>= SectionHeader
->VirtualAddress
&& RuntimeFunction
->UnwindInfoAddress
< (SectionHeader
->VirtualAddress
+ SectionHeader
->SizeOfRawData
)) {
3315 UnwindInfo
= (UNWIND_INFO
*)(FileBuffer
+ SectionHeader
->PointerToRawData
+ (RuntimeFunction
->UnwindInfoAddress
- SectionHeader
->VirtualAddress
));
3316 if (UnwindInfo
->Version
== 1) {
3317 memset (UnwindInfo
+ 1, 0, UnwindInfo
->CountOfUnwindCodes
* sizeof (UINT16
));
3318 memset (UnwindInfo
, 0, sizeof (UNWIND_INFO
));
3323 memset (RuntimeFunction
, 0, sizeof (RUNTIME_FUNCTION
));
3326 // Zero Execption Table
3328 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
3329 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
3330 DebugMsg (NULL
, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL
);
3338 // Strip zero padding at the end of the .reloc section
3340 if (!KeepZeroPendingFlag
&& Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
3341 if (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
3342 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3343 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
3345 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
3347 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
3348 SectionHeader
->Misc
.VirtualSize
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
3349 AllignedRelocSize
= (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional64
->FileAlignment
- 1) & (~(Optional64
->FileAlignment
- 1));
3351 // Check to see if there is zero padding at the end of the base relocations
3353 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
3355 // Check to see if the base relocations are at the end of the file
3357 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional64
->SizeOfImage
) {
3359 // All the required conditions are met to strip the zero padding of the end of the base relocations section
3361 Optional64
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
3362 Optional64
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
3363 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
3364 FileLength
= Optional64
->SizeOfImage
;
3365 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
));
3373 Error (NULL
, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr
->Pe32
.OptionalHeader
.Magic
, mInImageName
);
3377 if (((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) == 0) && \
3378 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
== 0) && \
3379 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
== 0)) {
3381 // PeImage can be loaded into memory, but it has no relocation section.
3382 // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
3384 if (Optional32
!= NULL
) {
3385 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
3386 } else if (Optional64
!= NULL
) {
3387 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
3392 // Fill HII section data
3394 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3395 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++) {
3396 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".hii") == 0) {
3398 // Update resource section header offset
3400 SetHiiResourceHeader ((UINT8
*) FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, SectionHeader
[Index
].VirtualAddress
);
3402 // Update resource section name
3404 strcpy((char *) SectionHeader
[Index
].Name
, ".rsrc");
3406 // Update resource data directory.
3408 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
3409 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
3410 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= SectionHeader
[Index
].VirtualAddress
;
3411 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= SectionHeader
[Index
].Misc
.VirtualSize
;
3412 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
3413 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
3414 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= SectionHeader
[Index
].VirtualAddress
;
3415 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= SectionHeader
[Index
].Misc
.VirtualSize
;
3422 // Zero ExceptionTable Xdata
3424 if (!KeepExceptionTableFlag
) {
3425 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
3426 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++) {
3427 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".xdata") == 0) {
3429 // zero .xdata section
3431 memset (FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, 0, SectionHeader
[Index
].SizeOfRawData
);
3432 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
);
3439 // Zero Time/Data field
3441 ZeroDebugData (FileBuffer
, FALSE
);
3443 if (OutImageType
== FW_TE_IMAGE
) {
3444 if ((PeHdr
->Pe32
.FileHeader
.NumberOfSections
&~0xFF) || (Type
&~0xFF)) {
3446 // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
3448 Error (NULL
, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName
);
3452 if ((PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
)) {
3454 // TeImage has the same section alignment and file alignment.
3456 Error (NULL
, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName
);
3460 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",
3461 TEImageHeader
.Machine
, TEImageHeader
.NumberOfSections
, TEImageHeader
.StrippedSize
, (unsigned) TEImageHeader
.AddressOfEntryPoint
, (unsigned) TEImageHeader
.BaseOfCode
, (unsigned long long) TEImageHeader
.ImageBase
);
3463 // Update Image to TeImage
3465 FileLength
= FileLength
- TEImageHeader
.StrippedSize
;
3466 memcpy (FileBuffer
+ sizeof (EFI_TE_IMAGE_HEADER
), FileBuffer
+ TEImageHeader
.StrippedSize
, FileLength
);
3467 FileLength
= FileLength
+ sizeof (EFI_TE_IMAGE_HEADER
);
3468 memcpy (FileBuffer
, &TEImageHeader
, sizeof (EFI_TE_IMAGE_HEADER
));
3469 VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength
));
3474 // Update Image to EfiImage or TE image
3477 if ((FileLength
!= InputFileLength
) || (memcmp (FileBuffer
, InputFileBuffer
, FileLength
) != 0)) {
3479 // Update File when File is changed.
3481 fpInOut
= fopen (mInImageName
, "wb");
3482 if (fpInOut
== NULL
) {
3483 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
3486 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
3487 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
3490 if ((FileLength
!= OutputFileLength
) || (memcmp (FileBuffer
, OutputFileBuffer
, FileLength
) != 0)) {
3491 fpOut
= fopen (OutImageName
, "wb");
3492 if (fpOut
== NULL
) {
3493 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
3496 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
3497 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
3500 mImageSize
= FileLength
;
3503 if (fpInOut
!= NULL
) {
3504 if (GetUtilityStatus () != STATUS_SUCCESS
) {
3506 // when file updates failed, original file is still recovered.
3508 fwrite (InputFileBuffer
, 1, InputFileLength
, fpInOut
);
3511 // Write converted data into fpInOut file and close input file.
3516 if (FileBuffer
!= NULL
) {
3520 if (InputFileName
!= NULL
) {
3521 free (InputFileName
);
3524 if (fpOut
!= NULL
) {
3526 // Write converted data into fpOut file and close output file.
3529 if (GetUtilityStatus () != STATUS_SUCCESS
) {
3530 if (OutputFileBuffer
== NULL
) {
3531 remove (OutImageName
);
3533 fpOut
= fopen (OutImageName
, "wb");
3534 fwrite (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
3540 if (InputFileBuffer
!= NULL
) {
3541 free (InputFileBuffer
);
3544 if (OutputFileBuffer
!= NULL
) {
3545 free (OutputFileBuffer
);
3549 // Write module size and time stamp to report file.
3551 if (OutImageName
!= NULL
) {
3552 FileLen
= strlen (OutImageName
);
3554 if (FileLen
>= 4 && strcmp (OutImageName
+ (FileLen
- 4), ".efi") == 0) {
3555 ReportFileName
= (CHAR8
*) malloc (FileLen
+ 1);
3556 if (ReportFileName
!= NULL
) {
3557 strcpy (ReportFileName
, OutImageName
);
3558 strcpy (ReportFileName
+ (FileLen
- 4), ".txt");
3559 ReportFile
= fopen (ReportFileName
, "w+");
3560 if (ReportFile
!= NULL
) {
3561 fprintf (ReportFile
, "MODULE_SIZE = %u\n", (unsigned) mImageSize
);
3562 fprintf (ReportFile
, "TIME_STAMP = %u\n", (unsigned) mImageTimeStamp
);
3565 free (ReportFileName
);
3568 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
3570 return GetUtilityStatus ();
3576 IN OUT UINT8
*FileBuffer
,
3577 BOOLEAN ZeroDebugFlag
3581 Routine Description:
3583 Zero debug information in PeImage.
3587 FileBuffer - Pointer to PeImage.
3588 ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp
3592 EFI_ABORTED - PeImage is invalid.
3593 EFI_SUCCESS - Zero debug data successfully.
3598 UINT32 DebugDirectoryEntryRva
;
3599 UINT32 DebugDirectoryEntryFileOffset
;
3600 UINT32 ExportDirectoryEntryRva
;
3601 UINT32 ExportDirectoryEntryFileOffset
;
3602 UINT32 ResourceDirectoryEntryRva
;
3603 UINT32 ResourceDirectoryEntryFileOffset
;
3604 EFI_IMAGE_DOS_HEADER
*DosHdr
;
3605 EFI_IMAGE_FILE_HEADER
*FileHdr
;
3606 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
3607 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
3608 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
3609 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
3610 UINT32
*NewTimeStamp
;
3615 DebugDirectoryEntryRva
= 0;
3616 ExportDirectoryEntryRva
= 0;
3617 ResourceDirectoryEntryRva
= 0;
3618 DebugDirectoryEntryFileOffset
= 0;
3619 ExportDirectoryEntryFileOffset
= 0;
3620 ResourceDirectoryEntryFileOffset
= 0;
3621 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
3622 FileHdr
= (EFI_IMAGE_FILE_HEADER
*) (FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
3625 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
3626 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
3627 // NO DOS header, must start with PE/COFF header
3628 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
3630 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
3634 // Get Debug, Export and Resource EntryTable RVA address.
3635 // Resource Directory entry need to review.
3637 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
3638 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3639 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3640 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3641 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3642 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3644 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3645 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3646 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3648 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3649 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3650 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3651 if (ZeroDebugFlag
) {
3652 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
3653 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
3657 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3658 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3659 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3660 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3661 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3663 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3664 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3665 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3667 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3668 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3669 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3670 if (ZeroDebugFlag
) {
3671 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
3672 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
3678 // Get DirectoryEntryTable file offset.
3680 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
3681 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3682 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3683 DebugDirectoryEntryFileOffset
=
3684 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3686 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3687 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3688 ExportDirectoryEntryFileOffset
=
3689 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3691 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3692 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3693 ResourceDirectoryEntryFileOffset
=
3694 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3699 //Zero Debug Data and TimeStamp
3701 FileHdr
->TimeDateStamp
= 0;
3702 mImageTimeStamp
= 0;
3703 if (ExportDirectoryEntryFileOffset
!= 0) {
3704 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
3708 if (ResourceDirectoryEntryFileOffset
!= 0) {
3709 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
3713 if (DebugDirectoryEntryFileOffset
!= 0) {
3714 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
);
3715 DebugEntry
->TimeDateStamp
= 0;
3716 mImageTimeStamp
= 0;
3717 if (ZeroDebugFlag
) {
3718 memset (FileBuffer
+ DebugEntry
->FileOffset
, 0, DebugEntry
->SizeOfData
);
3719 memset (DebugEntry
, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
3729 IN OUT UINT8
*FileBuffer
,
3734 Routine Description:
3736 Set new time stamp into PeImage FileHdr and Directory table:
3737 Debug, Export and Resource.
3741 FileBuffer - Pointer to PeImage.
3742 TimeStamp - Time stamp string.
3746 EFI_INVALID_PARAMETER - TimeStamp format is not recognized.
3747 EFI_SUCCESS - Set new time stamp in this image successfully.
3755 UINT32 DebugDirectoryEntryRva
;
3756 UINT32 DebugDirectoryEntryFileOffset
;
3757 UINT32 ExportDirectoryEntryRva
;
3758 UINT32 ExportDirectoryEntryFileOffset
;
3759 UINT32 ResourceDirectoryEntryRva
;
3760 UINT32 ResourceDirectoryEntryFileOffset
;
3761 EFI_IMAGE_DOS_HEADER
*DosHdr
;
3762 EFI_IMAGE_FILE_HEADER
*FileHdr
;
3763 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
3764 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
3765 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
3766 UINT32
*NewTimeStamp
;
3771 DebugDirectoryEntryRva
= 0;
3772 DebugDirectoryEntryFileOffset
= 0;
3773 ExportDirectoryEntryRva
= 0;
3774 ExportDirectoryEntryFileOffset
= 0;
3775 ResourceDirectoryEntryRva
= 0;
3776 ResourceDirectoryEntryFileOffset
= 0;
3778 // Get time and date that will be set.
3780 if (TimeStamp
== NULL
) {
3781 Error (NULL
, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");
3782 return EFI_INVALID_PARAMETER
;
3785 // compare the value with "NOW", if yes, current system time is set.
3787 if (stricmp (TimeStamp
, "NOW") == 0) {
3789 // get system current time and date
3794 // Check Time Format strictly yyyy-mm-dd 00:00:00
3796 for (Index
= 0; TimeStamp
[Index
] != '\0' && Index
< 20; Index
++) {
3797 if (Index
== 4 || Index
== 7) {
3798 if (TimeStamp
[Index
] == '-') {
3801 } else if (Index
== 13 || Index
== 16) {
3802 if (TimeStamp
[Index
] == ':') {
3805 } else if (Index
== 10 && TimeStamp
[Index
] == ' ') {
3807 } else if ((TimeStamp
[Index
] < '0') || (TimeStamp
[Index
] > '9')) {
3812 if (Index
< 19 || TimeStamp
[19] != '\0') {
3813 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
3814 return EFI_INVALID_PARAMETER
;
3818 // get the date and time from TimeStamp
3820 if (sscanf (TimeStamp
, "%d-%d-%d %d:%d:%d",
3828 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
3829 return EFI_INVALID_PARAMETER
;
3833 // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
3835 if (stime
.tm_mon
<= 0 || stime
.tm_mday
<=0) {
3836 Error (NULL
, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp
);
3837 return EFI_INVALID_PARAMETER
;
3842 // in struct, Year (current year minus 1900)
3843 // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
3846 // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
3848 if (stime
.tm_year
>= 1970 && stime
.tm_year
<= 2038) {
3850 // convert 1970 -> 70, 2000 -> 100, ...
3852 stime
.tm_year
-= 1900;
3854 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
3855 return EFI_INVALID_PARAMETER
;
3859 // convert the date and time to time_t format
3861 newtime
= mktime (&stime
);
3862 if (newtime
== (time_t) - 1) {
3863 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
3864 return EFI_INVALID_PARAMETER
;
3868 ptime
= localtime (&newtime
);
3869 DebugMsg (NULL
, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",
3870 ptime
->tm_year
+ 1900, ptime
->tm_mon
+ 1, ptime
->tm_mday
, ptime
->tm_hour
, ptime
->tm_min
, ptime
->tm_sec
);
3872 // Set new time and data into PeImage.
3874 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
3875 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
3876 // NO DOS header, must start with PE/COFF header
3877 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
3879 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
3883 // Get Debug, Export and Resource EntryTable RVA address.
3884 // Resource Directory entry need to review.
3886 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
3887 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3888 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3889 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3890 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3891 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3893 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3894 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3895 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3897 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3898 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3899 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3902 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3903 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3904 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3905 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3906 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3908 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3909 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3910 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3912 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3913 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3914 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3919 // Get DirectoryEntryTable file offset.
3921 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
3922 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3923 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3924 DebugDirectoryEntryFileOffset
=
3925 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3927 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3928 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3929 ExportDirectoryEntryFileOffset
=
3930 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3932 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3933 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3934 ResourceDirectoryEntryFileOffset
=
3935 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3942 FileHdr
->TimeDateStamp
= (UINT32
) newtime
;
3943 mImageTimeStamp
= (UINT32
) newtime
;
3944 if (ExportDirectoryEntryRva
!= 0) {
3945 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
3946 *NewTimeStamp
= (UINT32
) newtime
;
3949 if (ResourceDirectoryEntryRva
!= 0) {
3950 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
3951 *NewTimeStamp
= (UINT32
) newtime
;
3954 if (DebugDirectoryEntryRva
!= 0) {
3955 NewTimeStamp
= (UINT32
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
+ sizeof (UINT32
));
3956 *NewTimeStamp
= (UINT32
) newtime
;
3970 Routine Description:
3971 Read a 32-bit microcode data value from a text file and convert to raw binary form.
3974 InFptr - file pointer to input text file
3975 Data - pointer to where to return the data parsed
3978 STATUS_SUCCESS - no errors or warnings, Data contains valid information
3979 STATUS_ERROR - errors were encountered
3983 CHAR8 Line
[MAX_LINE_LEN
];
3985 unsigned ScannedData
= 0;
3987 Line
[MAX_LINE_LEN
- 1] = 0;
3989 if (fgets (Line
, MAX_LINE_LEN
, InFptr
) == NULL
) {
3990 return STATUS_ERROR
;
3993 // If it was a binary file, then it may have overwritten our null terminator
3995 if (Line
[MAX_LINE_LEN
- 1] != 0) {
3996 return STATUS_ERROR
;
4002 for (cptr
= Line
; *cptr
&& isspace((int)*cptr
); cptr
++) {
4005 // Skip Blank Lines and Comment Lines
4006 if ((strlen(cptr
) != 0) && (*cptr
!= ';')) {
4012 // dd 000000001h ; comment
4017 if ((tolower((int)cptr
[0]) == 'd') && (tolower((int)cptr
[1]) == 'd') && isspace ((int)cptr
[2])) {
4019 // Skip blanks and look for a hex digit
4022 for (; *cptr
&& isspace((int)*cptr
); cptr
++) {
4024 if (isxdigit ((int)*cptr
)) {
4025 if (sscanf (cptr
, "%X", &ScannedData
) != 1) {
4026 return STATUS_ERROR
;
4029 *Data
= (UINT32
) ScannedData
;
4030 return STATUS_SUCCESS
;
4033 return STATUS_ERROR
;