2 Converts a pe32+ image to an FW, Te image type, or other specific image.
4 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "WinNtInclude.h"
20 #include <sys/types.h>
29 #include <Common/UefiBaseTypes.h>
30 #include <IndustryStandard/PeImage.h>
31 #include <Common/UefiInternalFormRepresentation.h>
34 // Acpi Table definition
36 #include <IndustryStandard/Acpi.h>
37 #include <IndustryStandard/Acpi1_0.h>
38 #include <IndustryStandard/Acpi2_0.h>
39 #include <IndustryStandard/Acpi3_0.h>
40 #include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
42 #include "CommonLib.h"
43 #include "PeCoffLib.h"
45 #include "EfiUtilityMsgs.h"
50 // Version of this utility
52 #define UTILITY_NAME "GenFw"
53 #define UTILITY_MAJOR_VERSION 0
54 #define UTILITY_MINOR_VERSION 2
56 #define HII_RESOURCE_SECTION_INDEX 1
57 #define HII_RESOURCE_SECTION_NAME "HII"
59 #define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
60 #define DEFAULT_MC_ALIGNMENT 16
62 #define STATUS_IGNORE 0xA
64 // Structure definition for a microcode header
74 UINT32 DataSize
; // if 0, then TotalSize = 2048, and TotalSize field is invalid
75 UINT32 TotalSize
; // number of bytes
77 } MICROCODE_IMAGE_HEADER
;
79 static EFI_GUID mZeroGuid
= {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
81 static const char *gHiiPackageRCFileHeader
[] = {
83 "// DO NOT EDIT -- auto-generated file",
89 // Module image information
92 UINT32 mImageTimeStamp
= 0;
93 UINT32 mImageSize
= 0;
94 UINT32 mOutImageType
= FW_DUMMY_IMAGE
;
100 IN OUT UINT8
*FileBuffer
,
107 IN OUT UINT8
*FileBuffer
,
127 Print out version information for this utility.
139 fprintf (stdout
, "%s Version %d.%d %s \n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
166 fprintf (stdout
, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME
);
169 // Copyright declaration
171 fprintf (stdout
, "Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.\n\n");
176 fprintf (stdout
, "Options:\n");
177 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
178 File will be created to store the ouput content.\n");
179 fprintf (stdout
, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\
180 Create Efi Image. EFI_FILETYPE is one of BASE,SMM_CORE,\n\
181 PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\
182 SEC, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER,\n\
183 DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER,\n\
184 PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\
185 APPLICATION, SAL_RT_DRIVER to support all module types\n\
186 It can only be used together with --keepexceptiontable,\n\
187 --keepzeropending, --keepoptionalheader, -r, -o option.\n\
188 It is a action option. If it is combined with other action options,\n\
189 the later input action option will override the previous one.\n");
190 fprintf (stdout
, " -c, --acpi Create Acpi table.\n\
191 It can't be combined with other action options\n\
192 except for -o, -r option. It is a action option.\n\
193 If it is combined with other action options, the later\n\
194 input action option will override the previous one.\n");
195 fprintf (stdout
, " -t, --terse Create Te Image.\n\
196 It can only be used together with --keepexceptiontable,\n\
197 --keepzeropending, --keepoptionalheader, -r, -o option.\n\
198 It is a action option. If it is combined with other action options,\n\
199 the later input action option will override the previous one.\n");
200 fprintf (stdout
, " -u, --dump Dump TeImage Header.\n\
201 It can't be combined with other action options\n\
202 except for -o, -r option. It is a action option.\n\
203 If it is combined with other action options, the later\n\
204 input action option will override the previous one.\n");
205 fprintf (stdout
, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\
206 It also zeros the time stamp fields.\n\
207 This option can be used to compare the binary efi image.\n\
208 It can't be combined with other action options\n\
209 except for -o, -r option. It is a action option.\n\
210 If it is combined with other action options, the later\n\
211 input action option will override the previous one.\n");
212 fprintf (stdout
, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\
213 It can't be combined with other action options\n\
214 except for -o, -r option. It is a action option.\n\
215 If it is combined with other action options, the later\n\
216 input action option will override the previous one.\n");;
217 fprintf (stdout
, " -l, --stripped Strip off the relocation info from PE or TE image.\n\
218 It can't be combined with other action options\n\
219 except for -o, -r option. It is a action option.\n\
220 If it is combined with other action options, the later\n\
221 input action option will override the previous one.\n");
222 fprintf (stdout
, " -s timedate, --stamp timedate\n\
223 timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\
224 is set to NOW, current system time is used. The support\n\
225 date scope is 1970-01-01 00+timezone:00:00\n\
226 ~ 2038-01-19 03+timezone:14:07\n\
227 The scope is adjusted according to the different zones.\n\
228 It can't be combined with other action options\n\
229 except for -o, -r option. It is a action option.\n\
230 If it is combined with other action options, the later\n\
231 input action option will override the previous one.\n");
232 fprintf (stdout
, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\
233 It can't be combined with other action options\n\
234 except for -o option. It is a action option.\n\
235 If it is combined with other action options, the later\n\
236 input action option will override the previous one.\n");
237 fprintf (stdout
, " -j, --join Combine multi microcode bin files to one file.\n\
238 It can be specified with -a, -p, -o option.\n\
239 No other options can be combined with it.\n\
240 If it is combined with other action options, the later\n\
241 input action option will override the previous one.\n");
242 fprintf (stdout
, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\
243 This option is only used together with -j option.\n");
244 fprintf (stdout
, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\
245 This option is only used together with -j option.\n");
246 fprintf (stdout
, " --keepexceptiontable Don't clear exception table.\n\
247 This option can be used together with -e or -t.\n\
248 It doesn't work for other options.\n");
249 fprintf (stdout
, " --keepoptionalheader Don't zero PE/COFF optional header fields.\n\
250 This option can be used together with -e or -t.\n\
251 It doesn't work for other options.\n");
252 fprintf (stdout
, " --keepzeropending Don't strip zero pending of .reloc.\n\
253 This option can be used together with -e or -t.\n\
254 It doesn't work for other options.\n");
255 fprintf (stdout
, " -r, --replace Overwrite the input file with the output content.\n\
256 If more input files are specified,\n\
257 the last input file will be as the output file.\n");
258 fprintf (stdout
, " -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\
259 Guid is used to specify hii package list guid.\n\
260 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\
261 If not specified, the first Form FormSet guid is used.\n");
262 fprintf (stdout
, " --hiipackage Combine all input binary hii pacakges into \n\
263 a single package list as the text resource data(RC).\n\
264 It can't be combined with other action options\n\
265 except for -o option. It is a action option.\n\
266 If it is combined with other action options, the later\n\
267 input action option will override the previous one.\n");
268 fprintf (stdout
, " --hiibinpackage Combine all input binary hii pacakges into \n\
269 a single package list as the binary resource section.\n\
270 It can't be combined with other action options\n\
271 except for -o option. It is a action option.\n\
272 If it is combined with other action options, the later\n\
273 input action option will override the previous one.\n");
274 fprintf (stdout
, " --rebase NewAddress Rebase image to new base address. New address \n\
275 is also set to the first none code section header.\n\
276 It can't be combined with other action options\n\
277 except for -o or -r option. It is a action option.\n\
278 If it is combined with other action options, the later\n\
279 input action option will override the previous one.\n");
280 fprintf (stdout
, " --address NewAddress Set new address into the first none code \n\
281 section header of the input image.\n\
282 It can't be combined with other action options\n\
283 except for -o or -r option. It is a action option.\n\
284 If it is combined with other action options, the later\n\
285 input action option will override the previous one.\n");
286 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
287 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
288 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
289 fprintf (stdout
, " --version Show program's version number and exit\n");
290 fprintf (stdout
, " -h, --help Show this help message and exit\n");
307 AcpiTable Buffer for AcpiSection
308 Length AcpiSection Length
317 EFI_ACPI_DESCRIPTION_HEADER
*AcpiHeader
;
318 EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs
;
319 UINT32 ExpectedLength
;
321 AcpiHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTable
;
324 // Generic check for AcpiTable length.
326 if (AcpiHeader
->Length
> Length
) {
327 Error (NULL
, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL
);
332 // Currently, we only check must-have tables: FADT, FACS, DSDT,
333 // and some important tables: MADT, MCFG.
335 switch (AcpiHeader
->Signature
) {
338 // "FACP" Fixed ACPI Description Table
340 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
:
341 switch (AcpiHeader
->Revision
) {
342 case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
343 ExpectedLength
= sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
);
345 case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
346 ExpectedLength
= sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
);
348 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
349 ExpectedLength
= sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
);
352 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
) {
353 ExpectedLength
= AcpiHeader
->Length
;
356 Error (NULL
, 0, 3000, "Invalid", "FACP revision check failed.");
359 if (ExpectedLength
!= AcpiHeader
->Length
) {
360 Error (NULL
, 0, 3000, "Invalid", "FACP length check failed.");
366 // "FACS" Firmware ACPI Control Structure
368 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE
:
369 Facs
= (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)AcpiTable
;
370 if (Facs
->Version
> EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) {
373 if ((Facs
->Version
!= EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
374 (Facs
->Version
!= EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
375 (Facs
->Version
!= EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
)){
376 Error (NULL
, 0, 3000, "Invalid", "FACS version check failed.");
379 if ((Facs
->Length
!= sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
380 (Facs
->Length
!= sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
381 (Facs
->Length
!= sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
))) {
382 Error (NULL
, 0, 3000, "Invalid", "FACS length check failed.");
388 // "DSDT" Differentiated System Description Table
390 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
391 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION
) {
394 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
)) {
395 Error (NULL
, 0, 3000, "Invalid", "DSDT length check failed.");
401 // "APIC" Multiple APIC Description Table
403 case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE
:
404 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) {
407 if ((AcpiHeader
->Revision
!= EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
408 (AcpiHeader
->Revision
!= EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
409 (AcpiHeader
->Revision
!= EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
)) {
410 Error (NULL
, 0, 3000, "Invalid", "APIC revision check failed.");
413 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT32
) + sizeof(UINT32
)) {
414 Error (NULL
, 0, 3000, "Invalid", "APIC length check failed.");
420 // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
422 case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE
:
423 if (AcpiHeader
->Revision
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
426 if (AcpiHeader
->Revision
!= EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
427 Error (NULL
, 0, 3000, "Invalid", "MCFG revision check failed.");
430 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT64
)) {
431 Error (NULL
, 0, 3000, "Invalid", "MCFG length check failed.");
437 // Other table pass check
443 return STATUS_SUCCESS
;
447 SetHiiResourceHeader (
453 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
454 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*ResourceDirectoryEntry
;
455 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
456 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
459 // Fill Resource section entry
461 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
);
462 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
463 for (Index
= 0; Index
< ResourceDirectory
->NumberOfNamedEntries
; Index
++) {
464 if (ResourceDirectoryEntry
->u1
.s
.NameIsString
) {
465 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiBinData
+ ResourceDirectoryEntry
->u1
.s
.NameOffset
);
467 if (ResourceDirectoryString
->Length
== 3 &&
468 ResourceDirectoryString
->String
[0] == L
'H' &&
469 ResourceDirectoryString
->String
[1] == L
'I' &&
470 ResourceDirectoryString
->String
[2] == L
'I') {
472 // Resource Type "HII" found
474 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
476 // Move to next level - resource Name
478 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
479 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
481 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
483 // Move to next level - resource Language
485 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
486 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
491 // Now it ought to be resource Data and update its OffsetToData value
493 if (!ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
494 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.OffsetToData
);
495 ResourceDataEntry
->OffsetToData
= ResourceDataEntry
->OffsetToData
+ OffsetToFile
;
500 ResourceDirectoryEntry
++;
506 EFI_IMAGE_OPTIONAL_HEADER_UNION
*
511 EFI_IMAGE_DOS_HEADER
*DosHdr
;
512 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
515 // Read the dos & pe hdrs of the image
517 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Data
;
518 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
519 // NO DOS header, check for PE/COFF header
520 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(Data
);
521 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
526 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(((UINT8
*)Data
) + DosHdr
->e_lfanew
);
527 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
536 PeCoffConvertImageToXip (
541 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
542 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NewPeHdr
;
543 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
544 UINTN TotalNecessaryFileSize
;
549 UINTN FirstSectionOffset
;
550 BOOLEAN ConversionNeeded
;
552 PeHdr
= GetPeCoffHeader ((void *) *FileBuffer
);
557 if (PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
) {
559 // The only reason to expand zero fill sections is to make them compatible with XIP images.
560 // If SectionAlignment is not equal to FileAlginment then it is not an XIP type image.
566 // Calculate size of XIP file, and determine if the conversion is needed.
568 ConversionNeeded
= FALSE
;
570 FirstSectionOffset
= *FileLength
;
571 TotalNecessaryFileSize
= 0;
572 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
573 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
574 SectionSize
= MAX (SectionHeader
->Misc
.VirtualSize
, SectionHeader
->SizeOfRawData
);
575 TotalNecessaryFileSize
+= SectionSize
;
576 if (SectionSize
> 0) {
577 FirstSectionOffset
= MIN (FirstSectionOffset
, SectionHeader
->VirtualAddress
);
578 XipLength
= MAX (XipLength
, SectionHeader
->VirtualAddress
+ SectionSize
);
579 if (SectionHeader
->VirtualAddress
!= SectionHeader
->PointerToRawData
) {
580 ConversionNeeded
= TRUE
;
583 if (SectionHeader
->Misc
.VirtualSize
> SectionHeader
->SizeOfRawData
) {
584 ConversionNeeded
= TRUE
;
588 if (FirstSectionOffset
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
590 // If one of the sections should be loaded to an offset overlapping with
591 // the executable header, then it cannot be made into an XIP image.
593 VerboseMsg ("PE/COFF conversion to XIP is impossible due to overlap");
594 VerboseMsg ("of section data with the executable header.");
598 if (FirstSectionOffset
== *FileLength
) {
600 // If we never found a section with a non-zero size, then we
601 // skip the conversion.
606 TotalNecessaryFileSize
+= FirstSectionOffset
;
608 if (!ConversionNeeded
) {
612 if (XipLength
> (2 * TotalNecessaryFileSize
)) {
613 VerboseMsg ("PE/COFF conversion to XIP appears to be larger than necessary.");
614 VerboseMsg ("The image linking process may have left unused memory ranges.");
617 if (PeHdr
->Pe32
.FileHeader
.PointerToSymbolTable
!= 0) {
619 // This field is obsolete and should be zero
621 PeHdr
->Pe32
.FileHeader
.PointerToSymbolTable
= 0;
625 // Allocate the extra space that we need to grow the image
627 XipFile
= malloc (XipLength
);
628 memset (XipFile
, 0, XipLength
);
631 // Copy the file headers
633 memcpy (XipFile
, *FileBuffer
, PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
);
635 NewPeHdr
= GetPeCoffHeader ((void *)XipFile
);
636 if (NewPeHdr
== NULL
) {
642 // Copy the section data over to the appropriate XIP offsets
644 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(NewPeHdr
->Pe32
.OptionalHeader
) + NewPeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
645 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
646 if (SectionHeader
->SizeOfRawData
> 0) {
648 XipFile
+ SectionHeader
->VirtualAddress
,
649 *FileBuffer
+ SectionHeader
->PointerToRawData
,
650 SectionHeader
->SizeOfRawData
654 // Make the size of raw data in section header alignment.
656 SectionHeader
->SizeOfRawData
= (SectionHeader
->Misc
.VirtualSize
+ PeHdr
->Pe32
.OptionalHeader
.FileAlignment
- 1) & (~(PeHdr
->Pe32
.OptionalHeader
.FileAlignment
- 1));
657 SectionHeader
->PointerToRawData
= SectionHeader
->VirtualAddress
;
661 *FileLength
= XipLength
;
662 *FileBuffer
= XipFile
;
666 CreateHiiResouceSectionHeader (
667 UINT32
*pSectionHeaderSize
,
674 Create COFF resource section header
678 pSectionHeaderSize - Pointer to section header size.
679 HiiDataSize - Size of the total HII data in section.
682 The created section header buffer.
686 UINT32 HiiSectionHeaderSize
;
687 UINT32 HiiSectionOffset
;
688 UINT8
*HiiSectionHeader
;
689 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
690 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*TypeResourceDirectoryEntry
;
691 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*NameResourceDirectoryEntry
;
692 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*LanguageResourceDirectoryEntry
;
693 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
694 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
697 // Calculate the total size for the resource header (include Type, Name and Language)
698 // then allocate memory for the resource header.
700 HiiSectionHeaderSize
= 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
))
701 + 3 * (sizeof (UINT16
) + 3 * sizeof (CHAR16
))
702 + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
703 HiiSectionHeader
= malloc (HiiSectionHeaderSize
);
704 memset (HiiSectionHeader
, 0, HiiSectionHeaderSize
);
706 HiiSectionOffset
= 0;
710 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
711 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
712 ResourceDirectory
->NumberOfNamedEntries
= 1;
713 TypeResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
714 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
715 TypeResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
716 TypeResourceDirectoryEntry
->u2
.s
.DataIsDirectory
= 1;
717 TypeResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
= HiiSectionOffset
;
721 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
722 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
723 ResourceDirectory
->NumberOfNamedEntries
= 1;
724 NameResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
725 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
726 NameResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
727 NameResourceDirectoryEntry
->u2
.s
.DataIsDirectory
= 1;
728 NameResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
= HiiSectionOffset
;
730 // Create Language entry
732 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
733 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
734 ResourceDirectory
->NumberOfNamedEntries
= 1;
735 LanguageResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
736 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
737 LanguageResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
739 // Create string entry for Type
741 TypeResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
742 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
743 ResourceDirectoryString
->Length
= 3;
744 ResourceDirectoryString
->String
[0] = L
'H';
745 ResourceDirectoryString
->String
[1] = L
'I';
746 ResourceDirectoryString
->String
[2] = L
'I';
747 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
749 // Create string entry for Name
751 NameResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
752 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
753 ResourceDirectoryString
->Length
= 3;
754 ResourceDirectoryString
->String
[0] = L
'E';
755 ResourceDirectoryString
->String
[1] = L
'F';
756 ResourceDirectoryString
->String
[2] = L
'I';
757 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
759 // Create string entry for Language
761 LanguageResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
762 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
763 ResourceDirectoryString
->Length
= 3;
764 ResourceDirectoryString
->String
[0] = L
'B';
765 ResourceDirectoryString
->String
[1] = L
'I';
766 ResourceDirectoryString
->String
[2] = L
'N';
767 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
771 LanguageResourceDirectoryEntry
->u2
.OffsetToData
= HiiSectionOffset
;
772 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
773 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
774 ResourceDataEntry
->OffsetToData
= HiiSectionOffset
;
775 ResourceDataEntry
->Size
= HiiDataSize
;
777 *pSectionHeaderSize
= HiiSectionHeaderSize
;
778 return HiiSectionHeader
;
785 IN OUT UINT32
*ReadSize
,
792 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
796 FileHandle - The handle to the PE/COFF file
798 FileOffset - The offset, in bytes, into the file to read
800 ReadSize - The number of bytes to read from the file starting at FileOffset
802 Buffer - A pointer to the buffer to read the data into.
806 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
814 Destination8
= Buffer
;
815 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
818 *(Destination8
++) = *(Source8
++);
825 SetAddressToSectionHeader (
827 IN OUT UINT8
*FileBuffer
,
828 IN UINT64 NewPe32BaseAddress
834 Set new base address into the section header of PeImage
838 FileName - Name of file
839 FileBuffer - Pointer to PeImage.
840 NewPe32BaseAddress - New Base Address for PE image.
844 EFI_SUCCESS Set new base address into this image successfully.
849 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
851 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
852 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
855 // Initialize context
857 memset (&ImageContext
, 0, sizeof (ImageContext
));
858 ImageContext
.Handle
= (VOID
*) FileBuffer
;
859 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
860 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
861 if (EFI_ERROR (Status
)) {
862 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
866 if (ImageContext
.RelocationsStripped
) {
867 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
872 // Get PeHeader pointer
874 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
877 // Get section header list
879 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
882 sizeof (EFI_IMAGE_FILE_HEADER
) +
883 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
887 // Set base address into the first section header that doesn't point to code section.
889 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
890 if ((SectionHeader
->Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
891 *(UINT64
*) &SectionHeader
->PointerToRelocations
= NewPe32BaseAddress
;
897 // BaseAddress is set to section header.
905 IN OUT UINT8
*FileBuffer
,
906 IN UINT64 NewPe32BaseAddress
912 Set new base address into PeImage, and fix up PeImage based on new address.
916 FileName - Name of file
917 FileBuffer - Pointer to PeImage.
918 NewPe32BaseAddress - New Base Address for PE image.
922 EFI_INVALID_PARAMETER - BaseAddress is not valid.
923 EFI_SUCCESS - Update PeImage is correctly.
928 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
930 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
931 UINT8
*MemoryImagePointer
;
932 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
935 // Initialize context
937 memset (&ImageContext
, 0, sizeof (ImageContext
));
938 ImageContext
.Handle
= (VOID
*) FileBuffer
;
939 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
940 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
941 if (EFI_ERROR (Status
)) {
942 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
946 if (ImageContext
.RelocationsStripped
) {
947 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
952 // Get PeHeader pointer
954 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
957 // Load and Relocate Image Data
959 MemoryImagePointer
= (UINT8
*) malloc ((UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
960 if (MemoryImagePointer
== NULL
) {
961 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
962 return EFI_OUT_OF_RESOURCES
;
964 memset ((VOID
*) MemoryImagePointer
, 0, (UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
965 ImageContext
.ImageAddress
= ((UINTN
) MemoryImagePointer
+ ImageContext
.SectionAlignment
- 1) & (~((INT64
)ImageContext
.SectionAlignment
- 1));
967 Status
= PeCoffLoaderLoadImage (&ImageContext
);
968 if (EFI_ERROR (Status
)) {
969 Error (NULL
, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName
);
970 free ((VOID
*) MemoryImagePointer
);
974 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
975 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
976 if (EFI_ERROR (Status
)) {
977 Error (NULL
, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName
);
978 free ((VOID
*) MemoryImagePointer
);
983 // Copy Relocated data to raw image file.
985 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
988 sizeof (EFI_IMAGE_FILE_HEADER
) +
989 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
992 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
994 FileBuffer
+ SectionHeader
->PointerToRawData
,
995 (VOID
*) (UINTN
) (ImageContext
.ImageAddress
+ SectionHeader
->VirtualAddress
),
996 SectionHeader
->SizeOfRawData
1000 free ((VOID
*) MemoryImagePointer
);
1003 // Update Image Base Address
1005 if ((ImgHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) && (ImgHdr
->Pe32
.FileHeader
.Machine
!= IMAGE_FILE_MACHINE_IA64
)) {
1006 ImgHdr
->Pe32
.OptionalHeader
.ImageBase
= (UINT32
) NewPe32BaseAddress
;
1007 } else if (ImgHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1008 ImgHdr
->Pe32Plus
.OptionalHeader
.ImageBase
= NewPe32BaseAddress
;
1010 Error (NULL
, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
1011 ImgHdr
->Pe32
.OptionalHeader
.Magic
,
1018 // Set new base address into section header
1020 Status
= SetAddressToSectionHeader (FileName
, FileBuffer
, NewPe32BaseAddress
);
1032 Routine Description:
1038 argc - Number of command line parameters.
1039 argv - Array of pointers to command line parameter strings.
1042 STATUS_SUCCESS - Utility exits successfully.
1043 STATUS_ERROR - Some error occurred during execution.
1048 UINT32 InputFileNum
;
1049 CHAR8
**InputFileName
;
1057 UINT32
*DataPointer
;
1058 UINT32
*OldDataPointer
;
1064 UINT32 MciAlignment
;
1066 UINT32 AllignedRelocSize
;
1069 UINT8
*OutputFileBuffer
;
1070 UINT32 OutputFileLength
;
1071 UINT8
*InputFileBuffer
;
1072 UINT32 InputFileLength
;
1073 RUNTIME_FUNCTION
*RuntimeFunction
;
1074 UNWIND_INFO
*UnwindInfo
;
1076 BOOLEAN ReplaceFlag
;
1077 BOOLEAN KeepExceptionTableFlag
;
1078 BOOLEAN KeepOptionalHeaderFlag
;
1079 BOOLEAN KeepZeroPendingFlag
;
1081 EFI_TE_IMAGE_HEADER TEImageHeader
;
1082 EFI_TE_IMAGE_HEADER
*TeHdr
;
1083 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1084 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1085 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1086 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32
;
1087 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64
;
1088 EFI_IMAGE_DOS_HEADER BackupDosHdr
;
1089 MICROCODE_IMAGE_HEADER
*MciHeader
;
1090 UINT8
*HiiPackageListBuffer
;
1091 UINT8
*HiiPackageDataPointer
;
1092 EFI_GUID HiiPackageListGuid
;
1093 EFI_HII_PACKAGE_LIST_HEADER HiiPackageListHeader
;
1094 EFI_HII_PACKAGE_HEADER HiiPackageHeader
;
1095 EFI_IFR_FORM_SET IfrFormSet
;
1096 UINT8 NumberOfFormPacakge
;
1097 EFI_HII_PACKAGE_HEADER EndPackage
;
1098 UINT32 HiiSectionHeaderSize
;
1099 UINT8
*HiiSectionHeader
;
1100 UINT64 NewBaseAddress
;
1101 BOOLEAN NegativeAddr
;
1103 CHAR8
*ReportFileName
;
1105 time_t InputFileTime
;
1106 time_t OutputFileTime
;
1107 struct stat Stat_Buf
;
1109 SetUtilityName (UTILITY_NAME
);
1112 // Assign to fix compile warning
1116 InputFileName
= NULL
;
1117 mInImageName
= NULL
;
1118 OutImageName
= NULL
;
1121 Status
= STATUS_SUCCESS
;
1127 MciAlignment
= DEFAULT_MC_ALIGNMENT
;
1128 MciPadValue
= DEFAULT_MC_PAD_BYTE_VALUE
;
1132 ReplaceFlag
= FALSE
;
1134 OutputFileBuffer
= NULL
;
1135 OutputFileLength
= 0;
1136 InputFileBuffer
= NULL
;
1137 InputFileLength
= 0;
1140 KeepExceptionTableFlag
= FALSE
;
1141 KeepOptionalHeaderFlag
= FALSE
;
1142 KeepZeroPendingFlag
= FALSE
;
1143 NumberOfFormPacakge
= 0;
1144 HiiPackageListBuffer
= NULL
;
1145 HiiPackageDataPointer
= NULL
;
1146 EndPackage
.Length
= sizeof (EFI_HII_PACKAGE_HEADER
);
1147 EndPackage
.Type
= EFI_HII_PACKAGE_END
;
1148 memset (&HiiPackageListGuid
, 0, sizeof (HiiPackageListGuid
));
1149 HiiSectionHeaderSize
= 0;
1150 HiiSectionHeader
= NULL
;
1152 NegativeAddr
= FALSE
;
1157 Error (NULL
, 0, 1001, "Missing options", "No input options.");
1159 return STATUS_ERROR
;
1165 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
1168 return STATUS_SUCCESS
;
1171 if (stricmp (argv
[0], "--version") == 0) {
1173 return STATUS_SUCCESS
;
1177 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
1178 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1179 Error (NULL
, 0, 1003, "Invalid option value", "Output file name is missing for -o option");
1182 OutImageName
= argv
[1];
1188 if ((stricmp (argv
[0], "-e") == 0) || (stricmp (argv
[0], "--efiImage") == 0)) {
1189 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1190 Error (NULL
, 0, 1003, "Invalid option value", "Module Type is missing for -o option");
1193 ModuleType
= argv
[1];
1194 if (mOutImageType
!= FW_TE_IMAGE
) {
1195 mOutImageType
= FW_EFI_IMAGE
;
1202 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--stripped") == 0)) {
1203 mOutImageType
= FW_RELOC_STRIPEED_IMAGE
;
1209 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--acpi") == 0)) {
1210 mOutImageType
= FW_ACPI_IMAGE
;
1216 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--terse") == 0)) {
1217 mOutImageType
= FW_TE_IMAGE
;
1223 if ((stricmp (argv
[0], "-u") == 0) || (stricmp (argv
[0], "--dump") == 0)) {
1224 mOutImageType
= DUMP_TE_HEADER
;
1230 if ((stricmp (argv
[0], "-b") == 0) || (stricmp (argv
[0], "--exe2bin") == 0)) {
1231 mOutImageType
= FW_BIN_IMAGE
;
1237 if ((stricmp (argv
[0], "-z") == 0) || (stricmp (argv
[0], "--zero") == 0)) {
1238 mOutImageType
= FW_ZERO_DEBUG_IMAGE
;
1244 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--stamp") == 0)) {
1245 mOutImageType
= FW_SET_STAMP_IMAGE
;
1246 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1247 Error (NULL
, 0, 1003, "Invalid option value", "time stamp is missing for -s option");
1250 TimeStamp
= argv
[1];
1256 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--replace") == 0)) {
1263 if (stricmp (argv
[0], "--keepexceptiontable") == 0) {
1264 KeepExceptionTableFlag
= TRUE
;
1270 if (stricmp(argv
[0], "--keepoptionalheader") == 0) {
1271 KeepOptionalHeaderFlag
= TRUE
;
1277 if (stricmp (argv
[0], "--keepzeropending") == 0) {
1278 KeepZeroPendingFlag
= TRUE
;
1284 if ((stricmp (argv
[0], "-m") == 0) || (stricmp (argv
[0], "--mcifile") == 0)) {
1285 mOutImageType
= FW_MCI_IMAGE
;
1291 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--join") == 0)) {
1292 mOutImageType
= FW_MERGE_IMAGE
;
1298 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
1299 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1300 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1303 MciAlignment
= (UINT32
) Temp64
;
1309 if ((stricmp (argv
[0], "--rebase") == 0)) {
1310 if (argv
[1][0] == '-') {
1311 NegativeAddr
= TRUE
;
1312 Status
= AsciiStringToUint64 (argv
[1] + 1, FALSE
, &Temp64
);
1314 NegativeAddr
= FALSE
;
1315 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
);
1317 if (Status
!= EFI_SUCCESS
) {
1318 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1321 mOutImageType
= FW_REBASE_IMAGE
;
1322 NewBaseAddress
= (UINT64
) Temp64
;
1328 if ((stricmp (argv
[0], "--address") == 0)) {
1329 if (argv
[1][0] == '-') {
1330 NegativeAddr
= TRUE
;
1331 Status
= AsciiStringToUint64 (argv
[1] + 1, FALSE
, &Temp64
);
1333 NegativeAddr
= FALSE
;
1334 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
);
1336 if (Status
!= EFI_SUCCESS
) {
1337 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1340 mOutImageType
= FW_SET_ADDRESS_IMAGE
;
1341 NewBaseAddress
= (UINT64
) Temp64
;
1347 if ((stricmp (argv
[0], "-p") == 0) || (stricmp (argv
[0], "--pad") == 0)) {
1348 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1349 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1352 MciPadValue
= (UINT8
) Temp64
;
1358 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
1359 SetPrintLevel (VERBOSE_LOG_LEVEL
);
1360 VerboseMsg ("Verbose output Mode Set!");
1366 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1367 SetPrintLevel (KEY_LOG_LEVEL
);
1368 KeyMsg ("Quiet output Mode Set!");
1374 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
1375 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
1376 if (EFI_ERROR (Status
)) {
1377 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1381 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel
);
1384 SetPrintLevel (LogLevel
);
1385 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
1391 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--hiiguid") == 0)) {
1392 Status
= StringToGuid (argv
[1], &HiiPackageListGuid
);
1393 if (EFI_ERROR (Status
)) {
1394 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1402 if (stricmp (argv
[0], "--hiipackage") == 0) {
1403 mOutImageType
= FW_HII_PACKAGE_LIST_RCIMAGE
;
1409 if (stricmp (argv
[0], "--hiibinpackage") == 0) {
1410 mOutImageType
= FW_HII_PACKAGE_LIST_BINIMAGE
;
1416 if (argv
[0][0] == '-') {
1417 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
1421 // Get Input file name
1423 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
1424 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
1425 if (InputFileName
== NULL
) {
1426 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1430 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1431 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1433 // InputFileName buffer too small, need to realloc
1435 InputFileName
= (CHAR8
**) realloc (
1437 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1440 if (InputFileName
== NULL
) {
1441 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1445 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1448 InputFileName
[InputFileNum
++] = argv
[0];
1453 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1455 if (mOutImageType
== FW_DUMMY_IMAGE
) {
1456 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!");
1458 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.");
1464 // check input files
1466 if (InputFileNum
== 0) {
1467 Error (NULL
, 0, 1001, "Missing option", "Input files");
1472 // Combine MciBinary files to one file
1474 if ((mOutImageType
== FW_MERGE_IMAGE
) && ReplaceFlag
) {
1475 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");
1480 // Combine HiiBinary packages to a single package list
1482 if ((mOutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) && ReplaceFlag
) {
1483 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option.");
1487 if ((mOutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) && ReplaceFlag
) {
1488 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiibinpackage merge files option.");
1495 mInImageName
= InputFileName
[InputFileNum
- 1];
1496 VerboseMsg ("the input file name is %s", mInImageName
);
1499 // Action will be taken for the input file.
1501 switch (mOutImageType
) {
1503 VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType
);
1506 VerboseMsg ("Create Te Image based on the input PE image.");
1509 VerboseMsg ("Get acpi table data from the input PE image.");
1511 case FW_RELOC_STRIPEED_IMAGE
:
1512 VerboseMsg ("Remove relocation section from Pe or Te image.");
1515 VerboseMsg ("Convert the input EXE to the output BIN file.");
1517 case FW_ZERO_DEBUG_IMAGE
:
1518 VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");
1520 case FW_SET_STAMP_IMAGE
:
1521 VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp
);
1523 case DUMP_TE_HEADER
:
1524 VerboseMsg ("Dump the TE header information of the input TE image.");
1527 VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");
1529 case FW_MERGE_IMAGE
:
1530 VerboseMsg ("Combine the input multi microcode bin files to one bin file.");
1532 case FW_HII_PACKAGE_LIST_RCIMAGE
:
1533 VerboseMsg ("Combine the input multi hii bin packages to one text pacakge list RC file.");
1535 case FW_HII_PACKAGE_LIST_BINIMAGE
:
1536 VerboseMsg ("Combine the input multi hii bin packages to one binary pacakge list file.");
1538 case FW_REBASE_IMAGE
:
1539 VerboseMsg ("Rebase the input image to new base address.");
1541 case FW_SET_ADDRESS_IMAGE
:
1542 VerboseMsg ("Set the preferred address into the section header of the input image");
1549 VerboseMsg ("Overwrite the input file with the output content.");
1553 // Open output file and Write image into the output file.
1555 if (OutImageName
!= NULL
) {
1556 fpOut
= fopen (LongFilePath (OutImageName
), "rb");
1557 if (fpOut
!= NULL
) {
1559 // Get Output file time stamp
1561 fstat(fileno (fpOut
), &Stat_Buf
);
1562 OutputFileTime
= Stat_Buf
.st_mtime
;
1564 // Get Output file data
1566 OutputFileLength
= _filelength (fileno (fpOut
));
1567 OutputFileBuffer
= malloc (OutputFileLength
);
1568 if (OutputFileBuffer
== NULL
) {
1569 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1574 fread (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
1578 VerboseMsg ("Output file name is %s", OutImageName
);
1579 } else if (!ReplaceFlag
&& mOutImageType
!= DUMP_TE_HEADER
) {
1580 Error (NULL
, 0, 1001, "Missing option", "output file");
1585 // Open input file and read file data into file buffer.
1587 fpIn
= fopen (LongFilePath (mInImageName
), "rb");
1589 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1593 // Get Iutput file time stamp
1595 fstat(fileno (fpIn
), &Stat_Buf
);
1596 InputFileTime
= Stat_Buf
.st_mtime
;
1598 // Get Input file data
1600 InputFileLength
= _filelength (fileno (fpIn
));
1601 InputFileBuffer
= malloc (InputFileLength
);
1602 if (InputFileBuffer
== NULL
) {
1603 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1607 fread (InputFileBuffer
, 1, InputFileLength
, fpIn
);
1609 DebugMsg (NULL
, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) InputFileLength
);
1612 // Combine multi binary HII package files.
1614 if (mOutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
|| mOutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) {
1616 // Open output file handle.
1618 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
1620 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1624 // Get hii package list lenght
1626 HiiPackageListHeader
.PackageLength
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1627 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1628 fpIn
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
1630 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1633 FileLength
= _filelength (fileno (fpIn
));
1634 fread (&HiiPackageHeader
, 1, sizeof (HiiPackageHeader
), fpIn
);
1635 if (HiiPackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) {
1636 if (HiiPackageHeader
.Length
!= FileLength
) {
1637 Error (NULL
, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName
[Index
]);
1641 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
1642 fread (&IfrFormSet
, 1, sizeof (IfrFormSet
), fpIn
);
1643 memcpy (&HiiPackageListGuid
, &IfrFormSet
.Guid
, sizeof (EFI_GUID
));
1645 NumberOfFormPacakge
++;
1647 HiiPackageListHeader
.PackageLength
+= FileLength
;
1650 HiiPackageListHeader
.PackageLength
+= sizeof (EndPackage
);
1652 // Check whether hii packages are valid
1654 if (NumberOfFormPacakge
> 1) {
1655 Error (NULL
, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package");
1658 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
1659 Error (NULL
, 0, 3000, "Invalid", "HII pacakge list guid is not specified!");
1662 memcpy (&HiiPackageListHeader
.PackageListGuid
, &HiiPackageListGuid
, sizeof (EFI_GUID
));
1664 // read hii packages
1666 HiiPackageListBuffer
= malloc (HiiPackageListHeader
.PackageLength
);
1667 if (HiiPackageListBuffer
== NULL
) {
1668 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1671 memcpy (HiiPackageListBuffer
, &HiiPackageListHeader
, sizeof (HiiPackageListHeader
));
1672 HiiPackageDataPointer
= HiiPackageListBuffer
+ sizeof (HiiPackageListHeader
);
1673 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1674 fpIn
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
1676 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1677 free (HiiPackageListBuffer
);
1681 FileLength
= _filelength (fileno (fpIn
));
1682 fread (HiiPackageDataPointer
, 1, FileLength
, fpIn
);
1684 HiiPackageDataPointer
= HiiPackageDataPointer
+ FileLength
;
1686 memcpy (HiiPackageDataPointer
, &EndPackage
, sizeof (EndPackage
));
1689 // write the hii package into the binary package list file with the resource section header
1691 if (mOutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) {
1693 // Create the resource section header
1695 HiiSectionHeader
= CreateHiiResouceSectionHeader (&HiiSectionHeaderSize
, HiiPackageListHeader
.PackageLength
);
1697 // Wrtie section header and HiiData into File.
1699 fwrite (HiiSectionHeader
, 1, HiiSectionHeaderSize
, fpOut
);
1700 fwrite (HiiPackageListBuffer
, 1, HiiPackageListHeader
.PackageLength
, fpOut
);
1702 // Free allocated resources.
1704 free (HiiSectionHeader
);
1705 free (HiiPackageListBuffer
);
1707 // Done successfully
1713 // write the hii package into the text package list rc file.
1715 if (mOutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) {
1716 for (Index
= 0; gHiiPackageRCFileHeader
[Index
] != NULL
; Index
++) {
1717 fprintf (fpOut
, "%s\n", gHiiPackageRCFileHeader
[Index
]);
1719 fprintf (fpOut
, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX
, HII_RESOURCE_SECTION_NAME
);
1721 HiiPackageDataPointer
= HiiPackageListBuffer
;
1722 for (Index
= 0; Index
+ 2 < HiiPackageListHeader
.PackageLength
; Index
+= 2) {
1723 if (Index
% 16 == 0) {
1724 fprintf (fpOut
, "\n ");
1726 fprintf (fpOut
, " 0x%04X,", *(UINT16
*) HiiPackageDataPointer
);
1727 HiiPackageDataPointer
+= 2;
1730 if (Index
% 16 == 0) {
1731 fprintf (fpOut
, "\n ");
1733 if ((Index
+ 2) == HiiPackageListHeader
.PackageLength
) {
1734 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT16
*) HiiPackageDataPointer
);
1736 if ((Index
+ 1) == HiiPackageListHeader
.PackageLength
) {
1737 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT8
*) HiiPackageDataPointer
);
1739 free (HiiPackageListBuffer
);
1741 // Done successfully
1748 // Combine MciBinary files to one file
1750 if (mOutImageType
== FW_MERGE_IMAGE
) {
1752 // Open output file handle.
1754 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
1756 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1759 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1760 fpIn
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
1762 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1766 FileLength
= _filelength (fileno (fpIn
));
1767 FileBuffer
= malloc (FileLength
);
1768 if (FileBuffer
== NULL
) {
1769 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1774 fread (FileBuffer
, 1, FileLength
, fpIn
);
1777 // write input file to out file
1779 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
1781 // write pad value to out file.
1783 while (FileLength
++ % MciAlignment
!= 0) {
1784 fwrite (&MciPadValue
, 1, 1, fpOut
);
1787 // free allocated memory space
1793 // Done successfully
1799 // Convert MicroCode.txt file to MicroCode.bin file
1801 if (mOutImageType
== FW_MCI_IMAGE
) {
1802 fpIn
= fopen (LongFilePath (mInImageName
), "r");
1804 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1809 // The first pass is to determine
1810 // how much data is in the file so we can allocate a working buffer.
1814 Status
= MicrocodeReadData (fpIn
, &Data
);
1815 if (Status
== STATUS_SUCCESS
) {
1816 FileLength
+= sizeof (Data
);
1818 if (Status
== STATUS_IGNORE
) {
1819 Status
= STATUS_SUCCESS
;
1821 } while (Status
== STATUS_SUCCESS
);
1823 // Error if no data.
1825 if (FileLength
== 0) {
1826 Error (NULL
, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName
);
1829 if (FileLength
< sizeof (MICROCODE_IMAGE_HEADER
)) {
1830 Error (NULL
, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName
);
1835 // Allocate a buffer for the data
1837 FileBuffer
= malloc (FileLength
);
1838 if (FileBuffer
== NULL
) {
1839 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1843 // Re-read the file, storing the data into our buffer
1845 fseek (fpIn
, 0, SEEK_SET
);
1846 DataPointer
= (UINT32
*) FileBuffer
;
1847 OldDataPointer
= DataPointer
;
1849 OldDataPointer
= DataPointer
;
1850 Status
= MicrocodeReadData (fpIn
, DataPointer
++);
1851 if (Status
== STATUS_IGNORE
) {
1852 DataPointer
= OldDataPointer
;
1853 Status
= STATUS_SUCCESS
;
1855 } while (Status
== STATUS_SUCCESS
);
1857 // close input file after read data
1862 // Can't do much checking on the header because, per the spec, the
1863 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
1864 // and the TotalSize field is invalid (actually missing). Thus we can't
1865 // even verify the Reserved fields are 0.
1867 MciHeader
= (MICROCODE_IMAGE_HEADER
*) FileBuffer
;
1868 if (MciHeader
->DataSize
== 0) {
1871 Index
= MciHeader
->TotalSize
;
1874 if (Index
!= FileLength
) {
1875 Error (NULL
, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName
, (unsigned) FileLength
, (unsigned) Index
);
1880 // Checksum the contents
1882 DataPointer
= (UINT32
*) FileBuffer
;
1885 while (Index
< FileLength
) {
1886 CheckSum
+= *DataPointer
;
1888 Index
+= sizeof (*DataPointer
);
1890 if (CheckSum
!= 0) {
1891 Error (NULL
, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum
, mInImageName
);
1895 // Open the output file and write the buffer contents
1897 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
1902 // Open input file and read file data into file buffer.
1904 FileLength
= InputFileLength
;
1905 FileBuffer
= malloc (FileLength
);
1906 if (FileBuffer
== NULL
) {
1907 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1910 memcpy (FileBuffer
, InputFileBuffer
, InputFileLength
);
1913 // Dump TeImage Header into output file.
1915 if (mOutImageType
== DUMP_TE_HEADER
) {
1916 memcpy (&TEImageHeader
, FileBuffer
, sizeof (TEImageHeader
));
1917 if (TEImageHeader
.Signature
!= EFI_TE_IMAGE_HEADER_SIGNATURE
) {
1918 Error (NULL
, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName
);
1922 // Open the output file handle.
1925 fpInOut
= fopen (LongFilePath (mInImageName
), "wb");
1926 if (fpInOut
== NULL
) {
1927 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1931 if (OutImageName
!= NULL
) {
1932 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
1936 if (fpOut
== NULL
) {
1937 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1941 if (fpInOut
!= NULL
) {
1942 fprintf (fpInOut
, "Dump of file %s\n\n", mInImageName
);
1943 fprintf (fpInOut
, "TE IMAGE HEADER VALUES\n");
1944 fprintf (fpInOut
, "%17X machine\n", TEImageHeader
.Machine
);
1945 fprintf (fpInOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
1946 fprintf (fpInOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
1947 fprintf (fpInOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
1948 fprintf (fpInOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
1949 fprintf (fpInOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
1950 fprintf (fpInOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
1951 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
1952 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
1954 if (fpOut
!= NULL
) {
1955 fprintf (fpOut
, "Dump of file %s\n\n", mInImageName
);
1956 fprintf (fpOut
, "TE IMAGE HEADER VALUES\n");
1957 fprintf (fpOut
, "%17X machine\n", TEImageHeader
.Machine
);
1958 fprintf (fpOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
1959 fprintf (fpOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
1960 fprintf (fpOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
1961 fprintf (fpOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
1962 fprintf (fpOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
1963 fprintf (fpOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
1964 fprintf (fpOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
1965 fprintf (fpOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
1971 // Following code to convert dll to efi image or te image.
1972 // Get new image type
1974 if ((mOutImageType
== FW_EFI_IMAGE
) || (mOutImageType
== FW_TE_IMAGE
)) {
1975 if (ModuleType
== NULL
) {
1976 if (mOutImageType
== FW_EFI_IMAGE
) {
1977 Error (NULL
, 0, 1001, "Missing option", "EFI_FILETYPE");
1979 } else if (mOutImageType
== FW_TE_IMAGE
) {
1981 // Default TE Image Type is Boot service driver
1983 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
1984 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
1987 if (stricmp (ModuleType
, "BASE") == 0 ||
1988 stricmp (ModuleType
, "SEC") == 0 ||
1989 stricmp (ModuleType
, "SECURITY_CORE") == 0 ||
1990 stricmp (ModuleType
, "PEI_CORE") == 0 ||
1991 stricmp (ModuleType
, "PEIM") == 0 ||
1992 stricmp (ModuleType
, "COMBINED_PEIM_DRIVER") == 0 ||
1993 stricmp (ModuleType
, "PIC_PEIM") == 0 ||
1994 stricmp (ModuleType
, "RELOCATABLE_PEIM") == 0 ||
1995 stricmp (ModuleType
, "DXE_CORE") == 0 ||
1996 stricmp (ModuleType
, "BS_DRIVER") == 0 ||
1997 stricmp (ModuleType
, "DXE_DRIVER") == 0 ||
1998 stricmp (ModuleType
, "DXE_SMM_DRIVER") == 0 ||
1999 stricmp (ModuleType
, "UEFI_DRIVER") == 0 ||
2000 stricmp (ModuleType
, "SMM_CORE") == 0) {
2001 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2002 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2004 } else if (stricmp (ModuleType
, "UEFI_APPLICATION") == 0 ||
2005 stricmp (ModuleType
, "APPLICATION") == 0) {
2006 Type
= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
;
2007 VerboseMsg ("Efi Image subsystem type is efi application.");
2009 } else if (stricmp (ModuleType
, "DXE_RUNTIME_DRIVER") == 0 ||
2010 stricmp (ModuleType
, "RT_DRIVER") == 0) {
2011 Type
= EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
;
2012 VerboseMsg ("Efi Image subsystem type is efi runtime driver.");
2014 } else if (stricmp (ModuleType
, "DXE_SAL_DRIVER") == 0 ||
2015 stricmp (ModuleType
, "SAL_RT_DRIVER") == 0) {
2016 Type
= EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
;
2017 VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");
2020 Error (NULL
, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType
);
2027 // Convert ELF image to PeImage
2029 if (IsElfHeader(FileBuffer
)) {
2030 VerboseMsg ("Convert %s from ELF to PE/COFF.", mInImageName
);
2031 if (!ConvertElf(&FileBuffer
, &FileLength
)) {
2032 Error (NULL
, 0, 3000, "Invalid", "Unable to convert %s from ELF to PE/COFF.", mInImageName
);
2038 // Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP
2039 // XIP == eXecute In Place
2041 PeCoffConvertImageToXip (&FileBuffer
, &FileLength
);
2044 // Remove reloc section from PE or TE image
2046 if (mOutImageType
== FW_RELOC_STRIPEED_IMAGE
) {
2050 TeHdr
= (EFI_TE_IMAGE_HEADER
*) FileBuffer
;
2051 if (TeHdr
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2052 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (TeHdr
+ 1);
2053 for (Index
= 0; Index
< TeHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2054 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2056 // Check the reloc section is in the end of image.
2058 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) ==
2059 (FileLength
+ TeHdr
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
))) {
2061 // Remove .reloc section and update TeImage Header
2063 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2064 SectionHeader
->SizeOfRawData
= 0;
2065 SectionHeader
->Misc
.VirtualSize
= 0;
2066 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2067 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2076 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2077 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2078 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2079 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2080 Error (NULL
, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName
);
2085 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2086 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2087 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2091 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2092 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2093 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2095 // Check the reloc section is in the end of image.
2097 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) == FileLength
) {
2099 // Remove .reloc section and update PeImage Header
2101 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2103 PeHdr
->Pe32
.FileHeader
.Characteristics
|= EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2104 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2105 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2106 Optional32
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2107 Optional32
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2108 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2109 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2110 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2113 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2114 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2115 Optional64
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2116 Optional64
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2117 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2118 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2119 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2122 SectionHeader
->Misc
.VirtualSize
= 0;
2123 SectionHeader
->SizeOfRawData
= 0;
2135 // Read the dos & pe hdrs of the image
2137 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2138 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2139 // NO DOS header, check for PE/COFF header
2140 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2141 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2142 Error (NULL
, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName
);
2148 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2149 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2150 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2155 if (PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_ARM
) {
2156 // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
2157 // so patch back to the offical UEFI value.
2158 PeHdr
->Pe32
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_ARMT
;
2162 // Set new base address into image
2164 if (mOutImageType
== FW_REBASE_IMAGE
|| mOutImageType
== FW_SET_ADDRESS_IMAGE
) {
2165 if ((PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) && (PeHdr
->Pe32
.FileHeader
.Machine
!= IMAGE_FILE_MACHINE_IA64
)) {
2166 if (NewBaseAddress
>= 0x100000000ULL
) {
2167 Error (NULL
, 0, 3000, "Invalid", "New base address is larger than 4G for 32bit PE image");
2174 // Set Base Address to a negative value.
2176 NewBaseAddress
= (UINT64
) (0 - NewBaseAddress
);
2178 if (mOutImageType
== FW_REBASE_IMAGE
) {
2179 Status
= RebaseImage (mInImageName
, FileBuffer
, NewBaseAddress
);
2181 Status
= SetAddressToSectionHeader (mInImageName
, FileBuffer
, NewBaseAddress
);
2183 if (EFI_ERROR (Status
)) {
2185 Error (NULL
, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address -0x%llx can't success", mInImageName
, 0 - NewBaseAddress
);
2187 Error (NULL
, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address 0x%llx can't success", mInImageName
, NewBaseAddress
);
2199 // Extract bin data from Pe image.
2201 if (mOutImageType
== FW_BIN_IMAGE
) {
2202 if (FileLength
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
2203 Error (NULL
, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName
);
2207 // Output bin data from exe file
2209 FileLength
= FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
;
2210 memmove (FileBuffer
, FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, FileLength
);
2211 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2216 // Zero Debug Information of Pe Image
2218 if (mOutImageType
== FW_ZERO_DEBUG_IMAGE
) {
2219 Status
= ZeroDebugData (FileBuffer
, TRUE
);
2220 if (EFI_ERROR (Status
)) {
2221 Error (NULL
, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status
);
2226 // Write the updated Image
2228 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2233 // Set Time Stamp of Pe Image
2235 if (mOutImageType
== FW_SET_STAMP_IMAGE
) {
2236 Status
= SetStamp (FileBuffer
, TimeStamp
);
2237 if (EFI_ERROR (Status
)) {
2242 // Write the updated Image
2244 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2249 // Extract acpi data from pe image.
2251 if (mOutImageType
== FW_ACPI_IMAGE
) {
2252 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2253 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2254 if (strcmp ((char *)SectionHeader
->Name
, ".data") == 0 || strcmp ((char *)SectionHeader
->Name
, ".sdata") == 0) {
2258 if (SectionHeader
->Misc
.VirtualSize
< SectionHeader
->SizeOfRawData
) {
2259 FileLength
= SectionHeader
->Misc
.VirtualSize
;
2261 FileLength
= SectionHeader
->SizeOfRawData
;
2264 if (CheckAcpiTable (FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
) != STATUS_SUCCESS
) {
2265 Error (NULL
, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName
);
2270 // Output Apci data to file
2272 memmove (FileBuffer
, FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
);
2273 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2277 Error (NULL
, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName
);
2281 // Zero all unused fields of the DOS header
2283 if (DosHdr
!= NULL
) {
2284 memcpy (&BackupDosHdr
, DosHdr
, sizeof (EFI_IMAGE_DOS_HEADER
));
2285 memset (DosHdr
, 0, sizeof (EFI_IMAGE_DOS_HEADER
));
2286 DosHdr
->e_magic
= BackupDosHdr
.e_magic
;
2287 DosHdr
->e_lfanew
= BackupDosHdr
.e_lfanew
;
2289 for (Index
= sizeof (EFI_IMAGE_DOS_HEADER
); Index
< (UINT32
) DosHdr
->e_lfanew
; Index
++) {
2290 FileBuffer
[Index
] = (UINT8
) DosHdr
->e_cp
;
2295 // Initialize TeImage Header
2297 memset (&TEImageHeader
, 0, sizeof (EFI_TE_IMAGE_HEADER
));
2298 TEImageHeader
.Signature
= EFI_TE_IMAGE_HEADER_SIGNATURE
;
2299 TEImageHeader
.Machine
= PeHdr
->Pe32
.FileHeader
.Machine
;
2300 TEImageHeader
.NumberOfSections
= (UINT8
) PeHdr
->Pe32
.FileHeader
.NumberOfSections
;
2301 TEImageHeader
.StrippedSize
= (UINT16
) ((UINTN
) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
) - (UINTN
) FileBuffer
);
2302 TEImageHeader
.Subsystem
= (UINT8
) Type
;
2305 // Patch the PE header
2307 PeHdr
->Pe32
.OptionalHeader
.Subsystem
= (UINT16
) Type
;
2309 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2310 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2311 if (!KeepOptionalHeaderFlag
) {
2312 Optional32
->MajorOperatingSystemVersion
= 0;
2313 Optional32
->MinorOperatingSystemVersion
= 0;
2314 Optional32
->MajorImageVersion
= 0;
2315 Optional32
->MinorImageVersion
= 0;
2316 Optional32
->MajorSubsystemVersion
= 0;
2317 Optional32
->MinorSubsystemVersion
= 0;
2318 Optional32
->Win32VersionValue
= 0;
2319 Optional32
->CheckSum
= 0;
2320 Optional32
->SizeOfStackReserve
= 0;
2321 Optional32
->SizeOfStackCommit
= 0;
2322 Optional32
->SizeOfHeapReserve
= 0;
2323 Optional32
->SizeOfHeapCommit
= 0;
2325 TEImageHeader
.AddressOfEntryPoint
= Optional32
->AddressOfEntryPoint
;
2326 TEImageHeader
.BaseOfCode
= Optional32
->BaseOfCode
;
2327 TEImageHeader
.ImageBase
= (UINT64
) (Optional32
->ImageBase
);
2329 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2330 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2331 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2334 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2335 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2336 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2340 // Zero .pdata section data.
2342 if (!KeepExceptionTableFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2343 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2344 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2345 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2346 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2347 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2349 // Zero .pdata Section data
2351 memset (FileBuffer
+ SectionHeader
->PointerToRawData
, 0, SectionHeader
->SizeOfRawData
);
2353 // Zero .pdata Section header name
2355 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2357 // Zero Execption Table
2359 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2360 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2361 DebugMsg (NULL
, 0, 9, "Zero the .pdata section for PE image", NULL
);
2368 // Strip zero padding at the end of the .reloc section
2370 if (!KeepZeroPendingFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2371 if (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2372 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2373 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2375 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2377 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2378 SectionHeader
->Misc
.VirtualSize
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2379 AllignedRelocSize
= (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional32
->FileAlignment
- 1) & (~(Optional32
->FileAlignment
- 1));
2381 // Check to see if there is zero padding at the end of the base relocations
2383 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2385 // Check to see if the base relocations are at the end of the file
2387 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional32
->SizeOfImage
) {
2389 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2391 Optional32
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2392 Optional32
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2393 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2394 FileLength
= Optional32
->SizeOfImage
;
2395 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
));
2402 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2403 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2404 if (!KeepOptionalHeaderFlag
) {
2405 Optional64
->MajorOperatingSystemVersion
= 0;
2406 Optional64
->MinorOperatingSystemVersion
= 0;
2407 Optional64
->MajorImageVersion
= 0;
2408 Optional64
->MinorImageVersion
= 0;
2409 Optional64
->MajorSubsystemVersion
= 0;
2410 Optional64
->MinorSubsystemVersion
= 0;
2411 Optional64
->Win32VersionValue
= 0;
2412 Optional64
->CheckSum
= 0;
2413 Optional64
->SizeOfStackReserve
= 0;
2414 Optional64
->SizeOfStackCommit
= 0;
2415 Optional64
->SizeOfHeapReserve
= 0;
2416 Optional64
->SizeOfHeapCommit
= 0;
2418 TEImageHeader
.AddressOfEntryPoint
= Optional64
->AddressOfEntryPoint
;
2419 TEImageHeader
.BaseOfCode
= Optional64
->BaseOfCode
;
2420 TEImageHeader
.ImageBase
= (UINT64
) (Optional64
->ImageBase
);
2422 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2423 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2424 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2427 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2428 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2429 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2433 // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
2434 // For Itaninum and X64 Image, remove .pdata section.
2436 if ((!KeepExceptionTableFlag
&& PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_X64
) || PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
) {
2437 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2438 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2439 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2440 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2441 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2442 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2444 // Zero .pdata Section header name
2446 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2448 RuntimeFunction
= (RUNTIME_FUNCTION
*)(FileBuffer
+ SectionHeader
->PointerToRawData
);
2449 for (Index1
= 0; Index1
< Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
/ sizeof (RUNTIME_FUNCTION
); Index1
++, RuntimeFunction
++) {
2450 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2451 for (Index2
= 0; Index2
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index2
++, SectionHeader
++) {
2452 if (RuntimeFunction
->UnwindInfoAddress
>= SectionHeader
->VirtualAddress
&& RuntimeFunction
->UnwindInfoAddress
< (SectionHeader
->VirtualAddress
+ SectionHeader
->SizeOfRawData
)) {
2453 UnwindInfo
= (UNWIND_INFO
*)(FileBuffer
+ SectionHeader
->PointerToRawData
+ (RuntimeFunction
->UnwindInfoAddress
- SectionHeader
->VirtualAddress
));
2454 if (UnwindInfo
->Version
== 1) {
2455 memset (UnwindInfo
+ 1, 0, UnwindInfo
->CountOfUnwindCodes
* sizeof (UINT16
));
2456 memset (UnwindInfo
, 0, sizeof (UNWIND_INFO
));
2461 memset (RuntimeFunction
, 0, sizeof (RUNTIME_FUNCTION
));
2464 // Zero Execption Table
2466 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2467 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2468 DebugMsg (NULL
, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL
);
2476 // Strip zero padding at the end of the .reloc section
2478 if (!KeepZeroPendingFlag
&& Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2479 if (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2480 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2481 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2483 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2485 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2486 SectionHeader
->Misc
.VirtualSize
= Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2487 AllignedRelocSize
= (Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional64
->FileAlignment
- 1) & (~(Optional64
->FileAlignment
- 1));
2489 // Check to see if there is zero padding at the end of the base relocations
2491 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2493 // Check to see if the base relocations are at the end of the file
2495 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional64
->SizeOfImage
) {
2497 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2499 Optional64
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2500 Optional64
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2501 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2502 FileLength
= Optional64
->SizeOfImage
;
2503 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
));
2511 Error (NULL
, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr
->Pe32
.OptionalHeader
.Magic
, mInImageName
);
2515 if (((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) == 0) && \
2516 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
== 0) && \
2517 (TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
== 0)) {
2519 // PeImage can be loaded into memory, but it has no relocation section.
2520 // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
2522 if (Optional32
!= NULL
) {
2523 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
2524 } else if (Optional64
!= NULL
) {
2525 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional64
->SizeOfImage
- sizeof (EFI_IMAGE_BASE_RELOCATION
);
2530 // Fill HII section data
2532 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2533 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++) {
2534 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".hii") == 0) {
2536 // Update resource section header offset
2538 SetHiiResourceHeader ((UINT8
*) FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, SectionHeader
[Index
].VirtualAddress
);
2540 // Update resource section name
2542 strcpy((char *) SectionHeader
[Index
].Name
, ".rsrc");
2544 // Update resource data directory.
2546 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2547 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2548 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= SectionHeader
[Index
].VirtualAddress
;
2549 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= SectionHeader
[Index
].Misc
.VirtualSize
;
2550 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2551 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2552 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
= SectionHeader
[Index
].VirtualAddress
;
2553 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
= SectionHeader
[Index
].Misc
.VirtualSize
;
2560 // Zero ExceptionTable Xdata
2562 if (!KeepExceptionTableFlag
) {
2563 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2564 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++) {
2565 if (stricmp ((char *)SectionHeader
[Index
].Name
, ".xdata") == 0) {
2567 // zero .xdata section
2569 memset (FileBuffer
+ SectionHeader
[Index
].PointerToRawData
, 0, SectionHeader
[Index
].SizeOfRawData
);
2570 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
);
2577 // Zero Time/Data field
2579 ZeroDebugData (FileBuffer
, FALSE
);
2581 if (mOutImageType
== FW_TE_IMAGE
) {
2582 if ((PeHdr
->Pe32
.FileHeader
.NumberOfSections
&~0xFF) || (Type
&~0xFF)) {
2584 // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
2586 Error (NULL
, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName
);
2590 if ((PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
)) {
2592 // TeImage has the same section alignment and file alignment.
2594 Error (NULL
, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName
);
2598 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",
2599 TEImageHeader
.Machine
, TEImageHeader
.NumberOfSections
, TEImageHeader
.StrippedSize
, (unsigned) TEImageHeader
.AddressOfEntryPoint
, (unsigned) TEImageHeader
.BaseOfCode
, (unsigned long long) TEImageHeader
.ImageBase
);
2601 // Update Image to TeImage
2603 FileLength
= FileLength
- TEImageHeader
.StrippedSize
;
2604 memmove (FileBuffer
+ sizeof (EFI_TE_IMAGE_HEADER
), FileBuffer
+ TEImageHeader
.StrippedSize
, FileLength
);
2605 FileLength
= FileLength
+ sizeof (EFI_TE_IMAGE_HEADER
);
2606 memcpy (FileBuffer
, &TEImageHeader
, sizeof (EFI_TE_IMAGE_HEADER
));
2607 VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength
));
2611 // Following codes are to fix the objcopy's issue:
2612 // objcopy in binutil 2.50.18 will set PE image's charactices to "RELOC_STRIPPED" if image has no ".reloc" section
2613 // It cause issue for EFI image which has no ".reloc" sections.
2614 // Following codes will be removed when objcopy in binutil fix this problem for PE image.
2616 if ((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) != 0) {
2617 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2618 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2619 if (Optional32
->ImageBase
== 0) {
2620 PeHdr
->Pe32
.FileHeader
.Characteristics
&= ~EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2622 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2623 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2624 if (Optional64
->ImageBase
== 0) {
2625 PeHdr
->Pe32
.FileHeader
.Characteristics
&= ~EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2633 // Update Image to EfiImage or TE image
2636 if ((FileLength
!= InputFileLength
) || (memcmp (FileBuffer
, InputFileBuffer
, FileLength
) != 0)) {
2638 // Update File when File is changed.
2640 fpInOut
= fopen (LongFilePath (mInImageName
), "wb");
2641 if (fpInOut
== NULL
) {
2642 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
2645 fwrite (FileBuffer
, 1, FileLength
, fpInOut
);
2646 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2649 if ((OutputFileTime
< InputFileTime
) || (FileLength
!= OutputFileLength
) || (memcmp (FileBuffer
, OutputFileBuffer
, FileLength
) != 0)) {
2651 // Update File when File is changed or File is old.
2653 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
2654 if (fpOut
== NULL
) {
2655 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
2658 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
2659 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2662 mImageSize
= FileLength
;
2665 if (fpInOut
!= NULL
) {
2666 if (GetUtilityStatus () != STATUS_SUCCESS
) {
2668 // when file updates failed, original file is still recovered.
2670 fwrite (InputFileBuffer
, 1, InputFileLength
, fpInOut
);
2673 // Write converted data into fpInOut file and close input file.
2678 if (FileBuffer
!= NULL
) {
2682 if (InputFileName
!= NULL
) {
2683 free (InputFileName
);
2686 if (fpOut
!= NULL
) {
2688 // Write converted data into fpOut file and close output file.
2691 if (GetUtilityStatus () != STATUS_SUCCESS
) {
2692 if (OutputFileBuffer
== NULL
) {
2693 remove (OutImageName
);
2695 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
2696 fwrite (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
2702 if (InputFileBuffer
!= NULL
) {
2703 free (InputFileBuffer
);
2706 if (OutputFileBuffer
!= NULL
) {
2707 free (OutputFileBuffer
);
2711 // Write module size and time stamp to report file.
2713 if (OutImageName
!= NULL
) {
2714 FileLen
= strlen (OutImageName
);
2716 if (FileLen
>= 4 && strcmp (OutImageName
+ (FileLen
- 4), ".efi") == 0) {
2717 ReportFileName
= (CHAR8
*) malloc (FileLen
+ 1);
2718 if (ReportFileName
!= NULL
) {
2719 strcpy (ReportFileName
, OutImageName
);
2720 strcpy (ReportFileName
+ (FileLen
- 4), ".txt");
2721 ReportFile
= fopen (LongFilePath (ReportFileName
), "w+");
2722 if (ReportFile
!= NULL
) {
2723 fprintf (ReportFile
, "MODULE_SIZE = %u\n", (unsigned) mImageSize
);
2724 fprintf (ReportFile
, "TIME_STAMP = %u\n", (unsigned) mImageTimeStamp
);
2727 free (ReportFileName
);
2730 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
2732 return GetUtilityStatus ();
2738 IN OUT UINT8
*FileBuffer
,
2739 BOOLEAN ZeroDebugFlag
2743 Routine Description:
2745 Zero debug information in PeImage.
2749 FileBuffer - Pointer to PeImage.
2750 ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp
2754 EFI_ABORTED - PeImage is invalid.
2755 EFI_SUCCESS - Zero debug data successfully.
2760 UINT32 DebugDirectoryEntryRva
;
2761 UINT32 DebugDirectoryEntryFileOffset
;
2762 UINT32 ExportDirectoryEntryRva
;
2763 UINT32 ExportDirectoryEntryFileOffset
;
2764 UINT32 ResourceDirectoryEntryRva
;
2765 UINT32 ResourceDirectoryEntryFileOffset
;
2766 EFI_IMAGE_DOS_HEADER
*DosHdr
;
2767 EFI_IMAGE_FILE_HEADER
*FileHdr
;
2768 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
2769 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
2770 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
2771 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
2772 UINT32
*NewTimeStamp
;
2777 DebugDirectoryEntryRva
= 0;
2778 ExportDirectoryEntryRva
= 0;
2779 ResourceDirectoryEntryRva
= 0;
2780 DebugDirectoryEntryFileOffset
= 0;
2781 ExportDirectoryEntryFileOffset
= 0;
2782 ResourceDirectoryEntryFileOffset
= 0;
2783 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2784 FileHdr
= (EFI_IMAGE_FILE_HEADER
*) (FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2787 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2788 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2789 // NO DOS header, must start with PE/COFF header
2790 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
2792 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
2796 // Get Debug, Export and Resource EntryTable RVA address.
2797 // Resource Directory entry need to review.
2799 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2800 if (Optional32Hdr
->Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2801 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2802 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2803 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2804 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2806 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2807 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2808 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2810 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2811 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2812 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2813 if (ZeroDebugFlag
) {
2814 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
2815 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
2819 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
2820 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
2821 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
2822 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
2823 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
2825 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
2826 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
2827 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
2829 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
2830 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
2831 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2832 if (ZeroDebugFlag
) {
2833 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= 0;
2834 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= 0;
2840 // Get DirectoryEntryTable file offset.
2842 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2843 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2844 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2845 DebugDirectoryEntryFileOffset
=
2846 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2848 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2849 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2850 ExportDirectoryEntryFileOffset
=
2851 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2853 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
2854 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
2855 ResourceDirectoryEntryFileOffset
=
2856 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
2861 //Zero Debug Data and TimeStamp
2863 FileHdr
->TimeDateStamp
= 0;
2864 mImageTimeStamp
= 0;
2865 if (ExportDirectoryEntryFileOffset
!= 0) {
2866 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
2870 if (ResourceDirectoryEntryFileOffset
!= 0) {
2871 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
2875 if (DebugDirectoryEntryFileOffset
!= 0) {
2876 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
);
2877 DebugEntry
->TimeDateStamp
= 0;
2878 mImageTimeStamp
= 0;
2879 if (ZeroDebugFlag
) {
2880 memset (FileBuffer
+ DebugEntry
->FileOffset
, 0, DebugEntry
->SizeOfData
);
2881 memset (DebugEntry
, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
));
2891 IN OUT UINT8
*FileBuffer
,
2896 Routine Description:
2898 Set new time stamp into PeImage FileHdr and Directory table:
2899 Debug, Export and Resource.
2903 FileBuffer - Pointer to PeImage.
2904 TimeStamp - Time stamp string.
2908 EFI_INVALID_PARAMETER - TimeStamp format is not recognized.
2909 EFI_SUCCESS - Set new time stamp in this image successfully.
2917 UINT32 DebugDirectoryEntryRva
;
2918 UINT32 DebugDirectoryEntryFileOffset
;
2919 UINT32 ExportDirectoryEntryRva
;
2920 UINT32 ExportDirectoryEntryFileOffset
;
2921 UINT32 ResourceDirectoryEntryRva
;
2922 UINT32 ResourceDirectoryEntryFileOffset
;
2923 EFI_IMAGE_DOS_HEADER
*DosHdr
;
2924 EFI_IMAGE_FILE_HEADER
*FileHdr
;
2925 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32Hdr
;
2926 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64Hdr
;
2927 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
2928 UINT32
*NewTimeStamp
;
2933 DebugDirectoryEntryRva
= 0;
2934 DebugDirectoryEntryFileOffset
= 0;
2935 ExportDirectoryEntryRva
= 0;
2936 ExportDirectoryEntryFileOffset
= 0;
2937 ResourceDirectoryEntryRva
= 0;
2938 ResourceDirectoryEntryFileOffset
= 0;
2940 // Get time and date that will be set.
2942 if (TimeStamp
== NULL
) {
2943 Error (NULL
, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");
2944 return EFI_INVALID_PARAMETER
;
2947 // compare the value with "NOW", if yes, current system time is set.
2949 if (stricmp (TimeStamp
, "NOW") == 0) {
2951 // get system current time and date
2956 // Check Time Format strictly yyyy-mm-dd 00:00:00
2958 for (Index
= 0; TimeStamp
[Index
] != '\0' && Index
< 20; Index
++) {
2959 if (Index
== 4 || Index
== 7) {
2960 if (TimeStamp
[Index
] == '-') {
2963 } else if (Index
== 13 || Index
== 16) {
2964 if (TimeStamp
[Index
] == ':') {
2967 } else if (Index
== 10 && TimeStamp
[Index
] == ' ') {
2969 } else if ((TimeStamp
[Index
] < '0') || (TimeStamp
[Index
] > '9')) {
2974 if (Index
< 19 || TimeStamp
[19] != '\0') {
2975 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
2976 return EFI_INVALID_PARAMETER
;
2980 // get the date and time from TimeStamp
2982 if (sscanf (TimeStamp
, "%d-%d-%d %d:%d:%d",
2990 Error (NULL
, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp
);
2991 return EFI_INVALID_PARAMETER
;
2995 // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
2997 if (stime
.tm_mon
<= 0 || stime
.tm_mday
<=0) {
2998 Error (NULL
, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp
);
2999 return EFI_INVALID_PARAMETER
;
3004 // in struct, Year (current year minus 1900)
3005 // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
3008 // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
3010 if (stime
.tm_year
>= 1970 && stime
.tm_year
<= 2038) {
3012 // convert 1970 -> 70, 2000 -> 100, ...
3014 stime
.tm_year
-= 1900;
3016 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
3017 return EFI_INVALID_PARAMETER
;
3021 // convert the date and time to time_t format
3023 newtime
= mktime (&stime
);
3024 if (newtime
== (time_t) - 1) {
3025 Error (NULL
, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp
);
3026 return EFI_INVALID_PARAMETER
;
3030 ptime
= localtime (&newtime
);
3031 DebugMsg (NULL
, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",
3032 ptime
->tm_year
+ 1900, ptime
->tm_mon
+ 1, ptime
->tm_mday
, ptime
->tm_hour
, ptime
->tm_min
, ptime
->tm_sec
);
3034 // Set new time and data into PeImage.
3036 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
3037 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
3038 // NO DOS header, must start with PE/COFF header
3039 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ sizeof (UINT32
));
3041 FileHdr
= (EFI_IMAGE_FILE_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof (UINT32
));
3045 // Get Debug, Export and Resource EntryTable RVA address.
3046 // Resource Directory entry need to review.
3048 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
3049 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3050 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional32Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3051 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3052 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3053 ExportDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3055 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3056 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3057 ResourceDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3059 if (Optional32Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3060 Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3061 DebugDirectoryEntryRva
= Optional32Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3064 Optional64Hdr
= (EFI_IMAGE_OPTIONAL_HEADER64
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
3065 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) Optional64Hdr
+ FileHdr
->SizeOfOptionalHeader
);
3066 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
&& \
3067 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
!= 0) {
3068 ExportDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
3070 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
&& \
3071 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
!= 0) {
3072 ResourceDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
;
3074 if (Optional64Hdr
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
&& \
3075 Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
!= 0) {
3076 DebugDirectoryEntryRva
= Optional64Hdr
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
3081 // Get DirectoryEntryTable file offset.
3083 for (Index
= 0; Index
< FileHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
3084 if (DebugDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3085 DebugDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3086 DebugDirectoryEntryFileOffset
=
3087 DebugDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3089 if (ExportDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3090 ExportDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3091 ExportDirectoryEntryFileOffset
=
3092 ExportDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3094 if (ResourceDirectoryEntryRva
>= SectionHeader
->VirtualAddress
&&
3095 ResourceDirectoryEntryRva
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
) {
3096 ResourceDirectoryEntryFileOffset
=
3097 ResourceDirectoryEntryRva
- SectionHeader
->VirtualAddress
+ SectionHeader
->PointerToRawData
;
3104 FileHdr
->TimeDateStamp
= (UINT32
) newtime
;
3105 mImageTimeStamp
= (UINT32
) newtime
;
3106 if (ExportDirectoryEntryRva
!= 0) {
3107 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ExportDirectoryEntryFileOffset
+ sizeof (UINT32
));
3108 *NewTimeStamp
= (UINT32
) newtime
;
3111 if (ResourceDirectoryEntryRva
!= 0) {
3112 NewTimeStamp
= (UINT32
*) (FileBuffer
+ ResourceDirectoryEntryFileOffset
+ sizeof (UINT32
));
3113 *NewTimeStamp
= (UINT32
) newtime
;
3116 if (DebugDirectoryEntryRva
!= 0) {
3117 NewTimeStamp
= (UINT32
*) (FileBuffer
+ DebugDirectoryEntryFileOffset
+ sizeof (UINT32
));
3118 *NewTimeStamp
= (UINT32
) newtime
;
3132 Routine Description:
3133 Read a 32-bit microcode data value from a text file and convert to raw binary form.
3136 InFptr - file pointer to input text file
3137 Data - pointer to where to return the data parsed
3140 STATUS_SUCCESS - no errors or warnings, Data contains valid information
3141 STATUS_ERROR - errors were encountered
3145 CHAR8 Line
[MAX_LINE_LEN
];
3147 unsigned ScannedData
= 0;
3149 Line
[MAX_LINE_LEN
- 1] = 0;
3151 if (fgets (Line
, MAX_LINE_LEN
, InFptr
) == NULL
) {
3152 return STATUS_ERROR
;
3155 // If it was a binary file, then it may have overwritten our null terminator
3157 if (Line
[MAX_LINE_LEN
- 1] != 0) {
3158 return STATUS_ERROR
;
3164 for (cptr
= Line
; *cptr
&& isspace((int)*cptr
); cptr
++) {
3167 // Skip Blank Lines and Comment Lines
3168 if ((strlen(cptr
) != 0) && (*cptr
!= ';')) {
3174 // dd 000000001h ; comment
3179 if ((tolower((int)cptr
[0]) == 'd') && (tolower((int)cptr
[1]) == 'd') && isspace ((int)cptr
[2])) {
3181 // Skip blanks and look for a hex digit
3184 for (; *cptr
&& isspace((int)*cptr
); cptr
++) {
3186 if (isxdigit ((int)*cptr
)) {
3187 if (sscanf (cptr
, "%X", &ScannedData
) != 1) {
3188 return STATUS_ERROR
;
3191 *Data
= (UINT32
) ScannedData
;
3192 return STATUS_SUCCESS
;
3195 return STATUS_ERROR
;