3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Converts a pe32+ image to an FW, Te image type, or other specific image.
22 #include "WinNtInclude.h"
27 #include <sys/types.h>
36 #include <Common/UefiBaseTypes.h>
37 #include <IndustryStandard/PeImage.h>
38 #include <Common/UefiInternalFormRepresentation.h>
41 // Acpi Table definition
43 #include <IndustryStandard/Acpi.h>
44 #include <IndustryStandard/Acpi1_0.h>
45 #include <IndustryStandard/Acpi2_0.h>
46 #include <IndustryStandard/Acpi3_0.h>
47 #include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
49 #include "CommonLib.h"
50 #include "PeCoffLib.h"
52 #include "EfiUtilityMsgs.h"
57 // Version of this utility
59 #define UTILITY_NAME "GenFw"
60 #define UTILITY_MAJOR_VERSION 0
61 #define UTILITY_MINOR_VERSION 2
63 #define HII_RESOURCE_SECTION_INDEX 1
64 #define HII_RESOURCE_SECTION_NAME "HII"
66 #define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
67 #define DEFAULT_MC_ALIGNMENT 16
69 #define STATUS_IGNORE 0xA
71 // Structure definition for a microcode header
81 UINT32 DataSize
; // if 0, then TotalSize = 2048, and TotalSize field is invalid
82 UINT32 TotalSize
; // number of bytes
84 } MICROCODE_IMAGE_HEADER
;
86 static EFI_GUID mZeroGuid
= {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
88 static const char *gHiiPackageRCFileHeader
[] = {
90 "// DO NOT EDIT -- auto-generated file",
96 // Module image information
99 UINT32 mImageTimeStamp
= 0;
100 UINT32 mImageSize
= 0;
101 UINT32 mOutImageType
= FW_DUMMY_IMAGE
;
107 IN OUT UINT8
*FileBuffer
,
114 IN OUT UINT8
*FileBuffer
,
134 Print out version information for this utility.
146 fprintf (stdout
, "%s Version %d.%d %s \n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
173 fprintf (stdout
, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME
);
176 // Copyright declaration
178 fprintf (stdout
, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");
183 fprintf (stdout
, "Options:\n");
184 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
185 File will be created to store the ouput content.\n");
186 fprintf (stdout
, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\
187 Create Efi Image. EFI_FILETYPE is one of BASE,SMM_CORE,\n\
188 PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\
189 SEC, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER,\n\
190 DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER,\n\
191 PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\
192 APPLICATION, SAL_RT_DRIVER to support all module types\n\
193 It can only be used together with --keepexceptiontable,\n\
194 --keepzeropending, -r, -o option.It is a action option.\n\
195 If it is combined with other action options, the later\n\
196 input action option will override the previous one.\n");
197 fprintf (stdout
, " -c, --acpi Create Acpi table.\n\
198 It can't be combined with other action options\n\
199 except for -o, -r option. It is a action option.\n\
200 If it is combined with other action options, the later\n\
201 input action option will override the previous one.\n");
202 fprintf (stdout
, " -t, --terse Create Te Image.\n\
203 It can only be used together with --keepexceptiontable,\n\
204 --keepzeropending, -r, -o option.It is a action option.\n\
205 If it is combined with other action options, the later\n\
206 input action option will override the previous one.\n");
207 fprintf (stdout
, " -u, --dump Dump TeImage Header.\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
, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\
213 It also zeros the time stamp fields.\n\
214 This option can be used to compare the binary efi image.\n\
215 It can't be combined with other action options\n\
216 except for -o, -r option. It is a action option.\n\
217 If it is combined with other action options, the later\n\
218 input action option will override the previous one.\n");
219 fprintf (stdout
, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\
220 It can't be combined with other action options\n\
221 except for -o, -r option. It is a action option.\n\
222 If it is combined with other action options, the later\n\
223 input action option will override the previous one.\n");;
224 fprintf (stdout
, " -l, --stripped Strip off the relocation info from PE or TE image.\n\
225 It can't be combined with other action options\n\
226 except for -o, -r option. It is a action option.\n\
227 If it is combined with other action options, the later\n\
228 input action option will override the previous one.\n");
229 fprintf (stdout
, " -s timedate, --stamp timedate\n\
230 timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\
231 is set to NOW, current system time is used. The support\n\
232 date scope is 1970-01-01 00+timezone:00:00\n\
233 ~ 2038-01-19 03+timezone:14:07\n\
234 The scope is adjusted according to the different zones.\n\
235 It can't be combined with other action options\n\
236 except for -o, -r option. It is a action option.\n\
237 If it is combined with other action options, the later\n\
238 input action option will override the previous one.\n");
239 fprintf (stdout
, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\
240 It can't be combined with other action options\n\
241 except for -o option. It is a action option.\n\
242 If it is combined with other action options, the later\n\
243 input action option will override the previous one.\n");
244 fprintf (stdout
, " -j, --join Combine multi microcode bin files to one file.\n\
245 It can be specified with -a, -p, -o option.\n\
246 No other options can be combined with it.\n\
247 If it is combined with other action options, the later\n\
248 input action option will override the previous one.\n");
249 fprintf (stdout
, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\
250 This option is only used together with -j option.\n");
251 fprintf (stdout
, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\
252 This option is only used together with -j option.\n");
253 fprintf (stdout
, " --keepexceptiontable Don't clear exception table.\n\
254 This option can be used together with -e or -t.\n\
255 It doesn't work for other options.\n");
256 fprintf (stdout
, " --keepzeropending Don't strip zero pending of .reloc.\n\
257 This option can be used together with -e or -t.\n\
258 It doesn't work for other options.\n");
259 fprintf (stdout
, " -r, --replace Overwrite the input file with the output content.\n\
260 If more input files are specified,\n\
261 the last input file will be as the output file.\n");
262 fprintf (stdout
, " -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\
263 Guid is used to specify hii package list guid.\n\
264 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\
265 If not specified, the first Form FormSet guid is used.\n");
266 fprintf (stdout
, " --hiipackage Combine all input binary hii pacakges into \n\
267 a single package list as the text resource data(RC).\n\
268 It can't be combined with other action options\n\
269 except for -o option. It is a action option.\n\
270 If it is combined with other action options, the later\n\
271 input action option will override the previous one.\n");
272 fprintf (stdout
, " --hiibinpackage Combine all input binary hii pacakges into \n\
273 a single package list as the binary resource section.\n\
274 It can't be combined with other action options\n\
275 except for -o option. It is a action option.\n\
276 If it is combined with other action options, the later\n\
277 input action option will override the previous one.\n");
278 fprintf (stdout
, " --rebase NewAddress Rebase image to new base address. New address \n\
279 is also set to the first none code section header.\n\
280 It can't be combined with other action options\n\
281 except for -o or -r option. It is a action option.\n\
282 If it is combined with other action options, the later\n\
283 input action option will override the previous one.\n");
284 fprintf (stdout
, " --address NewAddress Set new address into the first none code \n\
285 section header of the input image.\n\
286 It can't be combined with other action options\n\
287 except for -o or -r option. It is a action option.\n\
288 If it is combined with other action options, the later\n\
289 input action option will override the previous one.\n");
290 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
291 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
292 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
293 fprintf (stdout
, " --version Show program's version number and exit\n");
294 fprintf (stdout
, " -h, --help Show this help message and exit\n");
311 AcpiTable Buffer for AcpiSection
312 Length AcpiSection Length
321 EFI_ACPI_DESCRIPTION_HEADER
*AcpiHeader
;
322 EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*Facs
;
323 UINT32 ExpectedLength
;
325 AcpiHeader
= (EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTable
;
328 // Generic check for AcpiTable length.
330 if (AcpiHeader
->Length
> Length
) {
331 Error (NULL
, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL
);
336 // Currently, we only check must-have tables: FADT, FACS, DSDT,
337 // and some important tables: MADT, MCFG.
339 switch (AcpiHeader
->Signature
) {
342 // "FACP" Fixed ACPI Description Table
344 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
:
345 switch (AcpiHeader
->Revision
) {
346 case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
347 ExpectedLength
= sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE
);
349 case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
350 ExpectedLength
= sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE
);
352 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
:
353 ExpectedLength
= sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE
);
356 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION
) {
357 ExpectedLength
= AcpiHeader
->Length
;
360 Error (NULL
, 0, 3000, "Invalid", "FACP revision check failed.");
363 if (ExpectedLength
!= AcpiHeader
->Length
) {
364 Error (NULL
, 0, 3000, "Invalid", "FACP length check failed.");
370 // "FACS" Firmware ACPI Control Structure
372 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE
:
373 Facs
= (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
*)AcpiTable
;
374 if (Facs
->Version
> EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) {
377 if ((Facs
->Version
!= EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
378 (Facs
->Version
!= EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
) &&
379 (Facs
->Version
!= EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION
)){
380 Error (NULL
, 0, 3000, "Invalid", "FACS version check failed.");
383 if ((Facs
->Length
!= sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
384 (Facs
->Length
!= sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
)) &&
385 (Facs
->Length
!= sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE
))) {
386 Error (NULL
, 0, 3000, "Invalid", "FACS length check failed.");
392 // "DSDT" Differentiated System Description Table
394 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
:
395 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION
) {
398 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
)) {
399 Error (NULL
, 0, 3000, "Invalid", "DSDT length check failed.");
405 // "APIC" Multiple APIC Description Table
407 case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE
:
408 if (AcpiHeader
->Revision
> EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) {
411 if ((AcpiHeader
->Revision
!= EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
412 (AcpiHeader
->Revision
!= EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
) &&
413 (AcpiHeader
->Revision
!= EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION
)) {
414 Error (NULL
, 0, 3000, "Invalid", "APIC revision check failed.");
417 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT32
) + sizeof(UINT32
)) {
418 Error (NULL
, 0, 3000, "Invalid", "APIC length check failed.");
424 // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
426 case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE
:
427 if (AcpiHeader
->Revision
> EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
430 if (AcpiHeader
->Revision
!= EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
) {
431 Error (NULL
, 0, 3000, "Invalid", "MCFG revision check failed.");
434 if (AcpiHeader
->Length
<= sizeof(EFI_ACPI_DESCRIPTION_HEADER
) + sizeof(UINT64
)) {
435 Error (NULL
, 0, 3000, "Invalid", "MCFG length check failed.");
441 // Other table pass check
447 return STATUS_SUCCESS
;
451 SetHiiResourceHeader (
457 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
458 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*ResourceDirectoryEntry
;
459 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
460 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
463 // Fill Resource section entry
465 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
);
466 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
467 for (Index
= 0; Index
< ResourceDirectory
->NumberOfNamedEntries
; Index
++) {
468 if (ResourceDirectoryEntry
->u1
.s
.NameIsString
) {
469 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiBinData
+ ResourceDirectoryEntry
->u1
.s
.NameOffset
);
471 if (ResourceDirectoryString
->Length
== 3 &&
472 ResourceDirectoryString
->String
[0] == L
'H' &&
473 ResourceDirectoryString
->String
[1] == L
'I' &&
474 ResourceDirectoryString
->String
[2] == L
'I') {
476 // Resource Type "HII" found
478 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
480 // Move to next level - resource Name
482 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
483 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
485 if (ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
487 // Move to next level - resource Language
489 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
);
490 ResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (ResourceDirectory
+ 1);
495 // Now it ought to be resource Data and update its OffsetToData value
497 if (!ResourceDirectoryEntry
->u2
.s
.DataIsDirectory
) {
498 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (HiiBinData
+ ResourceDirectoryEntry
->u2
.OffsetToData
);
499 ResourceDataEntry
->OffsetToData
= ResourceDataEntry
->OffsetToData
+ OffsetToFile
;
504 ResourceDirectoryEntry
++;
510 EFI_IMAGE_OPTIONAL_HEADER_UNION
*
515 EFI_IMAGE_DOS_HEADER
*DosHdr
;
516 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
519 // Read the dos & pe hdrs of the image
521 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Data
;
522 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
523 // NO DOS header, check for PE/COFF header
524 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(Data
);
525 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
530 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(((UINT8
*)Data
) + DosHdr
->e_lfanew
);
531 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
540 PeCoffConvertImageToXip (
545 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
546 EFI_IMAGE_OPTIONAL_HEADER_UNION
*NewPeHdr
;
547 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
548 UINTN TotalNecessaryFileSize
;
553 UINTN FirstSectionOffset
;
554 BOOLEAN ConversionNeeded
;
556 PeHdr
= GetPeCoffHeader ((void *) *FileBuffer
);
561 if (PeHdr
->Pe32
.OptionalHeader
.SectionAlignment
!= PeHdr
->Pe32
.OptionalHeader
.FileAlignment
) {
563 // The only reason to expand zero fill sections is to make them compatible with XIP images.
564 // If SectionAlignment is not equal to FileAlginment then it is not an XIP type image.
570 // Calculate size of XIP file, and determine if the conversion is needed.
572 ConversionNeeded
= FALSE
;
574 FirstSectionOffset
= *FileLength
;
575 TotalNecessaryFileSize
= 0;
576 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
577 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
578 SectionSize
= MAX (SectionHeader
->Misc
.VirtualSize
, SectionHeader
->SizeOfRawData
);
579 TotalNecessaryFileSize
+= SectionSize
;
580 if (SectionSize
> 0) {
581 FirstSectionOffset
= MIN (FirstSectionOffset
, SectionHeader
->VirtualAddress
);
582 XipLength
= MAX (XipLength
, SectionHeader
->VirtualAddress
+ SectionSize
);
583 if (SectionHeader
->VirtualAddress
!= SectionHeader
->PointerToRawData
) {
584 ConversionNeeded
= TRUE
;
587 if (SectionHeader
->Misc
.VirtualSize
> SectionHeader
->SizeOfRawData
) {
588 ConversionNeeded
= TRUE
;
592 if (FirstSectionOffset
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
594 // If one of the sections should be loaded to an offset overlapping with
595 // the executable header, then it cannot be made into an XIP image.
597 VerboseMsg ("PE/COFF conversion to XIP is impossible due to overlap");
598 VerboseMsg ("of section data with the executable header.");
602 if (FirstSectionOffset
== *FileLength
) {
604 // If we never found a section with a non-zero size, then we
605 // skip the conversion.
610 TotalNecessaryFileSize
+= FirstSectionOffset
;
612 if (!ConversionNeeded
) {
616 if (XipLength
> (2 * TotalNecessaryFileSize
)) {
617 VerboseMsg ("PE/COFF conversion to XIP appears to be larger than necessary.");
618 VerboseMsg ("The image linking process may have left unused memory ranges.");
621 if (PeHdr
->Pe32
.FileHeader
.PointerToSymbolTable
!= 0) {
623 // This field is obsolete and should be zero
625 PeHdr
->Pe32
.FileHeader
.PointerToSymbolTable
= 0;
629 // Allocate the extra space that we need to grow the image
631 XipFile
= malloc (XipLength
);
632 memset (XipFile
, 0, XipLength
);
635 // Copy the file headers
637 memcpy (XipFile
, *FileBuffer
, PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
);
639 NewPeHdr
= GetPeCoffHeader ((void *)XipFile
);
640 if (NewPeHdr
== NULL
) {
646 // Copy the section data over to the appropriate XIP offsets
648 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(NewPeHdr
->Pe32
.OptionalHeader
) + NewPeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
649 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
650 if (SectionHeader
->SizeOfRawData
> 0) {
652 XipFile
+ SectionHeader
->VirtualAddress
,
653 *FileBuffer
+ SectionHeader
->PointerToRawData
,
654 SectionHeader
->SizeOfRawData
658 // Make the size of raw data in section header alignment.
660 SectionHeader
->SizeOfRawData
= (SectionHeader
->Misc
.VirtualSize
+ PeHdr
->Pe32
.OptionalHeader
.FileAlignment
- 1) & (~(PeHdr
->Pe32
.OptionalHeader
.FileAlignment
- 1));
661 SectionHeader
->PointerToRawData
= SectionHeader
->VirtualAddress
;
665 *FileLength
= XipLength
;
666 *FileBuffer
= XipFile
;
670 CreateHiiResouceSectionHeader (
671 UINT32
*pSectionHeaderSize
,
678 Create COFF resource section header
682 pSectionHeaderSize - Pointer to section header size.
683 HiiDataSize - Size of the total HII data in section.
686 The created section header buffer.
690 UINT32 HiiSectionHeaderSize
;
691 UINT32 HiiSectionOffset
;
692 UINT8
*HiiSectionHeader
;
693 EFI_IMAGE_RESOURCE_DIRECTORY
*ResourceDirectory
;
694 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*TypeResourceDirectoryEntry
;
695 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*NameResourceDirectoryEntry
;
696 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*LanguageResourceDirectoryEntry
;
697 EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*ResourceDirectoryString
;
698 EFI_IMAGE_RESOURCE_DATA_ENTRY
*ResourceDataEntry
;
701 // Calculate the total size for the resource header (include Type, Name and Language)
702 // then allocate memory for the resource header.
704 HiiSectionHeaderSize
= 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
))
705 + 3 * (sizeof (UINT16
) + 3 * sizeof (CHAR16
))
706 + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
707 HiiSectionHeader
= malloc (HiiSectionHeaderSize
);
708 memset (HiiSectionHeader
, 0, HiiSectionHeaderSize
);
710 HiiSectionOffset
= 0;
714 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
715 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
716 ResourceDirectory
->NumberOfNamedEntries
= 1;
717 TypeResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
718 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
719 TypeResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
720 TypeResourceDirectoryEntry
->u2
.s
.DataIsDirectory
= 1;
721 TypeResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
= HiiSectionOffset
;
725 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
726 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
727 ResourceDirectory
->NumberOfNamedEntries
= 1;
728 NameResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
729 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
730 NameResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
731 NameResourceDirectoryEntry
->u2
.s
.DataIsDirectory
= 1;
732 NameResourceDirectoryEntry
->u2
.s
.OffsetToDirectory
= HiiSectionOffset
;
734 // Create Language entry
736 ResourceDirectory
= (EFI_IMAGE_RESOURCE_DIRECTORY
*) (HiiSectionHeader
+ HiiSectionOffset
);
737 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY
);
738 ResourceDirectory
->NumberOfNamedEntries
= 1;
739 LanguageResourceDirectoryEntry
= (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
740 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY
);
741 LanguageResourceDirectoryEntry
->u1
.s
.NameIsString
= 1;
743 // Create string entry for Type
745 TypeResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
746 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
747 ResourceDirectoryString
->Length
= 3;
748 ResourceDirectoryString
->String
[0] = L
'H';
749 ResourceDirectoryString
->String
[1] = L
'I';
750 ResourceDirectoryString
->String
[2] = L
'I';
751 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
753 // Create string entry for Name
755 NameResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
756 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
757 ResourceDirectoryString
->Length
= 3;
758 ResourceDirectoryString
->String
[0] = L
'E';
759 ResourceDirectoryString
->String
[1] = L
'F';
760 ResourceDirectoryString
->String
[2] = L
'I';
761 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
763 // Create string entry for Language
765 LanguageResourceDirectoryEntry
->u1
.s
.NameOffset
= HiiSectionOffset
;
766 ResourceDirectoryString
= (EFI_IMAGE_RESOURCE_DIRECTORY_STRING
*) (HiiSectionHeader
+ HiiSectionOffset
);
767 ResourceDirectoryString
->Length
= 3;
768 ResourceDirectoryString
->String
[0] = L
'B';
769 ResourceDirectoryString
->String
[1] = L
'I';
770 ResourceDirectoryString
->String
[2] = L
'N';
771 HiiSectionOffset
= HiiSectionOffset
+ sizeof (ResourceDirectoryString
->Length
) + ResourceDirectoryString
->Length
* sizeof (ResourceDirectoryString
->String
[0]);
775 LanguageResourceDirectoryEntry
->u2
.OffsetToData
= HiiSectionOffset
;
776 ResourceDataEntry
= (EFI_IMAGE_RESOURCE_DATA_ENTRY
*) (HiiSectionHeader
+ HiiSectionOffset
);
777 HiiSectionOffset
+= sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY
);
778 ResourceDataEntry
->OffsetToData
= HiiSectionOffset
;
779 ResourceDataEntry
->Size
= HiiDataSize
;
781 *pSectionHeaderSize
= HiiSectionHeaderSize
;
782 return HiiSectionHeader
;
789 IN OUT UINT32
*ReadSize
,
796 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
800 FileHandle - The handle to the PE/COFF file
802 FileOffset - The offset, in bytes, into the file to read
804 ReadSize - The number of bytes to read from the file starting at FileOffset
806 Buffer - A pointer to the buffer to read the data into.
810 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
818 Destination8
= Buffer
;
819 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
822 *(Destination8
++) = *(Source8
++);
829 SetAddressToSectionHeader (
831 IN OUT UINT8
*FileBuffer
,
832 IN UINT64 NewPe32BaseAddress
838 Set new base address into the section header of PeImage
842 FileName - Name of file
843 FileBuffer - Pointer to PeImage.
844 NewPe32BaseAddress - New Base Address for PE image.
848 EFI_SUCCESS Set new base address into this image successfully.
853 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
855 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
856 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
859 // Initialize context
861 memset (&ImageContext
, 0, sizeof (ImageContext
));
862 ImageContext
.Handle
= (VOID
*) FileBuffer
;
863 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
864 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
865 if (EFI_ERROR (Status
)) {
866 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
870 if (ImageContext
.RelocationsStripped
) {
871 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
876 // Get PeHeader pointer
878 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
881 // Get section header list
883 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
886 sizeof (EFI_IMAGE_FILE_HEADER
) +
887 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
891 // Set base address into the first section header that doesn't point to code section.
893 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
894 if ((SectionHeader
->Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
895 *(UINT64
*) &SectionHeader
->PointerToRelocations
= NewPe32BaseAddress
;
901 // No available section header is found.
903 if (Index
== ImgHdr
->Pe32
.FileHeader
.NumberOfSections
) {
904 return EFI_NOT_FOUND
;
908 // BaseAddress is set to section header.
916 IN OUT UINT8
*FileBuffer
,
917 IN UINT64 NewPe32BaseAddress
923 Set new base address into PeImage, and fix up PeImage based on new address.
927 FileName - Name of file
928 FileBuffer - Pointer to PeImage.
929 NewPe32BaseAddress - New Base Address for PE image.
933 EFI_INVALID_PARAMETER - BaseAddress is not valid.
934 EFI_SUCCESS - Update PeImage is correctly.
939 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
941 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
942 UINT8
*MemoryImagePointer
;
943 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
946 // Initialize context
948 memset (&ImageContext
, 0, sizeof (ImageContext
));
949 ImageContext
.Handle
= (VOID
*) FileBuffer
;
950 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
951 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
952 if (EFI_ERROR (Status
)) {
953 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
957 if (ImageContext
.RelocationsStripped
) {
958 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
963 // Get PeHeader pointer
965 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
968 // Load and Relocate Image Data
970 MemoryImagePointer
= (UINT8
*) malloc ((UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
971 if (MemoryImagePointer
== NULL
) {
972 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
973 return EFI_OUT_OF_RESOURCES
;
975 memset ((VOID
*) MemoryImagePointer
, 0, (UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
976 ImageContext
.ImageAddress
= ((UINTN
) MemoryImagePointer
+ ImageContext
.SectionAlignment
- 1) & (~((INT64
)ImageContext
.SectionAlignment
- 1));
978 Status
= PeCoffLoaderLoadImage (&ImageContext
);
979 if (EFI_ERROR (Status
)) {
980 Error (NULL
, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName
);
981 free ((VOID
*) MemoryImagePointer
);
985 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
986 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
987 if (EFI_ERROR (Status
)) {
988 Error (NULL
, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName
);
989 free ((VOID
*) MemoryImagePointer
);
994 // Copy Relocated data to raw image file.
996 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
999 sizeof (EFI_IMAGE_FILE_HEADER
) +
1000 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1003 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1005 FileBuffer
+ SectionHeader
->PointerToRawData
,
1006 (VOID
*) (UINTN
) (ImageContext
.ImageAddress
+ SectionHeader
->VirtualAddress
),
1007 SectionHeader
->SizeOfRawData
1011 free ((VOID
*) MemoryImagePointer
);
1014 // Update Image Base Address
1016 if ((ImgHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) && (ImgHdr
->Pe32
.FileHeader
.Machine
!= IMAGE_FILE_MACHINE_IA64
)) {
1017 ImgHdr
->Pe32
.OptionalHeader
.ImageBase
= (UINT32
) NewPe32BaseAddress
;
1018 } else if (ImgHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1019 ImgHdr
->Pe32Plus
.OptionalHeader
.ImageBase
= NewPe32BaseAddress
;
1021 Error (NULL
, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
1022 ImgHdr
->Pe32
.OptionalHeader
.Magic
,
1029 // Set new base address into section header
1031 Status
= SetAddressToSectionHeader (FileName
, FileBuffer
, NewPe32BaseAddress
);
1043 Routine Description:
1049 argc - Number of command line parameters.
1050 argv - Array of pointers to command line parameter strings.
1053 STATUS_SUCCESS - Utility exits successfully.
1054 STATUS_ERROR - Some error occurred during execution.
1059 UINT32 InputFileNum
;
1060 CHAR8
**InputFileName
;
1068 UINT32
*DataPointer
;
1069 UINT32
*OldDataPointer
;
1075 UINT32 MciAlignment
;
1077 UINT32 AllignedRelocSize
;
1080 UINT8
*OutputFileBuffer
;
1081 UINT32 OutputFileLength
;
1082 UINT8
*InputFileBuffer
;
1083 UINT32 InputFileLength
;
1084 RUNTIME_FUNCTION
*RuntimeFunction
;
1085 UNWIND_INFO
*UnwindInfo
;
1087 BOOLEAN ReplaceFlag
;
1088 BOOLEAN KeepExceptionTableFlag
;
1089 BOOLEAN KeepZeroPendingFlag
;
1091 EFI_TE_IMAGE_HEADER TEImageHeader
;
1092 EFI_TE_IMAGE_HEADER
*TeHdr
;
1093 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1094 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1095 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
1096 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32
;
1097 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64
;
1098 EFI_IMAGE_DOS_HEADER BackupDosHdr
;
1099 MICROCODE_IMAGE_HEADER
*MciHeader
;
1100 UINT8
*HiiPackageListBuffer
;
1101 UINT8
*HiiPackageDataPointer
;
1102 EFI_GUID HiiPackageListGuid
;
1103 EFI_HII_PACKAGE_LIST_HEADER HiiPackageListHeader
;
1104 EFI_HII_PACKAGE_HEADER HiiPackageHeader
;
1105 EFI_IFR_FORM_SET IfrFormSet
;
1106 UINT8 NumberOfFormPacakge
;
1107 EFI_HII_PACKAGE_HEADER EndPackage
;
1108 UINT32 HiiSectionHeaderSize
;
1109 UINT8
*HiiSectionHeader
;
1110 UINT64 NewBaseAddress
;
1111 BOOLEAN NegativeAddr
;
1113 CHAR8
*ReportFileName
;
1115 time_t InputFileTime
;
1116 time_t OutputFileTime
;
1117 struct stat Stat_Buf
;
1119 SetUtilityName (UTILITY_NAME
);
1122 // Assign to fix compile warning
1126 InputFileName
= NULL
;
1127 mInImageName
= NULL
;
1128 OutImageName
= NULL
;
1131 Status
= STATUS_SUCCESS
;
1137 MciAlignment
= DEFAULT_MC_ALIGNMENT
;
1138 MciPadValue
= DEFAULT_MC_PAD_BYTE_VALUE
;
1142 ReplaceFlag
= FALSE
;
1144 OutputFileBuffer
= NULL
;
1145 OutputFileLength
= 0;
1146 InputFileBuffer
= NULL
;
1147 InputFileLength
= 0;
1150 KeepExceptionTableFlag
= FALSE
;
1151 KeepZeroPendingFlag
= FALSE
;
1152 NumberOfFormPacakge
= 0;
1153 HiiPackageListBuffer
= NULL
;
1154 HiiPackageDataPointer
= NULL
;
1155 EndPackage
.Length
= sizeof (EFI_HII_PACKAGE_HEADER
);
1156 EndPackage
.Type
= EFI_HII_PACKAGE_END
;
1157 memset (&HiiPackageListGuid
, 0, sizeof (HiiPackageListGuid
));
1158 HiiSectionHeaderSize
= 0;
1159 HiiSectionHeader
= NULL
;
1161 NegativeAddr
= FALSE
;
1166 Error (NULL
, 0, 1001, "Missing options", "No input options.");
1168 return STATUS_ERROR
;
1174 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
1177 return STATUS_SUCCESS
;
1180 if (stricmp (argv
[0], "--version") == 0) {
1182 return STATUS_SUCCESS
;
1186 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
1187 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1188 Error (NULL
, 0, 1003, "Invalid option value", "Output file name is missing for -o option");
1191 OutImageName
= argv
[1];
1197 if ((stricmp (argv
[0], "-e") == 0) || (stricmp (argv
[0], "--efiImage") == 0)) {
1198 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1199 Error (NULL
, 0, 1003, "Invalid option value", "Module Type is missing for -o option");
1202 ModuleType
= argv
[1];
1203 if (mOutImageType
!= FW_TE_IMAGE
) {
1204 mOutImageType
= FW_EFI_IMAGE
;
1211 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--stripped") == 0)) {
1212 mOutImageType
= FW_RELOC_STRIPEED_IMAGE
;
1218 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--acpi") == 0)) {
1219 mOutImageType
= FW_ACPI_IMAGE
;
1225 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--terse") == 0)) {
1226 mOutImageType
= FW_TE_IMAGE
;
1232 if ((stricmp (argv
[0], "-u") == 0) || (stricmp (argv
[0], "--dump") == 0)) {
1233 mOutImageType
= DUMP_TE_HEADER
;
1239 if ((stricmp (argv
[0], "-b") == 0) || (stricmp (argv
[0], "--exe2bin") == 0)) {
1240 mOutImageType
= FW_BIN_IMAGE
;
1246 if ((stricmp (argv
[0], "-z") == 0) || (stricmp (argv
[0], "--zero") == 0)) {
1247 mOutImageType
= FW_ZERO_DEBUG_IMAGE
;
1253 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--stamp") == 0)) {
1254 mOutImageType
= FW_SET_STAMP_IMAGE
;
1255 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
1256 Error (NULL
, 0, 1003, "Invalid option value", "time stamp is missing for -s option");
1259 TimeStamp
= argv
[1];
1265 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--replace") == 0)) {
1272 if (stricmp (argv
[0], "--keepexceptiontable") == 0) {
1273 KeepExceptionTableFlag
= TRUE
;
1279 if (stricmp (argv
[0], "--keepzeropending") == 0) {
1280 KeepZeroPendingFlag
= TRUE
;
1286 if ((stricmp (argv
[0], "-m") == 0) || (stricmp (argv
[0], "--mcifile") == 0)) {
1287 mOutImageType
= FW_MCI_IMAGE
;
1293 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--join") == 0)) {
1294 mOutImageType
= FW_MERGE_IMAGE
;
1300 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
1301 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1302 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1305 MciAlignment
= (UINT32
) Temp64
;
1311 if ((stricmp (argv
[0], "--rebase") == 0)) {
1312 if (argv
[1][0] == '-') {
1313 NegativeAddr
= TRUE
;
1314 Status
= AsciiStringToUint64 (argv
[1] + 1, FALSE
, &Temp64
);
1316 NegativeAddr
= FALSE
;
1317 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
);
1319 if (Status
!= EFI_SUCCESS
) {
1320 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1323 mOutImageType
= FW_REBASE_IMAGE
;
1324 NewBaseAddress
= (UINT64
) Temp64
;
1330 if ((stricmp (argv
[0], "--address") == 0)) {
1331 if (argv
[1][0] == '-') {
1332 NegativeAddr
= TRUE
;
1333 Status
= AsciiStringToUint64 (argv
[1] + 1, FALSE
, &Temp64
);
1335 NegativeAddr
= FALSE
;
1336 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
);
1338 if (Status
!= EFI_SUCCESS
) {
1339 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1342 mOutImageType
= FW_SET_ADDRESS_IMAGE
;
1343 NewBaseAddress
= (UINT64
) Temp64
;
1349 if ((stricmp (argv
[0], "-p") == 0) || (stricmp (argv
[0], "--pad") == 0)) {
1350 if (AsciiStringToUint64 (argv
[1], FALSE
, &Temp64
) != EFI_SUCCESS
) {
1351 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1354 MciPadValue
= (UINT8
) Temp64
;
1360 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
1361 SetPrintLevel (VERBOSE_LOG_LEVEL
);
1362 VerboseMsg ("Verbose output Mode Set!");
1368 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1369 SetPrintLevel (KEY_LOG_LEVEL
);
1370 KeyMsg ("Quiet output Mode Set!");
1376 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
1377 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
1378 if (EFI_ERROR (Status
)) {
1379 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1383 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel
);
1386 SetPrintLevel (LogLevel
);
1387 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
1393 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--hiiguid") == 0)) {
1394 Status
= StringToGuid (argv
[1], &HiiPackageListGuid
);
1395 if (EFI_ERROR (Status
)) {
1396 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1404 if (stricmp (argv
[0], "--hiipackage") == 0) {
1405 mOutImageType
= FW_HII_PACKAGE_LIST_RCIMAGE
;
1411 if (stricmp (argv
[0], "--hiibinpackage") == 0) {
1412 mOutImageType
= FW_HII_PACKAGE_LIST_BINIMAGE
;
1418 if (argv
[0][0] == '-') {
1419 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
1423 // Get Input file name
1425 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
1426 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
1427 if (InputFileName
== NULL
) {
1428 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1432 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1433 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1435 // InputFileName buffer too small, need to realloc
1437 InputFileName
= (CHAR8
**) realloc (
1439 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1442 if (InputFileName
== NULL
) {
1443 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1447 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1450 InputFileName
[InputFileNum
++] = argv
[0];
1455 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1457 if (mOutImageType
== FW_DUMMY_IMAGE
) {
1458 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!");
1460 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.");
1466 // check input files
1468 if (InputFileNum
== 0) {
1469 Error (NULL
, 0, 1001, "Missing option", "Input files");
1474 // Combine MciBinary files to one file
1476 if ((mOutImageType
== FW_MERGE_IMAGE
) && ReplaceFlag
) {
1477 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");
1482 // Combine HiiBinary packages to a single package list
1484 if ((mOutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) && ReplaceFlag
) {
1485 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option.");
1489 if ((mOutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) && ReplaceFlag
) {
1490 Error (NULL
, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiibinpackage merge files option.");
1497 mInImageName
= InputFileName
[InputFileNum
- 1];
1498 VerboseMsg ("the input file name is %s", mInImageName
);
1501 // Action will be taken for the input file.
1503 switch (mOutImageType
) {
1505 VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType
);
1508 VerboseMsg ("Create Te Image based on the input PE image.");
1511 VerboseMsg ("Get acpi table data from the input PE image.");
1513 case FW_RELOC_STRIPEED_IMAGE
:
1514 VerboseMsg ("Remove relocation section from Pe or Te image.");
1517 VerboseMsg ("Convert the input EXE to the output BIN file.");
1519 case FW_ZERO_DEBUG_IMAGE
:
1520 VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");
1522 case FW_SET_STAMP_IMAGE
:
1523 VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp
);
1525 case DUMP_TE_HEADER
:
1526 VerboseMsg ("Dump the TE header information of the input TE image.");
1529 VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");
1531 case FW_MERGE_IMAGE
:
1532 VerboseMsg ("Combine the input multi microcode bin files to one bin file.");
1534 case FW_HII_PACKAGE_LIST_RCIMAGE
:
1535 VerboseMsg ("Combine the input multi hii bin packages to one text pacakge list RC file.");
1537 case FW_HII_PACKAGE_LIST_BINIMAGE
:
1538 VerboseMsg ("Combine the input multi hii bin packages to one binary pacakge list file.");
1540 case FW_REBASE_IMAGE
:
1541 VerboseMsg ("Rebase the input image to new base address.");
1543 case FW_SET_ADDRESS_IMAGE
:
1544 VerboseMsg ("Set the preferred address into the section header of the input image");
1551 VerboseMsg ("Overwrite the input file with the output content.");
1555 // Open output file and Write image into the output file.
1557 if (OutImageName
!= NULL
) {
1558 fpOut
= fopen (LongFilePath (OutImageName
), "rb");
1559 if (fpOut
!= NULL
) {
1561 // Get Output file time stamp
1563 fstat(fileno (fpOut
), &Stat_Buf
);
1564 OutputFileTime
= Stat_Buf
.st_mtime
;
1566 // Get Output file data
1568 OutputFileLength
= _filelength (fileno (fpOut
));
1569 OutputFileBuffer
= malloc (OutputFileLength
);
1570 if (OutputFileBuffer
== NULL
) {
1571 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1576 fread (OutputFileBuffer
, 1, OutputFileLength
, fpOut
);
1580 VerboseMsg ("Output file name is %s", OutImageName
);
1581 } else if (!ReplaceFlag
&& mOutImageType
!= DUMP_TE_HEADER
) {
1582 Error (NULL
, 0, 1001, "Missing option", "output file");
1587 // Open input file and read file data into file buffer.
1589 fpIn
= fopen (LongFilePath (mInImageName
), "rb");
1591 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1595 // Get Iutput file time stamp
1597 fstat(fileno (fpIn
), &Stat_Buf
);
1598 InputFileTime
= Stat_Buf
.st_mtime
;
1600 // Get Input file data
1602 InputFileLength
= _filelength (fileno (fpIn
));
1603 InputFileBuffer
= malloc (InputFileLength
);
1604 if (InputFileBuffer
== NULL
) {
1605 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1609 fread (InputFileBuffer
, 1, InputFileLength
, fpIn
);
1611 DebugMsg (NULL
, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) InputFileLength
);
1614 // Combine multi binary HII package files.
1616 if (mOutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
|| mOutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) {
1618 // Open output file handle.
1620 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
1622 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1626 // Get hii package list lenght
1628 HiiPackageListHeader
.PackageLength
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1629 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1630 fpIn
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
1632 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1635 FileLength
= _filelength (fileno (fpIn
));
1636 fread (&HiiPackageHeader
, 1, sizeof (HiiPackageHeader
), fpIn
);
1637 if (HiiPackageHeader
.Type
== EFI_HII_PACKAGE_FORM
) {
1638 if (HiiPackageHeader
.Length
!= FileLength
) {
1639 Error (NULL
, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName
[Index
]);
1643 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
1644 fread (&IfrFormSet
, 1, sizeof (IfrFormSet
), fpIn
);
1645 memcpy (&HiiPackageListGuid
, &IfrFormSet
.Guid
, sizeof (EFI_GUID
));
1647 NumberOfFormPacakge
++;
1649 HiiPackageListHeader
.PackageLength
+= FileLength
;
1652 HiiPackageListHeader
.PackageLength
+= sizeof (EndPackage
);
1654 // Check whether hii packages are valid
1656 if (NumberOfFormPacakge
> 1) {
1657 Error (NULL
, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package");
1660 if (memcmp (&HiiPackageListGuid
, &mZeroGuid
, sizeof (EFI_GUID
)) == 0) {
1661 Error (NULL
, 0, 3000, "Invalid", "HII pacakge list guid is not specified!");
1664 memcpy (&HiiPackageListHeader
.PackageListGuid
, &HiiPackageListGuid
, sizeof (EFI_GUID
));
1666 // read hii packages
1668 HiiPackageListBuffer
= malloc (HiiPackageListHeader
.PackageLength
);
1669 if (HiiPackageListBuffer
== NULL
) {
1670 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1673 memcpy (HiiPackageListBuffer
, &HiiPackageListHeader
, sizeof (HiiPackageListHeader
));
1674 HiiPackageDataPointer
= HiiPackageListBuffer
+ sizeof (HiiPackageListHeader
);
1675 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1676 fpIn
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
1678 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1679 free (HiiPackageListBuffer
);
1683 FileLength
= _filelength (fileno (fpIn
));
1684 fread (HiiPackageDataPointer
, 1, FileLength
, fpIn
);
1686 HiiPackageDataPointer
= HiiPackageDataPointer
+ FileLength
;
1688 memcpy (HiiPackageDataPointer
, &EndPackage
, sizeof (EndPackage
));
1691 // write the hii package into the binary package list file with the resource section header
1693 if (mOutImageType
== FW_HII_PACKAGE_LIST_BINIMAGE
) {
1695 // Create the resource section header
1697 HiiSectionHeader
= CreateHiiResouceSectionHeader (&HiiSectionHeaderSize
, HiiPackageListHeader
.PackageLength
);
1699 // Wrtie section header and HiiData into File.
1701 fwrite (HiiSectionHeader
, 1, HiiSectionHeaderSize
, fpOut
);
1702 fwrite (HiiPackageListBuffer
, 1, HiiPackageListHeader
.PackageLength
, fpOut
);
1704 // Free allocated resources.
1706 free (HiiSectionHeader
);
1707 free (HiiPackageListBuffer
);
1709 // Done successfully
1715 // write the hii package into the text package list rc file.
1717 if (mOutImageType
== FW_HII_PACKAGE_LIST_RCIMAGE
) {
1718 for (Index
= 0; gHiiPackageRCFileHeader
[Index
] != NULL
; Index
++) {
1719 fprintf (fpOut
, "%s\n", gHiiPackageRCFileHeader
[Index
]);
1721 fprintf (fpOut
, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX
, HII_RESOURCE_SECTION_NAME
);
1723 HiiPackageDataPointer
= HiiPackageListBuffer
;
1724 for (Index
= 0; Index
+ 2 < HiiPackageListHeader
.PackageLength
; Index
+= 2) {
1725 if (Index
% 16 == 0) {
1726 fprintf (fpOut
, "\n ");
1728 fprintf (fpOut
, " 0x%04X,", *(UINT16
*) HiiPackageDataPointer
);
1729 HiiPackageDataPointer
+= 2;
1732 if (Index
% 16 == 0) {
1733 fprintf (fpOut
, "\n ");
1735 if ((Index
+ 2) == HiiPackageListHeader
.PackageLength
) {
1736 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT16
*) HiiPackageDataPointer
);
1738 if ((Index
+ 1) == HiiPackageListHeader
.PackageLength
) {
1739 fprintf (fpOut
, " 0x%04X\n}\n", *(UINT8
*) HiiPackageDataPointer
);
1741 free (HiiPackageListBuffer
);
1743 // Done successfully
1750 // Combine MciBinary files to one file
1752 if (mOutImageType
== FW_MERGE_IMAGE
) {
1754 // Open output file handle.
1756 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
1758 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1761 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1762 fpIn
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
1764 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
1768 FileLength
= _filelength (fileno (fpIn
));
1769 FileBuffer
= malloc (FileLength
);
1770 if (FileBuffer
== NULL
) {
1771 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1776 fread (FileBuffer
, 1, FileLength
, fpIn
);
1779 // write input file to out file
1781 fwrite (FileBuffer
, 1, FileLength
, fpOut
);
1783 // write pad value to out file.
1785 while (FileLength
++ % MciAlignment
!= 0) {
1786 fwrite (&MciPadValue
, 1, 1, fpOut
);
1789 // free allocated memory space
1795 // Done successfully
1801 // Convert MicroCode.txt file to MicroCode.bin file
1803 if (mOutImageType
== FW_MCI_IMAGE
) {
1804 fpIn
= fopen (LongFilePath (mInImageName
), "r");
1806 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1811 // The first pass is to determine
1812 // how much data is in the file so we can allocate a working buffer.
1816 Status
= MicrocodeReadData (fpIn
, &Data
);
1817 if (Status
== STATUS_SUCCESS
) {
1818 FileLength
+= sizeof (Data
);
1820 if (Status
== STATUS_IGNORE
) {
1821 Status
= STATUS_SUCCESS
;
1823 } while (Status
== STATUS_SUCCESS
);
1825 // Error if no data.
1827 if (FileLength
== 0) {
1828 Error (NULL
, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName
);
1831 if (FileLength
< sizeof (MICROCODE_IMAGE_HEADER
)) {
1832 Error (NULL
, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName
);
1837 // Allocate a buffer for the data
1839 FileBuffer
= malloc (FileLength
);
1840 if (FileBuffer
== NULL
) {
1841 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1845 // Re-read the file, storing the data into our buffer
1847 fseek (fpIn
, 0, SEEK_SET
);
1848 DataPointer
= (UINT32
*) FileBuffer
;
1849 OldDataPointer
= DataPointer
;
1851 OldDataPointer
= DataPointer
;
1852 Status
= MicrocodeReadData (fpIn
, DataPointer
++);
1853 if (Status
== STATUS_IGNORE
) {
1854 DataPointer
= OldDataPointer
;
1855 Status
= STATUS_SUCCESS
;
1857 } while (Status
== STATUS_SUCCESS
);
1859 // close input file after read data
1864 // Can't do much checking on the header because, per the spec, the
1865 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
1866 // and the TotalSize field is invalid (actually missing). Thus we can't
1867 // even verify the Reserved fields are 0.
1869 MciHeader
= (MICROCODE_IMAGE_HEADER
*) FileBuffer
;
1870 if (MciHeader
->DataSize
== 0) {
1873 Index
= MciHeader
->TotalSize
;
1876 if (Index
!= FileLength
) {
1877 Error (NULL
, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName
, (unsigned) FileLength
, (unsigned) Index
);
1882 // Checksum the contents
1884 DataPointer
= (UINT32
*) FileBuffer
;
1887 while (Index
< FileLength
) {
1888 CheckSum
+= *DataPointer
;
1890 Index
+= sizeof (*DataPointer
);
1892 if (CheckSum
!= 0) {
1893 Error (NULL
, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum
, mInImageName
);
1897 // Open the output file and write the buffer contents
1899 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
1904 // Open input file and read file data into file buffer.
1906 FileLength
= InputFileLength
;
1907 FileBuffer
= malloc (FileLength
);
1908 if (FileBuffer
== NULL
) {
1909 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1912 memcpy (FileBuffer
, InputFileBuffer
, InputFileLength
);
1915 // Dump TeImage Header into output file.
1917 if (mOutImageType
== DUMP_TE_HEADER
) {
1918 memcpy (&TEImageHeader
, FileBuffer
, sizeof (TEImageHeader
));
1919 if (TEImageHeader
.Signature
!= EFI_TE_IMAGE_HEADER_SIGNATURE
) {
1920 Error (NULL
, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName
);
1924 // Open the output file handle.
1927 fpInOut
= fopen (LongFilePath (mInImageName
), "wb");
1928 if (fpInOut
== NULL
) {
1929 Error (NULL
, 0, 0001, "Error opening file", mInImageName
);
1933 if (OutImageName
!= NULL
) {
1934 fpOut
= fopen (LongFilePath (OutImageName
), "wb");
1938 if (fpOut
== NULL
) {
1939 Error (NULL
, 0, 0001, "Error opening output file", OutImageName
);
1943 if (fpInOut
!= NULL
) {
1944 fprintf (fpInOut
, "Dump of file %s\n\n", mInImageName
);
1945 fprintf (fpInOut
, "TE IMAGE HEADER VALUES\n");
1946 fprintf (fpInOut
, "%17X machine\n", TEImageHeader
.Machine
);
1947 fprintf (fpInOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
1948 fprintf (fpInOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
1949 fprintf (fpInOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
1950 fprintf (fpInOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
1951 fprintf (fpInOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
1952 fprintf (fpInOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
1953 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
1954 fprintf (fpInOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
1956 if (fpOut
!= NULL
) {
1957 fprintf (fpOut
, "Dump of file %s\n\n", mInImageName
);
1958 fprintf (fpOut
, "TE IMAGE HEADER VALUES\n");
1959 fprintf (fpOut
, "%17X machine\n", TEImageHeader
.Machine
);
1960 fprintf (fpOut
, "%17X number of sections\n", TEImageHeader
.NumberOfSections
);
1961 fprintf (fpOut
, "%17X subsystems\n", TEImageHeader
.Subsystem
);
1962 fprintf (fpOut
, "%17X stripped size\n", TEImageHeader
.StrippedSize
);
1963 fprintf (fpOut
, "%17X entry point\n", (unsigned) TEImageHeader
.AddressOfEntryPoint
);
1964 fprintf (fpOut
, "%17X base of code\n", (unsigned) TEImageHeader
.BaseOfCode
);
1965 fprintf (fpOut
, "%17llX image base\n", (unsigned long long)TEImageHeader
.ImageBase
);
1966 fprintf (fpOut
, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader
.DataDirectory
[0].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[0].Size
);
1967 fprintf (fpOut
, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader
.DataDirectory
[1].VirtualAddress
, (unsigned) TEImageHeader
.DataDirectory
[1].Size
);
1973 // Following code to convert dll to efi image or te image.
1974 // Get new image type
1976 if ((mOutImageType
== FW_EFI_IMAGE
) || (mOutImageType
== FW_TE_IMAGE
)) {
1977 if (ModuleType
== NULL
) {
1978 if (mOutImageType
== FW_EFI_IMAGE
) {
1979 Error (NULL
, 0, 1001, "Missing option", "EFI_FILETYPE");
1981 } else if (mOutImageType
== FW_TE_IMAGE
) {
1983 // Default TE Image Type is Boot service driver
1985 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
1986 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
1989 if (stricmp (ModuleType
, "BASE") == 0 ||
1990 stricmp (ModuleType
, "SEC") == 0 ||
1991 stricmp (ModuleType
, "SECURITY_CORE") == 0 ||
1992 stricmp (ModuleType
, "PEI_CORE") == 0 ||
1993 stricmp (ModuleType
, "PEIM") == 0 ||
1994 stricmp (ModuleType
, "COMBINED_PEIM_DRIVER") == 0 ||
1995 stricmp (ModuleType
, "PIC_PEIM") == 0 ||
1996 stricmp (ModuleType
, "RELOCATABLE_PEIM") == 0 ||
1997 stricmp (ModuleType
, "DXE_CORE") == 0 ||
1998 stricmp (ModuleType
, "BS_DRIVER") == 0 ||
1999 stricmp (ModuleType
, "DXE_DRIVER") == 0 ||
2000 stricmp (ModuleType
, "DXE_SMM_DRIVER") == 0 ||
2001 stricmp (ModuleType
, "UEFI_DRIVER") == 0 ||
2002 stricmp (ModuleType
, "SMM_CORE") == 0) {
2003 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
2004 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2006 } else if (stricmp (ModuleType
, "UEFI_APPLICATION") == 0 ||
2007 stricmp (ModuleType
, "APPLICATION") == 0) {
2008 Type
= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
;
2009 VerboseMsg ("Efi Image subsystem type is efi application.");
2011 } else if (stricmp (ModuleType
, "DXE_RUNTIME_DRIVER") == 0 ||
2012 stricmp (ModuleType
, "RT_DRIVER") == 0) {
2013 Type
= EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
;
2014 VerboseMsg ("Efi Image subsystem type is efi runtime driver.");
2016 } else if (stricmp (ModuleType
, "DXE_SAL_DRIVER") == 0 ||
2017 stricmp (ModuleType
, "SAL_RT_DRIVER") == 0) {
2018 Type
= EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
;
2019 VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");
2022 Error (NULL
, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType
);
2029 // Convert ELF image to PeImage
2031 if (IsElfHeader(FileBuffer
)) {
2032 VerboseMsg ("Convert %s from ELF to PE/COFF.", mInImageName
);
2033 if (!ConvertElf(&FileBuffer
, &FileLength
)) {
2034 Error (NULL
, 0, 3000, "Invalid", "Unable to convert %s from ELF to PE/COFF.", mInImageName
);
2040 // Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP
2041 // XIP == eXecute In Place
2043 PeCoffConvertImageToXip (&FileBuffer
, &FileLength
);
2046 // Remove reloc section from PE or TE image
2048 if (mOutImageType
== FW_RELOC_STRIPEED_IMAGE
) {
2052 TeHdr
= (EFI_TE_IMAGE_HEADER
*) FileBuffer
;
2053 if (TeHdr
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
2054 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (TeHdr
+ 1);
2055 for (Index
= 0; Index
< TeHdr
->NumberOfSections
; Index
++, SectionHeader
++) {
2056 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2058 // Check the reloc section is in the end of image.
2060 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) ==
2061 (FileLength
+ TeHdr
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
))) {
2063 // Remove .reloc section and update TeImage Header
2065 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2066 SectionHeader
->SizeOfRawData
= 0;
2067 SectionHeader
->Misc
.VirtualSize
= 0;
2068 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2069 TeHdr
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2078 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) FileBuffer
;
2079 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2080 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2081 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2082 Error (NULL
, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName
);
2087 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2088 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2089 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2093 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2094 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2095 if (strcmp ((char *)SectionHeader
->Name
, ".reloc") == 0) {
2097 // Check the reloc section is in the end of image.
2099 if ((SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
) == FileLength
) {
2101 // Remove .reloc section and update PeImage Header
2103 FileLength
= FileLength
- SectionHeader
->SizeOfRawData
;
2105 PeHdr
->Pe32
.FileHeader
.Characteristics
|= EFI_IMAGE_FILE_RELOCS_STRIPPED
;
2106 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2107 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2108 Optional32
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2109 Optional32
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2110 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2111 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2112 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2115 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2116 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
2117 Optional64
->SizeOfImage
-= SectionHeader
->SizeOfRawData
;
2118 Optional64
->SizeOfInitializedData
-= SectionHeader
->SizeOfRawData
;
2119 if (Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2120 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= 0;
2121 Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= 0;
2124 SectionHeader
->Misc
.VirtualSize
= 0;
2125 SectionHeader
->SizeOfRawData
= 0;
2137 // Read the dos & pe hdrs of the image
2139 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
2140 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
2141 // NO DOS header, check for PE/COFF header
2142 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
);
2143 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2144 Error (NULL
, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName
);
2150 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ DosHdr
->e_lfanew
);
2151 if (PeHdr
->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
2152 Error (NULL
, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName
);
2157 if (PeHdr
->Pe32
.FileHeader
.Machine
== IMAGE_FILE_MACHINE_ARM
) {
2158 // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
2159 // so patch back to the offical UEFI value.
2160 PeHdr
->Pe32
.FileHeader
.Machine
= IMAGE_FILE_MACHINE_ARMT
;
2164 // Set new base address into image
2166 if (mOutImageType
== FW_REBASE_IMAGE
|| mOutImageType
== FW_SET_ADDRESS_IMAGE
) {
2167 if ((PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) && (PeHdr
->Pe32
.FileHeader
.Machine
!= IMAGE_FILE_MACHINE_IA64
)) {
2168 if (NewBaseAddress
>= 0x100000000ULL
) {
2169 Error (NULL
, 0, 3000, "Invalid", "New base address is larger than 4G for 32bit PE image");
2176 // Set Base Address to a negative value.
2178 NewBaseAddress
= (UINT64
) (0 - NewBaseAddress
);
2180 if (mOutImageType
== FW_REBASE_IMAGE
) {
2181 Status
= RebaseImage (mInImageName
, FileBuffer
, NewBaseAddress
);
2183 Status
= SetAddressToSectionHeader (mInImageName
, FileBuffer
, NewBaseAddress
);
2185 if (EFI_ERROR (Status
)) {
2187 Error (NULL
, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address -0x%llx can't success", mInImageName
, 0 - NewBaseAddress
);
2189 Error (NULL
, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address 0x%llx can't success", mInImageName
, NewBaseAddress
);
2201 // Extract bin data from Pe image.
2203 if (mOutImageType
== FW_BIN_IMAGE
) {
2204 if (FileLength
< PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
) {
2205 Error (NULL
, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName
);
2209 // Output bin data from exe file
2211 FileLength
= FileLength
- PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
;
2212 memmove (FileBuffer
, FileBuffer
+ PeHdr
->Pe32
.OptionalHeader
.SizeOfHeaders
, FileLength
);
2213 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2218 // Zero Debug Information of Pe Image
2220 if (mOutImageType
== FW_ZERO_DEBUG_IMAGE
) {
2221 Status
= ZeroDebugData (FileBuffer
, TRUE
);
2222 if (EFI_ERROR (Status
)) {
2223 Error (NULL
, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status
);
2228 // Write the updated Image
2230 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2235 // Set Time Stamp of Pe Image
2237 if (mOutImageType
== FW_SET_STAMP_IMAGE
) {
2238 Status
= SetStamp (FileBuffer
, TimeStamp
);
2239 if (EFI_ERROR (Status
)) {
2244 // Write the updated Image
2246 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2251 // Extract acpi data from pe image.
2253 if (mOutImageType
== FW_ACPI_IMAGE
) {
2254 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2255 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2256 if (strcmp ((char *)SectionHeader
->Name
, ".data") == 0 || strcmp ((char *)SectionHeader
->Name
, ".sdata") == 0) {
2260 if (SectionHeader
->Misc
.VirtualSize
< SectionHeader
->SizeOfRawData
) {
2261 FileLength
= SectionHeader
->Misc
.VirtualSize
;
2263 FileLength
= SectionHeader
->SizeOfRawData
;
2266 if (CheckAcpiTable (FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
) != STATUS_SUCCESS
) {
2267 Error (NULL
, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName
);
2272 // Output Apci data to file
2274 memmove (FileBuffer
, FileBuffer
+ SectionHeader
->PointerToRawData
, FileLength
);
2275 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength
);
2279 Error (NULL
, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName
);
2283 // Zero all unused fields of the DOS header
2285 if (DosHdr
!= NULL
) {
2286 memcpy (&BackupDosHdr
, DosHdr
, sizeof (EFI_IMAGE_DOS_HEADER
));
2287 memset (DosHdr
, 0, sizeof (EFI_IMAGE_DOS_HEADER
));
2288 DosHdr
->e_magic
= BackupDosHdr
.e_magic
;
2289 DosHdr
->e_lfanew
= BackupDosHdr
.e_lfanew
;
2291 for (Index
= sizeof (EFI_IMAGE_DOS_HEADER
); Index
< (UINT32
) DosHdr
->e_lfanew
; Index
++) {
2292 FileBuffer
[Index
] = (UINT8
) DosHdr
->e_cp
;
2297 // Initialize TeImage Header
2299 memset (&TEImageHeader
, 0, sizeof (EFI_TE_IMAGE_HEADER
));
2300 TEImageHeader
.Signature
= EFI_TE_IMAGE_HEADER_SIGNATURE
;
2301 TEImageHeader
.Machine
= PeHdr
->Pe32
.FileHeader
.Machine
;
2302 TEImageHeader
.NumberOfSections
= (UINT8
) PeHdr
->Pe32
.FileHeader
.NumberOfSections
;
2303 TEImageHeader
.StrippedSize
= (UINT16
) ((UINTN
) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
) - (UINTN
) FileBuffer
);
2304 TEImageHeader
.Subsystem
= (UINT8
) Type
;
2307 // Patch the PE header
2309 PeHdr
->Pe32
.OptionalHeader
.Subsystem
= (UINT16
) Type
;
2311 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
2312 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->Pe32
.OptionalHeader
;
2313 Optional32
->MajorOperatingSystemVersion
= 0;
2314 Optional32
->MinorOperatingSystemVersion
= 0;
2315 Optional32
->MajorImageVersion
= 0;
2316 Optional32
->MinorImageVersion
= 0;
2317 Optional32
->MajorSubsystemVersion
= 0;
2318 Optional32
->MinorSubsystemVersion
= 0;
2319 Optional32
->Win32VersionValue
= 0;
2320 Optional32
->CheckSum
= 0;
2321 Optional32
->SizeOfStackReserve
= 0;
2322 Optional32
->SizeOfStackCommit
= 0;
2323 Optional32
->SizeOfHeapReserve
= 0;
2324 Optional32
->SizeOfHeapCommit
= 0;
2326 TEImageHeader
.AddressOfEntryPoint
= Optional32
->AddressOfEntryPoint
;
2327 TEImageHeader
.BaseOfCode
= Optional32
->BaseOfCode
;
2328 TEImageHeader
.ImageBase
= (UINT64
) (Optional32
->ImageBase
);
2330 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2331 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
;
2332 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2335 if (Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
2336 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
;
2337 TEImageHeader
.DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
;
2341 // Zero .pdata section data.
2343 if (!KeepExceptionTableFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
&&
2344 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
!= 0 &&
2345 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
!= 0) {
2346 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2347 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2348 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
) {
2350 // Zero .pdata Section data
2352 memset (FileBuffer
+ SectionHeader
->PointerToRawData
, 0, SectionHeader
->SizeOfRawData
);
2354 // Zero .pdata Section header name
2356 memset (SectionHeader
->Name
, 0, sizeof (SectionHeader
->Name
));
2358 // Zero Execption Table
2360 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
= 0;
2361 Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
= 0;
2362 DebugMsg (NULL
, 0, 9, "Zero the .pdata section for PE image", NULL
);
2369 // Strip zero padding at the end of the .reloc section
2371 if (!KeepZeroPendingFlag
&& Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
2372 if (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
!= 0) {
2373 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) ((UINT8
*) &(PeHdr
->Pe32
.OptionalHeader
) + PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
);
2374 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
2376 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2378 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
) {
2379 SectionHeader
->Misc
.VirtualSize
= Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
2380 AllignedRelocSize
= (Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
+ Optional32
->FileAlignment
- 1) & (~(Optional32
->FileAlignment
- 1));
2382 // Check to see if there is zero padding at the end of the base relocations
2384 if (AllignedRelocSize
< SectionHeader
->SizeOfRawData
) {
2386 // Check to see if the base relocations are at the end of the file
2388 if (SectionHeader
->PointerToRawData
+ SectionHeader
->SizeOfRawData
== Optional32
->SizeOfImage
) {
2390 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2392 Optional32
->SizeOfImage
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2393 Optional32
->SizeOfInitializedData
-= (SectionHeader
->SizeOfRawData
- AllignedRelocSize
);
2394 SectionHeader
->SizeOfRawData
= AllignedRelocSize
;
2395 FileLength
= Optional32
->SizeOfImage
;
2396 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
));
2403 } else if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
2404 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->Pe32
.OptionalHeader
;
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 if (FileHdr
->Machine
== EFI_IMAGE_MACHINE_IA32
) {
2800 Optional32Hdr
= (EFI_IMAGE_OPTIONAL_HEADER32
*) ((UINT8
*) FileHdr
+ sizeof (EFI_IMAGE_FILE_HEADER
));
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
;