2 Converts a pe32+ image to an FW, Te image type, or other specific image.
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "WinNtInclude.h"
14 #include <sys/types.h>
23 #include <Common/UefiBaseTypes.h>
24 #include <IndustryStandard/PeImage.h>
25 #include <Common/UefiInternalFormRepresentation.h>
28 // Acpi Table definition
30 #include <IndustryStandard/Acpi.h>
31 #include <IndustryStandard/Acpi1_0.h>
32 #include <IndustryStandard/Acpi2_0.h>
33 #include <IndustryStandard/Acpi3_0.h>
34 #include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
36 #include "CommonLib.h"
37 #include "PeCoffLib.h"
39 #include "EfiUtilityMsgs.h"
44 // Version of this utility
46 #define UTILITY_NAME "GenFw"
47 #define UTILITY_MAJOR_VERSION 0
48 #define UTILITY_MINOR_VERSION 2
50 #define HII_RESOURCE_SECTION_INDEX 1
51 #define HII_RESOURCE_SECTION_NAME "HII"
53 #define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
54 #define DEFAULT_MC_ALIGNMENT 16
56 #define STATUS_IGNORE 0xA
58 // Structure definition for a microcode header
68 UINT32 DataSize
; // if 0, then TotalSize = 2048, and TotalSize field is invalid
69 UINT32 TotalSize
; // number of bytes
71 } MICROCODE_IMAGE_HEADER
;
73 static EFI_GUID mZeroGuid
= {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
75 static const char *gHiiPackageRCFileHeader
[] = {
77 "// DO NOT EDIT -- auto-generated file",
83 // Module image information
86 UINT32 mImageTimeStamp
= 0;
87 UINT32 mImageSize
= 0;
88 UINT32 mOutImageType
= FW_DUMMY_IMAGE
;
89 BOOLEAN mIsConvertXip
= FALSE
;
90 BOOLEAN mExportFlag
= FALSE
;
95 IN OUT UINT8
*FileBuffer
,
102 IN OUT UINT8
*FileBuffer
,
122 Print out version information for this utility.
134 fprintf (stdout
, "%s Version %d.%d %s \n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
161 fprintf (stdout
, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME
);
164 // Copyright declaration
166 fprintf (stdout
, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
171 fprintf (stdout
, "Options:\n");
172 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
173 File will be created to store the output content.\n");
174 fprintf (stdout
, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\
175 Create Efi Image. EFI_FILETYPE is one of BASE,SMM_CORE,\n\
176 PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\
177 SEC, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER,\n\
178 DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER,\n\
179 MM_STANDALONE, MM_CORE_STANDALONE,\n\
180 PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\
181 APPLICATION, SAL_RT_DRIVER to support all module types\n\
182 It can only be used together with --keepexceptiontable,\n\
183 --keepzeropending, --keepoptionalheader, -r, -o option.\n\
184 It is a action option. If it is combined with other action options,\n\
185 the later input action option will override the previous one.\n");
186 fprintf (stdout
, " -c, --acpi Create Acpi table.\n\
187 It can't be combined with other action options\n\
188 except for -o, -r option. It is a action option.\n\
189 If it is combined with other action options, the later\n\
190 input action option will override the previous one.\n");
191 fprintf (stdout
, " -t, --terse Create Te Image.\n\
192 It can only be used together with --keepexceptiontable,\n\
193 --keepzeropending, --keepoptionalheader, -r, -o option.\n\
194 It is a action option. If it is combined with other action options,\n\
195 the later input action option will override the previous one.\n");
196 fprintf (stdout
, " -u, --dump Dump TeImage Header.\n\
197 It can't be combined with other action options\n\
198 except for -o, -r option. It is a action option.\n\
199 If it is combined with other action options, the later\n\
200 input action option will override the previous one.\n");
201 fprintf (stdout
, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\
202 It also zeros the time stamp fields.\n\
203 This option can be used to compare the binary efi image.\n\
204 It can't be combined with other action options\n\
205 except for -o, -r option. It is a action option.\n\
206 If it is combined with other action options, the later\n\
207 input action option will override the previous one.\n");
208 fprintf (stdout
, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\
209 It can't be combined with other action options\n\
210 except for -o, -r option. It is a action option.\n\
211 If it is combined with other action options, the later\n\
212 input action option will override the previous one.\n");;
213 fprintf (stdout
, " -l, --stripped Strip off the relocation info from PE or TE image.\n\
214 It can't be combined with other action options\n\
215 except for -o, -r option. It is a action option.\n\
216 If it is combined with other action options, the later\n\
217 input action option will override the previous one.\n");
218 fprintf (stdout
, " -s timedate, --stamp timedate\n\
219 timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\
220 is set to NOW, current system time is used. The support\n\
221 date scope is 1970-01-01 00+timezone:00:00\n\
222 ~ 2038-01-19 03+timezone:14:07\n\
223 The scope is adjusted according to the different zones.\n\
224 It can't be combined with other action options\n\
225 except for -o, -r option. It is a action option.\n\
226 If it is combined with other action options, the later\n\
227 input action option will override the previous one.\n");
228 fprintf (stdout
, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\
229 It can't be combined with other action options\n\
230 except for -o option. It is a action option.\n\
231 If it is combined with other action options, the later\n\
232 input action option will override the previous one.\n");
233 fprintf (stdout
, " -j, --join Combine multi microcode bin files to one file.\n\
234 It can be specified with -a, -p, -o option.\n\
235 No other options can be combined with it.\n\
236 If it is combined with other action options, the later\n\
237 input action option will override the previous one.\n");
238 fprintf (stdout
, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\
239 This option is only used together with -j option.\n");
240 fprintf (stdout
, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\
241 This option is only used together with -j option.\n");
242 fprintf (stdout
, " --keepexceptiontable Don't clear exception table.\n\
243 This option can be used together with -e or -t.\n\
244 It doesn't work for other options.\n");
245 fprintf (stdout
, " --keepoptionalheader Don't zero PE/COFF optional header fields.\n\
246 This option can be used together with -e or -t.\n\
247 It doesn't work for other options.\n");
248 fprintf (stdout
, " --keepzeropending Don't strip zero pending of .reloc.\n\
249 This option can be used together with -e or -t.\n\
250 It doesn't work for other options.\n");
251 fprintf (stdout
, " -r, --replace Overwrite the input file with the output content.\n\
252 If more input files are specified,\n\
253 the last input file will be as the output file.\n");
254 fprintf (stdout
, " -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\
255 Guid is used to specify hii package list guid.\n\
256 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\
257 If not specified, the first Form FormSet guid is used.\n");
258 fprintf (stdout
, " --hiipackage Combine all input binary hii packages into \n\
259 a single package list as the text resource data(RC).\n\
260 It can't be combined with other action options\n\
261 except for -o option. It is a action option.\n\
262 If it is combined with other action options, the later\n\
263 input action option will override the previous one.\n");
264 fprintf (stdout
, " --hiibinpackage Combine all input binary hii packages into \n\
265 a single package list as the binary resource section.\n\
266 It can't be combined with other action options\n\
267 except for -o option. It is a action option.\n\
268 If it is combined with other action options, the later\n\
269 input action option will override the previous one.\n");
270 fprintf (stdout
, " --rebase NewAddress Rebase image to new base address. New address \n\
271 is also set to the first none code section header.\n\
272 It can't be combined with other action options\n\
273 except for -o or -r option. It is a action option.\n\
274 If it is combined with other action options, the later\n\
275 input action option will override the previous one.\n");
276 fprintf (stdout
, " --address NewAddress Set new address into the first none code \n\
277 section header of the input image.\n\
278 It can't be combined with other action options\n\
279 except for -o or -r option. It is a action option.\n\
280 If it is combined with other action options, the later\n\
281 input action option will override the previous one.\n");
282 fprintf (stdout
, " --prm Scan symbol section from ELF image and \n\
283 write export table into PE-COFF.\n\
284 This option can be used together with -e.\n\
285 It doesn't work for other options.\n");
286 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
287 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
288 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
289 fprintf (stdout
, " --version Show program's version number and exit\n");
290 fprintf (stdout
, " -h, --help Show this help message and exit\n");
307 AcpiTable Buffer for AcpiSection
308 Length AcpiSection Length
317 EFI_ACPI_DESCRIPTION_HEADER
*AcpiHeader
;
318 EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs
;
319 UINT32 ExpectedLength
;
321 AcpiHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTable
;
324 // Generic check for AcpiTable length.
326 if (AcpiHeader
->Length
> Length
) {
327 Error (NULL
, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL
);
332 // Currently, we only check must-have tables: FADT, FACS, DSDT,
333 // and some important tables: MADT, MCFG.
335 switch (AcpiHeader
->Signature
) {
338 // "FACP" Fixed ACPI Description Table
340 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
:
341 switch (AcpiHeader
->Revision
) {
342 case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
343 ExpectedLength
= sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
);
345 case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
346 ExpectedLength
= sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
);
348 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
349 ExpectedLength
= sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
);
352 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
) {
353 ExpectedLength
= AcpiHeader
->Length
;
356 Error (NULL
, 0, 3000, "Invalid", "FACP revision check failed.");
359 if (ExpectedLength
!= AcpiHeader
->Length
) {
360 Error (NULL
, 0, 3000, "Invalid", "FACP length check failed.");
366 // "FACS" Firmware ACPI Control Structure
368 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE
:
369 Facs
= (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)AcpiTable
;
370 if (Facs
->Version
> EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) {
373 if ((Facs
->Version
!= EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
374 (Facs
->Version
!= EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
375 (Facs
->Version
!= EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
)){
376 Error (NULL
, 0, 3000, "Invalid", "FACS version check failed.");
379 if ((Facs
->Length
!= sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
380 (Facs
->Length
!= sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
381 (Facs
->Length
!= sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
))) {
382 Error (NULL
, 0, 3000, "Invalid", "FACS length check failed.");
388 // "DSDT" Differentiated System Description Table
390 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
391 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION
) {
394 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
)) {
395 Error (NULL
, 0, 3000, "Invalid", "DSDT length check failed.");
401 // "APIC" Multiple APIC Description Table
403 case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE
:
404 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) {
407 if ((AcpiHeader
->Revision
!= EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
408 (AcpiHeader
->Revision
!= EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
409 (AcpiHeader
->Revision
!= EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
)) {
410 Error (NULL
, 0, 3000, "Invalid", "APIC revision check failed.");
413 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT32
) + sizeof(UINT32
)) {
414 Error (NULL
, 0, 3000, "Invalid", "APIC length check failed.");
420 // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
422 case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE
:
423 if (AcpiHeader
->Revision
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
426 if (AcpiHeader
->Revision
!= EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
427 Error (NULL
, 0, 3000, "Invalid", "MCFG revision check failed.");
430 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT64
)) {
431 Error (NULL
, 0, 3000, "Invalid", "MCFG length check failed.");
437 // Other table pass check
443 return STATUS_SUCCESS
;
447 SetHiiResourceHeader (
453 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
454 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*ResourceDirectoryEntry
;
455 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
456 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
459 // Fill Resource section entry
461 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
);
462 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
463 for (Index
= 0; Index
< ResourceDirectory
->NumberOfNamedEntries
; Index
++) {
464 if (ResourceDirectoryEntry
->u1
.s
.NameIsString
) {
465 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiBinData
+ ResourceDirectoryEntry
->u1
.s
.NameOffset
);
467 if (ResourceDirectoryString
->Length
== 3 &&
468 ResourceDirectoryString
->String
[0] == L
'H' &&
469 ResourceDirectoryString
->String
[1] == L
'I' &&
470 ResourceDirectoryString
->String
[2] == L
'I') {
472 // Resource Type "HII" found
474 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
476 // Move to next level - resource Name
478 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
479 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
481 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
483 // Move to next level - resource Language
485 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
486 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
491 // Now it ought to be resource Data and update its OffsetToData value
493 if (!ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
494 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.OffsetToData
);
495 ResourceDataEntry
->OffsetToData
= ResourceDataEntry
->OffsetToData
+ OffsetToFile
;
500 ResourceDirectoryEntry
++;
506 EFI_IMAGE_OPTIONAL_HEADER_UNION
*
511 EFI_IMAGE_DOS_HEADER
*DosHdr
;
512 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
515 // Read the dos & pe hdrs of the image
517 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Data
;
518 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
519 // NO DOS header, check for PE/COFF header
520 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(Data
);
521 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
526 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(((UINT8
*)Data
) + DosHdr
->e_lfanew
);
527 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
536 PeCoffConvertImageToXip (
541 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
542 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NewPeHdr
;
543 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
544 UINTN TotalNecessaryFileSize
;
549 UINTN FirstSectionOffset
;
550 BOOLEAN ConversionNeeded
;
552 PeHdr
= GetPeCoffHeader ((void *) *FileBuffer
);
557 if (PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
) {
559 // The only reason to expand zero fill sections is to make them compatible with XIP images.
560 // If SectionAlignment is not equal to FileAlignment then it is not an XIP type image.
566 // Calculate size of XIP file, and determine if the conversion is needed.
568 ConversionNeeded
= FALSE
;
570 FirstSectionOffset
= *FileLength
;
571 TotalNecessaryFileSize
= 0;
572 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
573 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
574 SectionSize
= MAX (SectionHeader
->Misc
.VirtualSize
, SectionHeader
->SizeOfRawData
);
575 TotalNecessaryFileSize
+= SectionSize
;
576 if (SectionSize
> 0) {
577 FirstSectionOffset
= MIN (FirstSectionOffset
, SectionHeader
->VirtualAddress
);
578 XipLength
= MAX (XipLength
, SectionHeader
->VirtualAddress
+ SectionSize
);
579 if (SectionHeader
->VirtualAddress
!= SectionHeader
->PointerToRawData
) {
580 ConversionNeeded
= TRUE
;
583 if (SectionHeader
->Misc
.VirtualSize
> SectionHeader
->SizeOfRawData
) {
584 ConversionNeeded
= TRUE
;
588 if (FirstSectionOffset
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
590 // If one of the sections should be loaded to an offset overlapping with
591 // the executable header, then it cannot be made into an XIP image.
593 VerboseMsg ("PE/COFF conversion to XIP is impossible due to overlap");
594 VerboseMsg ("of section data with the executable header.");
598 if (FirstSectionOffset
== *FileLength
) {
600 // If we never found a section with a non-zero size, then we
601 // skip the conversion.
606 TotalNecessaryFileSize
+= FirstSectionOffset
;
608 if (!ConversionNeeded
) {
612 if (XipLength
> (2 * TotalNecessaryFileSize
)) {
613 VerboseMsg ("PE/COFF conversion to XIP appears to be larger than necessary.");
614 VerboseMsg ("The image linking process may have left unused memory ranges.");
617 if (PeHdr
->Pe32
.FileHeader
.PointerToSymbolTable
!= 0) {
619 // This field is obsolete and should be zero
621 PeHdr
->Pe32
.FileHeader
.PointerToSymbolTable
= 0;
625 // Allocate the extra space that we need to grow the image
627 XipFile
= malloc (XipLength
);
628 if (XipFile
== NULL
) {
629 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
632 memset (XipFile
, 0, XipLength
);
635 // Copy the file headers
637 memcpy (XipFile
, *FileBuffer
, PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
);
639 NewPeHdr
= GetPeCoffHeader ((void *)XipFile
);
640 if (NewPeHdr
== NULL
) {
646 // Copy the section data over to the appropriate XIP offsets
648 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(NewPeHdr
->Pe32
.OptionalHeader
) + NewPeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
649 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
650 if (SectionHeader
->SizeOfRawData
> 0) {
652 XipFile
+ SectionHeader
->VirtualAddress
,
653 *FileBuffer
+ SectionHeader
->PointerToRawData
,
654 SectionHeader
->SizeOfRawData
658 // Make the size of raw data in section header alignment.
660 SectionSize
= (SectionHeader
->Misc
.VirtualSize
+ PeHdr
->Pe32
.OptionalHeader
.FileAlignment
- 1) & (~(PeHdr
->Pe32
.OptionalHeader
.FileAlignment
- 1));
661 if (SectionSize
< SectionHeader
->SizeOfRawData
) {
662 SectionHeader
->SizeOfRawData
= SectionSize
;
665 SectionHeader
->PointerToRawData
= SectionHeader
->VirtualAddress
;
669 *FileLength
= XipLength
;
670 *FileBuffer
= XipFile
;
672 mIsConvertXip
= TRUE
;
676 CreateHiiResouceSectionHeader (
677 UINT32
*pSectionHeaderSize
,
684 Create COFF resource section header
688 pSectionHeaderSize - Pointer to section header size.
689 HiiDataSize - Size of the total HII data in section.
692 The created section header buffer.
696 UINT32 HiiSectionHeaderSize
;
697 UINT32 HiiSectionOffset
;
698 UINT8
*HiiSectionHeader
;
699 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
700 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*TypeResourceDirectoryEntry
;
701 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*NameResourceDirectoryEntry
;
702 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*LanguageResourceDirectoryEntry
;
703 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
704 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
707 // Calculate the total size for the resource header (include Type, Name and Language)
708 // then allocate memory for the resource header.
710 HiiSectionHeaderSize
= 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
))
711 + 3 * (sizeof (UINT16
) + 3 * sizeof (CHAR16
))
712 + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
713 HiiSectionHeader
= malloc (HiiSectionHeaderSize
);
714 if (HiiSectionHeader
== NULL
) {
715 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
718 memset (HiiSectionHeader
, 0, HiiSectionHeaderSize
);
720 HiiSectionOffset
= 0;
724 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
725 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
726 ResourceDirectory
->NumberOfNamedEntries
= 1;
727 TypeResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
728 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
729 TypeResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
730 TypeResourceDirectoryEntry
->u2
.s
.DataIsDirectory
= 1;
731 TypeResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
= HiiSectionOffset
;
735 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
736 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
737 ResourceDirectory
->NumberOfNamedEntries
= 1;
738 NameResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
739 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
740 NameResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
741 NameResourceDirectoryEntry
->u2
.s
.DataIsDirectory
= 1;
742 NameResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
= HiiSectionOffset
;
744 // Create Language entry
746 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
747 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
748 ResourceDirectory
->NumberOfNamedEntries
= 1;
749 LanguageResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
750 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
751 LanguageResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
753 // Create string entry for Type
755 TypeResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
756 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
757 ResourceDirectoryString
->Length
= 3;
758 ResourceDirectoryString
->String
[0] = L
'H';
759 ResourceDirectoryString
->String
[1] = L
'I';
760 ResourceDirectoryString
->String
[2] = L
'I';
761 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
763 // Create string entry for Name
765 NameResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
766 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
767 ResourceDirectoryString
->Length
= 3;
768 ResourceDirectoryString
->String
[0] = L
'E';
769 ResourceDirectoryString
->String
[1] = L
'F';
770 ResourceDirectoryString
->String
[2] = L
'I';
771 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
773 // Create string entry for Language
775 LanguageResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
776 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
777 ResourceDirectoryString
->Length
= 3;
778 ResourceDirectoryString
->String
[0] = L
'B';
779 ResourceDirectoryString
->String
[1] = L
'I';
780 ResourceDirectoryString
->String
[2] = L
'N';
781 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
785 LanguageResourceDirectoryEntry
->u2
.OffsetToData
= HiiSectionOffset
;
786 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
787 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
788 ResourceDataEntry
->OffsetToData
= HiiSectionOffset
;
789 ResourceDataEntry
->Size
= HiiDataSize
;
791 *pSectionHeaderSize
= HiiSectionHeaderSize
;
792 return HiiSectionHeader
;
799 IN OUT UINT32
*ReadSize
,
806 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
810 FileHandle - The handle to the PE/COFF file
812 FileOffset - The offset, in bytes, into the file to read
814 ReadSize - The number of bytes to read from the file starting at FileOffset
816 Buffer - A pointer to the buffer to read the data into.
820 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
828 Destination8
= Buffer
;
829 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
832 *(Destination8
++) = *(Source8
++);
839 SetAddressToSectionHeader (
841 IN OUT UINT8
*FileBuffer
,
842 IN UINT64 NewPe32BaseAddress
848 Set new base address into the section header of PeImage
852 FileName - Name of file
853 FileBuffer - Pointer to PeImage.
854 NewPe32BaseAddress - New Base Address for PE image.
858 EFI_SUCCESS Set new base address into this image successfully.
863 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
865 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
866 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
869 // Initialize context
871 memset (&ImageContext
, 0, sizeof (ImageContext
));
872 ImageContext
.Handle
= (VOID
*) FileBuffer
;
873 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
874 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
875 if (EFI_ERROR (Status
)) {
876 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
880 if (ImageContext
.RelocationsStripped
) {
881 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
886 // Get PeHeader pointer
888 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
891 // Get section header list
893 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
896 sizeof (EFI_IMAGE_FILE_HEADER
) +
897 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
901 // Set base address into the first section header that doesn't point to code section.
903 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
904 if ((SectionHeader
->Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
905 *(UINT64
*) &SectionHeader
->PointerToRelocations
= NewPe32BaseAddress
;
911 // BaseAddress is set to section header.
919 IN OUT UINT8
*FileBuffer
,
920 IN UINT64 NewPe32BaseAddress
926 Set new base address into PeImage, and fix up PeImage based on new address.
930 FileName - Name of file
931 FileBuffer - Pointer to PeImage.
932 NewPe32BaseAddress - New Base Address for PE image.
936 EFI_INVALID_PARAMETER - BaseAddress is not valid.
937 EFI_SUCCESS - Update PeImage is correctly.
942 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
944 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
945 UINT8
*MemoryImagePointer
;
946 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
949 // Initialize context
951 memset (&ImageContext
, 0, sizeof (ImageContext
));
952 ImageContext
.Handle
= (VOID
*) FileBuffer
;
953 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
954 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
955 if (EFI_ERROR (Status
)) {
956 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
960 if (ImageContext
.RelocationsStripped
) {
961 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
966 // Get PeHeader pointer
968 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
971 // Load and Relocate Image Data
973 MemoryImagePointer
= (UINT8
*) malloc ((UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
974 if (MemoryImagePointer
== NULL
) {
975 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
976 return EFI_OUT_OF_RESOURCES
;
978 memset ((VOID
*) MemoryImagePointer
, 0, (UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
979 ImageContext
.ImageAddress
= ((UINTN
) MemoryImagePointer
+ ImageContext
.SectionAlignment
- 1) & (~((INT64
)ImageContext
.SectionAlignment
- 1));
981 Status
= PeCoffLoaderLoadImage (&ImageContext
);
982 if (EFI_ERROR (Status
)) {
983 Error (NULL
, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName
);
984 free ((VOID
*) MemoryImagePointer
);
988 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
989 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
990 if (EFI_ERROR (Status
)) {
991 Error (NULL
, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName
);
992 free ((VOID
*) MemoryImagePointer
);
997 // Copy Relocated data to raw image file.
999 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1002 sizeof (EFI_IMAGE_FILE_HEADER
) +
1003 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1006 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1008 FileBuffer
+ SectionHeader
->PointerToRawData
,
1009 (VOID
*) (UINTN
) (ImageContext
.ImageAddress
+ SectionHeader
->VirtualAddress
),
1010 SectionHeader
->SizeOfRawData
< SectionHeader
->Misc
.VirtualSize
? SectionHeader
->SizeOfRawData
: SectionHeader
->Misc
.VirtualSize
1014 free ((VOID
*) MemoryImagePointer
);
1017 // Update Image Base Address
1019 if (ImgHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1020 ImgHdr
->Pe32
.OptionalHeader
.ImageBase
= (UINT32
) NewPe32BaseAddress
;
1021 } else if (ImgHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1022 ImgHdr
->Pe32Plus
.OptionalHeader
.ImageBase
= NewPe32BaseAddress
;
1024 Error (NULL
, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
1025 ImgHdr
->Pe32
.OptionalHeader
.Magic
,
1032 // Set new base address into section header
1034 Status
= SetAddressToSectionHeader (FileName
, FileBuffer
, NewPe32BaseAddress
);
1046 Routine Description:
1052 argc - Number of command line parameters.
1053 argv - Array of pointers to command line parameter strings.
1056 STATUS_SUCCESS - Utility exits successfully.
1057 STATUS_ERROR - Some error occurred during execution.
1062 UINT32 InputFileNum
;
1063 CHAR8
**InputFileName
;
1071 UINT32
*DataPointer
;
1072 UINT32
*OldDataPointer
;
1078 UINT32 MciAlignment
;
1080 UINT32 AllignedRelocSize
;
1083 UINT8
*OutputFileBuffer
;
1084 UINT32 OutputFileLength
;
1085 UINT8
*InputFileBuffer
;
1086 UINT32 InputFileLength
;
1087 RUNTIME_FUNCTION
*RuntimeFunction
;
1088 UNWIND_INFO
*UnwindInfo
;
1090 BOOLEAN ReplaceFlag
;
1091 BOOLEAN KeepExceptionTableFlag
;
1092 BOOLEAN KeepOptionalHeaderFlag
;
1093 BOOLEAN KeepZeroPendingFlag
;
1095 EFI_TE_IMAGE_HEADER TEImageHeader
;
1096 EFI_TE_IMAGE_HEADER
*TeHdr
;
1097 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1098 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1099 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1100 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32
;
1101 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64
;
1102 EFI_IMAGE_DOS_HEADER BackupDosHdr
;
1103 MICROCODE_IMAGE_HEADER
*MciHeader
;
1104 UINT8
*HiiPackageListBuffer
;
1105 UINT8
*HiiPackageDataPointer
;
1106 EFI_GUID HiiPackageListGuid
;
1107 EFI_HII_PACKAGE_LIST_HEADER HiiPackageListHeader
;
1108 EFI_HII_PACKAGE_HEADER HiiPackageHeader
;
1109 EFI_IFR_FORM_SET IfrFormSet
;
1110 UINT8 NumberOfFormPackage
;
1111 EFI_HII_PACKAGE_HEADER EndPackage
;
1112 UINT32 HiiSectionHeaderSize
;
1113 UINT8
*HiiSectionHeader
;
1114 UINT64 NewBaseAddress
;
1115 BOOLEAN NegativeAddr
;
1117 CHAR8
*ReportFileName
;
1119 time_t InputFileTime
;
1120 time_t OutputFileTime
;
1121 struct stat Stat_Buf
;
1122 BOOLEAN ZeroDebugFlag
;
1124 SetUtilityName (UTILITY_NAME
);
1127 // Assign to fix compile warning
1131 InputFileName
= NULL
;
1132 mInImageName
= NULL
;
1133 OutImageName
= NULL
;
1136 Status
= STATUS_SUCCESS
;
1142 MciAlignment
= DEFAULT_MC_ALIGNMENT
;
1143 MciPadValue
= DEFAULT_MC_PAD_BYTE_VALUE
;
1147 ReplaceFlag
= FALSE
;
1149 OutputFileBuffer
= NULL
;
1150 OutputFileLength
= 0;
1151 InputFileBuffer
= NULL
;
1152 InputFileLength
= 0;
1155 KeepExceptionTableFlag
= FALSE
;
1156 KeepOptionalHeaderFlag
= FALSE
;
1157 KeepZeroPendingFlag
= FALSE
;
1158 NumberOfFormPackage
= 0;
1159 HiiPackageListBuffer
= NULL
;
1160 HiiPackageDataPointer
= NULL
;
1161 EndPackage
.Length
= sizeof (EFI_HII_PACKAGE_HEADER
);
1162 EndPackage
.Type
= EFI_HII_PACKAGE_END
;
1163 memset (&HiiPackageListGuid
, 0, sizeof (HiiPackageListGuid
));
1164 HiiSectionHeaderSize
= 0;
1165 HiiSectionHeader
= NULL
;
1167 NegativeAddr
= FALSE
;
1170 ZeroDebugFlag
= FALSE
;
1173 Error (NULL
, 0, 1001, "Missing options", "No input options.");
1175 return STATUS_ERROR
;
1181 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
1184 return STATUS_SUCCESS
;
1187 if (stricmp (argv
[0], "--version") == 0) {
1189 return STATUS_SUCCESS
;
1193 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
1194 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1195 Error (NULL
, 0, 1003, "Invalid option value", "Output file name is missing for -o option");
1198 OutImageName
= argv
[1];
1204 if ((stricmp (argv
[0], "-e") == 0) || (stricmp (argv
[0], "--efiImage") == 0)) {
1205 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1206 Error (NULL
, 0, 1003, "Invalid option value", "Module Type is missing for -o option");
1209 ModuleType
= argv
[1];
1210 if (mOutImageType
== FW_ZERO_DEBUG_IMAGE
) {
1211 ZeroDebugFlag
= TRUE
;
1213 if (mOutImageType
!= FW_TE_IMAGE
) {
1214 mOutImageType
= FW_EFI_IMAGE
;
1221 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--stripped") == 0)) {
1222 mOutImageType
= FW_RELOC_STRIPEED_IMAGE
;
1228 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--acpi") == 0)) {
1229 mOutImageType
= FW_ACPI_IMAGE
;
1235 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--terse") == 0)) {
1236 if (mOutImageType
== FW_ZERO_DEBUG_IMAGE
) {
1237 ZeroDebugFlag
= TRUE
;
1239 mOutImageType
= FW_TE_IMAGE
;
1245 if ((stricmp (argv
[0], "-u") == 0) || (stricmp (argv
[0], "--dump") == 0)) {
1246 mOutImageType
= DUMP_TE_HEADER
;
1252 if ((stricmp (argv
[0], "-b") == 0) || (stricmp (argv
[0], "--exe2bin") == 0)) {
1253 mOutImageType
= FW_BIN_IMAGE
;
1259 if ((stricmp (argv
[0], "-z") == 0) || (stricmp (argv
[0], "--zero") == 0)) {
1260 if (mOutImageType
== FW_DUMMY_IMAGE
) {
1261 mOutImageType
= FW_ZERO_DEBUG_IMAGE
;
1263 if (mOutImageType
== FW_TE_IMAGE
|| mOutImageType
== FW_EFI_IMAGE
) {
1264 ZeroDebugFlag
= TRUE
;
1271 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--stamp") == 0)) {
1272 mOutImageType
= FW_SET_STAMP_IMAGE
;
1273 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1274 Error (NULL
, 0, 1003, "Invalid option value", "time stamp is missing for -s option");
1277 TimeStamp
= argv
[1];
1283 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--replace") == 0)) {
1290 if (stricmp (argv
[0], "--keepexceptiontable") == 0) {
1291 KeepExceptionTableFlag
= TRUE
;
1297 if (stricmp(argv
[0], "--keepoptionalheader") == 0) {
1298 KeepOptionalHeaderFlag
= TRUE
;
1304 if (stricmp (argv
[0], "--keepzeropending") == 0) {
1305 KeepZeroPendingFlag
= TRUE
;
1311 if ((stricmp (argv
[0], "-m") == 0) || (stricmp (argv
[0], "--mcifile") == 0)) {
1312 mOutImageType
= FW_MCI_IMAGE
;
1318 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--join") == 0)) {
1319 mOutImageType
= FW_MERGE_IMAGE
;
1325 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
1326 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1327 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1330 MciAlignment
= (UINT32
) Temp64
;
1336 if ((stricmp (argv
[0], "--rebase") == 0)) {
1337 if (argv
[1][0] == '-') {
1338 NegativeAddr
= TRUE
;
1339 Status
= AsciiStringToUint64 (argv
[1] + 1, FALSE
, &Temp64
);
1341 NegativeAddr
= FALSE
;
1342 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
);
1344 if (Status
!= EFI_SUCCESS
) {
1345 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1348 mOutImageType
= FW_REBASE_IMAGE
;
1349 NewBaseAddress
= (UINT64
) Temp64
;
1355 if ((stricmp (argv
[0], "--address") == 0)) {
1356 if (argv
[1][0] == '-') {
1357 NegativeAddr
= TRUE
;
1358 Status
= AsciiStringToUint64 (argv
[1] + 1, FALSE
, &Temp64
);
1360 NegativeAddr
= FALSE
;
1361 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
);
1363 if (Status
!= EFI_SUCCESS
) {
1364 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1367 mOutImageType
= FW_SET_ADDRESS_IMAGE
;
1368 NewBaseAddress
= (UINT64
) Temp64
;
1374 if ((stricmp (argv
[0], "-p") == 0) || (stricmp (argv
[0], "--pad") == 0)) {
1375 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1376 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1379 MciPadValue
= (UINT8
) Temp64
;
1385 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
1386 SetPrintLevel (VERBOSE_LOG_LEVEL
);
1387 VerboseMsg ("Verbose output Mode Set!");
1393 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1394 SetPrintLevel (KEY_LOG_LEVEL
);
1395 KeyMsg ("Quiet output Mode Set!");
1401 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
1402 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
1403 if (EFI_ERROR (Status
)) {
1404 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1408 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel
);
1411 SetPrintLevel (LogLevel
);
1412 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
1418 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--hiiguid") == 0)) {
1419 Status
= StringToGuid (argv
[1], &HiiPackageListGuid
);
1420 if (EFI_ERROR (Status
)) {
1421 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1429 if (stricmp (argv
[0], "--hiipackage") == 0) {
1430 mOutImageType
= FW_HII_PACKAGE_LIST_RCIMAGE
;
1436 if (stricmp (argv
[0], "--hiibinpackage") == 0) {
1437 mOutImageType
= FW_HII_PACKAGE_LIST_BINIMAGE
;
1443 if (stricmp (argv
[0], "--prm") == 0) {
1444 if (stricmp (ModuleType
, "DXE_RUNTIME_DRIVER") != 0 ){
1445 Error (NULL
, 0, 1001, "Invalid", "--prm option only supports DXE RUNTIME driver.");
1457 if (argv
[0][0] == '-') {
1458 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
1462 // Get Input file name
1464 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
1465 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
1466 if (InputFileName
== NULL
) {
1467 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1471 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1472 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1474 // InputFileName buffer too small, need to realloc
1476 InputFileName
= (CHAR8
**) realloc (
1478 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1481 if (InputFileName
== NULL
) {
1482 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1486 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1489 InputFileName
[InputFileNum
++] = argv
[0];
1494 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1496 if (mOutImageType
== FW_DUMMY_IMAGE
) {
1497 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!");
1499 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.");
1505 // check input files
1507 if (InputFileNum
== 0) {
1508 Error (NULL
, 0, 1001, "Missing option", "Input files");
1513 // Combine MciBinary files to one file
1515 if ((mOutImageType
== FW_MERGE_IMAGE
) && ReplaceFlag
) {
1516 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");
1521 // Combine HiiBinary packages to a single package list
1523 if ((mOutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) && ReplaceFlag
) {
1524 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option.");
1528 if ((mOutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) && ReplaceFlag
) {
1529 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiibinpackage merge files option.");
1536 mInImageName
= InputFileName
[InputFileNum
- 1];
1537 VerboseMsg ("the input file name is %s", mInImageName
);
1540 // Action will be taken for the input file.
1542 switch (mOutImageType
) {
1544 VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType
);
1547 VerboseMsg ("Create Te Image based on the input PE image.");
1550 VerboseMsg ("Get acpi table data from the input PE image.");
1552 case FW_RELOC_STRIPEED_IMAGE
:
1553 VerboseMsg ("Remove relocation section from Pe or Te image.");
1556 VerboseMsg ("Convert the input EXE to the output BIN file.");
1558 case FW_ZERO_DEBUG_IMAGE
:
1559 VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");
1561 case FW_SET_STAMP_IMAGE
:
1562 VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp
);
1564 case DUMP_TE_HEADER
:
1565 VerboseMsg ("Dump the TE header information of the input TE image.");
1568 VerboseMsg ("Convert input MicroCode.txt file to MicroCode.bin file.");
1570 case FW_MERGE_IMAGE
:
1571 VerboseMsg ("Combine the input multi microcode bin files to one bin file.");
1573 case FW_HII_PACKAGE_LIST_RCIMAGE
:
1574 VerboseMsg ("Combine the input multi hii bin packages to one text package list RC file.");
1576 case FW_HII_PACKAGE_LIST_BINIMAGE
:
1577 VerboseMsg ("Combine the input multi hii bin packages to one binary package list file.");
1579 case FW_REBASE_IMAGE
:
1580 VerboseMsg ("Rebase the input image to new base address.");
1582 case FW_SET_ADDRESS_IMAGE
:
1583 VerboseMsg ("Set the preferred address into the section header of the input image");
1590 VerboseMsg ("Overwrite the input file with the output content.");
1594 // Open output file and Write image into the output file.
1596 if (OutImageName
!= NULL
) {
1597 fpOut
= fopen (LongFilePath (OutImageName
), "rb");
1598 if (fpOut
!= NULL
) {
1600 // Get Output file time stamp
1602 fstat(fileno (fpOut
), &Stat_Buf
);
1603 OutputFileTime
= Stat_Buf
.st_mtime
;
1605 // Get Output file data
1607 OutputFileLength
= _filelength (fileno (fpOut
));
1608 OutputFileBuffer
= malloc (OutputFileLength
);
1609 if (OutputFileBuffer
== NULL
) {
1610 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1615 fread (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
1619 VerboseMsg ("Output file name is %s", OutImageName
);
1620 } else if (!ReplaceFlag
&& mOutImageType
!= DUMP_TE_HEADER
) {
1621 Error (NULL
, 0, 1001, "Missing option", "output file");
1626 // Open input file and read file data into file buffer.
1628 fpIn
= fopen (LongFilePath (mInImageName
), "rb");
1630 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1634 // Get Iutput file time stamp
1636 fstat(fileno (fpIn
), &Stat_Buf
);
1637 InputFileTime
= Stat_Buf
.st_mtime
;
1639 // Get Input file data
1641 InputFileLength
= _filelength (fileno (fpIn
));
1642 InputFileBuffer
= malloc (InputFileLength
);
1643 if (InputFileBuffer
== NULL
) {
1644 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1648 fread (InputFileBuffer
, 1, InputFileLength
, fpIn
);
1650 DebugMsg (NULL
, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) InputFileLength
);
1653 // Combine multi binary HII package files.
1655 if (mOutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
|| mOutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) {
1657 // Open output file handle.
1659 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
1661 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1665 // Get hii package list length
1667 HiiPackageListHeader
.PackageLength
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1668 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1669 fpIn
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
1671 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1674 FileLength
= _filelength (fileno (fpIn
));
1675 fread (&HiiPackageHeader
, 1, sizeof (HiiPackageHeader
), fpIn
);
1676 if (HiiPackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) {
1677 if (HiiPackageHeader
.Length
!= FileLength
) {
1678 Error (NULL
, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName
[Index
]);
1682 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
1683 fread (&IfrFormSet
, 1, sizeof (IfrFormSet
), fpIn
);
1684 memcpy (&HiiPackageListGuid
, &IfrFormSet
.Guid
, sizeof (EFI_GUID
));
1686 NumberOfFormPackage
++;
1688 HiiPackageListHeader
.PackageLength
+= FileLength
;
1691 HiiPackageListHeader
.PackageLength
+= sizeof (EndPackage
);
1693 // Check whether hii packages are valid
1695 if (NumberOfFormPackage
> 1) {
1696 Error (NULL
, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package");
1699 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
1700 Error (NULL
, 0, 3000, "Invalid", "HII package list guid is not specified!");
1703 memcpy (&HiiPackageListHeader
.PackageListGuid
, &HiiPackageListGuid
, sizeof (EFI_GUID
));
1705 // read hii packages
1707 HiiPackageListBuffer
= malloc (HiiPackageListHeader
.PackageLength
);
1708 if (HiiPackageListBuffer
== NULL
) {
1709 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1712 memcpy (HiiPackageListBuffer
, &HiiPackageListHeader
, sizeof (HiiPackageListHeader
));
1713 HiiPackageDataPointer
= HiiPackageListBuffer
+ sizeof (HiiPackageListHeader
);
1714 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1715 fpIn
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
1717 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1718 free (HiiPackageListBuffer
);
1722 FileLength
= _filelength (fileno (fpIn
));
1723 fread (HiiPackageDataPointer
, 1, FileLength
, fpIn
);
1725 HiiPackageDataPointer
= HiiPackageDataPointer
+ FileLength
;
1727 memcpy (HiiPackageDataPointer
, &EndPackage
, sizeof (EndPackage
));
1730 // write the hii package into the binary package list file with the resource section header
1732 if (mOutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) {
1734 // Create the resource section header
1736 HiiSectionHeader
= CreateHiiResouceSectionHeader (&HiiSectionHeaderSize
, HiiPackageListHeader
.PackageLength
);
1737 if (HiiSectionHeader
== NULL
) {
1738 free (HiiPackageListBuffer
);
1742 // Wrtie section header and HiiData into File.
1744 fwrite (HiiSectionHeader
, 1, HiiSectionHeaderSize
, fpOut
);
1745 fwrite (HiiPackageListBuffer
, 1, HiiPackageListHeader
.PackageLength
, fpOut
);
1747 // Free allocated resources.
1749 free (HiiSectionHeader
);
1750 free (HiiPackageListBuffer
);
1752 // Done successfully
1758 // write the hii package into the text package list rc file.
1760 if (mOutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) {
1761 for (Index
= 0; gHiiPackageRCFileHeader
[Index
] != NULL
; Index
++) {
1762 fprintf (fpOut
, "%s\n", gHiiPackageRCFileHeader
[Index
]);
1764 fprintf (fpOut
, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX
, HII_RESOURCE_SECTION_NAME
);
1766 HiiPackageDataPointer
= HiiPackageListBuffer
;
1767 for (Index
= 0; Index
+ 2 < HiiPackageListHeader
.PackageLength
; Index
+= 2) {
1768 if (Index
% 16 == 0) {
1769 fprintf (fpOut
, "\n ");
1771 fprintf (fpOut
, " 0x%04X,", *(UINT16
*) HiiPackageDataPointer
);
1772 HiiPackageDataPointer
+= 2;
1775 if (Index
% 16 == 0) {
1776 fprintf (fpOut
, "\n ");
1778 if ((Index
+ 2) == HiiPackageListHeader
.PackageLength
) {
1779 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT16
*) HiiPackageDataPointer
);
1781 if ((Index
+ 1) == HiiPackageListHeader
.PackageLength
) {
1782 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT8
*) HiiPackageDataPointer
);
1784 free (HiiPackageListBuffer
);
1786 // Done successfully
1793 // Combine MciBinary files to one file
1795 if (mOutImageType
== FW_MERGE_IMAGE
) {
1797 // Open output file handle.
1799 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
1801 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1804 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1805 fpIn
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
1807 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1811 FileLength
= _filelength (fileno (fpIn
));
1812 FileBuffer
= malloc (FileLength
);
1813 if (FileBuffer
== NULL
) {
1814 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1819 fread (FileBuffer
, 1, FileLength
, fpIn
);
1822 // write input file to out file
1824 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
1826 // write pad value to out file.
1828 while (FileLength
++ % MciAlignment
!= 0) {
1829 fwrite (&MciPadValue
, 1, 1, fpOut
);
1832 // free allocated memory space
1838 // Done successfully
1844 // Convert MicroCode.txt file to MicroCode.bin file
1846 if (mOutImageType
== FW_MCI_IMAGE
) {
1847 fpIn
= fopen (LongFilePath (mInImageName
), "r");
1849 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1854 // The first pass is to determine
1855 // how much data is in the file so we can allocate a working buffer.
1859 Status
= MicrocodeReadData (fpIn
, &Data
);
1860 if (Status
== STATUS_SUCCESS
) {
1861 FileLength
+= sizeof (Data
);
1863 if (Status
== STATUS_IGNORE
) {
1864 Status
= STATUS_SUCCESS
;
1866 } while (Status
== STATUS_SUCCESS
);
1868 // Error if no data.
1870 if (FileLength
== 0) {
1871 Error (NULL
, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName
);
1874 if (FileLength
< sizeof (MICROCODE_IMAGE_HEADER
)) {
1875 Error (NULL
, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName
);
1880 // Allocate a buffer for the data
1882 FileBuffer
= malloc (FileLength
);
1883 if (FileBuffer
== NULL
) {
1884 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1888 // Re-read the file, storing the data into our buffer
1890 fseek (fpIn
, 0, SEEK_SET
);
1891 DataPointer
= (UINT32
*) FileBuffer
;
1892 OldDataPointer
= DataPointer
;
1894 OldDataPointer
= DataPointer
;
1895 Status
= MicrocodeReadData (fpIn
, DataPointer
++);
1896 if (Status
== STATUS_IGNORE
) {
1897 DataPointer
= OldDataPointer
;
1898 Status
= STATUS_SUCCESS
;
1900 } while (Status
== STATUS_SUCCESS
);
1902 // close input file after read data
1907 // Can't do much checking on the header because, per the spec, the
1908 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
1909 // and the TotalSize field is invalid (actually missing). Thus we can't
1910 // even verify the Reserved fields are 0.
1912 MciHeader
= (MICROCODE_IMAGE_HEADER
*) FileBuffer
;
1913 if (MciHeader
->DataSize
== 0) {
1916 Index
= MciHeader
->TotalSize
;
1919 if (Index
!= FileLength
) {
1920 Error (NULL
, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName
, (unsigned) FileLength
, (unsigned) Index
);
1925 // Checksum the contents
1927 DataPointer
= (UINT32
*) FileBuffer
;
1930 while (Index
< FileLength
) {
1931 CheckSum
+= *DataPointer
;
1933 Index
+= sizeof (*DataPointer
);
1935 if (CheckSum
!= 0) {
1936 Error (NULL
, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum
, mInImageName
);
1940 // Open the output file and write the buffer contents
1942 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
1947 // Open input file and read file data into file buffer.
1949 FileLength
= InputFileLength
;
1950 FileBuffer
= malloc (FileLength
);
1951 if (FileBuffer
== NULL
) {
1952 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1955 memcpy (FileBuffer
, InputFileBuffer
, InputFileLength
);
1958 // Dump TeImage Header into output file.
1960 if (mOutImageType
== DUMP_TE_HEADER
) {
1961 memcpy (&TEImageHeader
, FileBuffer
, sizeof (TEImageHeader
));
1962 if (TEImageHeader
.Signature
!= EFI_TE_IMAGE_HEADER_SIGNATURE
) {
1963 Error (NULL
, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName
);
1967 // Open the output file handle.
1970 fpInOut
= fopen (LongFilePath (mInImageName
), "wb");
1971 if (fpInOut
== NULL
) {
1972 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1976 if (OutImageName
!= NULL
) {
1977 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
1981 if (fpOut
== NULL
) {
1982 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1986 if (fpInOut
!= NULL
) {
1987 fprintf (fpInOut
, "Dump of file %s\n\n", mInImageName
);
1988 fprintf (fpInOut
, "TE IMAGE HEADER VALUES\n");
1989 fprintf (fpInOut
, "%17X machine\n", TEImageHeader
.Machine
);
1990 fprintf (fpInOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
1991 fprintf (fpInOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
1992 fprintf (fpInOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
1993 fprintf (fpInOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
1994 fprintf (fpInOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
1995 fprintf (fpInOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
1996 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
1997 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
1999 if (fpOut
!= NULL
) {
2000 fprintf (fpOut
, "Dump of file %s\n\n", mInImageName
);
2001 fprintf (fpOut
, "TE IMAGE HEADER VALUES\n");
2002 fprintf (fpOut
, "%17X machine\n", TEImageHeader
.Machine
);
2003 fprintf (fpOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
2004 fprintf (fpOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
2005 fprintf (fpOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
2006 fprintf (fpOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
2007 fprintf (fpOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
2008 fprintf (fpOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
2009 fprintf (fpOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
2010 fprintf (fpOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
2016 // Following code to convert dll to efi image or te image.
2017 // Get new image type
2019 if ((mOutImageType
== FW_EFI_IMAGE
) || (mOutImageType
== FW_TE_IMAGE
)) {
2020 if (ModuleType
== NULL
) {
2021 if (mOutImageType
== FW_EFI_IMAGE
) {
2022 Error (NULL
, 0, 1001, "Missing option", "EFI_FILETYPE");
2024 } else if (mOutImageType
== FW_TE_IMAGE
) {
2026 // Default TE Image Type is Boot service driver
2028 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2029 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2032 if (stricmp (ModuleType
, "BASE") == 0 ||
2033 stricmp (ModuleType
, "SEC") == 0 ||
2034 stricmp (ModuleType
, "SECURITY_CORE") == 0 ||
2035 stricmp (ModuleType
, "PEI_CORE") == 0 ||
2036 stricmp (ModuleType
, "PEIM") == 0 ||
2037 stricmp (ModuleType
, "COMBINED_PEIM_DRIVER") == 0 ||
2038 stricmp (ModuleType
, "PIC_PEIM") == 0 ||
2039 stricmp (ModuleType
, "RELOCATABLE_PEIM") == 0 ||
2040 stricmp (ModuleType
, "DXE_CORE") == 0 ||
2041 stricmp (ModuleType
, "BS_DRIVER") == 0 ||
2042 stricmp (ModuleType
, "DXE_DRIVER") == 0 ||
2043 stricmp (ModuleType
, "DXE_SMM_DRIVER") == 0 ||
2044 stricmp (ModuleType
, "UEFI_DRIVER") == 0 ||
2045 stricmp (ModuleType
, "SMM_CORE") == 0 ||
2046 stricmp (ModuleType
, "MM_STANDALONE") == 0 ||
2047 stricmp (ModuleType
, "MM_CORE_STANDALONE") == 0) {
2048 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2049 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2051 } else if (stricmp (ModuleType
, "UEFI_APPLICATION") == 0 ||
2052 stricmp (ModuleType
, "APPLICATION") == 0) {
2053 Type
= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
;
2054 VerboseMsg ("Efi Image subsystem type is efi application.");
2056 } else if (stricmp (ModuleType
, "DXE_RUNTIME_DRIVER") == 0 ||
2057 stricmp (ModuleType
, "RT_DRIVER") == 0) {
2058 Type
= EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
;
2059 VerboseMsg ("Efi Image subsystem type is efi runtime driver.");
2061 } else if (stricmp (ModuleType
, "DXE_SAL_DRIVER") == 0 ||
2062 stricmp (ModuleType
, "SAL_RT_DRIVER") == 0) {
2063 Type
= EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
;
2064 VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");
2067 Error (NULL
, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType
);
2074 // Convert ELF image to PeImage
2076 if (IsElfHeader(FileBuffer
)) {
2077 VerboseMsg ("Convert %s from ELF to PE/COFF.", mInImageName
);
2078 if (!ConvertElf(&FileBuffer
, &FileLength
)) {
2079 Error (NULL
, 0, 3000, "Invalid", "Unable to convert %s from ELF to PE/COFF.", mInImageName
);
2085 // Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP
2086 // XIP == eXecute In Place
2088 PeCoffConvertImageToXip (&FileBuffer
, &FileLength
);
2091 // Remove reloc section from PE or TE image
2093 if (mOutImageType
== FW_RELOC_STRIPEED_IMAGE
) {
2097 TeHdr
= (EFI_TE_IMAGE_HEADER
*) FileBuffer
;
2098 if (TeHdr
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2099 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (TeHdr
+ 1);
2100 for (Index
= 0; Index
< TeHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2101 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2103 // Check the reloc section is in the end of image.
2105 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) ==
2106 (FileLength
+ TeHdr
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
))) {
2108 // Remove .reloc section and update TeImage Header
2110 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2111 SectionHeader
->SizeOfRawData
= 0;
2112 SectionHeader
->Misc
.VirtualSize
= 0;
2113 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2114 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2123 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2124 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2125 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2126 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2127 Error (NULL
, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName
);
2132 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2133 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2134 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2138 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2139 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2140 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2142 // Check the reloc section is in the end of image.
2144 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) == FileLength
) {
2146 // Remove .reloc section and update PeImage Header
2148 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2150 PeHdr
->Pe32
.FileHeader
.Characteristics
|= EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2151 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2152 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2153 Optional32
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2154 Optional32
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2155 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2156 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2157 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2160 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2161 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2162 Optional64
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2163 Optional64
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2164 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2165 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2166 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2169 SectionHeader
->Misc
.VirtualSize
= 0;
2170 SectionHeader
->SizeOfRawData
= 0;
2182 // Read the dos & pe hdrs of the image
2184 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2185 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2186 // NO DOS header, check for PE/COFF header
2187 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2188 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2189 Error (NULL
, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName
);
2195 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2196 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2197 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2202 if (PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_ARM
) {
2203 // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
2204 // so patch back to the official UEFI value.
2205 PeHdr
->Pe32
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_ARMT
;
2209 // Set new base address into image
2211 if (mOutImageType
== FW_REBASE_IMAGE
|| mOutImageType
== FW_SET_ADDRESS_IMAGE
) {
2212 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2213 if (NewBaseAddress
>= 0x100000000ULL
) {
2214 Error (NULL
, 0, 3000, "Invalid", "New base address is larger than 4G for 32bit PE image");
2221 // Set Base Address to a negative value.
2223 NewBaseAddress
= (UINT64
) (0 - NewBaseAddress
);
2225 if (mOutImageType
== FW_REBASE_IMAGE
) {
2226 Status
= RebaseImage (mInImageName
, FileBuffer
, NewBaseAddress
);
2228 Status
= SetAddressToSectionHeader (mInImageName
, FileBuffer
, NewBaseAddress
);
2230 if (EFI_ERROR (Status
)) {
2232 Error (NULL
, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address -0x%llx can't success", mInImageName
, 0 - NewBaseAddress
);
2234 Error (NULL
, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address 0x%llx can't success", mInImageName
, NewBaseAddress
);
2246 // Extract bin data from Pe image.
2248 if (mOutImageType
== FW_BIN_IMAGE
) {
2249 if (FileLength
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
2250 Error (NULL
, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName
);
2254 // Output bin data from exe file
2256 FileLength
= FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
;
2257 memmove (FileBuffer
, FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, FileLength
);
2258 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2263 // Zero Debug Information of Pe Image
2265 if (mOutImageType
== FW_ZERO_DEBUG_IMAGE
) {
2266 Status
= ZeroDebugData (FileBuffer
, TRUE
);
2267 if (EFI_ERROR (Status
)) {
2268 Error (NULL
, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status
);
2273 // Write the updated Image
2275 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2280 // Set Time Stamp of Pe Image
2282 if (mOutImageType
== FW_SET_STAMP_IMAGE
) {
2283 Status
= SetStamp (FileBuffer
, TimeStamp
);
2284 if (EFI_ERROR (Status
)) {
2289 // Write the updated Image
2291 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2296 // Extract acpi data from pe image.
2298 if (mOutImageType
== FW_ACPI_IMAGE
) {
2299 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2300 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2301 if (strcmp ((char *)SectionHeader
->Name
, ".data") == 0 || strcmp ((char *)SectionHeader
->Name
, ".sdata") == 0) {
2305 if (SectionHeader
->Misc
.VirtualSize
< SectionHeader
->SizeOfRawData
) {
2306 FileLength
= SectionHeader
->Misc
.VirtualSize
;
2308 FileLength
= SectionHeader
->SizeOfRawData
;
2311 if (CheckAcpiTable (FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
) != STATUS_SUCCESS
) {
2312 Error (NULL
, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName
);
2317 // Output Apci data to file
2319 memmove (FileBuffer
, FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
);
2320 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2324 Error (NULL
, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName
);
2328 // Zero all unused fields of the DOS header
2330 if (DosHdr
!= NULL
) {
2331 memcpy (&BackupDosHdr
, DosHdr
, sizeof (EFI_IMAGE_DOS_HEADER
));
2332 memset (DosHdr
, 0, sizeof (EFI_IMAGE_DOS_HEADER
));
2333 DosHdr
->e_magic
= BackupDosHdr
.e_magic
;
2334 DosHdr
->e_lfanew
= BackupDosHdr
.e_lfanew
;
2336 for (Index
= sizeof (EFI_IMAGE_DOS_HEADER
); Index
< (UINT32
) DosHdr
->e_lfanew
; Index
++) {
2337 FileBuffer
[Index
] = (UINT8
) DosHdr
->e_cp
;
2342 // Initialize TeImage Header
2344 memset (&TEImageHeader
, 0, sizeof (EFI_TE_IMAGE_HEADER
));
2345 TEImageHeader
.Signature
= EFI_TE_IMAGE_HEADER_SIGNATURE
;
2346 TEImageHeader
.Machine
= PeHdr
->Pe32
.FileHeader
.Machine
;
2347 TEImageHeader
.NumberOfSections
= (UINT8
) PeHdr
->Pe32
.FileHeader
.NumberOfSections
;
2348 TEImageHeader
.StrippedSize
= (UINT16
) ((UINTN
) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
) - (UINTN
) FileBuffer
);
2349 TEImageHeader
.Subsystem
= (UINT8
) Type
;
2352 // Patch the PE header
2354 PeHdr
->Pe32
.OptionalHeader
.Subsystem
= (UINT16
) Type
;
2356 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2357 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2358 if (!KeepOptionalHeaderFlag
) {
2359 Optional32
->MajorOperatingSystemVersion
= 0;
2360 Optional32
->MinorOperatingSystemVersion
= 0;
2361 Optional32
->MajorImageVersion
= 0;
2362 Optional32
->MinorImageVersion
= 0;
2363 Optional32
->MajorSubsystemVersion
= 0;
2364 Optional32
->MinorSubsystemVersion
= 0;
2365 Optional32
->Win32VersionValue
= 0;
2366 Optional32
->CheckSum
= 0;
2367 Optional32
->SizeOfStackReserve
= 0;
2368 Optional32
->SizeOfStackCommit
= 0;
2369 Optional32
->SizeOfHeapReserve
= 0;
2370 Optional32
->SizeOfHeapCommit
= 0;
2372 TEImageHeader
.AddressOfEntryPoint
= Optional32
->AddressOfEntryPoint
;
2373 TEImageHeader
.BaseOfCode
= Optional32
->BaseOfCode
;
2374 TEImageHeader
.ImageBase
= (UINT64
) (Optional32
->ImageBase
);
2376 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2377 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2378 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2381 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2382 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2383 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2387 // Zero .pdata section data.
2389 if (!KeepExceptionTableFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2390 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2391 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2392 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2393 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2394 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2396 // Zero .pdata Section data
2398 memset (FileBuffer
+ SectionHeader
->PointerToRawData
, 0, SectionHeader
->SizeOfRawData
);
2400 // Zero .pdata Section header name
2402 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2404 // Zero Exception Table
2406 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2407 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2408 DebugMsg (NULL
, 0, 9, "Zero the .pdata section for PE image", NULL
);
2415 // Strip zero padding at the end of the .reloc section
2417 if (!KeepZeroPendingFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2418 if (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2419 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2420 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2422 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2424 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2425 SectionHeader
->Misc
.VirtualSize
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2426 AllignedRelocSize
= (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional32
->FileAlignment
- 1) & (~(Optional32
->FileAlignment
- 1));
2428 // Check to see if there is zero padding at the end of the base relocations
2430 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2432 // Check to see if the base relocations are at the end of the file
2434 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional32
->SizeOfImage
) {
2436 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2438 Optional32
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2439 Optional32
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2440 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2441 FileLength
= Optional32
->SizeOfImage
;
2442 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
));
2449 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2450 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2451 if (!KeepOptionalHeaderFlag
) {
2452 Optional64
->MajorOperatingSystemVersion
= 0;
2453 Optional64
->MinorOperatingSystemVersion
= 0;
2454 Optional64
->MajorImageVersion
= 0;
2455 Optional64
->MinorImageVersion
= 0;
2456 Optional64
->MajorSubsystemVersion
= 0;
2457 Optional64
->MinorSubsystemVersion
= 0;
2458 Optional64
->Win32VersionValue
= 0;
2459 Optional64
->CheckSum
= 0;
2460 Optional64
->SizeOfStackReserve
= 0;
2461 Optional64
->SizeOfStackCommit
= 0;
2462 Optional64
->SizeOfHeapReserve
= 0;
2463 Optional64
->SizeOfHeapCommit
= 0;
2465 TEImageHeader
.AddressOfEntryPoint
= Optional64
->AddressOfEntryPoint
;
2466 TEImageHeader
.BaseOfCode
= Optional64
->BaseOfCode
;
2467 TEImageHeader
.ImageBase
= (UINT64
) (Optional64
->ImageBase
);
2469 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2470 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2471 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2474 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2475 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2476 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2480 // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
2481 // For Itaninum and X64 Image, remove .pdata section.
2483 if ((!KeepExceptionTableFlag
&& PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_X64
)) {
2484 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2485 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2486 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2487 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2488 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2489 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2491 // Zero .pdata Section header name
2493 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2495 RuntimeFunction
= (RUNTIME_FUNCTION
*)(FileBuffer
+ SectionHeader
->PointerToRawData
);
2496 for (Index1
= 0; Index1
< Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
/ sizeof (RUNTIME_FUNCTION
); Index1
++, RuntimeFunction
++) {
2497 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2498 for (Index2
= 0; Index2
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index2
++, SectionHeader
++) {
2499 if (RuntimeFunction
->UnwindInfoAddress
>= SectionHeader
->VirtualAddress
&& RuntimeFunction
->UnwindInfoAddress
< (SectionHeader
->VirtualAddress
+ SectionHeader
->SizeOfRawData
)) {
2500 UnwindInfo
= (UNWIND_INFO
*)(FileBuffer
+ SectionHeader
->PointerToRawData
+ (RuntimeFunction
->UnwindInfoAddress
- SectionHeader
->VirtualAddress
));
2501 if (UnwindInfo
->Version
== 1) {
2502 memset (UnwindInfo
+ 1, 0, UnwindInfo
->CountOfUnwindCodes
* sizeof (UINT16
));
2503 memset (UnwindInfo
, 0, sizeof (UNWIND_INFO
));
2508 memset (RuntimeFunction
, 0, sizeof (RUNTIME_FUNCTION
));
2511 // Zero Exception Table
2513 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2514 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2515 DebugMsg (NULL
, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL
);
2523 // Strip zero padding at the end of the .reloc section
2525 if (!KeepZeroPendingFlag
&& Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2526 if (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2527 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2528 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2530 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2532 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2533 SectionHeader
->Misc
.VirtualSize
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2534 AllignedRelocSize
= (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional64
->FileAlignment
- 1) & (~(Optional64
->FileAlignment
- 1));
2536 // Check to see if there is zero padding at the end of the base relocations
2538 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2540 // Check to see if the base relocations are at the end of the file
2542 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional64
->SizeOfImage
) {
2544 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2546 Optional64
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2547 Optional64
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2548 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2549 FileLength
= Optional64
->SizeOfImage
;
2550 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
));
2558 Error (NULL
, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr
->Pe32
.OptionalHeader
.Magic
, mInImageName
);
2562 if (((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) == 0) && \
2563 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
== 0) && \
2564 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
== 0)) {
2566 // PeImage can be loaded into memory, but it has no relocation section.
2567 // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
2569 if (Optional32
!= NULL
) {
2570 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
2571 } else if (Optional64
!= NULL
) {
2572 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
2577 // Fill HII section data
2579 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2580 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++) {
2581 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".hii") == 0) {
2583 // Update resource section header offset
2585 SetHiiResourceHeader ((UINT8
*) FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, SectionHeader
[Index
].VirtualAddress
);
2587 // Update resource section name
2589 strcpy((char *) SectionHeader
[Index
].Name
, ".rsrc");
2591 // Update resource data directory.
2593 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2594 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2595 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= SectionHeader
[Index
].VirtualAddress
;
2596 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= SectionHeader
[Index
].Misc
.VirtualSize
;
2597 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2598 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2599 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= SectionHeader
[Index
].VirtualAddress
;
2600 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= SectionHeader
[Index
].Misc
.VirtualSize
;
2607 // Zero ExceptionTable Xdata
2609 if (!KeepExceptionTableFlag
) {
2610 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2611 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++) {
2612 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".xdata") == 0) {
2614 // zero .xdata section
2616 memset (FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, 0, SectionHeader
[Index
].SizeOfRawData
);
2617 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
);
2624 // Zero Time/Data field
2626 ZeroDebugData (FileBuffer
, ZeroDebugFlag
);
2628 if (mOutImageType
== FW_TE_IMAGE
) {
2629 if ((PeHdr
->Pe32
.FileHeader
.NumberOfSections
&~0xFF) || (Type
&~0xFF)) {
2631 // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
2633 Error (NULL
, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName
);
2637 if ((PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
)) {
2639 // TeImage has the same section alignment and file alignment.
2641 Error (NULL
, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName
);
2645 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",
2646 TEImageHeader
.Machine
, TEImageHeader
.NumberOfSections
, TEImageHeader
.StrippedSize
, (unsigned) TEImageHeader
.AddressOfEntryPoint
, (unsigned) TEImageHeader
.BaseOfCode
, (unsigned long long) TEImageHeader
.ImageBase
);
2648 // Update Image to TeImage
2650 FileLength
= FileLength
- TEImageHeader
.StrippedSize
;
2651 memmove (FileBuffer
+ sizeof (EFI_TE_IMAGE_HEADER
), FileBuffer
+ TEImageHeader
.StrippedSize
, FileLength
);
2652 FileLength
= FileLength
+ sizeof (EFI_TE_IMAGE_HEADER
);
2653 memcpy (FileBuffer
, &TEImageHeader
, sizeof (EFI_TE_IMAGE_HEADER
));
2654 VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength
));
2658 // Following codes are to fix the objcopy's issue:
2659 // objcopy in binutil 2.50.18 will set PE image's charactices to "RELOC_STRIPPED" if image has no ".reloc" section
2660 // It cause issue for EFI image which has no ".reloc" sections.
2661 // Following codes will be removed when objcopy in binutil fix this problem for PE image.
2663 if ((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) != 0) {
2664 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2665 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2666 if (Optional32
->ImageBase
== 0) {
2667 PeHdr
->Pe32
.FileHeader
.Characteristics
&= ~EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2669 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2670 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2671 if (Optional64
->ImageBase
== 0) {
2672 PeHdr
->Pe32
.FileHeader
.Characteristics
&= ~EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2680 // Update Image to EfiImage or TE image
2683 if ((FileLength
!= InputFileLength
) || (memcmp (FileBuffer
, InputFileBuffer
, FileLength
) != 0)) {
2685 // Update File when File is changed.
2687 fpInOut
= fopen (LongFilePath (mInImageName
), "wb");
2688 if (fpInOut
== NULL
) {
2689 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2692 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2693 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2696 if ((OutputFileTime
< InputFileTime
) || (FileLength
!= OutputFileLength
) || (memcmp (FileBuffer
, OutputFileBuffer
, FileLength
) != 0)) {
2698 // Update File when File is changed or File is old.
2700 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
2701 if (fpOut
== NULL
) {
2702 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
2705 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2706 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2709 mImageSize
= FileLength
;
2712 if (fpInOut
!= NULL
) {
2713 if (GetUtilityStatus () != STATUS_SUCCESS
) {
2715 // when file updates failed, original file is still recovered.
2717 fwrite (InputFileBuffer
, 1, InputFileLength
, fpInOut
);
2720 // Write converted data into fpInOut file and close input file.
2725 if (FileBuffer
!= NULL
) {
2729 if (InputFileName
!= NULL
) {
2730 free (InputFileName
);
2733 if (fpOut
!= NULL
) {
2735 // Write converted data into fpOut file and close output file.
2738 if (GetUtilityStatus () != STATUS_SUCCESS
) {
2739 if (OutputFileBuffer
== NULL
) {
2740 remove (OutImageName
);
2742 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
2743 fwrite (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
2749 if (InputFileBuffer
!= NULL
) {
2750 free (InputFileBuffer
);
2753 if (OutputFileBuffer
!= NULL
) {
2754 free (OutputFileBuffer
);
2758 // Write module size and time stamp to report file.
2760 if (OutImageName
!= NULL
) {
2761 FileLen
= strlen (OutImageName
);
2763 if (FileLen
>= 4 && strcmp (OutImageName
+ (FileLen
- 4), ".efi") == 0) {
2764 ReportFileName
= (CHAR8
*) malloc (FileLen
+ 1);
2765 if (ReportFileName
!= NULL
) {
2766 strcpy (ReportFileName
, OutImageName
);
2767 strcpy (ReportFileName
+ (FileLen
- 4), ".txt");
2768 ReportFile
= fopen (LongFilePath (ReportFileName
), "w+");
2769 if (ReportFile
!= NULL
) {
2770 fprintf (ReportFile
, "MODULE_SIZE = %u\n", (unsigned) mImageSize
);
2771 fprintf (ReportFile
, "TIME_STAMP = %u\n", (unsigned) mImageTimeStamp
);
2774 free (ReportFileName
);
2777 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
2779 return GetUtilityStatus ();
2785 IN OUT UINT8
*FileBuffer
,
2786 BOOLEAN ZeroDebugFlag
2790 Routine Description:
2792 Zero debug information in PeImage.
2796 FileBuffer - Pointer to PeImage.
2797 ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp
2801 EFI_ABORTED - PeImage is invalid.
2802 EFI_SUCCESS - Zero debug data successfully.
2807 UINT32 DebugDirectoryEntryRva
;
2808 UINT32 DebugDirectoryEntrySize
;
2809 UINT32 DebugDirectoryEntryFileOffset
;
2810 UINT32 ExportDirectoryEntryRva
;
2811 UINT32 ExportDirectoryEntryFileOffset
;
2812 UINT32 ResourceDirectoryEntryRva
;
2813 UINT32 ResourceDirectoryEntryFileOffset
;
2814 EFI_IMAGE_DOS_HEADER
*DosHdr
;
2815 EFI_IMAGE_FILE_HEADER
*FileHdr
;
2816 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
2817 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
2818 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
2819 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
2820 EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
*RsdsEntry
;
2821 UINT32
*NewTimeStamp
;
2826 DebugDirectoryEntryRva
= 0;
2827 DebugDirectoryEntrySize
= 0;
2828 ExportDirectoryEntryRva
= 0;
2829 ResourceDirectoryEntryRva
= 0;
2830 DebugDirectoryEntryFileOffset
= 0;
2831 ExportDirectoryEntryFileOffset
= 0;
2832 ResourceDirectoryEntryFileOffset
= 0;
2833 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2834 FileHdr
= (EFI_IMAGE_FILE_HEADER
*) (FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2837 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2838 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2839 // NO DOS header, must start with PE/COFF header
2840 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
2842 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2846 // Get Debug, Export and Resource EntryTable RVA address.
2847 // Resource Directory entry need to review.
2849 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2850 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2851 if (Optional32Hdr
->Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2852 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2853 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2854 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2855 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2857 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2858 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2859 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2861 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2862 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2863 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2864 DebugDirectoryEntrySize
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2865 if (ZeroDebugFlag
) {
2866 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
2867 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
2871 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2872 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2873 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2874 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2876 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2877 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2878 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2880 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2881 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2882 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2883 DebugDirectoryEntrySize
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2884 if (ZeroDebugFlag
) {
2885 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
2886 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
2892 // Get DirectoryEntryTable file offset.
2894 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2895 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2896 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2897 DebugDirectoryEntryFileOffset
=
2898 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2900 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2901 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2902 ExportDirectoryEntryFileOffset
=
2903 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2905 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2906 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2907 ResourceDirectoryEntryFileOffset
=
2908 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2913 //Zero Debug Data and TimeStamp
2915 FileHdr
->TimeDateStamp
= 0;
2916 mImageTimeStamp
= 0;
2917 if (ExportDirectoryEntryFileOffset
!= 0) {
2918 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
2922 if (ResourceDirectoryEntryFileOffset
!= 0) {
2923 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
2927 if (DebugDirectoryEntryFileOffset
!= 0) {
2928 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
);
2930 for (Index
=0; Index
< DebugDirectoryEntrySize
/ sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
); Index
++, DebugEntry
++) {
2931 DebugEntry
->TimeDateStamp
= 0;
2932 if (mIsConvertXip
) {
2933 DebugEntry
->FileOffset
= DebugEntry
->RVA
;
2935 if (ZeroDebugFlag
|| DebugEntry
->Type
!= EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
2936 memset (FileBuffer
+ DebugEntry
->FileOffset
, 0, DebugEntry
->SizeOfData
);
2937 memset (DebugEntry
, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
2939 if (DebugEntry
->Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
2940 RsdsEntry
= (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
*) (FileBuffer
+ DebugEntry
->FileOffset
);
2941 if (RsdsEntry
->Signature
== CODEVIEW_SIGNATURE_MTOC
) {
2942 // MTOC sets DebugDirectoryEntrySize to size of the .debug section, so fix it.
2943 if (!ZeroDebugFlag
) {
2944 if (Optional32Hdr
->Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2945 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
2947 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
2962 IN OUT UINT8
*FileBuffer
,
2967 Routine Description:
2969 Set new time stamp into PeImage FileHdr and Directory table:
2970 Debug, Export and Resource.
2974 FileBuffer - Pointer to PeImage.
2975 TimeStamp - Time stamp string.
2979 EFI_INVALID_PARAMETER - TimeStamp format is not recognized.
2980 EFI_SUCCESS - Set new time stamp in this image successfully.
2988 UINT32 DebugDirectoryEntryRva
;
2989 UINT32 DebugDirectoryEntryFileOffset
;
2990 UINT32 ExportDirectoryEntryRva
;
2991 UINT32 ExportDirectoryEntryFileOffset
;
2992 UINT32 ResourceDirectoryEntryRva
;
2993 UINT32 ResourceDirectoryEntryFileOffset
;
2994 EFI_IMAGE_DOS_HEADER
*DosHdr
;
2995 EFI_IMAGE_FILE_HEADER
*FileHdr
;
2996 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
2997 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
2998 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
2999 UINT32
*NewTimeStamp
;
3004 DebugDirectoryEntryRva
= 0;
3005 DebugDirectoryEntryFileOffset
= 0;
3006 ExportDirectoryEntryRva
= 0;
3007 ExportDirectoryEntryFileOffset
= 0;
3008 ResourceDirectoryEntryRva
= 0;
3009 ResourceDirectoryEntryFileOffset
= 0;
3011 // Get time and date that will be set.
3013 if (TimeStamp
== NULL
) {
3014 Error (NULL
, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");
3015 return EFI_INVALID_PARAMETER
;
3018 // compare the value with "NOW", if yes, current system time is set.
3020 if (stricmp (TimeStamp
, "NOW") == 0) {
3022 // get system current time and date
3027 // Check Time Format strictly yyyy-mm-dd 00:00:00
3029 for (Index
= 0; TimeStamp
[Index
] != '\0' && Index
< 20; Index
++) {
3030 if (Index
== 4 || Index
== 7) {
3031 if (TimeStamp
[Index
] == '-') {
3034 } else if (Index
== 13 || Index
== 16) {
3035 if (TimeStamp
[Index
] == ':') {
3038 } else if (Index
== 10 && TimeStamp
[Index
] == ' ') {
3040 } else if ((TimeStamp
[Index
] < '0') || (TimeStamp
[Index
] > '9')) {
3045 if (Index
< 19 || TimeStamp
[19] != '\0') {
3046 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
3047 return EFI_INVALID_PARAMETER
;
3051 // get the date and time from TimeStamp
3053 if (sscanf (TimeStamp
, "%d-%d-%d %d:%d:%d",
3061 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
3062 return EFI_INVALID_PARAMETER
;
3066 // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
3068 if (stime
.tm_mon
<= 0 || stime
.tm_mday
<=0) {
3069 Error (NULL
, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp
);
3070 return EFI_INVALID_PARAMETER
;
3075 // in struct, Year (current year minus 1900)
3076 // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
3079 // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
3081 if (stime
.tm_year
>= 1970 && stime
.tm_year
<= 2038) {
3083 // convert 1970 -> 70, 2000 -> 100, ...
3085 stime
.tm_year
-= 1900;
3087 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
3088 return EFI_INVALID_PARAMETER
;
3092 // convert the date and time to time_t format
3094 newtime
= mktime (&stime
);
3095 if (newtime
== (time_t) - 1) {
3096 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
3097 return EFI_INVALID_PARAMETER
;
3101 ptime
= localtime (&newtime
);
3102 if (ptime
!= NULL
) {
3103 DebugMsg (NULL
, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",
3104 ptime
->tm_year
+ 1900, ptime
->tm_mon
+ 1, ptime
->tm_mday
, ptime
->tm_hour
, ptime
->tm_min
, ptime
->tm_sec
);
3107 // Set new time and data into PeImage.
3109 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
3110 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
3111 // NO DOS header, must start with PE/COFF header
3112 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
3114 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
3118 // Get Debug, Export and Resource EntryTable RVA address.
3119 // Resource Directory entry need to review.
3121 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
3122 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3123 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3124 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3125 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3126 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3128 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3129 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3130 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3132 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3133 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3134 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3137 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3138 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3139 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3140 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3141 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3143 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3144 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3145 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3147 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3148 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3149 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3154 // Get DirectoryEntryTable file offset.
3156 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
3157 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3158 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3159 DebugDirectoryEntryFileOffset
=
3160 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3162 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3163 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3164 ExportDirectoryEntryFileOffset
=
3165 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3167 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3168 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3169 ResourceDirectoryEntryFileOffset
=
3170 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3177 FileHdr
->TimeDateStamp
= (UINT32
) newtime
;
3178 mImageTimeStamp
= (UINT32
) newtime
;
3179 if (ExportDirectoryEntryRva
!= 0) {
3180 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
3181 *NewTimeStamp
= (UINT32
) newtime
;
3184 if (ResourceDirectoryEntryRva
!= 0) {
3185 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
3186 *NewTimeStamp
= (UINT32
) newtime
;
3189 if (DebugDirectoryEntryRva
!= 0) {
3190 NewTimeStamp
= (UINT32
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
+ sizeof (UINT32
));
3191 *NewTimeStamp
= (UINT32
) newtime
;
3205 Routine Description:
3206 Read a 32-bit microcode data value from a text file and convert to raw binary form.
3209 InFptr - file pointer to input text file
3210 Data - pointer to where to return the data parsed
3213 STATUS_SUCCESS - no errors or warnings, Data contains valid information
3214 STATUS_ERROR - errors were encountered
3218 CHAR8 Line
[MAX_LINE_LEN
];
3220 int ScannedData
= 0;
3222 Line
[MAX_LINE_LEN
- 1] = 0;
3224 if (fgets (Line
, MAX_LINE_LEN
, InFptr
) == NULL
) {
3225 return STATUS_ERROR
;
3228 // If it was a binary file, then it may have overwritten our null terminator
3230 if (Line
[MAX_LINE_LEN
- 1] != 0) {
3231 return STATUS_ERROR
;
3237 for (cptr
= Line
; *cptr
&& isspace((int)*cptr
); cptr
++) {
3240 // Skip Blank Lines and Comment Lines
3241 if ((strlen(cptr
) != 0) && (*cptr
!= ';')) {
3247 // dd 000000001h ; comment
3252 if ((tolower((int)cptr
[0]) == 'd') && (tolower((int)cptr
[1]) == 'd') && isspace ((int)cptr
[2])) {
3254 // Skip blanks and look for a hex digit
3257 for (; *cptr
&& isspace((int)*cptr
); cptr
++) {
3259 if (isxdigit ((int)*cptr
)) {
3260 if (sscanf (cptr
, "%X", &ScannedData
) != 1) {
3261 return STATUS_ERROR
;
3264 *Data
= (UINT32
) ScannedData
;
3265 return STATUS_SUCCESS
;
3268 return STATUS_ERROR
;