2 Converts a pe32+ image to an FW, Te image type, or other specific image.
4 Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "WinNtInclude.h"
20 #include <sys/types.h>
29 #include <Common/UefiBaseTypes.h>
30 #include <IndustryStandard/PeImage.h>
31 #include <Common/UefiInternalFormRepresentation.h>
34 // Acpi Table definition
36 #include <IndustryStandard/Acpi.h>
37 #include <IndustryStandard/Acpi1_0.h>
38 #include <IndustryStandard/Acpi2_0.h>
39 #include <IndustryStandard/Acpi3_0.h>
40 #include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
42 #include "CommonLib.h"
43 #include "PeCoffLib.h"
45 #include "EfiUtilityMsgs.h"
50 // Version of this utility
52 #define UTILITY_NAME "GenFw"
53 #define UTILITY_MAJOR_VERSION 0
54 #define UTILITY_MINOR_VERSION 2
56 #define HII_RESOURCE_SECTION_INDEX 1
57 #define HII_RESOURCE_SECTION_NAME "HII"
59 #define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
60 #define DEFAULT_MC_ALIGNMENT 16
62 #define STATUS_IGNORE 0xA
64 // Structure definition for a microcode header
74 UINT32 DataSize
; // if 0, then TotalSize = 2048, and TotalSize field is invalid
75 UINT32 TotalSize
; // number of bytes
77 } MICROCODE_IMAGE_HEADER
;
79 static EFI_GUID mZeroGuid
= {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
81 static const char *gHiiPackageRCFileHeader
[] = {
83 "// DO NOT EDIT -- auto-generated file",
89 // Module image information
92 UINT32 mImageTimeStamp
= 0;
93 UINT32 mImageSize
= 0;
94 UINT32 mOutImageType
= FW_DUMMY_IMAGE
;
100 IN OUT UINT8
*FileBuffer
,
107 IN OUT UINT8
*FileBuffer
,
127 Print out version information for this utility.
139 fprintf (stdout
, "%s Version %d.%d %s \n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
166 fprintf (stdout
, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME
);
169 // Copyright declaration
171 fprintf (stdout
, "Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.\n\n");
176 fprintf (stdout
, "Options:\n");
177 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
178 File will be created to store the ouput content.\n");
179 fprintf (stdout
, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\
180 Create Efi Image. EFI_FILETYPE is one of BASE,SMM_CORE,\n\
181 PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\
182 SEC, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER,\n\
183 DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER,\n\
184 PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\
185 APPLICATION, SAL_RT_DRIVER to support all module types\n\
186 It can only be used together with --keepexceptiontable,\n\
187 --keepzeropending, --keepoptionalheader, -r, -o option.\n\
188 It is a action option. If it is combined with other action options,\n\
189 the later input action option will override the previous one.\n");
190 fprintf (stdout
, " -c, --acpi Create Acpi table.\n\
191 It can't be combined with other action options\n\
192 except for -o, -r option. It is a action option.\n\
193 If it is combined with other action options, the later\n\
194 input action option will override the previous one.\n");
195 fprintf (stdout
, " -t, --terse Create Te Image.\n\
196 It can only be used together with --keepexceptiontable,\n\
197 --keepzeropending, --keepoptionalheader, -r, -o option.\n\
198 It is a action option. If it is combined with other action options,\n\
199 the later input action option will override the previous one.\n");
200 fprintf (stdout
, " -u, --dump Dump TeImage Header.\n\
201 It can't be combined with other action options\n\
202 except for -o, -r option. It is a action option.\n\
203 If it is combined with other action options, the later\n\
204 input action option will override the previous one.\n");
205 fprintf (stdout
, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\
206 It also zeros the time stamp fields.\n\
207 This option can be used to compare the binary efi image.\n\
208 It can't be combined with other action options\n\
209 except for -o, -r option. It is a action option.\n\
210 If it is combined with other action options, the later\n\
211 input action option will override the previous one.\n");
212 fprintf (stdout
, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\
213 It can't be combined with other action options\n\
214 except for -o, -r option. It is a action option.\n\
215 If it is combined with other action options, the later\n\
216 input action option will override the previous one.\n");;
217 fprintf (stdout
, " -l, --stripped Strip off the relocation info from PE or TE image.\n\
218 It can't be combined with other action options\n\
219 except for -o, -r option. It is a action option.\n\
220 If it is combined with other action options, the later\n\
221 input action option will override the previous one.\n");
222 fprintf (stdout
, " -s timedate, --stamp timedate\n\
223 timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\
224 is set to NOW, current system time is used. The support\n\
225 date scope is 1970-01-01 00+timezone:00:00\n\
226 ~ 2038-01-19 03+timezone:14:07\n\
227 The scope is adjusted according to the different zones.\n\
228 It can't be combined with other action options\n\
229 except for -o, -r option. It is a action option.\n\
230 If it is combined with other action options, the later\n\
231 input action option will override the previous one.\n");
232 fprintf (stdout
, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\
233 It can't be combined with other action options\n\
234 except for -o option. It is a action option.\n\
235 If it is combined with other action options, the later\n\
236 input action option will override the previous one.\n");
237 fprintf (stdout
, " -j, --join Combine multi microcode bin files to one file.\n\
238 It can be specified with -a, -p, -o option.\n\
239 No other options can be combined with it.\n\
240 If it is combined with other action options, the later\n\
241 input action option will override the previous one.\n");
242 fprintf (stdout
, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\
243 This option is only used together with -j option.\n");
244 fprintf (stdout
, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\
245 This option is only used together with -j option.\n");
246 fprintf (stdout
, " --keepexceptiontable Don't clear exception table.\n\
247 This option can be used together with -e or -t.\n\
248 It doesn't work for other options.\n");
249 fprintf (stdout
, " --keepoptionalheader Don't zero PE/COFF optional header fields.\n\
250 This option can be used together with -e or -t.\n\
251 It doesn't work for other options.\n");
252 fprintf (stdout
, " --keepzeropending Don't strip zero pending of .reloc.\n\
253 This option can be used together with -e or -t.\n\
254 It doesn't work for other options.\n");
255 fprintf (stdout
, " -r, --replace Overwrite the input file with the output content.\n\
256 If more input files are specified,\n\
257 the last input file will be as the output file.\n");
258 fprintf (stdout
, " -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\
259 Guid is used to specify hii package list guid.\n\
260 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\
261 If not specified, the first Form FormSet guid is used.\n");
262 fprintf (stdout
, " --hiipackage Combine all input binary hii pacakges into \n\
263 a single package list as the text resource data(RC).\n\
264 It can't be combined with other action options\n\
265 except for -o option. It is a action option.\n\
266 If it is combined with other action options, the later\n\
267 input action option will override the previous one.\n");
268 fprintf (stdout
, " --hiibinpackage Combine all input binary hii pacakges into \n\
269 a single package list as the binary resource section.\n\
270 It can't be combined with other action options\n\
271 except for -o option. It is a action option.\n\
272 If it is combined with other action options, the later\n\
273 input action option will override the previous one.\n");
274 fprintf (stdout
, " --rebase NewAddress Rebase image to new base address. New address \n\
275 is also set to the first none code section header.\n\
276 It can't be combined with other action options\n\
277 except for -o or -r option. It is a action option.\n\
278 If it is combined with other action options, the later\n\
279 input action option will override the previous one.\n");
280 fprintf (stdout
, " --address NewAddress Set new address into the first none code \n\
281 section header of the input image.\n\
282 It can't be combined with other action options\n\
283 except for -o or -r option. It is a action option.\n\
284 If it is combined with other action options, the later\n\
285 input action option will override the previous one.\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 FileAlginment 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 memset (XipFile
, 0, XipLength
);
631 // Copy the file headers
633 memcpy (XipFile
, *FileBuffer
, PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
);
635 NewPeHdr
= GetPeCoffHeader ((void *)XipFile
);
636 if (NewPeHdr
== NULL
) {
642 // Copy the section data over to the appropriate XIP offsets
644 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(NewPeHdr
->Pe32
.OptionalHeader
) + NewPeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
645 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
646 if (SectionHeader
->SizeOfRawData
> 0) {
648 XipFile
+ SectionHeader
->VirtualAddress
,
649 *FileBuffer
+ SectionHeader
->PointerToRawData
,
650 SectionHeader
->SizeOfRawData
654 // Make the size of raw data in section header alignment.
656 SectionHeader
->SizeOfRawData
= (SectionHeader
->Misc
.VirtualSize
+ PeHdr
->Pe32
.OptionalHeader
.FileAlignment
- 1) & (~(PeHdr
->Pe32
.OptionalHeader
.FileAlignment
- 1));
657 SectionHeader
->PointerToRawData
= SectionHeader
->VirtualAddress
;
661 *FileLength
= XipLength
;
662 *FileBuffer
= XipFile
;
666 CreateHiiResouceSectionHeader (
667 UINT32
*pSectionHeaderSize
,
674 Create COFF resource section header
678 pSectionHeaderSize - Pointer to section header size.
679 HiiDataSize - Size of the total HII data in section.
682 The created section header buffer.
686 UINT32 HiiSectionHeaderSize
;
687 UINT32 HiiSectionOffset
;
688 UINT8
*HiiSectionHeader
;
689 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
690 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*TypeResourceDirectoryEntry
;
691 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*NameResourceDirectoryEntry
;
692 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*LanguageResourceDirectoryEntry
;
693 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
694 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
697 // Calculate the total size for the resource header (include Type, Name and Language)
698 // then allocate memory for the resource header.
700 HiiSectionHeaderSize
= 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
))
701 + 3 * (sizeof (UINT16
) + 3 * sizeof (CHAR16
))
702 + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
703 HiiSectionHeader
= malloc (HiiSectionHeaderSize
);
704 memset (HiiSectionHeader
, 0, HiiSectionHeaderSize
);
706 HiiSectionOffset
= 0;
710 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
711 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
712 ResourceDirectory
->NumberOfNamedEntries
= 1;
713 TypeResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
714 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
715 TypeResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
716 TypeResourceDirectoryEntry
->u2
.s
.DataIsDirectory
= 1;
717 TypeResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
= HiiSectionOffset
;
721 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
722 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
723 ResourceDirectory
->NumberOfNamedEntries
= 1;
724 NameResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
725 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
726 NameResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
727 NameResourceDirectoryEntry
->u2
.s
.DataIsDirectory
= 1;
728 NameResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
= HiiSectionOffset
;
730 // Create Language entry
732 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
733 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
734 ResourceDirectory
->NumberOfNamedEntries
= 1;
735 LanguageResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
736 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
737 LanguageResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
739 // Create string entry for Type
741 TypeResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
742 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
743 ResourceDirectoryString
->Length
= 3;
744 ResourceDirectoryString
->String
[0] = L
'H';
745 ResourceDirectoryString
->String
[1] = L
'I';
746 ResourceDirectoryString
->String
[2] = L
'I';
747 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
749 // Create string entry for Name
751 NameResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
752 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
753 ResourceDirectoryString
->Length
= 3;
754 ResourceDirectoryString
->String
[0] = L
'E';
755 ResourceDirectoryString
->String
[1] = L
'F';
756 ResourceDirectoryString
->String
[2] = L
'I';
757 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
759 // Create string entry for Language
761 LanguageResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
762 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
763 ResourceDirectoryString
->Length
= 3;
764 ResourceDirectoryString
->String
[0] = L
'B';
765 ResourceDirectoryString
->String
[1] = L
'I';
766 ResourceDirectoryString
->String
[2] = L
'N';
767 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
771 LanguageResourceDirectoryEntry
->u2
.OffsetToData
= HiiSectionOffset
;
772 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
773 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
774 ResourceDataEntry
->OffsetToData
= HiiSectionOffset
;
775 ResourceDataEntry
->Size
= HiiDataSize
;
777 *pSectionHeaderSize
= HiiSectionHeaderSize
;
778 return HiiSectionHeader
;
785 IN OUT UINT32
*ReadSize
,
792 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
796 FileHandle - The handle to the PE/COFF file
798 FileOffset - The offset, in bytes, into the file to read
800 ReadSize - The number of bytes to read from the file starting at FileOffset
802 Buffer - A pointer to the buffer to read the data into.
806 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
814 Destination8
= Buffer
;
815 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
818 *(Destination8
++) = *(Source8
++);
825 SetAddressToSectionHeader (
827 IN OUT UINT8
*FileBuffer
,
828 IN UINT64 NewPe32BaseAddress
834 Set new base address into the section header of PeImage
838 FileName - Name of file
839 FileBuffer - Pointer to PeImage.
840 NewPe32BaseAddress - New Base Address for PE image.
844 EFI_SUCCESS Set new base address into this image successfully.
849 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
851 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
852 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
855 // Initialize context
857 memset (&ImageContext
, 0, sizeof (ImageContext
));
858 ImageContext
.Handle
= (VOID
*) FileBuffer
;
859 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
860 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
861 if (EFI_ERROR (Status
)) {
862 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
866 if (ImageContext
.RelocationsStripped
) {
867 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
872 // Get PeHeader pointer
874 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
877 // Get section header list
879 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
882 sizeof (EFI_IMAGE_FILE_HEADER
) +
883 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
887 // Set base address into the first section header that doesn't point to code section.
889 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
890 if ((SectionHeader
->Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
891 *(UINT64
*) &SectionHeader
->PointerToRelocations
= NewPe32BaseAddress
;
897 // No available section header is found.
899 if (Index
== ImgHdr
->Pe32
.FileHeader
.NumberOfSections
) {
900 return EFI_NOT_FOUND
;
904 // BaseAddress is set to section header.
912 IN OUT UINT8
*FileBuffer
,
913 IN UINT64 NewPe32BaseAddress
919 Set new base address into PeImage, and fix up PeImage based on new address.
923 FileName - Name of file
924 FileBuffer - Pointer to PeImage.
925 NewPe32BaseAddress - New Base Address for PE image.
929 EFI_INVALID_PARAMETER - BaseAddress is not valid.
930 EFI_SUCCESS - Update PeImage is correctly.
935 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
937 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
938 UINT8
*MemoryImagePointer
;
939 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
942 // Initialize context
944 memset (&ImageContext
, 0, sizeof (ImageContext
));
945 ImageContext
.Handle
= (VOID
*) FileBuffer
;
946 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
947 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
948 if (EFI_ERROR (Status
)) {
949 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
953 if (ImageContext
.RelocationsStripped
) {
954 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
959 // Get PeHeader pointer
961 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
964 // Load and Relocate Image Data
966 MemoryImagePointer
= (UINT8
*) malloc ((UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
967 if (MemoryImagePointer
== NULL
) {
968 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
969 return EFI_OUT_OF_RESOURCES
;
971 memset ((VOID
*) MemoryImagePointer
, 0, (UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
972 ImageContext
.ImageAddress
= ((UINTN
) MemoryImagePointer
+ ImageContext
.SectionAlignment
- 1) & (~((INT64
)ImageContext
.SectionAlignment
- 1));
974 Status
= PeCoffLoaderLoadImage (&ImageContext
);
975 if (EFI_ERROR (Status
)) {
976 Error (NULL
, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName
);
977 free ((VOID
*) MemoryImagePointer
);
981 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
982 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
983 if (EFI_ERROR (Status
)) {
984 Error (NULL
, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName
);
985 free ((VOID
*) MemoryImagePointer
);
990 // Copy Relocated data to raw image file.
992 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
995 sizeof (EFI_IMAGE_FILE_HEADER
) +
996 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
999 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1001 FileBuffer
+ SectionHeader
->PointerToRawData
,
1002 (VOID
*) (UINTN
) (ImageContext
.ImageAddress
+ SectionHeader
->VirtualAddress
),
1003 SectionHeader
->SizeOfRawData
1007 free ((VOID
*) MemoryImagePointer
);
1010 // Update Image Base Address
1012 if ((ImgHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) && (ImgHdr
->Pe32
.FileHeader
.Machine
!= IMAGE_FILE_MACHINE_IA64
)) {
1013 ImgHdr
->Pe32
.OptionalHeader
.ImageBase
= (UINT32
) NewPe32BaseAddress
;
1014 } else if (ImgHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1015 ImgHdr
->Pe32Plus
.OptionalHeader
.ImageBase
= NewPe32BaseAddress
;
1017 Error (NULL
, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
1018 ImgHdr
->Pe32
.OptionalHeader
.Magic
,
1025 // Set new base address into section header
1027 Status
= SetAddressToSectionHeader (FileName
, FileBuffer
, NewPe32BaseAddress
);
1039 Routine Description:
1045 argc - Number of command line parameters.
1046 argv - Array of pointers to command line parameter strings.
1049 STATUS_SUCCESS - Utility exits successfully.
1050 STATUS_ERROR - Some error occurred during execution.
1055 UINT32 InputFileNum
;
1056 CHAR8
**InputFileName
;
1064 UINT32
*DataPointer
;
1065 UINT32
*OldDataPointer
;
1071 UINT32 MciAlignment
;
1073 UINT32 AllignedRelocSize
;
1076 UINT8
*OutputFileBuffer
;
1077 UINT32 OutputFileLength
;
1078 UINT8
*InputFileBuffer
;
1079 UINT32 InputFileLength
;
1080 RUNTIME_FUNCTION
*RuntimeFunction
;
1081 UNWIND_INFO
*UnwindInfo
;
1083 BOOLEAN ReplaceFlag
;
1084 BOOLEAN KeepExceptionTableFlag
;
1085 BOOLEAN KeepOptionalHeaderFlag
;
1086 BOOLEAN KeepZeroPendingFlag
;
1088 EFI_TE_IMAGE_HEADER TEImageHeader
;
1089 EFI_TE_IMAGE_HEADER
*TeHdr
;
1090 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1091 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1092 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1093 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32
;
1094 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64
;
1095 EFI_IMAGE_DOS_HEADER BackupDosHdr
;
1096 MICROCODE_IMAGE_HEADER
*MciHeader
;
1097 UINT8
*HiiPackageListBuffer
;
1098 UINT8
*HiiPackageDataPointer
;
1099 EFI_GUID HiiPackageListGuid
;
1100 EFI_HII_PACKAGE_LIST_HEADER HiiPackageListHeader
;
1101 EFI_HII_PACKAGE_HEADER HiiPackageHeader
;
1102 EFI_IFR_FORM_SET IfrFormSet
;
1103 UINT8 NumberOfFormPacakge
;
1104 EFI_HII_PACKAGE_HEADER EndPackage
;
1105 UINT32 HiiSectionHeaderSize
;
1106 UINT8
*HiiSectionHeader
;
1107 UINT64 NewBaseAddress
;
1108 BOOLEAN NegativeAddr
;
1110 CHAR8
*ReportFileName
;
1112 time_t InputFileTime
;
1113 time_t OutputFileTime
;
1114 struct stat Stat_Buf
;
1116 SetUtilityName (UTILITY_NAME
);
1119 // Assign to fix compile warning
1123 InputFileName
= NULL
;
1124 mInImageName
= NULL
;
1125 OutImageName
= NULL
;
1128 Status
= STATUS_SUCCESS
;
1134 MciAlignment
= DEFAULT_MC_ALIGNMENT
;
1135 MciPadValue
= DEFAULT_MC_PAD_BYTE_VALUE
;
1139 ReplaceFlag
= FALSE
;
1141 OutputFileBuffer
= NULL
;
1142 OutputFileLength
= 0;
1143 InputFileBuffer
= NULL
;
1144 InputFileLength
= 0;
1147 KeepExceptionTableFlag
= FALSE
;
1148 KeepOptionalHeaderFlag
= FALSE
;
1149 KeepZeroPendingFlag
= FALSE
;
1150 NumberOfFormPacakge
= 0;
1151 HiiPackageListBuffer
= NULL
;
1152 HiiPackageDataPointer
= NULL
;
1153 EndPackage
.Length
= sizeof (EFI_HII_PACKAGE_HEADER
);
1154 EndPackage
.Type
= EFI_HII_PACKAGE_END
;
1155 memset (&HiiPackageListGuid
, 0, sizeof (HiiPackageListGuid
));
1156 HiiSectionHeaderSize
= 0;
1157 HiiSectionHeader
= NULL
;
1159 NegativeAddr
= FALSE
;
1164 Error (NULL
, 0, 1001, "Missing options", "No input options.");
1166 return STATUS_ERROR
;
1172 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
1175 return STATUS_SUCCESS
;
1178 if (stricmp (argv
[0], "--version") == 0) {
1180 return STATUS_SUCCESS
;
1184 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
1185 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1186 Error (NULL
, 0, 1003, "Invalid option value", "Output file name is missing for -o option");
1189 OutImageName
= argv
[1];
1195 if ((stricmp (argv
[0], "-e") == 0) || (stricmp (argv
[0], "--efiImage") == 0)) {
1196 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1197 Error (NULL
, 0, 1003, "Invalid option value", "Module Type is missing for -o option");
1200 ModuleType
= argv
[1];
1201 if (mOutImageType
!= FW_TE_IMAGE
) {
1202 mOutImageType
= FW_EFI_IMAGE
;
1209 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--stripped") == 0)) {
1210 mOutImageType
= FW_RELOC_STRIPEED_IMAGE
;
1216 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--acpi") == 0)) {
1217 mOutImageType
= FW_ACPI_IMAGE
;
1223 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--terse") == 0)) {
1224 mOutImageType
= FW_TE_IMAGE
;
1230 if ((stricmp (argv
[0], "-u") == 0) || (stricmp (argv
[0], "--dump") == 0)) {
1231 mOutImageType
= DUMP_TE_HEADER
;
1237 if ((stricmp (argv
[0], "-b") == 0) || (stricmp (argv
[0], "--exe2bin") == 0)) {
1238 mOutImageType
= FW_BIN_IMAGE
;
1244 if ((stricmp (argv
[0], "-z") == 0) || (stricmp (argv
[0], "--zero") == 0)) {
1245 mOutImageType
= FW_ZERO_DEBUG_IMAGE
;
1251 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--stamp") == 0)) {
1252 mOutImageType
= FW_SET_STAMP_IMAGE
;
1253 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1254 Error (NULL
, 0, 1003, "Invalid option value", "time stamp is missing for -s option");
1257 TimeStamp
= argv
[1];
1263 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--replace") == 0)) {
1270 if (stricmp (argv
[0], "--keepexceptiontable") == 0) {
1271 KeepExceptionTableFlag
= TRUE
;
1277 if (stricmp(argv
[0], "--keepoptionalheader") == 0) {
1278 KeepOptionalHeaderFlag
= TRUE
;
1284 if (stricmp (argv
[0], "--keepzeropending") == 0) {
1285 KeepZeroPendingFlag
= TRUE
;
1291 if ((stricmp (argv
[0], "-m") == 0) || (stricmp (argv
[0], "--mcifile") == 0)) {
1292 mOutImageType
= FW_MCI_IMAGE
;
1298 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--join") == 0)) {
1299 mOutImageType
= FW_MERGE_IMAGE
;
1305 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
1306 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1307 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1310 MciAlignment
= (UINT32
) Temp64
;
1316 if ((stricmp (argv
[0], "--rebase") == 0)) {
1317 if (argv
[1][0] == '-') {
1318 NegativeAddr
= TRUE
;
1319 Status
= AsciiStringToUint64 (argv
[1] + 1, FALSE
, &Temp64
);
1321 NegativeAddr
= FALSE
;
1322 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
);
1324 if (Status
!= EFI_SUCCESS
) {
1325 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1328 mOutImageType
= FW_REBASE_IMAGE
;
1329 NewBaseAddress
= (UINT64
) Temp64
;
1335 if ((stricmp (argv
[0], "--address") == 0)) {
1336 if (argv
[1][0] == '-') {
1337 NegativeAddr
= TRUE
;
1338 Status
= AsciiStringToUint64 (argv
[1] + 1, FALSE
, &Temp64
);
1340 NegativeAddr
= FALSE
;
1341 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
);
1343 if (Status
!= EFI_SUCCESS
) {
1344 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1347 mOutImageType
= FW_SET_ADDRESS_IMAGE
;
1348 NewBaseAddress
= (UINT64
) Temp64
;
1354 if ((stricmp (argv
[0], "-p") == 0) || (stricmp (argv
[0], "--pad") == 0)) {
1355 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1356 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1359 MciPadValue
= (UINT8
) Temp64
;
1365 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
1366 SetPrintLevel (VERBOSE_LOG_LEVEL
);
1367 VerboseMsg ("Verbose output Mode Set!");
1373 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1374 SetPrintLevel (KEY_LOG_LEVEL
);
1375 KeyMsg ("Quiet output Mode Set!");
1381 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
1382 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
1383 if (EFI_ERROR (Status
)) {
1384 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1388 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel
);
1391 SetPrintLevel (LogLevel
);
1392 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
1398 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--hiiguid") == 0)) {
1399 Status
= StringToGuid (argv
[1], &HiiPackageListGuid
);
1400 if (EFI_ERROR (Status
)) {
1401 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1409 if (stricmp (argv
[0], "--hiipackage") == 0) {
1410 mOutImageType
= FW_HII_PACKAGE_LIST_RCIMAGE
;
1416 if (stricmp (argv
[0], "--hiibinpackage") == 0) {
1417 mOutImageType
= FW_HII_PACKAGE_LIST_BINIMAGE
;
1423 if (argv
[0][0] == '-') {
1424 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
1428 // Get Input file name
1430 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
1431 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
1432 if (InputFileName
== NULL
) {
1433 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1437 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1438 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1440 // InputFileName buffer too small, need to realloc
1442 InputFileName
= (CHAR8
**) realloc (
1444 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1447 if (InputFileName
== NULL
) {
1448 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1452 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1455 InputFileName
[InputFileNum
++] = argv
[0];
1460 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1462 if (mOutImageType
== FW_DUMMY_IMAGE
) {
1463 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!");
1465 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.");
1471 // check input files
1473 if (InputFileNum
== 0) {
1474 Error (NULL
, 0, 1001, "Missing option", "Input files");
1479 // Combine MciBinary files to one file
1481 if ((mOutImageType
== FW_MERGE_IMAGE
) && ReplaceFlag
) {
1482 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");
1487 // Combine HiiBinary packages to a single package list
1489 if ((mOutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) && ReplaceFlag
) {
1490 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option.");
1494 if ((mOutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) && ReplaceFlag
) {
1495 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiibinpackage merge files option.");
1502 mInImageName
= InputFileName
[InputFileNum
- 1];
1503 VerboseMsg ("the input file name is %s", mInImageName
);
1506 // Action will be taken for the input file.
1508 switch (mOutImageType
) {
1510 VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType
);
1513 VerboseMsg ("Create Te Image based on the input PE image.");
1516 VerboseMsg ("Get acpi table data from the input PE image.");
1518 case FW_RELOC_STRIPEED_IMAGE
:
1519 VerboseMsg ("Remove relocation section from Pe or Te image.");
1522 VerboseMsg ("Convert the input EXE to the output BIN file.");
1524 case FW_ZERO_DEBUG_IMAGE
:
1525 VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");
1527 case FW_SET_STAMP_IMAGE
:
1528 VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp
);
1530 case DUMP_TE_HEADER
:
1531 VerboseMsg ("Dump the TE header information of the input TE image.");
1534 VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");
1536 case FW_MERGE_IMAGE
:
1537 VerboseMsg ("Combine the input multi microcode bin files to one bin file.");
1539 case FW_HII_PACKAGE_LIST_RCIMAGE
:
1540 VerboseMsg ("Combine the input multi hii bin packages to one text pacakge list RC file.");
1542 case FW_HII_PACKAGE_LIST_BINIMAGE
:
1543 VerboseMsg ("Combine the input multi hii bin packages to one binary pacakge list file.");
1545 case FW_REBASE_IMAGE
:
1546 VerboseMsg ("Rebase the input image to new base address.");
1548 case FW_SET_ADDRESS_IMAGE
:
1549 VerboseMsg ("Set the preferred address into the section header of the input image");
1556 VerboseMsg ("Overwrite the input file with the output content.");
1560 // Open output file and Write image into the output file.
1562 if (OutImageName
!= NULL
) {
1563 fpOut
= fopen (LongFilePath (OutImageName
), "rb");
1564 if (fpOut
!= NULL
) {
1566 // Get Output file time stamp
1568 fstat(fileno (fpOut
), &Stat_Buf
);
1569 OutputFileTime
= Stat_Buf
.st_mtime
;
1571 // Get Output file data
1573 OutputFileLength
= _filelength (fileno (fpOut
));
1574 OutputFileBuffer
= malloc (OutputFileLength
);
1575 if (OutputFileBuffer
== NULL
) {
1576 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1581 fread (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
1585 VerboseMsg ("Output file name is %s", OutImageName
);
1586 } else if (!ReplaceFlag
&& mOutImageType
!= DUMP_TE_HEADER
) {
1587 Error (NULL
, 0, 1001, "Missing option", "output file");
1592 // Open input file and read file data into file buffer.
1594 fpIn
= fopen (LongFilePath (mInImageName
), "rb");
1596 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1600 // Get Iutput file time stamp
1602 fstat(fileno (fpIn
), &Stat_Buf
);
1603 InputFileTime
= Stat_Buf
.st_mtime
;
1605 // Get Input file data
1607 InputFileLength
= _filelength (fileno (fpIn
));
1608 InputFileBuffer
= malloc (InputFileLength
);
1609 if (InputFileBuffer
== NULL
) {
1610 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1614 fread (InputFileBuffer
, 1, InputFileLength
, fpIn
);
1616 DebugMsg (NULL
, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) InputFileLength
);
1619 // Combine multi binary HII package files.
1621 if (mOutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
|| mOutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) {
1623 // Open output file handle.
1625 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
1627 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1631 // Get hii package list lenght
1633 HiiPackageListHeader
.PackageLength
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1634 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1635 fpIn
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
1637 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1640 FileLength
= _filelength (fileno (fpIn
));
1641 fread (&HiiPackageHeader
, 1, sizeof (HiiPackageHeader
), fpIn
);
1642 if (HiiPackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) {
1643 if (HiiPackageHeader
.Length
!= FileLength
) {
1644 Error (NULL
, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName
[Index
]);
1648 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
1649 fread (&IfrFormSet
, 1, sizeof (IfrFormSet
), fpIn
);
1650 memcpy (&HiiPackageListGuid
, &IfrFormSet
.Guid
, sizeof (EFI_GUID
));
1652 NumberOfFormPacakge
++;
1654 HiiPackageListHeader
.PackageLength
+= FileLength
;
1657 HiiPackageListHeader
.PackageLength
+= sizeof (EndPackage
);
1659 // Check whether hii packages are valid
1661 if (NumberOfFormPacakge
> 1) {
1662 Error (NULL
, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package");
1665 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
1666 Error (NULL
, 0, 3000, "Invalid", "HII pacakge list guid is not specified!");
1669 memcpy (&HiiPackageListHeader
.PackageListGuid
, &HiiPackageListGuid
, sizeof (EFI_GUID
));
1671 // read hii packages
1673 HiiPackageListBuffer
= malloc (HiiPackageListHeader
.PackageLength
);
1674 if (HiiPackageListBuffer
== NULL
) {
1675 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1678 memcpy (HiiPackageListBuffer
, &HiiPackageListHeader
, sizeof (HiiPackageListHeader
));
1679 HiiPackageDataPointer
= HiiPackageListBuffer
+ sizeof (HiiPackageListHeader
);
1680 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1681 fpIn
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
1683 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1684 free (HiiPackageListBuffer
);
1688 FileLength
= _filelength (fileno (fpIn
));
1689 fread (HiiPackageDataPointer
, 1, FileLength
, fpIn
);
1691 HiiPackageDataPointer
= HiiPackageDataPointer
+ FileLength
;
1693 memcpy (HiiPackageDataPointer
, &EndPackage
, sizeof (EndPackage
));
1696 // write the hii package into the binary package list file with the resource section header
1698 if (mOutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) {
1700 // Create the resource section header
1702 HiiSectionHeader
= CreateHiiResouceSectionHeader (&HiiSectionHeaderSize
, HiiPackageListHeader
.PackageLength
);
1704 // Wrtie section header and HiiData into File.
1706 fwrite (HiiSectionHeader
, 1, HiiSectionHeaderSize
, fpOut
);
1707 fwrite (HiiPackageListBuffer
, 1, HiiPackageListHeader
.PackageLength
, fpOut
);
1709 // Free allocated resources.
1711 free (HiiSectionHeader
);
1712 free (HiiPackageListBuffer
);
1714 // Done successfully
1720 // write the hii package into the text package list rc file.
1722 if (mOutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) {
1723 for (Index
= 0; gHiiPackageRCFileHeader
[Index
] != NULL
; Index
++) {
1724 fprintf (fpOut
, "%s\n", gHiiPackageRCFileHeader
[Index
]);
1726 fprintf (fpOut
, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX
, HII_RESOURCE_SECTION_NAME
);
1728 HiiPackageDataPointer
= HiiPackageListBuffer
;
1729 for (Index
= 0; Index
+ 2 < HiiPackageListHeader
.PackageLength
; Index
+= 2) {
1730 if (Index
% 16 == 0) {
1731 fprintf (fpOut
, "\n ");
1733 fprintf (fpOut
, " 0x%04X,", *(UINT16
*) HiiPackageDataPointer
);
1734 HiiPackageDataPointer
+= 2;
1737 if (Index
% 16 == 0) {
1738 fprintf (fpOut
, "\n ");
1740 if ((Index
+ 2) == HiiPackageListHeader
.PackageLength
) {
1741 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT16
*) HiiPackageDataPointer
);
1743 if ((Index
+ 1) == HiiPackageListHeader
.PackageLength
) {
1744 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT8
*) HiiPackageDataPointer
);
1746 free (HiiPackageListBuffer
);
1748 // Done successfully
1755 // Combine MciBinary files to one file
1757 if (mOutImageType
== FW_MERGE_IMAGE
) {
1759 // Open output file handle.
1761 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
1763 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1766 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1767 fpIn
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
1769 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1773 FileLength
= _filelength (fileno (fpIn
));
1774 FileBuffer
= malloc (FileLength
);
1775 if (FileBuffer
== NULL
) {
1776 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1781 fread (FileBuffer
, 1, FileLength
, fpIn
);
1784 // write input file to out file
1786 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
1788 // write pad value to out file.
1790 while (FileLength
++ % MciAlignment
!= 0) {
1791 fwrite (&MciPadValue
, 1, 1, fpOut
);
1794 // free allocated memory space
1800 // Done successfully
1806 // Convert MicroCode.txt file to MicroCode.bin file
1808 if (mOutImageType
== FW_MCI_IMAGE
) {
1809 fpIn
= fopen (LongFilePath (mInImageName
), "r");
1811 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1816 // The first pass is to determine
1817 // how much data is in the file so we can allocate a working buffer.
1821 Status
= MicrocodeReadData (fpIn
, &Data
);
1822 if (Status
== STATUS_SUCCESS
) {
1823 FileLength
+= sizeof (Data
);
1825 if (Status
== STATUS_IGNORE
) {
1826 Status
= STATUS_SUCCESS
;
1828 } while (Status
== STATUS_SUCCESS
);
1830 // Error if no data.
1832 if (FileLength
== 0) {
1833 Error (NULL
, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName
);
1836 if (FileLength
< sizeof (MICROCODE_IMAGE_HEADER
)) {
1837 Error (NULL
, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName
);
1842 // Allocate a buffer for the data
1844 FileBuffer
= malloc (FileLength
);
1845 if (FileBuffer
== NULL
) {
1846 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1850 // Re-read the file, storing the data into our buffer
1852 fseek (fpIn
, 0, SEEK_SET
);
1853 DataPointer
= (UINT32
*) FileBuffer
;
1854 OldDataPointer
= DataPointer
;
1856 OldDataPointer
= DataPointer
;
1857 Status
= MicrocodeReadData (fpIn
, DataPointer
++);
1858 if (Status
== STATUS_IGNORE
) {
1859 DataPointer
= OldDataPointer
;
1860 Status
= STATUS_SUCCESS
;
1862 } while (Status
== STATUS_SUCCESS
);
1864 // close input file after read data
1869 // Can't do much checking on the header because, per the spec, the
1870 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
1871 // and the TotalSize field is invalid (actually missing). Thus we can't
1872 // even verify the Reserved fields are 0.
1874 MciHeader
= (MICROCODE_IMAGE_HEADER
*) FileBuffer
;
1875 if (MciHeader
->DataSize
== 0) {
1878 Index
= MciHeader
->TotalSize
;
1881 if (Index
!= FileLength
) {
1882 Error (NULL
, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName
, (unsigned) FileLength
, (unsigned) Index
);
1887 // Checksum the contents
1889 DataPointer
= (UINT32
*) FileBuffer
;
1892 while (Index
< FileLength
) {
1893 CheckSum
+= *DataPointer
;
1895 Index
+= sizeof (*DataPointer
);
1897 if (CheckSum
!= 0) {
1898 Error (NULL
, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum
, mInImageName
);
1902 // Open the output file and write the buffer contents
1904 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
1909 // Open input file and read file data into file buffer.
1911 FileLength
= InputFileLength
;
1912 FileBuffer
= malloc (FileLength
);
1913 if (FileBuffer
== NULL
) {
1914 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1917 memcpy (FileBuffer
, InputFileBuffer
, InputFileLength
);
1920 // Dump TeImage Header into output file.
1922 if (mOutImageType
== DUMP_TE_HEADER
) {
1923 memcpy (&TEImageHeader
, FileBuffer
, sizeof (TEImageHeader
));
1924 if (TEImageHeader
.Signature
!= EFI_TE_IMAGE_HEADER_SIGNATURE
) {
1925 Error (NULL
, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName
);
1929 // Open the output file handle.
1932 fpInOut
= fopen (LongFilePath (mInImageName
), "wb");
1933 if (fpInOut
== NULL
) {
1934 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1938 if (OutImageName
!= NULL
) {
1939 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
1943 if (fpOut
== NULL
) {
1944 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1948 if (fpInOut
!= NULL
) {
1949 fprintf (fpInOut
, "Dump of file %s\n\n", mInImageName
);
1950 fprintf (fpInOut
, "TE IMAGE HEADER VALUES\n");
1951 fprintf (fpInOut
, "%17X machine\n", TEImageHeader
.Machine
);
1952 fprintf (fpInOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
1953 fprintf (fpInOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
1954 fprintf (fpInOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
1955 fprintf (fpInOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
1956 fprintf (fpInOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
1957 fprintf (fpInOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
1958 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
1959 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
1961 if (fpOut
!= NULL
) {
1962 fprintf (fpOut
, "Dump of file %s\n\n", mInImageName
);
1963 fprintf (fpOut
, "TE IMAGE HEADER VALUES\n");
1964 fprintf (fpOut
, "%17X machine\n", TEImageHeader
.Machine
);
1965 fprintf (fpOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
1966 fprintf (fpOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
1967 fprintf (fpOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
1968 fprintf (fpOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
1969 fprintf (fpOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
1970 fprintf (fpOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
1971 fprintf (fpOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
1972 fprintf (fpOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
1978 // Following code to convert dll to efi image or te image.
1979 // Get new image type
1981 if ((mOutImageType
== FW_EFI_IMAGE
) || (mOutImageType
== FW_TE_IMAGE
)) {
1982 if (ModuleType
== NULL
) {
1983 if (mOutImageType
== FW_EFI_IMAGE
) {
1984 Error (NULL
, 0, 1001, "Missing option", "EFI_FILETYPE");
1986 } else if (mOutImageType
== FW_TE_IMAGE
) {
1988 // Default TE Image Type is Boot service driver
1990 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
1991 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
1994 if (stricmp (ModuleType
, "BASE") == 0 ||
1995 stricmp (ModuleType
, "SEC") == 0 ||
1996 stricmp (ModuleType
, "SECURITY_CORE") == 0 ||
1997 stricmp (ModuleType
, "PEI_CORE") == 0 ||
1998 stricmp (ModuleType
, "PEIM") == 0 ||
1999 stricmp (ModuleType
, "COMBINED_PEIM_DRIVER") == 0 ||
2000 stricmp (ModuleType
, "PIC_PEIM") == 0 ||
2001 stricmp (ModuleType
, "RELOCATABLE_PEIM") == 0 ||
2002 stricmp (ModuleType
, "DXE_CORE") == 0 ||
2003 stricmp (ModuleType
, "BS_DRIVER") == 0 ||
2004 stricmp (ModuleType
, "DXE_DRIVER") == 0 ||
2005 stricmp (ModuleType
, "DXE_SMM_DRIVER") == 0 ||
2006 stricmp (ModuleType
, "UEFI_DRIVER") == 0 ||
2007 stricmp (ModuleType
, "SMM_CORE") == 0) {
2008 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2009 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2011 } else if (stricmp (ModuleType
, "UEFI_APPLICATION") == 0 ||
2012 stricmp (ModuleType
, "APPLICATION") == 0) {
2013 Type
= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
;
2014 VerboseMsg ("Efi Image subsystem type is efi application.");
2016 } else if (stricmp (ModuleType
, "DXE_RUNTIME_DRIVER") == 0 ||
2017 stricmp (ModuleType
, "RT_DRIVER") == 0) {
2018 Type
= EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
;
2019 VerboseMsg ("Efi Image subsystem type is efi runtime driver.");
2021 } else if (stricmp (ModuleType
, "DXE_SAL_DRIVER") == 0 ||
2022 stricmp (ModuleType
, "SAL_RT_DRIVER") == 0) {
2023 Type
= EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
;
2024 VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");
2027 Error (NULL
, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType
);
2034 // Convert ELF image to PeImage
2036 if (IsElfHeader(FileBuffer
)) {
2037 VerboseMsg ("Convert %s from ELF to PE/COFF.", mInImageName
);
2038 if (!ConvertElf(&FileBuffer
, &FileLength
)) {
2039 Error (NULL
, 0, 3000, "Invalid", "Unable to convert %s from ELF to PE/COFF.", mInImageName
);
2045 // Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP
2046 // XIP == eXecute In Place
2048 PeCoffConvertImageToXip (&FileBuffer
, &FileLength
);
2051 // Remove reloc section from PE or TE image
2053 if (mOutImageType
== FW_RELOC_STRIPEED_IMAGE
) {
2057 TeHdr
= (EFI_TE_IMAGE_HEADER
*) FileBuffer
;
2058 if (TeHdr
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2059 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (TeHdr
+ 1);
2060 for (Index
= 0; Index
< TeHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2061 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2063 // Check the reloc section is in the end of image.
2065 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) ==
2066 (FileLength
+ TeHdr
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
))) {
2068 // Remove .reloc section and update TeImage Header
2070 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2071 SectionHeader
->SizeOfRawData
= 0;
2072 SectionHeader
->Misc
.VirtualSize
= 0;
2073 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2074 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2083 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2084 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2085 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2086 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2087 Error (NULL
, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName
);
2092 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2093 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2094 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2098 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2099 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2100 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2102 // Check the reloc section is in the end of image.
2104 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) == FileLength
) {
2106 // Remove .reloc section and update PeImage Header
2108 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2110 PeHdr
->Pe32
.FileHeader
.Characteristics
|= EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2111 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2112 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2113 Optional32
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2114 Optional32
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2115 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2116 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2117 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2120 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2121 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2122 Optional64
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2123 Optional64
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2124 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2125 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2126 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2129 SectionHeader
->Misc
.VirtualSize
= 0;
2130 SectionHeader
->SizeOfRawData
= 0;
2142 // Read the dos & pe hdrs of the image
2144 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2145 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2146 // NO DOS header, check for PE/COFF header
2147 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2148 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2149 Error (NULL
, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName
);
2155 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2156 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2157 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2162 if (PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_ARM
) {
2163 // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
2164 // so patch back to the offical UEFI value.
2165 PeHdr
->Pe32
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_ARMT
;
2169 // Set new base address into image
2171 if (mOutImageType
== FW_REBASE_IMAGE
|| mOutImageType
== FW_SET_ADDRESS_IMAGE
) {
2172 if ((PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) && (PeHdr
->Pe32
.FileHeader
.Machine
!= IMAGE_FILE_MACHINE_IA64
)) {
2173 if (NewBaseAddress
>= 0x100000000ULL
) {
2174 Error (NULL
, 0, 3000, "Invalid", "New base address is larger than 4G for 32bit PE image");
2181 // Set Base Address to a negative value.
2183 NewBaseAddress
= (UINT64
) (0 - NewBaseAddress
);
2185 if (mOutImageType
== FW_REBASE_IMAGE
) {
2186 Status
= RebaseImage (mInImageName
, FileBuffer
, NewBaseAddress
);
2188 Status
= SetAddressToSectionHeader (mInImageName
, FileBuffer
, NewBaseAddress
);
2190 if (EFI_ERROR (Status
)) {
2192 Error (NULL
, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address -0x%llx can't success", mInImageName
, 0 - NewBaseAddress
);
2194 Error (NULL
, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address 0x%llx can't success", mInImageName
, NewBaseAddress
);
2206 // Extract bin data from Pe image.
2208 if (mOutImageType
== FW_BIN_IMAGE
) {
2209 if (FileLength
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
2210 Error (NULL
, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName
);
2214 // Output bin data from exe file
2216 FileLength
= FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
;
2217 memmove (FileBuffer
, FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, FileLength
);
2218 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2223 // Zero Debug Information of Pe Image
2225 if (mOutImageType
== FW_ZERO_DEBUG_IMAGE
) {
2226 Status
= ZeroDebugData (FileBuffer
, TRUE
);
2227 if (EFI_ERROR (Status
)) {
2228 Error (NULL
, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status
);
2233 // Write the updated Image
2235 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2240 // Set Time Stamp of Pe Image
2242 if (mOutImageType
== FW_SET_STAMP_IMAGE
) {
2243 Status
= SetStamp (FileBuffer
, TimeStamp
);
2244 if (EFI_ERROR (Status
)) {
2249 // Write the updated Image
2251 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2256 // Extract acpi data from pe image.
2258 if (mOutImageType
== FW_ACPI_IMAGE
) {
2259 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2260 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2261 if (strcmp ((char *)SectionHeader
->Name
, ".data") == 0 || strcmp ((char *)SectionHeader
->Name
, ".sdata") == 0) {
2265 if (SectionHeader
->Misc
.VirtualSize
< SectionHeader
->SizeOfRawData
) {
2266 FileLength
= SectionHeader
->Misc
.VirtualSize
;
2268 FileLength
= SectionHeader
->SizeOfRawData
;
2271 if (CheckAcpiTable (FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
) != STATUS_SUCCESS
) {
2272 Error (NULL
, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName
);
2277 // Output Apci data to file
2279 memmove (FileBuffer
, FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
);
2280 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2284 Error (NULL
, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName
);
2288 // Zero all unused fields of the DOS header
2290 if (DosHdr
!= NULL
) {
2291 memcpy (&BackupDosHdr
, DosHdr
, sizeof (EFI_IMAGE_DOS_HEADER
));
2292 memset (DosHdr
, 0, sizeof (EFI_IMAGE_DOS_HEADER
));
2293 DosHdr
->e_magic
= BackupDosHdr
.e_magic
;
2294 DosHdr
->e_lfanew
= BackupDosHdr
.e_lfanew
;
2296 for (Index
= sizeof (EFI_IMAGE_DOS_HEADER
); Index
< (UINT32
) DosHdr
->e_lfanew
; Index
++) {
2297 FileBuffer
[Index
] = (UINT8
) DosHdr
->e_cp
;
2302 // Initialize TeImage Header
2304 memset (&TEImageHeader
, 0, sizeof (EFI_TE_IMAGE_HEADER
));
2305 TEImageHeader
.Signature
= EFI_TE_IMAGE_HEADER_SIGNATURE
;
2306 TEImageHeader
.Machine
= PeHdr
->Pe32
.FileHeader
.Machine
;
2307 TEImageHeader
.NumberOfSections
= (UINT8
) PeHdr
->Pe32
.FileHeader
.NumberOfSections
;
2308 TEImageHeader
.StrippedSize
= (UINT16
) ((UINTN
) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
) - (UINTN
) FileBuffer
);
2309 TEImageHeader
.Subsystem
= (UINT8
) Type
;
2312 // Patch the PE header
2314 PeHdr
->Pe32
.OptionalHeader
.Subsystem
= (UINT16
) Type
;
2316 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2317 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2318 if (!KeepOptionalHeaderFlag
) {
2319 Optional32
->MajorOperatingSystemVersion
= 0;
2320 Optional32
->MinorOperatingSystemVersion
= 0;
2321 Optional32
->MajorImageVersion
= 0;
2322 Optional32
->MinorImageVersion
= 0;
2323 Optional32
->MajorSubsystemVersion
= 0;
2324 Optional32
->MinorSubsystemVersion
= 0;
2325 Optional32
->Win32VersionValue
= 0;
2326 Optional32
->CheckSum
= 0;
2327 Optional32
->SizeOfStackReserve
= 0;
2328 Optional32
->SizeOfStackCommit
= 0;
2329 Optional32
->SizeOfHeapReserve
= 0;
2330 Optional32
->SizeOfHeapCommit
= 0;
2332 TEImageHeader
.AddressOfEntryPoint
= Optional32
->AddressOfEntryPoint
;
2333 TEImageHeader
.BaseOfCode
= Optional32
->BaseOfCode
;
2334 TEImageHeader
.ImageBase
= (UINT64
) (Optional32
->ImageBase
);
2336 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2337 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2338 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2341 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2342 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2343 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2347 // Zero .pdata section data.
2349 if (!KeepExceptionTableFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2350 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2351 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2352 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2353 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2354 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2356 // Zero .pdata Section data
2358 memset (FileBuffer
+ SectionHeader
->PointerToRawData
, 0, SectionHeader
->SizeOfRawData
);
2360 // Zero .pdata Section header name
2362 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2364 // Zero Execption Table
2366 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2367 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2368 DebugMsg (NULL
, 0, 9, "Zero the .pdata section for PE image", NULL
);
2375 // Strip zero padding at the end of the .reloc section
2377 if (!KeepZeroPendingFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2378 if (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2379 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2380 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2382 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2384 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2385 SectionHeader
->Misc
.VirtualSize
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2386 AllignedRelocSize
= (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional32
->FileAlignment
- 1) & (~(Optional32
->FileAlignment
- 1));
2388 // Check to see if there is zero padding at the end of the base relocations
2390 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2392 // Check to see if the base relocations are at the end of the file
2394 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional32
->SizeOfImage
) {
2396 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2398 Optional32
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2399 Optional32
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2400 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2401 FileLength
= Optional32
->SizeOfImage
;
2402 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
));
2409 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2410 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2411 if (!KeepOptionalHeaderFlag
) {
2412 Optional64
->MajorOperatingSystemVersion
= 0;
2413 Optional64
->MinorOperatingSystemVersion
= 0;
2414 Optional64
->MajorImageVersion
= 0;
2415 Optional64
->MinorImageVersion
= 0;
2416 Optional64
->MajorSubsystemVersion
= 0;
2417 Optional64
->MinorSubsystemVersion
= 0;
2418 Optional64
->Win32VersionValue
= 0;
2419 Optional64
->CheckSum
= 0;
2420 Optional64
->SizeOfStackReserve
= 0;
2421 Optional64
->SizeOfStackCommit
= 0;
2422 Optional64
->SizeOfHeapReserve
= 0;
2423 Optional64
->SizeOfHeapCommit
= 0;
2425 TEImageHeader
.AddressOfEntryPoint
= Optional64
->AddressOfEntryPoint
;
2426 TEImageHeader
.BaseOfCode
= Optional64
->BaseOfCode
;
2427 TEImageHeader
.ImageBase
= (UINT64
) (Optional64
->ImageBase
);
2429 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2430 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2431 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2434 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2435 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2436 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2440 // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
2441 // For Itaninum and X64 Image, remove .pdata section.
2443 if ((!KeepExceptionTableFlag
&& PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_X64
) || PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
) {
2444 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2445 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2446 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2447 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2448 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2449 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2451 // Zero .pdata Section header name
2453 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2455 RuntimeFunction
= (RUNTIME_FUNCTION
*)(FileBuffer
+ SectionHeader
->PointerToRawData
);
2456 for (Index1
= 0; Index1
< Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
/ sizeof (RUNTIME_FUNCTION
); Index1
++, RuntimeFunction
++) {
2457 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2458 for (Index2
= 0; Index2
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index2
++, SectionHeader
++) {
2459 if (RuntimeFunction
->UnwindInfoAddress
>= SectionHeader
->VirtualAddress
&& RuntimeFunction
->UnwindInfoAddress
< (SectionHeader
->VirtualAddress
+ SectionHeader
->SizeOfRawData
)) {
2460 UnwindInfo
= (UNWIND_INFO
*)(FileBuffer
+ SectionHeader
->PointerToRawData
+ (RuntimeFunction
->UnwindInfoAddress
- SectionHeader
->VirtualAddress
));
2461 if (UnwindInfo
->Version
== 1) {
2462 memset (UnwindInfo
+ 1, 0, UnwindInfo
->CountOfUnwindCodes
* sizeof (UINT16
));
2463 memset (UnwindInfo
, 0, sizeof (UNWIND_INFO
));
2468 memset (RuntimeFunction
, 0, sizeof (RUNTIME_FUNCTION
));
2471 // Zero Execption Table
2473 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2474 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2475 DebugMsg (NULL
, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL
);
2483 // Strip zero padding at the end of the .reloc section
2485 if (!KeepZeroPendingFlag
&& Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2486 if (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].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
++) {
2490 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2492 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2493 SectionHeader
->Misc
.VirtualSize
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2494 AllignedRelocSize
= (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional64
->FileAlignment
- 1) & (~(Optional64
->FileAlignment
- 1));
2496 // Check to see if there is zero padding at the end of the base relocations
2498 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2500 // Check to see if the base relocations are at the end of the file
2502 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional64
->SizeOfImage
) {
2504 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2506 Optional64
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2507 Optional64
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2508 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2509 FileLength
= Optional64
->SizeOfImage
;
2510 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
));
2518 Error (NULL
, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr
->Pe32
.OptionalHeader
.Magic
, mInImageName
);
2522 if (((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) == 0) && \
2523 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
== 0) && \
2524 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
== 0)) {
2526 // PeImage can be loaded into memory, but it has no relocation section.
2527 // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
2529 if (Optional32
!= NULL
) {
2530 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
2531 } else if (Optional64
!= NULL
) {
2532 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
2537 // Fill HII section data
2539 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2540 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++) {
2541 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".hii") == 0) {
2543 // Update resource section header offset
2545 SetHiiResourceHeader ((UINT8
*) FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, SectionHeader
[Index
].VirtualAddress
);
2547 // Update resource section name
2549 strcpy((char *) SectionHeader
[Index
].Name
, ".rsrc");
2551 // Update resource data directory.
2553 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2554 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2555 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= SectionHeader
[Index
].VirtualAddress
;
2556 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= SectionHeader
[Index
].Misc
.VirtualSize
;
2557 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2558 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2559 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= SectionHeader
[Index
].VirtualAddress
;
2560 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= SectionHeader
[Index
].Misc
.VirtualSize
;
2567 // Zero ExceptionTable Xdata
2569 if (!KeepExceptionTableFlag
) {
2570 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2571 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++) {
2572 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".xdata") == 0) {
2574 // zero .xdata section
2576 memset (FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, 0, SectionHeader
[Index
].SizeOfRawData
);
2577 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
);
2584 // Zero Time/Data field
2586 ZeroDebugData (FileBuffer
, FALSE
);
2588 if (mOutImageType
== FW_TE_IMAGE
) {
2589 if ((PeHdr
->Pe32
.FileHeader
.NumberOfSections
&~0xFF) || (Type
&~0xFF)) {
2591 // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
2593 Error (NULL
, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName
);
2597 if ((PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
)) {
2599 // TeImage has the same section alignment and file alignment.
2601 Error (NULL
, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName
);
2605 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",
2606 TEImageHeader
.Machine
, TEImageHeader
.NumberOfSections
, TEImageHeader
.StrippedSize
, (unsigned) TEImageHeader
.AddressOfEntryPoint
, (unsigned) TEImageHeader
.BaseOfCode
, (unsigned long long) TEImageHeader
.ImageBase
);
2608 // Update Image to TeImage
2610 FileLength
= FileLength
- TEImageHeader
.StrippedSize
;
2611 memmove (FileBuffer
+ sizeof (EFI_TE_IMAGE_HEADER
), FileBuffer
+ TEImageHeader
.StrippedSize
, FileLength
);
2612 FileLength
= FileLength
+ sizeof (EFI_TE_IMAGE_HEADER
);
2613 memcpy (FileBuffer
, &TEImageHeader
, sizeof (EFI_TE_IMAGE_HEADER
));
2614 VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength
));
2618 // Following codes are to fix the objcopy's issue:
2619 // objcopy in binutil 2.50.18 will set PE image's charactices to "RELOC_STRIPPED" if image has no ".reloc" section
2620 // It cause issue for EFI image which has no ".reloc" sections.
2621 // Following codes will be removed when objcopy in binutil fix this problem for PE image.
2623 if ((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) != 0) {
2624 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2625 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2626 if (Optional32
->ImageBase
== 0) {
2627 PeHdr
->Pe32
.FileHeader
.Characteristics
&= ~EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2629 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2630 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2631 if (Optional64
->ImageBase
== 0) {
2632 PeHdr
->Pe32
.FileHeader
.Characteristics
&= ~EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2640 // Update Image to EfiImage or TE image
2643 if ((FileLength
!= InputFileLength
) || (memcmp (FileBuffer
, InputFileBuffer
, FileLength
) != 0)) {
2645 // Update File when File is changed.
2647 fpInOut
= fopen (LongFilePath (mInImageName
), "wb");
2648 if (fpInOut
== NULL
) {
2649 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2652 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2653 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2656 if ((OutputFileTime
< InputFileTime
) || (FileLength
!= OutputFileLength
) || (memcmp (FileBuffer
, OutputFileBuffer
, FileLength
) != 0)) {
2658 // Update File when File is changed or File is old.
2660 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
2661 if (fpOut
== NULL
) {
2662 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
2665 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2666 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2669 mImageSize
= FileLength
;
2672 if (fpInOut
!= NULL
) {
2673 if (GetUtilityStatus () != STATUS_SUCCESS
) {
2675 // when file updates failed, original file is still recovered.
2677 fwrite (InputFileBuffer
, 1, InputFileLength
, fpInOut
);
2680 // Write converted data into fpInOut file and close input file.
2685 if (FileBuffer
!= NULL
) {
2689 if (InputFileName
!= NULL
) {
2690 free (InputFileName
);
2693 if (fpOut
!= NULL
) {
2695 // Write converted data into fpOut file and close output file.
2698 if (GetUtilityStatus () != STATUS_SUCCESS
) {
2699 if (OutputFileBuffer
== NULL
) {
2700 remove (OutImageName
);
2702 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
2703 fwrite (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
2709 if (InputFileBuffer
!= NULL
) {
2710 free (InputFileBuffer
);
2713 if (OutputFileBuffer
!= NULL
) {
2714 free (OutputFileBuffer
);
2718 // Write module size and time stamp to report file.
2720 if (OutImageName
!= NULL
) {
2721 FileLen
= strlen (OutImageName
);
2723 if (FileLen
>= 4 && strcmp (OutImageName
+ (FileLen
- 4), ".efi") == 0) {
2724 ReportFileName
= (CHAR8
*) malloc (FileLen
+ 1);
2725 if (ReportFileName
!= NULL
) {
2726 strcpy (ReportFileName
, OutImageName
);
2727 strcpy (ReportFileName
+ (FileLen
- 4), ".txt");
2728 ReportFile
= fopen (LongFilePath (ReportFileName
), "w+");
2729 if (ReportFile
!= NULL
) {
2730 fprintf (ReportFile
, "MODULE_SIZE = %u\n", (unsigned) mImageSize
);
2731 fprintf (ReportFile
, "TIME_STAMP = %u\n", (unsigned) mImageTimeStamp
);
2734 free (ReportFileName
);
2737 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
2739 return GetUtilityStatus ();
2745 IN OUT UINT8
*FileBuffer
,
2746 BOOLEAN ZeroDebugFlag
2750 Routine Description:
2752 Zero debug information in PeImage.
2756 FileBuffer - Pointer to PeImage.
2757 ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp
2761 EFI_ABORTED - PeImage is invalid.
2762 EFI_SUCCESS - Zero debug data successfully.
2767 UINT32 DebugDirectoryEntryRva
;
2768 UINT32 DebugDirectoryEntryFileOffset
;
2769 UINT32 ExportDirectoryEntryRva
;
2770 UINT32 ExportDirectoryEntryFileOffset
;
2771 UINT32 ResourceDirectoryEntryRva
;
2772 UINT32 ResourceDirectoryEntryFileOffset
;
2773 EFI_IMAGE_DOS_HEADER
*DosHdr
;
2774 EFI_IMAGE_FILE_HEADER
*FileHdr
;
2775 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
2776 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
2777 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
2778 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
2779 UINT32
*NewTimeStamp
;
2784 DebugDirectoryEntryRva
= 0;
2785 ExportDirectoryEntryRva
= 0;
2786 ResourceDirectoryEntryRva
= 0;
2787 DebugDirectoryEntryFileOffset
= 0;
2788 ExportDirectoryEntryFileOffset
= 0;
2789 ResourceDirectoryEntryFileOffset
= 0;
2790 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2791 FileHdr
= (EFI_IMAGE_FILE_HEADER
*) (FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2794 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2795 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2796 // NO DOS header, must start with PE/COFF header
2797 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
2799 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2803 // Get Debug, Export and Resource EntryTable RVA address.
2804 // Resource Directory entry need to review.
2806 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
2807 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2808 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2809 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2810 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2811 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2813 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2814 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2815 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2817 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2818 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2819 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2820 if (ZeroDebugFlag
) {
2821 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
2822 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
2826 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2827 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2828 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2829 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2830 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2832 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2833 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2834 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2836 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2837 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2838 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2839 if (ZeroDebugFlag
) {
2840 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
2841 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
2847 // Get DirectoryEntryTable file offset.
2849 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2850 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2851 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2852 DebugDirectoryEntryFileOffset
=
2853 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2855 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2856 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2857 ExportDirectoryEntryFileOffset
=
2858 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2860 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2861 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2862 ResourceDirectoryEntryFileOffset
=
2863 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2868 //Zero Debug Data and TimeStamp
2870 FileHdr
->TimeDateStamp
= 0;
2871 mImageTimeStamp
= 0;
2872 if (ExportDirectoryEntryFileOffset
!= 0) {
2873 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
2877 if (ResourceDirectoryEntryFileOffset
!= 0) {
2878 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
2882 if (DebugDirectoryEntryFileOffset
!= 0) {
2883 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
);
2884 DebugEntry
->TimeDateStamp
= 0;
2885 mImageTimeStamp
= 0;
2886 if (ZeroDebugFlag
) {
2887 memset (FileBuffer
+ DebugEntry
->FileOffset
, 0, DebugEntry
->SizeOfData
);
2888 memset (DebugEntry
, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
2898 IN OUT UINT8
*FileBuffer
,
2903 Routine Description:
2905 Set new time stamp into PeImage FileHdr and Directory table:
2906 Debug, Export and Resource.
2910 FileBuffer - Pointer to PeImage.
2911 TimeStamp - Time stamp string.
2915 EFI_INVALID_PARAMETER - TimeStamp format is not recognized.
2916 EFI_SUCCESS - Set new time stamp in this image successfully.
2924 UINT32 DebugDirectoryEntryRva
;
2925 UINT32 DebugDirectoryEntryFileOffset
;
2926 UINT32 ExportDirectoryEntryRva
;
2927 UINT32 ExportDirectoryEntryFileOffset
;
2928 UINT32 ResourceDirectoryEntryRva
;
2929 UINT32 ResourceDirectoryEntryFileOffset
;
2930 EFI_IMAGE_DOS_HEADER
*DosHdr
;
2931 EFI_IMAGE_FILE_HEADER
*FileHdr
;
2932 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
2933 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
2934 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
2935 UINT32
*NewTimeStamp
;
2940 DebugDirectoryEntryRva
= 0;
2941 DebugDirectoryEntryFileOffset
= 0;
2942 ExportDirectoryEntryRva
= 0;
2943 ExportDirectoryEntryFileOffset
= 0;
2944 ResourceDirectoryEntryRva
= 0;
2945 ResourceDirectoryEntryFileOffset
= 0;
2947 // Get time and date that will be set.
2949 if (TimeStamp
== NULL
) {
2950 Error (NULL
, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");
2951 return EFI_INVALID_PARAMETER
;
2954 // compare the value with "NOW", if yes, current system time is set.
2956 if (stricmp (TimeStamp
, "NOW") == 0) {
2958 // get system current time and date
2963 // Check Time Format strictly yyyy-mm-dd 00:00:00
2965 for (Index
= 0; TimeStamp
[Index
] != '\0' && Index
< 20; Index
++) {
2966 if (Index
== 4 || Index
== 7) {
2967 if (TimeStamp
[Index
] == '-') {
2970 } else if (Index
== 13 || Index
== 16) {
2971 if (TimeStamp
[Index
] == ':') {
2974 } else if (Index
== 10 && TimeStamp
[Index
] == ' ') {
2976 } else if ((TimeStamp
[Index
] < '0') || (TimeStamp
[Index
] > '9')) {
2981 if (Index
< 19 || TimeStamp
[19] != '\0') {
2982 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
2983 return EFI_INVALID_PARAMETER
;
2987 // get the date and time from TimeStamp
2989 if (sscanf (TimeStamp
, "%d-%d-%d %d:%d:%d",
2997 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
2998 return EFI_INVALID_PARAMETER
;
3002 // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
3004 if (stime
.tm_mon
<= 0 || stime
.tm_mday
<=0) {
3005 Error (NULL
, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp
);
3006 return EFI_INVALID_PARAMETER
;
3011 // in struct, Year (current year minus 1900)
3012 // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
3015 // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
3017 if (stime
.tm_year
>= 1970 && stime
.tm_year
<= 2038) {
3019 // convert 1970 -> 70, 2000 -> 100, ...
3021 stime
.tm_year
-= 1900;
3023 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
3024 return EFI_INVALID_PARAMETER
;
3028 // convert the date and time to time_t format
3030 newtime
= mktime (&stime
);
3031 if (newtime
== (time_t) - 1) {
3032 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
3033 return EFI_INVALID_PARAMETER
;
3037 ptime
= localtime (&newtime
);
3038 DebugMsg (NULL
, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",
3039 ptime
->tm_year
+ 1900, ptime
->tm_mon
+ 1, ptime
->tm_mday
, ptime
->tm_hour
, ptime
->tm_min
, ptime
->tm_sec
);
3041 // Set new time and data into PeImage.
3043 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
3044 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
3045 // NO DOS header, must start with PE/COFF header
3046 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
3048 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
3052 // Get Debug, Export and Resource EntryTable RVA address.
3053 // Resource Directory entry need to review.
3055 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
3056 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3057 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3058 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3059 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3060 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3062 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3063 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3064 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3066 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3067 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3068 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3071 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3072 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3073 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3074 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3075 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3077 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3078 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3079 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3081 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3082 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3083 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3088 // Get DirectoryEntryTable file offset.
3090 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
3091 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3092 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3093 DebugDirectoryEntryFileOffset
=
3094 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3096 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3097 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3098 ExportDirectoryEntryFileOffset
=
3099 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3101 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3102 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3103 ResourceDirectoryEntryFileOffset
=
3104 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3111 FileHdr
->TimeDateStamp
= (UINT32
) newtime
;
3112 mImageTimeStamp
= (UINT32
) newtime
;
3113 if (ExportDirectoryEntryRva
!= 0) {
3114 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
3115 *NewTimeStamp
= (UINT32
) newtime
;
3118 if (ResourceDirectoryEntryRva
!= 0) {
3119 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
3120 *NewTimeStamp
= (UINT32
) newtime
;
3123 if (DebugDirectoryEntryRva
!= 0) {
3124 NewTimeStamp
= (UINT32
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
+ sizeof (UINT32
));
3125 *NewTimeStamp
= (UINT32
) newtime
;
3139 Routine Description:
3140 Read a 32-bit microcode data value from a text file and convert to raw binary form.
3143 InFptr - file pointer to input text file
3144 Data - pointer to where to return the data parsed
3147 STATUS_SUCCESS - no errors or warnings, Data contains valid information
3148 STATUS_ERROR - errors were encountered
3152 CHAR8 Line
[MAX_LINE_LEN
];
3154 unsigned ScannedData
= 0;
3156 Line
[MAX_LINE_LEN
- 1] = 0;
3158 if (fgets (Line
, MAX_LINE_LEN
, InFptr
) == NULL
) {
3159 return STATUS_ERROR
;
3162 // If it was a binary file, then it may have overwritten our null terminator
3164 if (Line
[MAX_LINE_LEN
- 1] != 0) {
3165 return STATUS_ERROR
;
3171 for (cptr
= Line
; *cptr
&& isspace((int)*cptr
); cptr
++) {
3174 // Skip Blank Lines and Comment Lines
3175 if ((strlen(cptr
) != 0) && (*cptr
!= ';')) {
3181 // dd 000000001h ; comment
3186 if ((tolower((int)cptr
[0]) == 'd') && (tolower((int)cptr
[1]) == 'd') && isspace ((int)cptr
[2])) {
3188 // Skip blanks and look for a hex digit
3191 for (; *cptr
&& isspace((int)*cptr
); cptr
++) {
3193 if (isxdigit ((int)*cptr
)) {
3194 if (sscanf (cptr
, "%X", &ScannedData
) != 1) {
3195 return STATUS_ERROR
;
3198 *Data
= (UINT32
) ScannedData
;
3199 return STATUS_SUCCESS
;
3202 return STATUS_ERROR
;