2 Converts a pe32+ image to an FW, Te image type, or other specific image.
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 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
;
95 BOOLEAN mIsConvertXip
= FALSE
;
101 IN OUT UINT8
*FileBuffer
,
108 IN OUT UINT8
*FileBuffer
,
128 Print out version information for this utility.
140 fprintf (stdout
, "%s Version %d.%d %s \n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
167 fprintf (stdout
, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME
);
170 // Copyright declaration
172 fprintf (stdout
, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
177 fprintf (stdout
, "Options:\n");
178 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
179 File will be created to store the ouput content.\n");
180 fprintf (stdout
, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\
181 Create Efi Image. EFI_FILETYPE is one of BASE,SMM_CORE,\n\
182 PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\
183 SEC, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER,\n\
184 DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER,\n\
185 MM_STANDALONE, MM_CORE_STANDALONE,\n\
186 PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\
187 APPLICATION, SAL_RT_DRIVER to support all module types\n\
188 It can only be used together with --keepexceptiontable,\n\
189 --keepzeropending, --keepoptionalheader, -r, -o option.\n\
190 It is a action option. If it is combined with other action options,\n\
191 the later input action option will override the previous one.\n");
192 fprintf (stdout
, " -c, --acpi Create Acpi table.\n\
193 It can't be combined with other action options\n\
194 except for -o, -r option. It is a action option.\n\
195 If it is combined with other action options, the later\n\
196 input action option will override the previous one.\n");
197 fprintf (stdout
, " -t, --terse Create Te Image.\n\
198 It can only be used together with --keepexceptiontable,\n\
199 --keepzeropending, --keepoptionalheader, -r, -o option.\n\
200 It is a action option. If it is combined with other action options,\n\
201 the later input action option will override the previous one.\n");
202 fprintf (stdout
, " -u, --dump Dump TeImage Header.\n\
203 It can't be combined with other action options\n\
204 except for -o, -r option. It is a action option.\n\
205 If it is combined with other action options, the later\n\
206 input action option will override the previous one.\n");
207 fprintf (stdout
, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\
208 It also zeros the time stamp fields.\n\
209 This option can be used to compare the binary efi image.\n\
210 It can't be combined with other action options\n\
211 except for -o, -r option. It is a action option.\n\
212 If it is combined with other action options, the later\n\
213 input action option will override the previous one.\n");
214 fprintf (stdout
, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\
215 It can't be combined with other action options\n\
216 except for -o, -r option. It is a action option.\n\
217 If it is combined with other action options, the later\n\
218 input action option will override the previous one.\n");;
219 fprintf (stdout
, " -l, --stripped Strip off the relocation info from PE or TE image.\n\
220 It can't be combined with other action options\n\
221 except for -o, -r option. It is a action option.\n\
222 If it is combined with other action options, the later\n\
223 input action option will override the previous one.\n");
224 fprintf (stdout
, " -s timedate, --stamp timedate\n\
225 timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\
226 is set to NOW, current system time is used. The support\n\
227 date scope is 1970-01-01 00+timezone:00:00\n\
228 ~ 2038-01-19 03+timezone:14:07\n\
229 The scope is adjusted according to the different zones.\n\
230 It can't be combined with other action options\n\
231 except for -o, -r option. It is a action option.\n\
232 If it is combined with other action options, the later\n\
233 input action option will override the previous one.\n");
234 fprintf (stdout
, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\
235 It can't be combined with other action options\n\
236 except for -o option. It is a action option.\n\
237 If it is combined with other action options, the later\n\
238 input action option will override the previous one.\n");
239 fprintf (stdout
, " -j, --join Combine multi microcode bin files to one file.\n\
240 It can be specified with -a, -p, -o option.\n\
241 No other options can be combined with it.\n\
242 If it is combined with other action options, the later\n\
243 input action option will override the previous one.\n");
244 fprintf (stdout
, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\
245 This option is only used together with -j option.\n");
246 fprintf (stdout
, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\
247 This option is only used together with -j option.\n");
248 fprintf (stdout
, " --keepexceptiontable Don't clear exception table.\n\
249 This option can be used together with -e or -t.\n\
250 It doesn't work for other options.\n");
251 fprintf (stdout
, " --keepoptionalheader Don't zero PE/COFF optional header fields.\n\
252 This option can be used together with -e or -t.\n\
253 It doesn't work for other options.\n");
254 fprintf (stdout
, " --keepzeropending Don't strip zero pending of .reloc.\n\
255 This option can be used together with -e or -t.\n\
256 It doesn't work for other options.\n");
257 fprintf (stdout
, " -r, --replace Overwrite the input file with the output content.\n\
258 If more input files are specified,\n\
259 the last input file will be as the output file.\n");
260 fprintf (stdout
, " -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\
261 Guid is used to specify hii package list guid.\n\
262 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\
263 If not specified, the first Form FormSet guid is used.\n");
264 fprintf (stdout
, " --hiipackage Combine all input binary hii pacakges into \n\
265 a single package list as the text resource data(RC).\n\
266 It can't be combined with other action options\n\
267 except for -o option. It is a action option.\n\
268 If it is combined with other action options, the later\n\
269 input action option will override the previous one.\n");
270 fprintf (stdout
, " --hiibinpackage Combine all input binary hii pacakges into \n\
271 a single package list as the binary resource section.\n\
272 It can't be combined with other action options\n\
273 except for -o option. It is a action option.\n\
274 If it is combined with other action options, the later\n\
275 input action option will override the previous one.\n");
276 fprintf (stdout
, " --rebase NewAddress Rebase image to new base address. New address \n\
277 is also set to the first none code section header.\n\
278 It can't be combined with other action options\n\
279 except for -o or -r option. It is a action option.\n\
280 If it is combined with other action options, the later\n\
281 input action option will override the previous one.\n");
282 fprintf (stdout
, " --address NewAddress Set new address into the first none code \n\
283 section header of the input image.\n\
284 It can't be combined with other action options\n\
285 except for -o or -r option. It is a action option.\n\
286 If it is combined with other action options, the later\n\
287 input action option will override the previous one.\n");
288 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
289 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
290 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
291 fprintf (stdout
, " --version Show program's version number and exit\n");
292 fprintf (stdout
, " -h, --help Show this help message and exit\n");
309 AcpiTable Buffer for AcpiSection
310 Length AcpiSection Length
319 EFI_ACPI_DESCRIPTION_HEADER
*AcpiHeader
;
320 EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs
;
321 UINT32 ExpectedLength
;
323 AcpiHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTable
;
326 // Generic check for AcpiTable length.
328 if (AcpiHeader
->Length
> Length
) {
329 Error (NULL
, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL
);
334 // Currently, we only check must-have tables: FADT, FACS, DSDT,
335 // and some important tables: MADT, MCFG.
337 switch (AcpiHeader
->Signature
) {
340 // "FACP" Fixed ACPI Description Table
342 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
:
343 switch (AcpiHeader
->Revision
) {
344 case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
345 ExpectedLength
= sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
);
347 case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
348 ExpectedLength
= sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
);
350 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
351 ExpectedLength
= sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
);
354 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
) {
355 ExpectedLength
= AcpiHeader
->Length
;
358 Error (NULL
, 0, 3000, "Invalid", "FACP revision check failed.");
361 if (ExpectedLength
!= AcpiHeader
->Length
) {
362 Error (NULL
, 0, 3000, "Invalid", "FACP length check failed.");
368 // "FACS" Firmware ACPI Control Structure
370 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE
:
371 Facs
= (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)AcpiTable
;
372 if (Facs
->Version
> EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) {
375 if ((Facs
->Version
!= EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
376 (Facs
->Version
!= EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
377 (Facs
->Version
!= EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
)){
378 Error (NULL
, 0, 3000, "Invalid", "FACS version check failed.");
381 if ((Facs
->Length
!= sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
382 (Facs
->Length
!= sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
383 (Facs
->Length
!= sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
))) {
384 Error (NULL
, 0, 3000, "Invalid", "FACS length check failed.");
390 // "DSDT" Differentiated System Description Table
392 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
393 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION
) {
396 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
)) {
397 Error (NULL
, 0, 3000, "Invalid", "DSDT length check failed.");
403 // "APIC" Multiple APIC Description Table
405 case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE
:
406 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) {
409 if ((AcpiHeader
->Revision
!= EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
410 (AcpiHeader
->Revision
!= EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
411 (AcpiHeader
->Revision
!= EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
)) {
412 Error (NULL
, 0, 3000, "Invalid", "APIC revision check failed.");
415 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT32
) + sizeof(UINT32
)) {
416 Error (NULL
, 0, 3000, "Invalid", "APIC length check failed.");
422 // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
424 case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE
:
425 if (AcpiHeader
->Revision
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
428 if (AcpiHeader
->Revision
!= EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
429 Error (NULL
, 0, 3000, "Invalid", "MCFG revision check failed.");
432 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT64
)) {
433 Error (NULL
, 0, 3000, "Invalid", "MCFG length check failed.");
439 // Other table pass check
445 return STATUS_SUCCESS
;
449 SetHiiResourceHeader (
455 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
456 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*ResourceDirectoryEntry
;
457 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
458 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
461 // Fill Resource section entry
463 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
);
464 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
465 for (Index
= 0; Index
< ResourceDirectory
->NumberOfNamedEntries
; Index
++) {
466 if (ResourceDirectoryEntry
->u1
.s
.NameIsString
) {
467 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiBinData
+ ResourceDirectoryEntry
->u1
.s
.NameOffset
);
469 if (ResourceDirectoryString
->Length
== 3 &&
470 ResourceDirectoryString
->String
[0] == L
'H' &&
471 ResourceDirectoryString
->String
[1] == L
'I' &&
472 ResourceDirectoryString
->String
[2] == L
'I') {
474 // Resource Type "HII" found
476 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
478 // Move to next level - resource Name
480 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
481 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
483 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
485 // Move to next level - resource Language
487 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
488 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
493 // Now it ought to be resource Data and update its OffsetToData value
495 if (!ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
496 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.OffsetToData
);
497 ResourceDataEntry
->OffsetToData
= ResourceDataEntry
->OffsetToData
+ OffsetToFile
;
502 ResourceDirectoryEntry
++;
508 EFI_IMAGE_OPTIONAL_HEADER_UNION
*
513 EFI_IMAGE_DOS_HEADER
*DosHdr
;
514 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
517 // Read the dos & pe hdrs of the image
519 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Data
;
520 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
521 // NO DOS header, check for PE/COFF header
522 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(Data
);
523 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
528 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(((UINT8
*)Data
) + DosHdr
->e_lfanew
);
529 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
538 PeCoffConvertImageToXip (
543 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
544 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NewPeHdr
;
545 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
546 UINTN TotalNecessaryFileSize
;
551 UINTN FirstSectionOffset
;
552 BOOLEAN ConversionNeeded
;
554 PeHdr
= GetPeCoffHeader ((void *) *FileBuffer
);
559 if (PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
) {
561 // The only reason to expand zero fill sections is to make them compatible with XIP images.
562 // If SectionAlignment is not equal to FileAlginment then it is not an XIP type image.
568 // Calculate size of XIP file, and determine if the conversion is needed.
570 ConversionNeeded
= FALSE
;
572 FirstSectionOffset
= *FileLength
;
573 TotalNecessaryFileSize
= 0;
574 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
575 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
576 SectionSize
= MAX (SectionHeader
->Misc
.VirtualSize
, SectionHeader
->SizeOfRawData
);
577 TotalNecessaryFileSize
+= SectionSize
;
578 if (SectionSize
> 0) {
579 FirstSectionOffset
= MIN (FirstSectionOffset
, SectionHeader
->VirtualAddress
);
580 XipLength
= MAX (XipLength
, SectionHeader
->VirtualAddress
+ SectionSize
);
581 if (SectionHeader
->VirtualAddress
!= SectionHeader
->PointerToRawData
) {
582 ConversionNeeded
= TRUE
;
585 if (SectionHeader
->Misc
.VirtualSize
> SectionHeader
->SizeOfRawData
) {
586 ConversionNeeded
= TRUE
;
590 if (FirstSectionOffset
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
592 // If one of the sections should be loaded to an offset overlapping with
593 // the executable header, then it cannot be made into an XIP image.
595 VerboseMsg ("PE/COFF conversion to XIP is impossible due to overlap");
596 VerboseMsg ("of section data with the executable header.");
600 if (FirstSectionOffset
== *FileLength
) {
602 // If we never found a section with a non-zero size, then we
603 // skip the conversion.
608 TotalNecessaryFileSize
+= FirstSectionOffset
;
610 if (!ConversionNeeded
) {
614 if (XipLength
> (2 * TotalNecessaryFileSize
)) {
615 VerboseMsg ("PE/COFF conversion to XIP appears to be larger than necessary.");
616 VerboseMsg ("The image linking process may have left unused memory ranges.");
619 if (PeHdr
->Pe32
.FileHeader
.PointerToSymbolTable
!= 0) {
621 // This field is obsolete and should be zero
623 PeHdr
->Pe32
.FileHeader
.PointerToSymbolTable
= 0;
627 // Allocate the extra space that we need to grow the image
629 XipFile
= malloc (XipLength
);
630 if (XipFile
== NULL
) {
631 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
634 memset (XipFile
, 0, XipLength
);
637 // Copy the file headers
639 memcpy (XipFile
, *FileBuffer
, PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
);
641 NewPeHdr
= GetPeCoffHeader ((void *)XipFile
);
642 if (NewPeHdr
== NULL
) {
648 // Copy the section data over to the appropriate XIP offsets
650 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(NewPeHdr
->Pe32
.OptionalHeader
) + NewPeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
651 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
652 if (SectionHeader
->SizeOfRawData
> 0) {
654 XipFile
+ SectionHeader
->VirtualAddress
,
655 *FileBuffer
+ SectionHeader
->PointerToRawData
,
656 SectionHeader
->SizeOfRawData
660 // Make the size of raw data in section header alignment.
662 SectionHeader
->SizeOfRawData
= (SectionHeader
->Misc
.VirtualSize
+ PeHdr
->Pe32
.OptionalHeader
.FileAlignment
- 1) & (~(PeHdr
->Pe32
.OptionalHeader
.FileAlignment
- 1));
663 SectionHeader
->PointerToRawData
= SectionHeader
->VirtualAddress
;
667 *FileLength
= XipLength
;
668 *FileBuffer
= XipFile
;
670 mIsConvertXip
= TRUE
;
674 CreateHiiResouceSectionHeader (
675 UINT32
*pSectionHeaderSize
,
682 Create COFF resource section header
686 pSectionHeaderSize - Pointer to section header size.
687 HiiDataSize - Size of the total HII data in section.
690 The created section header buffer.
694 UINT32 HiiSectionHeaderSize
;
695 UINT32 HiiSectionOffset
;
696 UINT8
*HiiSectionHeader
;
697 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
698 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*TypeResourceDirectoryEntry
;
699 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*NameResourceDirectoryEntry
;
700 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*LanguageResourceDirectoryEntry
;
701 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
702 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
705 // Calculate the total size for the resource header (include Type, Name and Language)
706 // then allocate memory for the resource header.
708 HiiSectionHeaderSize
= 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
))
709 + 3 * (sizeof (UINT16
) + 3 * sizeof (CHAR16
))
710 + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
711 HiiSectionHeader
= malloc (HiiSectionHeaderSize
);
712 if (HiiSectionHeader
== NULL
) {
713 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
716 memset (HiiSectionHeader
, 0, HiiSectionHeaderSize
);
718 HiiSectionOffset
= 0;
722 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
723 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
724 ResourceDirectory
->NumberOfNamedEntries
= 1;
725 TypeResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
726 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
727 TypeResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
728 TypeResourceDirectoryEntry
->u2
.s
.DataIsDirectory
= 1;
729 TypeResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
= HiiSectionOffset
;
733 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
734 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
735 ResourceDirectory
->NumberOfNamedEntries
= 1;
736 NameResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
737 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
738 NameResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
739 NameResourceDirectoryEntry
->u2
.s
.DataIsDirectory
= 1;
740 NameResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
= HiiSectionOffset
;
742 // Create Language entry
744 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
745 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
746 ResourceDirectory
->NumberOfNamedEntries
= 1;
747 LanguageResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
748 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
749 LanguageResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
751 // Create string entry for Type
753 TypeResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
754 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
755 ResourceDirectoryString
->Length
= 3;
756 ResourceDirectoryString
->String
[0] = L
'H';
757 ResourceDirectoryString
->String
[1] = L
'I';
758 ResourceDirectoryString
->String
[2] = L
'I';
759 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
761 // Create string entry for Name
763 NameResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
764 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
765 ResourceDirectoryString
->Length
= 3;
766 ResourceDirectoryString
->String
[0] = L
'E';
767 ResourceDirectoryString
->String
[1] = L
'F';
768 ResourceDirectoryString
->String
[2] = L
'I';
769 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
771 // Create string entry for Language
773 LanguageResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
774 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
775 ResourceDirectoryString
->Length
= 3;
776 ResourceDirectoryString
->String
[0] = L
'B';
777 ResourceDirectoryString
->String
[1] = L
'I';
778 ResourceDirectoryString
->String
[2] = L
'N';
779 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
783 LanguageResourceDirectoryEntry
->u2
.OffsetToData
= HiiSectionOffset
;
784 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
785 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
786 ResourceDataEntry
->OffsetToData
= HiiSectionOffset
;
787 ResourceDataEntry
->Size
= HiiDataSize
;
789 *pSectionHeaderSize
= HiiSectionHeaderSize
;
790 return HiiSectionHeader
;
797 IN OUT UINT32
*ReadSize
,
804 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
808 FileHandle - The handle to the PE/COFF file
810 FileOffset - The offset, in bytes, into the file to read
812 ReadSize - The number of bytes to read from the file starting at FileOffset
814 Buffer - A pointer to the buffer to read the data into.
818 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
826 Destination8
= Buffer
;
827 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
830 *(Destination8
++) = *(Source8
++);
837 SetAddressToSectionHeader (
839 IN OUT UINT8
*FileBuffer
,
840 IN UINT64 NewPe32BaseAddress
846 Set new base address into the section header of PeImage
850 FileName - Name of file
851 FileBuffer - Pointer to PeImage.
852 NewPe32BaseAddress - New Base Address for PE image.
856 EFI_SUCCESS Set new base address into this image successfully.
861 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
863 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
864 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
867 // Initialize context
869 memset (&ImageContext
, 0, sizeof (ImageContext
));
870 ImageContext
.Handle
= (VOID
*) FileBuffer
;
871 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
872 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
873 if (EFI_ERROR (Status
)) {
874 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
878 if (ImageContext
.RelocationsStripped
) {
879 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
884 // Get PeHeader pointer
886 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
889 // Get section header list
891 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
894 sizeof (EFI_IMAGE_FILE_HEADER
) +
895 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
899 // Set base address into the first section header that doesn't point to code section.
901 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
902 if ((SectionHeader
->Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
903 *(UINT64
*) &SectionHeader
->PointerToRelocations
= NewPe32BaseAddress
;
909 // BaseAddress is set to section header.
917 IN OUT UINT8
*FileBuffer
,
918 IN UINT64 NewPe32BaseAddress
924 Set new base address into PeImage, and fix up PeImage based on new address.
928 FileName - Name of file
929 FileBuffer - Pointer to PeImage.
930 NewPe32BaseAddress - New Base Address for PE image.
934 EFI_INVALID_PARAMETER - BaseAddress is not valid.
935 EFI_SUCCESS - Update PeImage is correctly.
940 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
942 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
943 UINT8
*MemoryImagePointer
;
944 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
947 // Initialize context
949 memset (&ImageContext
, 0, sizeof (ImageContext
));
950 ImageContext
.Handle
= (VOID
*) FileBuffer
;
951 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
952 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
953 if (EFI_ERROR (Status
)) {
954 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
958 if (ImageContext
.RelocationsStripped
) {
959 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
964 // Get PeHeader pointer
966 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
969 // Load and Relocate Image Data
971 MemoryImagePointer
= (UINT8
*) malloc ((UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
972 if (MemoryImagePointer
== NULL
) {
973 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
974 return EFI_OUT_OF_RESOURCES
;
976 memset ((VOID
*) MemoryImagePointer
, 0, (UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
977 ImageContext
.ImageAddress
= ((UINTN
) MemoryImagePointer
+ ImageContext
.SectionAlignment
- 1) & (~((INT64
)ImageContext
.SectionAlignment
- 1));
979 Status
= PeCoffLoaderLoadImage (&ImageContext
);
980 if (EFI_ERROR (Status
)) {
981 Error (NULL
, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName
);
982 free ((VOID
*) MemoryImagePointer
);
986 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
987 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
988 if (EFI_ERROR (Status
)) {
989 Error (NULL
, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName
);
990 free ((VOID
*) MemoryImagePointer
);
995 // Copy Relocated data to raw image file.
997 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1000 sizeof (EFI_IMAGE_FILE_HEADER
) +
1001 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1004 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1006 FileBuffer
+ SectionHeader
->PointerToRawData
,
1007 (VOID
*) (UINTN
) (ImageContext
.ImageAddress
+ SectionHeader
->VirtualAddress
),
1008 SectionHeader
->SizeOfRawData
1012 free ((VOID
*) MemoryImagePointer
);
1015 // Update Image Base Address
1017 if ((ImgHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) && (ImgHdr
->Pe32
.FileHeader
.Machine
!= IMAGE_FILE_MACHINE_IA64
)) {
1018 ImgHdr
->Pe32
.OptionalHeader
.ImageBase
= (UINT32
) NewPe32BaseAddress
;
1019 } else if (ImgHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1020 ImgHdr
->Pe32Plus
.OptionalHeader
.ImageBase
= NewPe32BaseAddress
;
1022 Error (NULL
, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
1023 ImgHdr
->Pe32
.OptionalHeader
.Magic
,
1030 // Set new base address into section header
1032 Status
= SetAddressToSectionHeader (FileName
, FileBuffer
, NewPe32BaseAddress
);
1044 Routine Description:
1050 argc - Number of command line parameters.
1051 argv - Array of pointers to command line parameter strings.
1054 STATUS_SUCCESS - Utility exits successfully.
1055 STATUS_ERROR - Some error occurred during execution.
1060 UINT32 InputFileNum
;
1061 CHAR8
**InputFileName
;
1069 UINT32
*DataPointer
;
1070 UINT32
*OldDataPointer
;
1076 UINT32 MciAlignment
;
1078 UINT32 AllignedRelocSize
;
1081 UINT8
*OutputFileBuffer
;
1082 UINT32 OutputFileLength
;
1083 UINT8
*InputFileBuffer
;
1084 UINT32 InputFileLength
;
1085 RUNTIME_FUNCTION
*RuntimeFunction
;
1086 UNWIND_INFO
*UnwindInfo
;
1088 BOOLEAN ReplaceFlag
;
1089 BOOLEAN KeepExceptionTableFlag
;
1090 BOOLEAN KeepOptionalHeaderFlag
;
1091 BOOLEAN KeepZeroPendingFlag
;
1093 EFI_TE_IMAGE_HEADER TEImageHeader
;
1094 EFI_TE_IMAGE_HEADER
*TeHdr
;
1095 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1096 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1097 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1098 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32
;
1099 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64
;
1100 EFI_IMAGE_DOS_HEADER BackupDosHdr
;
1101 MICROCODE_IMAGE_HEADER
*MciHeader
;
1102 UINT8
*HiiPackageListBuffer
;
1103 UINT8
*HiiPackageDataPointer
;
1104 EFI_GUID HiiPackageListGuid
;
1105 EFI_HII_PACKAGE_LIST_HEADER HiiPackageListHeader
;
1106 EFI_HII_PACKAGE_HEADER HiiPackageHeader
;
1107 EFI_IFR_FORM_SET IfrFormSet
;
1108 UINT8 NumberOfFormPackage
;
1109 EFI_HII_PACKAGE_HEADER EndPackage
;
1110 UINT32 HiiSectionHeaderSize
;
1111 UINT8
*HiiSectionHeader
;
1112 UINT64 NewBaseAddress
;
1113 BOOLEAN NegativeAddr
;
1115 CHAR8
*ReportFileName
;
1117 time_t InputFileTime
;
1118 time_t OutputFileTime
;
1119 struct stat Stat_Buf
;
1121 SetUtilityName (UTILITY_NAME
);
1124 // Assign to fix compile warning
1128 InputFileName
= NULL
;
1129 mInImageName
= NULL
;
1130 OutImageName
= NULL
;
1133 Status
= STATUS_SUCCESS
;
1139 MciAlignment
= DEFAULT_MC_ALIGNMENT
;
1140 MciPadValue
= DEFAULT_MC_PAD_BYTE_VALUE
;
1144 ReplaceFlag
= FALSE
;
1146 OutputFileBuffer
= NULL
;
1147 OutputFileLength
= 0;
1148 InputFileBuffer
= NULL
;
1149 InputFileLength
= 0;
1152 KeepExceptionTableFlag
= FALSE
;
1153 KeepOptionalHeaderFlag
= FALSE
;
1154 KeepZeroPendingFlag
= FALSE
;
1155 NumberOfFormPackage
= 0;
1156 HiiPackageListBuffer
= NULL
;
1157 HiiPackageDataPointer
= NULL
;
1158 EndPackage
.Length
= sizeof (EFI_HII_PACKAGE_HEADER
);
1159 EndPackage
.Type
= EFI_HII_PACKAGE_END
;
1160 memset (&HiiPackageListGuid
, 0, sizeof (HiiPackageListGuid
));
1161 HiiSectionHeaderSize
= 0;
1162 HiiSectionHeader
= NULL
;
1164 NegativeAddr
= FALSE
;
1169 Error (NULL
, 0, 1001, "Missing options", "No input options.");
1171 return STATUS_ERROR
;
1177 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
1180 return STATUS_SUCCESS
;
1183 if (stricmp (argv
[0], "--version") == 0) {
1185 return STATUS_SUCCESS
;
1189 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
1190 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1191 Error (NULL
, 0, 1003, "Invalid option value", "Output file name is missing for -o option");
1194 OutImageName
= argv
[1];
1200 if ((stricmp (argv
[0], "-e") == 0) || (stricmp (argv
[0], "--efiImage") == 0)) {
1201 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1202 Error (NULL
, 0, 1003, "Invalid option value", "Module Type is missing for -o option");
1205 ModuleType
= argv
[1];
1206 if (mOutImageType
!= FW_TE_IMAGE
) {
1207 mOutImageType
= FW_EFI_IMAGE
;
1214 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--stripped") == 0)) {
1215 mOutImageType
= FW_RELOC_STRIPEED_IMAGE
;
1221 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--acpi") == 0)) {
1222 mOutImageType
= FW_ACPI_IMAGE
;
1228 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--terse") == 0)) {
1229 mOutImageType
= FW_TE_IMAGE
;
1235 if ((stricmp (argv
[0], "-u") == 0) || (stricmp (argv
[0], "--dump") == 0)) {
1236 mOutImageType
= DUMP_TE_HEADER
;
1242 if ((stricmp (argv
[0], "-b") == 0) || (stricmp (argv
[0], "--exe2bin") == 0)) {
1243 mOutImageType
= FW_BIN_IMAGE
;
1249 if ((stricmp (argv
[0], "-z") == 0) || (stricmp (argv
[0], "--zero") == 0)) {
1250 mOutImageType
= FW_ZERO_DEBUG_IMAGE
;
1256 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--stamp") == 0)) {
1257 mOutImageType
= FW_SET_STAMP_IMAGE
;
1258 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1259 Error (NULL
, 0, 1003, "Invalid option value", "time stamp is missing for -s option");
1262 TimeStamp
= argv
[1];
1268 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--replace") == 0)) {
1275 if (stricmp (argv
[0], "--keepexceptiontable") == 0) {
1276 KeepExceptionTableFlag
= TRUE
;
1282 if (stricmp(argv
[0], "--keepoptionalheader") == 0) {
1283 KeepOptionalHeaderFlag
= TRUE
;
1289 if (stricmp (argv
[0], "--keepzeropending") == 0) {
1290 KeepZeroPendingFlag
= TRUE
;
1296 if ((stricmp (argv
[0], "-m") == 0) || (stricmp (argv
[0], "--mcifile") == 0)) {
1297 mOutImageType
= FW_MCI_IMAGE
;
1303 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--join") == 0)) {
1304 mOutImageType
= FW_MERGE_IMAGE
;
1310 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
1311 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1312 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1315 MciAlignment
= (UINT32
) Temp64
;
1321 if ((stricmp (argv
[0], "--rebase") == 0)) {
1322 if (argv
[1][0] == '-') {
1323 NegativeAddr
= TRUE
;
1324 Status
= AsciiStringToUint64 (argv
[1] + 1, FALSE
, &Temp64
);
1326 NegativeAddr
= FALSE
;
1327 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
);
1329 if (Status
!= EFI_SUCCESS
) {
1330 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1333 mOutImageType
= FW_REBASE_IMAGE
;
1334 NewBaseAddress
= (UINT64
) Temp64
;
1340 if ((stricmp (argv
[0], "--address") == 0)) {
1341 if (argv
[1][0] == '-') {
1342 NegativeAddr
= TRUE
;
1343 Status
= AsciiStringToUint64 (argv
[1] + 1, FALSE
, &Temp64
);
1345 NegativeAddr
= FALSE
;
1346 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
);
1348 if (Status
!= EFI_SUCCESS
) {
1349 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1352 mOutImageType
= FW_SET_ADDRESS_IMAGE
;
1353 NewBaseAddress
= (UINT64
) Temp64
;
1359 if ((stricmp (argv
[0], "-p") == 0) || (stricmp (argv
[0], "--pad") == 0)) {
1360 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1361 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1364 MciPadValue
= (UINT8
) Temp64
;
1370 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
1371 SetPrintLevel (VERBOSE_LOG_LEVEL
);
1372 VerboseMsg ("Verbose output Mode Set!");
1378 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1379 SetPrintLevel (KEY_LOG_LEVEL
);
1380 KeyMsg ("Quiet output Mode Set!");
1386 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
1387 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
1388 if (EFI_ERROR (Status
)) {
1389 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1393 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel
);
1396 SetPrintLevel (LogLevel
);
1397 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
1403 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--hiiguid") == 0)) {
1404 Status
= StringToGuid (argv
[1], &HiiPackageListGuid
);
1405 if (EFI_ERROR (Status
)) {
1406 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1414 if (stricmp (argv
[0], "--hiipackage") == 0) {
1415 mOutImageType
= FW_HII_PACKAGE_LIST_RCIMAGE
;
1421 if (stricmp (argv
[0], "--hiibinpackage") == 0) {
1422 mOutImageType
= FW_HII_PACKAGE_LIST_BINIMAGE
;
1428 if (argv
[0][0] == '-') {
1429 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
1433 // Get Input file name
1435 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
1436 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
1437 if (InputFileName
== NULL
) {
1438 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1442 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1443 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1445 // InputFileName buffer too small, need to realloc
1447 InputFileName
= (CHAR8
**) realloc (
1449 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1452 if (InputFileName
== NULL
) {
1453 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1457 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1460 InputFileName
[InputFileNum
++] = argv
[0];
1465 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1467 if (mOutImageType
== FW_DUMMY_IMAGE
) {
1468 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!");
1470 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.");
1476 // check input files
1478 if (InputFileNum
== 0) {
1479 Error (NULL
, 0, 1001, "Missing option", "Input files");
1484 // Combine MciBinary files to one file
1486 if ((mOutImageType
== FW_MERGE_IMAGE
) && ReplaceFlag
) {
1487 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");
1492 // Combine HiiBinary packages to a single package list
1494 if ((mOutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) && ReplaceFlag
) {
1495 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option.");
1499 if ((mOutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) && ReplaceFlag
) {
1500 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiibinpackage merge files option.");
1507 mInImageName
= InputFileName
[InputFileNum
- 1];
1508 VerboseMsg ("the input file name is %s", mInImageName
);
1511 // Action will be taken for the input file.
1513 switch (mOutImageType
) {
1515 VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType
);
1518 VerboseMsg ("Create Te Image based on the input PE image.");
1521 VerboseMsg ("Get acpi table data from the input PE image.");
1523 case FW_RELOC_STRIPEED_IMAGE
:
1524 VerboseMsg ("Remove relocation section from Pe or Te image.");
1527 VerboseMsg ("Convert the input EXE to the output BIN file.");
1529 case FW_ZERO_DEBUG_IMAGE
:
1530 VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");
1532 case FW_SET_STAMP_IMAGE
:
1533 VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp
);
1535 case DUMP_TE_HEADER
:
1536 VerboseMsg ("Dump the TE header information of the input TE image.");
1539 VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");
1541 case FW_MERGE_IMAGE
:
1542 VerboseMsg ("Combine the input multi microcode bin files to one bin file.");
1544 case FW_HII_PACKAGE_LIST_RCIMAGE
:
1545 VerboseMsg ("Combine the input multi hii bin packages to one text pacakge list RC file.");
1547 case FW_HII_PACKAGE_LIST_BINIMAGE
:
1548 VerboseMsg ("Combine the input multi hii bin packages to one binary pacakge list file.");
1550 case FW_REBASE_IMAGE
:
1551 VerboseMsg ("Rebase the input image to new base address.");
1553 case FW_SET_ADDRESS_IMAGE
:
1554 VerboseMsg ("Set the preferred address into the section header of the input image");
1561 VerboseMsg ("Overwrite the input file with the output content.");
1565 // Open output file and Write image into the output file.
1567 if (OutImageName
!= NULL
) {
1568 fpOut
= fopen (LongFilePath (OutImageName
), "rb");
1569 if (fpOut
!= NULL
) {
1571 // Get Output file time stamp
1573 fstat(fileno (fpOut
), &Stat_Buf
);
1574 OutputFileTime
= Stat_Buf
.st_mtime
;
1576 // Get Output file data
1578 OutputFileLength
= _filelength (fileno (fpOut
));
1579 OutputFileBuffer
= malloc (OutputFileLength
);
1580 if (OutputFileBuffer
== NULL
) {
1581 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1586 fread (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
1590 VerboseMsg ("Output file name is %s", OutImageName
);
1591 } else if (!ReplaceFlag
&& mOutImageType
!= DUMP_TE_HEADER
) {
1592 Error (NULL
, 0, 1001, "Missing option", "output file");
1597 // Open input file and read file data into file buffer.
1599 fpIn
= fopen (LongFilePath (mInImageName
), "rb");
1601 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1605 // Get Iutput file time stamp
1607 fstat(fileno (fpIn
), &Stat_Buf
);
1608 InputFileTime
= Stat_Buf
.st_mtime
;
1610 // Get Input file data
1612 InputFileLength
= _filelength (fileno (fpIn
));
1613 InputFileBuffer
= malloc (InputFileLength
);
1614 if (InputFileBuffer
== NULL
) {
1615 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1619 fread (InputFileBuffer
, 1, InputFileLength
, fpIn
);
1621 DebugMsg (NULL
, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) InputFileLength
);
1624 // Combine multi binary HII package files.
1626 if (mOutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
|| mOutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) {
1628 // Open output file handle.
1630 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
1632 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1636 // Get hii package list lenght
1638 HiiPackageListHeader
.PackageLength
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1639 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1640 fpIn
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
1642 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1645 FileLength
= _filelength (fileno (fpIn
));
1646 fread (&HiiPackageHeader
, 1, sizeof (HiiPackageHeader
), fpIn
);
1647 if (HiiPackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) {
1648 if (HiiPackageHeader
.Length
!= FileLength
) {
1649 Error (NULL
, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName
[Index
]);
1653 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
1654 fread (&IfrFormSet
, 1, sizeof (IfrFormSet
), fpIn
);
1655 memcpy (&HiiPackageListGuid
, &IfrFormSet
.Guid
, sizeof (EFI_GUID
));
1657 NumberOfFormPackage
++;
1659 HiiPackageListHeader
.PackageLength
+= FileLength
;
1662 HiiPackageListHeader
.PackageLength
+= sizeof (EndPackage
);
1664 // Check whether hii packages are valid
1666 if (NumberOfFormPackage
> 1) {
1667 Error (NULL
, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package");
1670 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
1671 Error (NULL
, 0, 3000, "Invalid", "HII pacakge list guid is not specified!");
1674 memcpy (&HiiPackageListHeader
.PackageListGuid
, &HiiPackageListGuid
, sizeof (EFI_GUID
));
1676 // read hii packages
1678 HiiPackageListBuffer
= malloc (HiiPackageListHeader
.PackageLength
);
1679 if (HiiPackageListBuffer
== NULL
) {
1680 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1683 memcpy (HiiPackageListBuffer
, &HiiPackageListHeader
, sizeof (HiiPackageListHeader
));
1684 HiiPackageDataPointer
= HiiPackageListBuffer
+ sizeof (HiiPackageListHeader
);
1685 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1686 fpIn
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
1688 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1689 free (HiiPackageListBuffer
);
1693 FileLength
= _filelength (fileno (fpIn
));
1694 fread (HiiPackageDataPointer
, 1, FileLength
, fpIn
);
1696 HiiPackageDataPointer
= HiiPackageDataPointer
+ FileLength
;
1698 memcpy (HiiPackageDataPointer
, &EndPackage
, sizeof (EndPackage
));
1701 // write the hii package into the binary package list file with the resource section header
1703 if (mOutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) {
1705 // Create the resource section header
1707 HiiSectionHeader
= CreateHiiResouceSectionHeader (&HiiSectionHeaderSize
, HiiPackageListHeader
.PackageLength
);
1708 if (HiiSectionHeader
== NULL
) {
1709 free (HiiPackageListBuffer
);
1713 // Wrtie section header and HiiData into File.
1715 fwrite (HiiSectionHeader
, 1, HiiSectionHeaderSize
, fpOut
);
1716 fwrite (HiiPackageListBuffer
, 1, HiiPackageListHeader
.PackageLength
, fpOut
);
1718 // Free allocated resources.
1720 free (HiiSectionHeader
);
1721 free (HiiPackageListBuffer
);
1723 // Done successfully
1729 // write the hii package into the text package list rc file.
1731 if (mOutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) {
1732 for (Index
= 0; gHiiPackageRCFileHeader
[Index
] != NULL
; Index
++) {
1733 fprintf (fpOut
, "%s\n", gHiiPackageRCFileHeader
[Index
]);
1735 fprintf (fpOut
, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX
, HII_RESOURCE_SECTION_NAME
);
1737 HiiPackageDataPointer
= HiiPackageListBuffer
;
1738 for (Index
= 0; Index
+ 2 < HiiPackageListHeader
.PackageLength
; Index
+= 2) {
1739 if (Index
% 16 == 0) {
1740 fprintf (fpOut
, "\n ");
1742 fprintf (fpOut
, " 0x%04X,", *(UINT16
*) HiiPackageDataPointer
);
1743 HiiPackageDataPointer
+= 2;
1746 if (Index
% 16 == 0) {
1747 fprintf (fpOut
, "\n ");
1749 if ((Index
+ 2) == HiiPackageListHeader
.PackageLength
) {
1750 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT16
*) HiiPackageDataPointer
);
1752 if ((Index
+ 1) == HiiPackageListHeader
.PackageLength
) {
1753 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT8
*) HiiPackageDataPointer
);
1755 free (HiiPackageListBuffer
);
1757 // Done successfully
1764 // Combine MciBinary files to one file
1766 if (mOutImageType
== FW_MERGE_IMAGE
) {
1768 // Open output file handle.
1770 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
1772 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1775 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1776 fpIn
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
1778 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1782 FileLength
= _filelength (fileno (fpIn
));
1783 FileBuffer
= malloc (FileLength
);
1784 if (FileBuffer
== NULL
) {
1785 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1790 fread (FileBuffer
, 1, FileLength
, fpIn
);
1793 // write input file to out file
1795 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
1797 // write pad value to out file.
1799 while (FileLength
++ % MciAlignment
!= 0) {
1800 fwrite (&MciPadValue
, 1, 1, fpOut
);
1803 // free allocated memory space
1809 // Done successfully
1815 // Convert MicroCode.txt file to MicroCode.bin file
1817 if (mOutImageType
== FW_MCI_IMAGE
) {
1818 fpIn
= fopen (LongFilePath (mInImageName
), "r");
1820 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1825 // The first pass is to determine
1826 // how much data is in the file so we can allocate a working buffer.
1830 Status
= MicrocodeReadData (fpIn
, &Data
);
1831 if (Status
== STATUS_SUCCESS
) {
1832 FileLength
+= sizeof (Data
);
1834 if (Status
== STATUS_IGNORE
) {
1835 Status
= STATUS_SUCCESS
;
1837 } while (Status
== STATUS_SUCCESS
);
1839 // Error if no data.
1841 if (FileLength
== 0) {
1842 Error (NULL
, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName
);
1845 if (FileLength
< sizeof (MICROCODE_IMAGE_HEADER
)) {
1846 Error (NULL
, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName
);
1851 // Allocate a buffer for the data
1853 FileBuffer
= malloc (FileLength
);
1854 if (FileBuffer
== NULL
) {
1855 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1859 // Re-read the file, storing the data into our buffer
1861 fseek (fpIn
, 0, SEEK_SET
);
1862 DataPointer
= (UINT32
*) FileBuffer
;
1863 OldDataPointer
= DataPointer
;
1865 OldDataPointer
= DataPointer
;
1866 Status
= MicrocodeReadData (fpIn
, DataPointer
++);
1867 if (Status
== STATUS_IGNORE
) {
1868 DataPointer
= OldDataPointer
;
1869 Status
= STATUS_SUCCESS
;
1871 } while (Status
== STATUS_SUCCESS
);
1873 // close input file after read data
1878 // Can't do much checking on the header because, per the spec, the
1879 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
1880 // and the TotalSize field is invalid (actually missing). Thus we can't
1881 // even verify the Reserved fields are 0.
1883 MciHeader
= (MICROCODE_IMAGE_HEADER
*) FileBuffer
;
1884 if (MciHeader
->DataSize
== 0) {
1887 Index
= MciHeader
->TotalSize
;
1890 if (Index
!= FileLength
) {
1891 Error (NULL
, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName
, (unsigned) FileLength
, (unsigned) Index
);
1896 // Checksum the contents
1898 DataPointer
= (UINT32
*) FileBuffer
;
1901 while (Index
< FileLength
) {
1902 CheckSum
+= *DataPointer
;
1904 Index
+= sizeof (*DataPointer
);
1906 if (CheckSum
!= 0) {
1907 Error (NULL
, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum
, mInImageName
);
1911 // Open the output file and write the buffer contents
1913 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
1918 // Open input file and read file data into file buffer.
1920 FileLength
= InputFileLength
;
1921 FileBuffer
= malloc (FileLength
);
1922 if (FileBuffer
== NULL
) {
1923 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1926 memcpy (FileBuffer
, InputFileBuffer
, InputFileLength
);
1929 // Dump TeImage Header into output file.
1931 if (mOutImageType
== DUMP_TE_HEADER
) {
1932 memcpy (&TEImageHeader
, FileBuffer
, sizeof (TEImageHeader
));
1933 if (TEImageHeader
.Signature
!= EFI_TE_IMAGE_HEADER_SIGNATURE
) {
1934 Error (NULL
, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName
);
1938 // Open the output file handle.
1941 fpInOut
= fopen (LongFilePath (mInImageName
), "wb");
1942 if (fpInOut
== NULL
) {
1943 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1947 if (OutImageName
!= NULL
) {
1948 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
1952 if (fpOut
== NULL
) {
1953 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1957 if (fpInOut
!= NULL
) {
1958 fprintf (fpInOut
, "Dump of file %s\n\n", mInImageName
);
1959 fprintf (fpInOut
, "TE IMAGE HEADER VALUES\n");
1960 fprintf (fpInOut
, "%17X machine\n", TEImageHeader
.Machine
);
1961 fprintf (fpInOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
1962 fprintf (fpInOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
1963 fprintf (fpInOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
1964 fprintf (fpInOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
1965 fprintf (fpInOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
1966 fprintf (fpInOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
1967 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
1968 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
1970 if (fpOut
!= NULL
) {
1971 fprintf (fpOut
, "Dump of file %s\n\n", mInImageName
);
1972 fprintf (fpOut
, "TE IMAGE HEADER VALUES\n");
1973 fprintf (fpOut
, "%17X machine\n", TEImageHeader
.Machine
);
1974 fprintf (fpOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
1975 fprintf (fpOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
1976 fprintf (fpOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
1977 fprintf (fpOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
1978 fprintf (fpOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
1979 fprintf (fpOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
1980 fprintf (fpOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
1981 fprintf (fpOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
1987 // Following code to convert dll to efi image or te image.
1988 // Get new image type
1990 if ((mOutImageType
== FW_EFI_IMAGE
) || (mOutImageType
== FW_TE_IMAGE
)) {
1991 if (ModuleType
== NULL
) {
1992 if (mOutImageType
== FW_EFI_IMAGE
) {
1993 Error (NULL
, 0, 1001, "Missing option", "EFI_FILETYPE");
1995 } else if (mOutImageType
== FW_TE_IMAGE
) {
1997 // Default TE Image Type is Boot service driver
1999 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2000 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2003 if (stricmp (ModuleType
, "BASE") == 0 ||
2004 stricmp (ModuleType
, "SEC") == 0 ||
2005 stricmp (ModuleType
, "SECURITY_CORE") == 0 ||
2006 stricmp (ModuleType
, "PEI_CORE") == 0 ||
2007 stricmp (ModuleType
, "PEIM") == 0 ||
2008 stricmp (ModuleType
, "COMBINED_PEIM_DRIVER") == 0 ||
2009 stricmp (ModuleType
, "PIC_PEIM") == 0 ||
2010 stricmp (ModuleType
, "RELOCATABLE_PEIM") == 0 ||
2011 stricmp (ModuleType
, "DXE_CORE") == 0 ||
2012 stricmp (ModuleType
, "BS_DRIVER") == 0 ||
2013 stricmp (ModuleType
, "DXE_DRIVER") == 0 ||
2014 stricmp (ModuleType
, "DXE_SMM_DRIVER") == 0 ||
2015 stricmp (ModuleType
, "UEFI_DRIVER") == 0 ||
2016 stricmp (ModuleType
, "SMM_CORE") == 0 ||
2017 stricmp (ModuleType
, "MM_STANDALONE") == 0 ||
2018 stricmp (ModuleType
, "MM_CORE_STANDALONE") == 0) {
2019 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2020 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2022 } else if (stricmp (ModuleType
, "UEFI_APPLICATION") == 0 ||
2023 stricmp (ModuleType
, "APPLICATION") == 0) {
2024 Type
= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
;
2025 VerboseMsg ("Efi Image subsystem type is efi application.");
2027 } else if (stricmp (ModuleType
, "DXE_RUNTIME_DRIVER") == 0 ||
2028 stricmp (ModuleType
, "RT_DRIVER") == 0) {
2029 Type
= EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
;
2030 VerboseMsg ("Efi Image subsystem type is efi runtime driver.");
2032 } else if (stricmp (ModuleType
, "DXE_SAL_DRIVER") == 0 ||
2033 stricmp (ModuleType
, "SAL_RT_DRIVER") == 0) {
2034 Type
= EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
;
2035 VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");
2038 Error (NULL
, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType
);
2045 // Convert ELF image to PeImage
2047 if (IsElfHeader(FileBuffer
)) {
2048 VerboseMsg ("Convert %s from ELF to PE/COFF.", mInImageName
);
2049 if (!ConvertElf(&FileBuffer
, &FileLength
)) {
2050 Error (NULL
, 0, 3000, "Invalid", "Unable to convert %s from ELF to PE/COFF.", mInImageName
);
2056 // Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP
2057 // XIP == eXecute In Place
2059 PeCoffConvertImageToXip (&FileBuffer
, &FileLength
);
2062 // Remove reloc section from PE or TE image
2064 if (mOutImageType
== FW_RELOC_STRIPEED_IMAGE
) {
2068 TeHdr
= (EFI_TE_IMAGE_HEADER
*) FileBuffer
;
2069 if (TeHdr
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2070 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (TeHdr
+ 1);
2071 for (Index
= 0; Index
< TeHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2072 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2074 // Check the reloc section is in the end of image.
2076 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) ==
2077 (FileLength
+ TeHdr
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
))) {
2079 // Remove .reloc section and update TeImage Header
2081 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2082 SectionHeader
->SizeOfRawData
= 0;
2083 SectionHeader
->Misc
.VirtualSize
= 0;
2084 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2085 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2094 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2095 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2096 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2097 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2098 Error (NULL
, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName
);
2103 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2104 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2105 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2109 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2110 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2111 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2113 // Check the reloc section is in the end of image.
2115 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) == FileLength
) {
2117 // Remove .reloc section and update PeImage Header
2119 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2121 PeHdr
->Pe32
.FileHeader
.Characteristics
|= EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2122 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2123 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2124 Optional32
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2125 Optional32
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2126 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2127 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2128 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2131 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2132 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2133 Optional64
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2134 Optional64
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2135 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2136 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2137 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2140 SectionHeader
->Misc
.VirtualSize
= 0;
2141 SectionHeader
->SizeOfRawData
= 0;
2153 // Read the dos & pe hdrs of the image
2155 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2156 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2157 // NO DOS header, check for PE/COFF header
2158 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2159 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2160 Error (NULL
, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName
);
2166 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2167 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2168 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2173 if (PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_ARM
) {
2174 // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
2175 // so patch back to the offical UEFI value.
2176 PeHdr
->Pe32
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_ARMT
;
2180 // Set new base address into image
2182 if (mOutImageType
== FW_REBASE_IMAGE
|| mOutImageType
== FW_SET_ADDRESS_IMAGE
) {
2183 if ((PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) && (PeHdr
->Pe32
.FileHeader
.Machine
!= IMAGE_FILE_MACHINE_IA64
)) {
2184 if (NewBaseAddress
>= 0x100000000ULL
) {
2185 Error (NULL
, 0, 3000, "Invalid", "New base address is larger than 4G for 32bit PE image");
2192 // Set Base Address to a negative value.
2194 NewBaseAddress
= (UINT64
) (0 - NewBaseAddress
);
2196 if (mOutImageType
== FW_REBASE_IMAGE
) {
2197 Status
= RebaseImage (mInImageName
, FileBuffer
, NewBaseAddress
);
2199 Status
= SetAddressToSectionHeader (mInImageName
, FileBuffer
, NewBaseAddress
);
2201 if (EFI_ERROR (Status
)) {
2203 Error (NULL
, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address -0x%llx can't success", mInImageName
, 0 - NewBaseAddress
);
2205 Error (NULL
, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address 0x%llx can't success", mInImageName
, NewBaseAddress
);
2217 // Extract bin data from Pe image.
2219 if (mOutImageType
== FW_BIN_IMAGE
) {
2220 if (FileLength
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
2221 Error (NULL
, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName
);
2225 // Output bin data from exe file
2227 FileLength
= FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
;
2228 memmove (FileBuffer
, FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, FileLength
);
2229 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2234 // Zero Debug Information of Pe Image
2236 if (mOutImageType
== FW_ZERO_DEBUG_IMAGE
) {
2237 Status
= ZeroDebugData (FileBuffer
, TRUE
);
2238 if (EFI_ERROR (Status
)) {
2239 Error (NULL
, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status
);
2244 // Write the updated Image
2246 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2251 // Set Time Stamp of Pe Image
2253 if (mOutImageType
== FW_SET_STAMP_IMAGE
) {
2254 Status
= SetStamp (FileBuffer
, TimeStamp
);
2255 if (EFI_ERROR (Status
)) {
2260 // Write the updated Image
2262 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2267 // Extract acpi data from pe image.
2269 if (mOutImageType
== FW_ACPI_IMAGE
) {
2270 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2271 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2272 if (strcmp ((char *)SectionHeader
->Name
, ".data") == 0 || strcmp ((char *)SectionHeader
->Name
, ".sdata") == 0) {
2276 if (SectionHeader
->Misc
.VirtualSize
< SectionHeader
->SizeOfRawData
) {
2277 FileLength
= SectionHeader
->Misc
.VirtualSize
;
2279 FileLength
= SectionHeader
->SizeOfRawData
;
2282 if (CheckAcpiTable (FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
) != STATUS_SUCCESS
) {
2283 Error (NULL
, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName
);
2288 // Output Apci data to file
2290 memmove (FileBuffer
, FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
);
2291 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2295 Error (NULL
, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName
);
2299 // Zero all unused fields of the DOS header
2301 if (DosHdr
!= NULL
) {
2302 memcpy (&BackupDosHdr
, DosHdr
, sizeof (EFI_IMAGE_DOS_HEADER
));
2303 memset (DosHdr
, 0, sizeof (EFI_IMAGE_DOS_HEADER
));
2304 DosHdr
->e_magic
= BackupDosHdr
.e_magic
;
2305 DosHdr
->e_lfanew
= BackupDosHdr
.e_lfanew
;
2307 for (Index
= sizeof (EFI_IMAGE_DOS_HEADER
); Index
< (UINT32
) DosHdr
->e_lfanew
; Index
++) {
2308 FileBuffer
[Index
] = (UINT8
) DosHdr
->e_cp
;
2313 // Initialize TeImage Header
2315 memset (&TEImageHeader
, 0, sizeof (EFI_TE_IMAGE_HEADER
));
2316 TEImageHeader
.Signature
= EFI_TE_IMAGE_HEADER_SIGNATURE
;
2317 TEImageHeader
.Machine
= PeHdr
->Pe32
.FileHeader
.Machine
;
2318 TEImageHeader
.NumberOfSections
= (UINT8
) PeHdr
->Pe32
.FileHeader
.NumberOfSections
;
2319 TEImageHeader
.StrippedSize
= (UINT16
) ((UINTN
) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
) - (UINTN
) FileBuffer
);
2320 TEImageHeader
.Subsystem
= (UINT8
) Type
;
2323 // Patch the PE header
2325 PeHdr
->Pe32
.OptionalHeader
.Subsystem
= (UINT16
) Type
;
2327 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2328 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2329 if (!KeepOptionalHeaderFlag
) {
2330 Optional32
->MajorOperatingSystemVersion
= 0;
2331 Optional32
->MinorOperatingSystemVersion
= 0;
2332 Optional32
->MajorImageVersion
= 0;
2333 Optional32
->MinorImageVersion
= 0;
2334 Optional32
->MajorSubsystemVersion
= 0;
2335 Optional32
->MinorSubsystemVersion
= 0;
2336 Optional32
->Win32VersionValue
= 0;
2337 Optional32
->CheckSum
= 0;
2338 Optional32
->SizeOfStackReserve
= 0;
2339 Optional32
->SizeOfStackCommit
= 0;
2340 Optional32
->SizeOfHeapReserve
= 0;
2341 Optional32
->SizeOfHeapCommit
= 0;
2343 TEImageHeader
.AddressOfEntryPoint
= Optional32
->AddressOfEntryPoint
;
2344 TEImageHeader
.BaseOfCode
= Optional32
->BaseOfCode
;
2345 TEImageHeader
.ImageBase
= (UINT64
) (Optional32
->ImageBase
);
2347 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2348 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2349 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2352 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2353 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2354 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2358 // Zero .pdata section data.
2360 if (!KeepExceptionTableFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2361 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2362 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2363 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2364 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2365 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2367 // Zero .pdata Section data
2369 memset (FileBuffer
+ SectionHeader
->PointerToRawData
, 0, SectionHeader
->SizeOfRawData
);
2371 // Zero .pdata Section header name
2373 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2375 // Zero Execption Table
2377 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2378 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2379 DebugMsg (NULL
, 0, 9, "Zero the .pdata section for PE image", NULL
);
2386 // Strip zero padding at the end of the .reloc section
2388 if (!KeepZeroPendingFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2389 if (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2390 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2391 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2393 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2395 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2396 SectionHeader
->Misc
.VirtualSize
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2397 AllignedRelocSize
= (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional32
->FileAlignment
- 1) & (~(Optional32
->FileAlignment
- 1));
2399 // Check to see if there is zero padding at the end of the base relocations
2401 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2403 // Check to see if the base relocations are at the end of the file
2405 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional32
->SizeOfImage
) {
2407 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2409 Optional32
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2410 Optional32
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2411 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2412 FileLength
= Optional32
->SizeOfImage
;
2413 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
));
2420 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2421 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2422 if (!KeepOptionalHeaderFlag
) {
2423 Optional64
->MajorOperatingSystemVersion
= 0;
2424 Optional64
->MinorOperatingSystemVersion
= 0;
2425 Optional64
->MajorImageVersion
= 0;
2426 Optional64
->MinorImageVersion
= 0;
2427 Optional64
->MajorSubsystemVersion
= 0;
2428 Optional64
->MinorSubsystemVersion
= 0;
2429 Optional64
->Win32VersionValue
= 0;
2430 Optional64
->CheckSum
= 0;
2431 Optional64
->SizeOfStackReserve
= 0;
2432 Optional64
->SizeOfStackCommit
= 0;
2433 Optional64
->SizeOfHeapReserve
= 0;
2434 Optional64
->SizeOfHeapCommit
= 0;
2436 TEImageHeader
.AddressOfEntryPoint
= Optional64
->AddressOfEntryPoint
;
2437 TEImageHeader
.BaseOfCode
= Optional64
->BaseOfCode
;
2438 TEImageHeader
.ImageBase
= (UINT64
) (Optional64
->ImageBase
);
2440 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2441 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2442 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2445 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2446 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2447 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2451 // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
2452 // For Itaninum and X64 Image, remove .pdata section.
2454 if ((!KeepExceptionTableFlag
&& PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_X64
) || PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
) {
2455 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2456 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2457 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2458 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2459 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2460 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2462 // Zero .pdata Section header name
2464 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2466 RuntimeFunction
= (RUNTIME_FUNCTION
*)(FileBuffer
+ SectionHeader
->PointerToRawData
);
2467 for (Index1
= 0; Index1
< Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
/ sizeof (RUNTIME_FUNCTION
); Index1
++, RuntimeFunction
++) {
2468 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2469 for (Index2
= 0; Index2
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index2
++, SectionHeader
++) {
2470 if (RuntimeFunction
->UnwindInfoAddress
>= SectionHeader
->VirtualAddress
&& RuntimeFunction
->UnwindInfoAddress
< (SectionHeader
->VirtualAddress
+ SectionHeader
->SizeOfRawData
)) {
2471 UnwindInfo
= (UNWIND_INFO
*)(FileBuffer
+ SectionHeader
->PointerToRawData
+ (RuntimeFunction
->UnwindInfoAddress
- SectionHeader
->VirtualAddress
));
2472 if (UnwindInfo
->Version
== 1) {
2473 memset (UnwindInfo
+ 1, 0, UnwindInfo
->CountOfUnwindCodes
* sizeof (UINT16
));
2474 memset (UnwindInfo
, 0, sizeof (UNWIND_INFO
));
2479 memset (RuntimeFunction
, 0, sizeof (RUNTIME_FUNCTION
));
2482 // Zero Execption Table
2484 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2485 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2486 DebugMsg (NULL
, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL
);
2494 // Strip zero padding at the end of the .reloc section
2496 if (!KeepZeroPendingFlag
&& Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2497 if (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2498 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2499 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2501 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2503 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2504 SectionHeader
->Misc
.VirtualSize
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2505 AllignedRelocSize
= (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional64
->FileAlignment
- 1) & (~(Optional64
->FileAlignment
- 1));
2507 // Check to see if there is zero padding at the end of the base relocations
2509 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2511 // Check to see if the base relocations are at the end of the file
2513 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional64
->SizeOfImage
) {
2515 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2517 Optional64
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2518 Optional64
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2519 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2520 FileLength
= Optional64
->SizeOfImage
;
2521 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
));
2529 Error (NULL
, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr
->Pe32
.OptionalHeader
.Magic
, mInImageName
);
2533 if (((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) == 0) && \
2534 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
== 0) && \
2535 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
== 0)) {
2537 // PeImage can be loaded into memory, but it has no relocation section.
2538 // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
2540 if (Optional32
!= NULL
) {
2541 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
2542 } else if (Optional64
!= NULL
) {
2543 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
2548 // Fill HII section data
2550 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2551 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++) {
2552 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".hii") == 0) {
2554 // Update resource section header offset
2556 SetHiiResourceHeader ((UINT8
*) FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, SectionHeader
[Index
].VirtualAddress
);
2558 // Update resource section name
2560 strcpy((char *) SectionHeader
[Index
].Name
, ".rsrc");
2562 // Update resource data directory.
2564 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2565 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2566 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= SectionHeader
[Index
].VirtualAddress
;
2567 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= SectionHeader
[Index
].Misc
.VirtualSize
;
2568 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2569 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2570 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= SectionHeader
[Index
].VirtualAddress
;
2571 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= SectionHeader
[Index
].Misc
.VirtualSize
;
2578 // Zero ExceptionTable Xdata
2580 if (!KeepExceptionTableFlag
) {
2581 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2582 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++) {
2583 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".xdata") == 0) {
2585 // zero .xdata section
2587 memset (FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, 0, SectionHeader
[Index
].SizeOfRawData
);
2588 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
);
2595 // Zero Time/Data field
2597 ZeroDebugData (FileBuffer
, FALSE
);
2599 if (mOutImageType
== FW_TE_IMAGE
) {
2600 if ((PeHdr
->Pe32
.FileHeader
.NumberOfSections
&~0xFF) || (Type
&~0xFF)) {
2602 // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
2604 Error (NULL
, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName
);
2608 if ((PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
)) {
2610 // TeImage has the same section alignment and file alignment.
2612 Error (NULL
, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName
);
2616 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",
2617 TEImageHeader
.Machine
, TEImageHeader
.NumberOfSections
, TEImageHeader
.StrippedSize
, (unsigned) TEImageHeader
.AddressOfEntryPoint
, (unsigned) TEImageHeader
.BaseOfCode
, (unsigned long long) TEImageHeader
.ImageBase
);
2619 // Update Image to TeImage
2621 FileLength
= FileLength
- TEImageHeader
.StrippedSize
;
2622 memmove (FileBuffer
+ sizeof (EFI_TE_IMAGE_HEADER
), FileBuffer
+ TEImageHeader
.StrippedSize
, FileLength
);
2623 FileLength
= FileLength
+ sizeof (EFI_TE_IMAGE_HEADER
);
2624 memcpy (FileBuffer
, &TEImageHeader
, sizeof (EFI_TE_IMAGE_HEADER
));
2625 VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength
));
2629 // Following codes are to fix the objcopy's issue:
2630 // objcopy in binutil 2.50.18 will set PE image's charactices to "RELOC_STRIPPED" if image has no ".reloc" section
2631 // It cause issue for EFI image which has no ".reloc" sections.
2632 // Following codes will be removed when objcopy in binutil fix this problem for PE image.
2634 if ((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) != 0) {
2635 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2636 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2637 if (Optional32
->ImageBase
== 0) {
2638 PeHdr
->Pe32
.FileHeader
.Characteristics
&= ~EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2640 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2641 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2642 if (Optional64
->ImageBase
== 0) {
2643 PeHdr
->Pe32
.FileHeader
.Characteristics
&= ~EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2651 // Update Image to EfiImage or TE image
2654 if ((FileLength
!= InputFileLength
) || (memcmp (FileBuffer
, InputFileBuffer
, FileLength
) != 0)) {
2656 // Update File when File is changed.
2658 fpInOut
= fopen (LongFilePath (mInImageName
), "wb");
2659 if (fpInOut
== NULL
) {
2660 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2663 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2664 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2667 if ((OutputFileTime
< InputFileTime
) || (FileLength
!= OutputFileLength
) || (memcmp (FileBuffer
, OutputFileBuffer
, FileLength
) != 0)) {
2669 // Update File when File is changed or File is old.
2671 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
2672 if (fpOut
== NULL
) {
2673 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
2676 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2677 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2680 mImageSize
= FileLength
;
2683 if (fpInOut
!= NULL
) {
2684 if (GetUtilityStatus () != STATUS_SUCCESS
) {
2686 // when file updates failed, original file is still recovered.
2688 fwrite (InputFileBuffer
, 1, InputFileLength
, fpInOut
);
2691 // Write converted data into fpInOut file and close input file.
2696 if (FileBuffer
!= NULL
) {
2700 if (InputFileName
!= NULL
) {
2701 free (InputFileName
);
2704 if (fpOut
!= NULL
) {
2706 // Write converted data into fpOut file and close output file.
2709 if (GetUtilityStatus () != STATUS_SUCCESS
) {
2710 if (OutputFileBuffer
== NULL
) {
2711 remove (OutImageName
);
2713 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
2714 fwrite (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
2720 if (InputFileBuffer
!= NULL
) {
2721 free (InputFileBuffer
);
2724 if (OutputFileBuffer
!= NULL
) {
2725 free (OutputFileBuffer
);
2729 // Write module size and time stamp to report file.
2731 if (OutImageName
!= NULL
) {
2732 FileLen
= strlen (OutImageName
);
2734 if (FileLen
>= 4 && strcmp (OutImageName
+ (FileLen
- 4), ".efi") == 0) {
2735 ReportFileName
= (CHAR8
*) malloc (FileLen
+ 1);
2736 if (ReportFileName
!= NULL
) {
2737 strcpy (ReportFileName
, OutImageName
);
2738 strcpy (ReportFileName
+ (FileLen
- 4), ".txt");
2739 ReportFile
= fopen (LongFilePath (ReportFileName
), "w+");
2740 if (ReportFile
!= NULL
) {
2741 fprintf (ReportFile
, "MODULE_SIZE = %u\n", (unsigned) mImageSize
);
2742 fprintf (ReportFile
, "TIME_STAMP = %u\n", (unsigned) mImageTimeStamp
);
2745 free (ReportFileName
);
2748 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
2750 return GetUtilityStatus ();
2756 IN OUT UINT8
*FileBuffer
,
2757 BOOLEAN ZeroDebugFlag
2761 Routine Description:
2763 Zero debug information in PeImage.
2767 FileBuffer - Pointer to PeImage.
2768 ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp
2772 EFI_ABORTED - PeImage is invalid.
2773 EFI_SUCCESS - Zero debug data successfully.
2778 UINT32 DebugDirectoryEntryRva
;
2779 UINT32 DebugDirectoryEntrySize
;
2780 UINT32 DebugDirectoryEntryFileOffset
;
2781 UINT32 ExportDirectoryEntryRva
;
2782 UINT32 ExportDirectoryEntryFileOffset
;
2783 UINT32 ResourceDirectoryEntryRva
;
2784 UINT32 ResourceDirectoryEntryFileOffset
;
2785 EFI_IMAGE_DOS_HEADER
*DosHdr
;
2786 EFI_IMAGE_FILE_HEADER
*FileHdr
;
2787 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
2788 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
2789 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
2790 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
2791 EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
*RsdsEntry
;
2792 UINT32
*NewTimeStamp
;
2797 DebugDirectoryEntryRva
= 0;
2798 DebugDirectoryEntrySize
= 0;
2799 ExportDirectoryEntryRva
= 0;
2800 ResourceDirectoryEntryRva
= 0;
2801 DebugDirectoryEntryFileOffset
= 0;
2802 ExportDirectoryEntryFileOffset
= 0;
2803 ResourceDirectoryEntryFileOffset
= 0;
2804 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2805 FileHdr
= (EFI_IMAGE_FILE_HEADER
*) (FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2808 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2809 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2810 // NO DOS header, must start with PE/COFF header
2811 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
2813 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2817 // Get Debug, Export and Resource EntryTable RVA address.
2818 // Resource Directory entry need to review.
2820 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2821 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2822 if (Optional32Hdr
->Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2823 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2824 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2825 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2826 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2828 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2829 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2830 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2832 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2833 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2834 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2835 DebugDirectoryEntrySize
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2836 if (ZeroDebugFlag
) {
2837 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
2838 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
2842 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2843 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2844 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2845 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2847 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2848 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2849 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2851 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2852 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2853 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2854 DebugDirectoryEntrySize
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2855 if (ZeroDebugFlag
) {
2856 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
2857 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
2863 // Get DirectoryEntryTable file offset.
2865 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2866 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2867 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2868 DebugDirectoryEntryFileOffset
=
2869 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2871 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2872 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2873 ExportDirectoryEntryFileOffset
=
2874 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2876 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2877 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2878 ResourceDirectoryEntryFileOffset
=
2879 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2884 //Zero Debug Data and TimeStamp
2886 FileHdr
->TimeDateStamp
= 0;
2887 mImageTimeStamp
= 0;
2888 if (ExportDirectoryEntryFileOffset
!= 0) {
2889 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
2893 if (ResourceDirectoryEntryFileOffset
!= 0) {
2894 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
2898 if (DebugDirectoryEntryFileOffset
!= 0) {
2899 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
);
2901 for (Index
=0; Index
< DebugDirectoryEntrySize
/ sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
); Index
++, DebugEntry
++) {
2902 DebugEntry
->TimeDateStamp
= 0;
2903 if (mIsConvertXip
) {
2904 DebugEntry
->FileOffset
= DebugEntry
->RVA
;
2906 if (ZeroDebugFlag
|| DebugEntry
->Type
!= EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
2907 memset (FileBuffer
+ DebugEntry
->FileOffset
, 0, DebugEntry
->SizeOfData
);
2908 memset (DebugEntry
, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
2910 if (DebugEntry
->Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
2911 RsdsEntry
= (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
*) (FileBuffer
+ DebugEntry
->FileOffset
);
2912 if (RsdsEntry
->Signature
== CODEVIEW_SIGNATURE_MTOC
) {
2913 // MTOC sets DebugDirectoryEntrySize to size of the .debug section, so fix it.
2914 if (!ZeroDebugFlag
) {
2915 if (Optional32Hdr
->Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2916 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
2918 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
2933 IN OUT UINT8
*FileBuffer
,
2938 Routine Description:
2940 Set new time stamp into PeImage FileHdr and Directory table:
2941 Debug, Export and Resource.
2945 FileBuffer - Pointer to PeImage.
2946 TimeStamp - Time stamp string.
2950 EFI_INVALID_PARAMETER - TimeStamp format is not recognized.
2951 EFI_SUCCESS - Set new time stamp in this image successfully.
2959 UINT32 DebugDirectoryEntryRva
;
2960 UINT32 DebugDirectoryEntryFileOffset
;
2961 UINT32 ExportDirectoryEntryRva
;
2962 UINT32 ExportDirectoryEntryFileOffset
;
2963 UINT32 ResourceDirectoryEntryRva
;
2964 UINT32 ResourceDirectoryEntryFileOffset
;
2965 EFI_IMAGE_DOS_HEADER
*DosHdr
;
2966 EFI_IMAGE_FILE_HEADER
*FileHdr
;
2967 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
2968 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
2969 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
2970 UINT32
*NewTimeStamp
;
2975 DebugDirectoryEntryRva
= 0;
2976 DebugDirectoryEntryFileOffset
= 0;
2977 ExportDirectoryEntryRva
= 0;
2978 ExportDirectoryEntryFileOffset
= 0;
2979 ResourceDirectoryEntryRva
= 0;
2980 ResourceDirectoryEntryFileOffset
= 0;
2982 // Get time and date that will be set.
2984 if (TimeStamp
== NULL
) {
2985 Error (NULL
, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");
2986 return EFI_INVALID_PARAMETER
;
2989 // compare the value with "NOW", if yes, current system time is set.
2991 if (stricmp (TimeStamp
, "NOW") == 0) {
2993 // get system current time and date
2998 // Check Time Format strictly yyyy-mm-dd 00:00:00
3000 for (Index
= 0; TimeStamp
[Index
] != '\0' && Index
< 20; Index
++) {
3001 if (Index
== 4 || Index
== 7) {
3002 if (TimeStamp
[Index
] == '-') {
3005 } else if (Index
== 13 || Index
== 16) {
3006 if (TimeStamp
[Index
] == ':') {
3009 } else if (Index
== 10 && TimeStamp
[Index
] == ' ') {
3011 } else if ((TimeStamp
[Index
] < '0') || (TimeStamp
[Index
] > '9')) {
3016 if (Index
< 19 || TimeStamp
[19] != '\0') {
3017 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
3018 return EFI_INVALID_PARAMETER
;
3022 // get the date and time from TimeStamp
3024 if (sscanf (TimeStamp
, "%d-%d-%d %d:%d:%d",
3032 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
3033 return EFI_INVALID_PARAMETER
;
3037 // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
3039 if (stime
.tm_mon
<= 0 || stime
.tm_mday
<=0) {
3040 Error (NULL
, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp
);
3041 return EFI_INVALID_PARAMETER
;
3046 // in struct, Year (current year minus 1900)
3047 // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
3050 // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
3052 if (stime
.tm_year
>= 1970 && stime
.tm_year
<= 2038) {
3054 // convert 1970 -> 70, 2000 -> 100, ...
3056 stime
.tm_year
-= 1900;
3058 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
3059 return EFI_INVALID_PARAMETER
;
3063 // convert the date and time to time_t format
3065 newtime
= mktime (&stime
);
3066 if (newtime
== (time_t) - 1) {
3067 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
3068 return EFI_INVALID_PARAMETER
;
3072 ptime
= localtime (&newtime
);
3073 if (ptime
!= NULL
) {
3074 DebugMsg (NULL
, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",
3075 ptime
->tm_year
+ 1900, ptime
->tm_mon
+ 1, ptime
->tm_mday
, ptime
->tm_hour
, ptime
->tm_min
, ptime
->tm_sec
);
3078 // Set new time and data into PeImage.
3080 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
3081 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
3082 // NO DOS header, must start with PE/COFF header
3083 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
3085 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
3089 // Get Debug, Export and Resource EntryTable RVA address.
3090 // Resource Directory entry need to review.
3092 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
3093 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3094 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3095 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3096 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3097 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3099 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3100 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3101 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3103 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3104 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3105 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3108 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3109 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3110 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3111 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3112 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3114 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3115 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3116 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3118 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3119 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3120 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3125 // Get DirectoryEntryTable file offset.
3127 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
3128 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3129 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3130 DebugDirectoryEntryFileOffset
=
3131 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3133 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3134 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3135 ExportDirectoryEntryFileOffset
=
3136 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3138 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3139 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3140 ResourceDirectoryEntryFileOffset
=
3141 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3148 FileHdr
->TimeDateStamp
= (UINT32
) newtime
;
3149 mImageTimeStamp
= (UINT32
) newtime
;
3150 if (ExportDirectoryEntryRva
!= 0) {
3151 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
3152 *NewTimeStamp
= (UINT32
) newtime
;
3155 if (ResourceDirectoryEntryRva
!= 0) {
3156 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
3157 *NewTimeStamp
= (UINT32
) newtime
;
3160 if (DebugDirectoryEntryRva
!= 0) {
3161 NewTimeStamp
= (UINT32
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
+ sizeof (UINT32
));
3162 *NewTimeStamp
= (UINT32
) newtime
;
3176 Routine Description:
3177 Read a 32-bit microcode data value from a text file and convert to raw binary form.
3180 InFptr - file pointer to input text file
3181 Data - pointer to where to return the data parsed
3184 STATUS_SUCCESS - no errors or warnings, Data contains valid information
3185 STATUS_ERROR - errors were encountered
3189 CHAR8 Line
[MAX_LINE_LEN
];
3191 int ScannedData
= 0;
3193 Line
[MAX_LINE_LEN
- 1] = 0;
3195 if (fgets (Line
, MAX_LINE_LEN
, InFptr
) == NULL
) {
3196 return STATUS_ERROR
;
3199 // If it was a binary file, then it may have overwritten our null terminator
3201 if (Line
[MAX_LINE_LEN
- 1] != 0) {
3202 return STATUS_ERROR
;
3208 for (cptr
= Line
; *cptr
&& isspace((int)*cptr
); cptr
++) {
3211 // Skip Blank Lines and Comment Lines
3212 if ((strlen(cptr
) != 0) && (*cptr
!= ';')) {
3218 // dd 000000001h ; comment
3223 if ((tolower((int)cptr
[0]) == 'd') && (tolower((int)cptr
[1]) == 'd') && isspace ((int)cptr
[2])) {
3225 // Skip blanks and look for a hex digit
3228 for (; *cptr
&& isspace((int)*cptr
); cptr
++) {
3230 if (isxdigit ((int)*cptr
)) {
3231 if (sscanf (cptr
, "%X", &ScannedData
) != 1) {
3232 return STATUS_ERROR
;
3235 *Data
= (UINT32
) ScannedData
;
3236 return STATUS_SUCCESS
;
3239 return STATUS_ERROR
;