summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRegia König2021-08-06 14:50:15 +0200
committerRegia König2021-08-06 14:50:15 +0200
commit16e9728cfd2358557ecb1259f46b6cfec4d49c66 (patch)
tree5465c7bb5b55da741df71118acf4b529df5ea48b
parentAdd information to README (diff)
downloadmemtest86-16e9728cfd2358557ecb1259f46b6cfec4d49c66.tar.gz
memtest86-16e9728cfd2358557ecb1259f46b6cfec4d49c66.tar.xz
memtest86-16e9728cfd2358557ecb1259f46b6cfec4d49c66.zip
Provide source code of GenFW in __JustForReference__Unused__ directory
-rw-r--r--efi_memtest/__JustForReference__Unused__/GenFw.c3251
-rw-r--r--efi_memtest/__JustForReference__Unused__/GenFw.h50
2 files changed, 3301 insertions, 0 deletions
diff --git a/efi_memtest/__JustForReference__Unused__/GenFw.c b/efi_memtest/__JustForReference__Unused__/GenFw.c
new file mode 100644
index 0000000..8cab70b
--- /dev/null
+++ b/efi_memtest/__JustForReference__Unused__/GenFw.c
@@ -0,0 +1,3251 @@
+/** @file
+Converts a pe32+ image to an FW, Te image type, or other specific image.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "WinNtInclude.h"
+
+#ifndef __GNUC__
+#include <windows.h>
+#include <io.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <IndustryStandard/PeImage.h>
+#include <Common/UefiInternalFormRepresentation.h>
+
+//
+// Acpi Table definition
+//
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Acpi1_0.h>
+#include <IndustryStandard/Acpi2_0.h>
+#include <IndustryStandard/Acpi3_0.h>
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+
+#include "CommonLib.h"
+#include "PeCoffLib.h"
+#include "ParseInf.h"
+#include "EfiUtilityMsgs.h"
+
+#include "GenFw.h"
+
+//
+// Version of this utility
+//
+#define UTILITY_NAME "GenFw"
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 2
+
+#define HII_RESOURCE_SECTION_INDEX 1
+#define HII_RESOURCE_SECTION_NAME "HII"
+
+#define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
+#define DEFAULT_MC_ALIGNMENT 16
+
+#define STATUS_IGNORE 0xA
+//
+// Structure definition for a microcode header
+//
+typedef struct {
+ UINT32 HeaderVersion;
+ UINT32 PatchId;
+ UINT32 Date;
+ UINT32 CpuId;
+ UINT32 Checksum;
+ UINT32 LoaderVersion;
+ UINT32 PlatformId;
+ UINT32 DataSize; // if 0, then TotalSize = 2048, and TotalSize field is invalid
+ UINT32 TotalSize; // number of bytes
+ UINT32 Reserved[3];
+} MICROCODE_IMAGE_HEADER;
+
+static EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
+
+static const char *gHiiPackageRCFileHeader[] = {
+ "//",
+ "// DO NOT EDIT -- auto-generated file",
+ "//",
+ NULL
+};
+
+//
+// Module image information
+//
+CHAR8 *mInImageName;
+UINT32 mImageTimeStamp = 0;
+UINT32 mImageSize = 0;
+UINT32 mOutImageType = FW_DUMMY_IMAGE;
+BOOLEAN mIsConvertXip = FALSE;
+
+
+STATIC
+EFI_STATUS
+ZeroDebugData (
+ IN OUT UINT8 *FileBuffer,
+ BOOLEAN ZeroDebug
+ );
+
+STATIC
+EFI_STATUS
+SetStamp (
+ IN OUT UINT8 *FileBuffer,
+ IN CHAR8 *TimeStamp
+ );
+
+STATIC
+STATUS
+MicrocodeReadData (
+ FILE *InFptr,
+ UINT32 *Data
+ );
+
+STATIC
+VOID
+Version (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print out version information for this utility.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
+}
+
+STATIC
+VOID
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print Help message.
+
+Arguments:
+
+ VOID
+
+Returns:
+
+ None
+
+--*/
+{
+ //
+ // Summary usage
+ //
+ fprintf (stdout, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME);
+
+ //
+ // Copyright declaration
+ //
+ fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
+
+ //
+ // Details Option
+ //
+ fprintf (stdout, "Options:\n");
+ fprintf (stdout, " -o FileName, --outputfile FileName\n\
+ File will be created to store the output content.\n");
+ fprintf (stdout, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\
+ Create Efi Image. EFI_FILETYPE is one of BASE,SMM_CORE,\n\
+ PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\
+ SEC, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER,\n\
+ DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER,\n\
+ MM_STANDALONE, MM_CORE_STANDALONE,\n\
+ PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\
+ APPLICATION, SAL_RT_DRIVER to support all module types\n\
+ It can only be used together with --keepexceptiontable,\n\
+ --keepzeropending, --keepoptionalheader, -r, -o option.\n\
+ It is a action option. If it is combined with other action options,\n\
+ the later input action option will override the previous one.\n");
+ fprintf (stdout, " -c, --acpi Create Acpi table.\n\
+ It can't be combined with other action options\n\
+ except for -o, -r option. It is a action option.\n\
+ If it is combined with other action options, the later\n\
+ input action option will override the previous one.\n");
+ fprintf (stdout, " -t, --terse Create Te Image.\n\
+ It can only be used together with --keepexceptiontable,\n\
+ --keepzeropending, --keepoptionalheader, -r, -o option.\n\
+ It is a action option. If it is combined with other action options,\n\
+ the later input action option will override the previous one.\n");
+ fprintf (stdout, " -u, --dump Dump TeImage Header.\n\
+ It can't be combined with other action options\n\
+ except for -o, -r option. It is a action option.\n\
+ If it is combined with other action options, the later\n\
+ input action option will override the previous one.\n");
+ fprintf (stdout, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\
+ It also zeros the time stamp fields.\n\
+ This option can be used to compare the binary efi image.\n\
+ It can't be combined with other action options\n\
+ except for -o, -r option. It is a action option.\n\
+ If it is combined with other action options, the later\n\
+ input action option will override the previous one.\n");
+ fprintf (stdout, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\
+ It can't be combined with other action options\n\
+ except for -o, -r option. It is a action option.\n\
+ If it is combined with other action options, the later\n\
+ input action option will override the previous one.\n");;
+ fprintf (stdout, " -l, --stripped Strip off the relocation info from PE or TE image.\n\
+ It can't be combined with other action options\n\
+ except for -o, -r option. It is a action option.\n\
+ If it is combined with other action options, the later\n\
+ input action option will override the previous one.\n");
+ fprintf (stdout, " -s timedate, --stamp timedate\n\
+ timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\
+ is set to NOW, current system time is used. The support\n\
+ date scope is 1970-01-01 00+timezone:00:00\n\
+ ~ 2038-01-19 03+timezone:14:07\n\
+ The scope is adjusted according to the different zones.\n\
+ It can't be combined with other action options\n\
+ except for -o, -r option. It is a action option.\n\
+ If it is combined with other action options, the later\n\
+ input action option will override the previous one.\n");
+ fprintf (stdout, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\
+ It can't be combined with other action options\n\
+ except for -o option. It is a action option.\n\
+ If it is combined with other action options, the later\n\
+ input action option will override the previous one.\n");
+ fprintf (stdout, " -j, --join Combine multi microcode bin files to one file.\n\
+ It can be specified with -a, -p, -o option.\n\
+ No other options can be combined with it.\n\
+ If it is combined with other action options, the later\n\
+ input action option will override the previous one.\n");
+ fprintf (stdout, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\
+ This option is only used together with -j option.\n");
+ fprintf (stdout, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\
+ This option is only used together with -j option.\n");
+ fprintf (stdout, " --keepexceptiontable Don't clear exception table.\n\
+ This option can be used together with -e or -t.\n\
+ It doesn't work for other options.\n");
+ fprintf (stdout, " --keepoptionalheader Don't zero PE/COFF optional header fields.\n\
+ This option can be used together with -e or -t.\n\
+ It doesn't work for other options.\n");
+ fprintf (stdout, " --keepzeropending Don't strip zero pending of .reloc.\n\
+ This option can be used together with -e or -t.\n\
+ It doesn't work for other options.\n");
+ fprintf (stdout, " -r, --replace Overwrite the input file with the output content.\n\
+ If more input files are specified,\n\
+ the last input file will be as the output file.\n");
+ fprintf (stdout, " -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\
+ Guid is used to specify hii package list guid.\n\
+ Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\
+ If not specified, the first Form FormSet guid is used.\n");
+ fprintf (stdout, " --hiipackage Combine all input binary hii packages into \n\
+ a single package list as the text resource data(RC).\n\
+ It can't be combined with other action options\n\
+ except for -o option. It is a action option.\n\
+ If it is combined with other action options, the later\n\
+ input action option will override the previous one.\n");
+ fprintf (stdout, " --hiibinpackage Combine all input binary hii packages into \n\
+ a single package list as the binary resource section.\n\
+ It can't be combined with other action options\n\
+ except for -o option. It is a action option.\n\
+ If it is combined with other action options, the later\n\
+ input action option will override the previous one.\n");
+ fprintf (stdout, " --rebase NewAddress Rebase image to new base address. New address \n\
+ is also set to the first none code section header.\n\
+ It can't be combined with other action options\n\
+ except for -o or -r option. It is a action option.\n\
+ If it is combined with other action options, the later\n\
+ input action option will override the previous one.\n");
+ fprintf (stdout, " --address NewAddress Set new address into the first none code \n\
+ section header of the input image.\n\
+ It can't be combined with other action options\n\
+ except for -o or -r option. It is a action option.\n\
+ If it is combined with other action options, the later\n\
+ input action option will override the previous one.\n");
+ fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");
+ fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");
+ fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");
+ fprintf (stdout, " --version Show program's version number and exit\n");
+ fprintf (stdout, " -h, --help Show this help message and exit\n");
+}
+
+STATIC
+STATUS
+CheckAcpiTable (
+ VOID *AcpiTable,
+ UINT32 Length
+ )
+/*++
+
+Routine Description:
+
+ Check Acpi Table
+
+Arguments:
+
+ AcpiTable Buffer for AcpiSection
+ Length AcpiSection Length
+
+Returns:
+
+ 0 success
+ non-zero otherwise
+
+--*/
+{
+ EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader;
+ EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
+ UINT32 ExpectedLength;
+
+ AcpiHeader = (EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable;
+
+ //
+ // Generic check for AcpiTable length.
+ //
+ if (AcpiHeader->Length > Length) {
+ Error (NULL, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL);
+ return STATUS_ERROR;
+ }
+
+ //
+ // Currently, we only check must-have tables: FADT, FACS, DSDT,
+ // and some important tables: MADT, MCFG.
+ //
+ switch (AcpiHeader->Signature) {
+
+ //
+ // "FACP" Fixed ACPI Description Table
+ //
+ case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
+ switch (AcpiHeader->Revision) {
+ case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
+ ExpectedLength = sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE);
+ break;
+ case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
+ ExpectedLength = sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE);
+ break;
+ case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
+ ExpectedLength = sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE);
+ break;
+ default:
+ if (AcpiHeader->Revision > EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
+ ExpectedLength = AcpiHeader->Length;
+ break;
+ }
+ Error (NULL, 0, 3000, "Invalid", "FACP revision check failed.");
+ return STATUS_ERROR;
+ }
+ if (ExpectedLength != AcpiHeader->Length) {
+ Error (NULL, 0, 3000, "Invalid", "FACP length check failed.");
+ return STATUS_ERROR;
+ }
+ break;
+
+ //
+ // "FACS" Firmware ACPI Control Structure
+ //
+ case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
+ Facs = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)AcpiTable;
+ if (Facs->Version > EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) {
+ break;
+ }
+ if ((Facs->Version != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
+ (Facs->Version != EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
+ (Facs->Version != EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)){
+ Error (NULL, 0, 3000, "Invalid", "FACS version check failed.");
+ return STATUS_ERROR;
+ }
+ if ((Facs->Length != sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&
+ (Facs->Length != sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&
+ (Facs->Length != sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))) {
+ Error (NULL, 0, 3000, "Invalid", "FACS length check failed.");
+ return STATUS_ERROR;
+ }
+ break;
+
+ //
+ // "DSDT" Differentiated System Description Table
+ //
+ case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
+ if (AcpiHeader->Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION) {
+ break;
+ }
+ if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER)) {
+ Error (NULL, 0, 3000, "Invalid", "DSDT length check failed.");
+ return STATUS_ERROR;
+ }
+ break;
+
+ //
+ // "APIC" Multiple APIC Description Table
+ //
+ case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
+ if (AcpiHeader->Revision > EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) {
+ break;
+ }
+ if ((AcpiHeader->Revision != EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&
+ (AcpiHeader->Revision != EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&
+ (AcpiHeader->Revision != EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)) {
+ Error (NULL, 0, 3000, "Invalid", "APIC revision check failed.");
+ return STATUS_ERROR;
+ }
+ if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT32) + sizeof(UINT32)) {
+ Error (NULL, 0, 3000, "Invalid", "APIC length check failed.");
+ return STATUS_ERROR;
+ }
+ break;
+
+ //
+ // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
+ //
+ case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
+ if (AcpiHeader->Revision > EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {
+ break;
+ }
+ if (AcpiHeader->Revision != EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {
+ Error (NULL, 0, 3000, "Invalid", "MCFG revision check failed.");
+ return STATUS_ERROR;
+ }
+ if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64)) {
+ Error (NULL, 0, 3000, "Invalid", "MCFG length check failed.");
+ return STATUS_ERROR;
+ }
+ break;
+
+ //
+ // Other table pass check
+ //
+ default:
+ break;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+SetHiiResourceHeader (
+ UINT8 *HiiBinData,
+ UINT32 OffsetToFile
+ )
+{
+ UINT32 Index;
+ EFI_IMAGE_RESOURCE_DIRECTORY *ResourceDirectory;
+ EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *ResourceDirectoryEntry;
+ EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString;
+ EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry;
+
+ //
+ // Fill Resource section entry
+ //
+ ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData);
+ ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);
+ for (Index = 0; Index < ResourceDirectory->NumberOfNamedEntries; Index ++) {
+ if (ResourceDirectoryEntry->u1.s.NameIsString) {
+ ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiBinData + ResourceDirectoryEntry->u1.s.NameOffset);
+
+ if (ResourceDirectoryString->Length == 3 &&
+ ResourceDirectoryString->String[0] == L'H' &&
+ ResourceDirectoryString->String[1] == L'I' &&
+ ResourceDirectoryString->String[2] == L'I') {
+ //
+ // Resource Type "HII" found
+ //
+ if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {
+ //
+ // Move to next level - resource Name
+ //
+ ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData + ResourceDirectoryEntry->u2.s.OffsetToDirectory);
+ ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);
+
+ if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {
+ //
+ // Move to next level - resource Language
+ //
+ ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData + ResourceDirectoryEntry->u2.s.OffsetToDirectory);
+ ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);
+ }
+ }
+
+ //
+ // Now it ought to be resource Data and update its OffsetToData value
+ //
+ if (!ResourceDirectoryEntry->u2.s.DataIsDirectory) {
+ ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (HiiBinData + ResourceDirectoryEntry->u2.OffsetToData);
+ ResourceDataEntry->OffsetToData = ResourceDataEntry->OffsetToData + OffsetToFile;
+ break;
+ }
+ }
+ }
+ ResourceDirectoryEntry++;
+ }
+
+ return;
+}
+
+EFI_IMAGE_OPTIONAL_HEADER_UNION *
+GetPeCoffHeader (
+ void *Data
+ )
+{
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr;
+
+ //
+ // Read the dos & pe hdrs of the image
+ //
+ DosHdr = (EFI_IMAGE_DOS_HEADER *)Data;
+ if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ // NO DOS header, check for PE/COFF header
+ PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(Data);
+ if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
+ return NULL;
+ }
+ } else {
+
+ PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(((UINT8 *)Data) + DosHdr->e_lfanew);
+ if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
+ return NULL;
+ }
+ }
+
+ return PeHdr;
+}
+
+void
+PeCoffConvertImageToXip (
+ UINT8 **FileBuffer,
+ UINT32 *FileLength
+ )
+{
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *NewPeHdr;
+ EFI_IMAGE_SECTION_HEADER *SectionHeader;
+ UINTN TotalNecessaryFileSize;
+ UINTN SectionSize;
+ UINT8 *XipFile;
+ UINT32 XipLength;
+ UINTN Index;
+ UINTN FirstSectionOffset;
+ BOOLEAN ConversionNeeded;
+
+ PeHdr = GetPeCoffHeader ((void *) *FileBuffer);
+ if (PeHdr == NULL) {
+ return;
+ }
+
+ if (PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment) {
+ //
+ // The only reason to expand zero fill sections is to make them compatible with XIP images.
+ // If SectionAlignment is not equal to FileAlignment then it is not an XIP type image.
+ //
+ return;
+ }
+
+ //
+ // Calculate size of XIP file, and determine if the conversion is needed.
+ //
+ ConversionNeeded = FALSE;
+ XipLength = 0;
+ FirstSectionOffset = *FileLength;
+ TotalNecessaryFileSize = 0;
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
+ for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
+ SectionSize = MAX (SectionHeader->Misc.VirtualSize, SectionHeader->SizeOfRawData);
+ TotalNecessaryFileSize += SectionSize;
+ if (SectionSize > 0) {
+ FirstSectionOffset = MIN (FirstSectionOffset, SectionHeader->VirtualAddress);
+ XipLength = MAX (XipLength, SectionHeader->VirtualAddress + SectionSize);
+ if (SectionHeader->VirtualAddress != SectionHeader->PointerToRawData) {
+ ConversionNeeded = TRUE;
+ }
+ }
+ if (SectionHeader->Misc.VirtualSize > SectionHeader->SizeOfRawData) {
+ ConversionNeeded = TRUE;
+ }
+ }
+
+ if (FirstSectionOffset < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) {
+ //
+ // If one of the sections should be loaded to an offset overlapping with
+ // the executable header, then it cannot be made into an XIP image.
+ //
+ VerboseMsg ("PE/COFF conversion to XIP is impossible due to overlap");
+ VerboseMsg ("of section data with the executable header.");
+ return;
+ }
+
+ if (FirstSectionOffset == *FileLength) {
+ //
+ // If we never found a section with a non-zero size, then we
+ // skip the conversion.
+ //
+ return;
+ }
+
+ TotalNecessaryFileSize += FirstSectionOffset;
+
+ if (!ConversionNeeded) {
+ return;
+ }
+
+ if (XipLength > (2 * TotalNecessaryFileSize)) {
+ VerboseMsg ("PE/COFF conversion to XIP appears to be larger than necessary.");
+ VerboseMsg ("The image linking process may have left unused memory ranges.");
+ }
+
+ if (PeHdr->Pe32.FileHeader.PointerToSymbolTable != 0) {
+ //
+ // This field is obsolete and should be zero
+ //
+ PeHdr->Pe32.FileHeader.PointerToSymbolTable = 0;
+ }
+
+ //
+ // Allocate the extra space that we need to grow the image
+ //
+ XipFile = malloc (XipLength);
+ if (XipFile == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+ return;
+ }
+ memset (XipFile, 0, XipLength);
+
+ //
+ // Copy the file headers
+ //
+ memcpy (XipFile, *FileBuffer, PeHdr->Pe32.OptionalHeader.SizeOfHeaders);
+
+ NewPeHdr = GetPeCoffHeader ((void *)XipFile);
+ if (NewPeHdr == NULL) {
+ free (XipFile);
+ return;
+ }
+
+ //
+ // Copy the section data over to the appropriate XIP offsets
+ //
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(NewPeHdr->Pe32.OptionalHeader) + NewPeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
+ for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
+ if (SectionHeader->SizeOfRawData > 0) {
+ memcpy (
+ XipFile + SectionHeader->VirtualAddress,
+ *FileBuffer + SectionHeader->PointerToRawData,
+ SectionHeader->SizeOfRawData
+ );
+ }
+ //
+ // Make the size of raw data in section header alignment.
+ //
+ SectionSize = (SectionHeader->Misc.VirtualSize + PeHdr->Pe32.OptionalHeader.FileAlignment - 1) & (~(PeHdr->Pe32.OptionalHeader.FileAlignment - 1));
+ if (SectionSize < SectionHeader->SizeOfRawData) {
+ SectionHeader->SizeOfRawData = SectionSize;
+ }
+
+ SectionHeader->PointerToRawData = SectionHeader->VirtualAddress;
+ }
+
+ free (*FileBuffer);
+ *FileLength = XipLength;
+ *FileBuffer = XipFile;
+
+ mIsConvertXip = TRUE;
+}
+
+UINT8 *
+CreateHiiResouceSectionHeader (
+ UINT32 *pSectionHeaderSize,
+ UINT32 HiiDataSize
+ )
+/*++
+
+Routine Description:
+
+ Create COFF resource section header
+
+Arguments:
+
+ pSectionHeaderSize - Pointer to section header size.
+ HiiDataSize - Size of the total HII data in section.
+
+Returns:
+ The created section header buffer.
+
+--*/
+{
+ UINT32 HiiSectionHeaderSize;
+ UINT32 HiiSectionOffset;
+ UINT8 *HiiSectionHeader;
+ EFI_IMAGE_RESOURCE_DIRECTORY *ResourceDirectory;
+ EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *TypeResourceDirectoryEntry;
+ EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *NameResourceDirectoryEntry;
+ EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *LanguageResourceDirectoryEntry;
+ EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString;
+ EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry;
+
+ //
+ // Calculate the total size for the resource header (include Type, Name and Language)
+ // then allocate memory for the resource header.
+ //
+ HiiSectionHeaderSize = 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY))
+ + 3 * (sizeof (UINT16) + 3 * sizeof (CHAR16))
+ + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY);
+ HiiSectionHeader = malloc (HiiSectionHeaderSize);
+ if (HiiSectionHeader == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+ return NULL;
+ }
+ memset (HiiSectionHeader, 0, HiiSectionHeaderSize);
+
+ HiiSectionOffset = 0;
+ //
+ // Create Type entry
+ //
+ ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);
+ HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);
+ ResourceDirectory->NumberOfNamedEntries = 1;
+ TypeResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);
+ HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);
+ TypeResourceDirectoryEntry->u1.s.NameIsString = 1;
+ TypeResourceDirectoryEntry->u2.s.DataIsDirectory = 1;
+ TypeResourceDirectoryEntry->u2.s.OffsetToDirectory = HiiSectionOffset;
+ //
+ // Create Name entry
+ //
+ ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);
+ HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);
+ ResourceDirectory->NumberOfNamedEntries = 1;
+ NameResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);
+ HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);
+ NameResourceDirectoryEntry->u1.s.NameIsString = 1;
+ NameResourceDirectoryEntry->u2.s.DataIsDirectory = 1;
+ NameResourceDirectoryEntry->u2.s.OffsetToDirectory = HiiSectionOffset;
+ //
+ // Create Language entry
+ //
+ ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);
+ HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);
+ ResourceDirectory->NumberOfNamedEntries = 1;
+ LanguageResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);
+ HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);
+ LanguageResourceDirectoryEntry->u1.s.NameIsString = 1;
+ //
+ // Create string entry for Type
+ //
+ TypeResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;
+ ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);
+ ResourceDirectoryString->Length = 3;
+ ResourceDirectoryString->String[0] = L'H';
+ ResourceDirectoryString->String[1] = L'I';
+ ResourceDirectoryString->String[2] = L'I';
+ HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);
+ //
+ // Create string entry for Name
+ //
+ NameResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;
+ ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);
+ ResourceDirectoryString->Length = 3;
+ ResourceDirectoryString->String[0] = L'E';
+ ResourceDirectoryString->String[1] = L'F';
+ ResourceDirectoryString->String[2] = L'I';
+ HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);
+ //
+ // Create string entry for Language
+ //
+ LanguageResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;
+ ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);
+ ResourceDirectoryString->Length = 3;
+ ResourceDirectoryString->String[0] = L'B';
+ ResourceDirectoryString->String[1] = L'I';
+ ResourceDirectoryString->String[2] = L'N';
+ HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);
+ //
+ // Create Leaf data
+ //
+ LanguageResourceDirectoryEntry->u2.OffsetToData = HiiSectionOffset;
+ ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (HiiSectionHeader + HiiSectionOffset);
+ HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY);
+ ResourceDataEntry->OffsetToData = HiiSectionOffset;
+ ResourceDataEntry->Size = HiiDataSize;
+
+ *pSectionHeaderSize = HiiSectionHeaderSize;
+ return HiiSectionHeader;
+}
+
+EFI_STATUS
+RebaseImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINT32 *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
+
+Arguments:
+
+ FileHandle - The handle to the PE/COFF file
+
+ FileOffset - The offset, in bytes, into the file to read
+
+ ReadSize - The number of bytes to read from the file starting at FileOffset
+
+ Buffer - A pointer to the buffer to read the data into.
+
+Returns:
+
+ EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
+
+--*/
+{
+ CHAR8 *Destination8;
+ CHAR8 *Source8;
+ UINT32 Length;
+
+ Destination8 = Buffer;
+ Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
+ Length = *ReadSize;
+ while (Length--) {
+ *(Destination8++) = *(Source8++);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SetAddressToSectionHeader (
+ IN CHAR8 *FileName,
+ IN OUT UINT8 *FileBuffer,
+ IN UINT64 NewPe32BaseAddress
+ )
+/*++
+
+Routine Description:
+
+ Set new base address into the section header of PeImage
+
+Arguments:
+
+ FileName - Name of file
+ FileBuffer - Pointer to PeImage.
+ NewPe32BaseAddress - New Base Address for PE image.
+
+Returns:
+
+ EFI_SUCCESS Set new base address into this image successfully.
+
+--*/
+{
+ EFI_STATUS Status;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ UINTN Index;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
+ EFI_IMAGE_SECTION_HEADER *SectionHeader;
+
+ //
+ // Initialize context
+ //
+ memset (&ImageContext, 0, sizeof (ImageContext));
+ ImageContext.Handle = (VOID *) FileBuffer;
+ ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);
+ return Status;
+ }
+
+ if (ImageContext.RelocationsStripped) {
+ Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);
+ return Status;
+ }
+
+ //
+ // Get PeHeader pointer
+ //
+ ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);
+
+ //
+ // Get section header list
+ //
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
+ (UINTN) ImgHdr +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
+ ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
+ );
+
+ //
+ // Set base address into the first section header that doesn't point to code section.
+ //
+ for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
+ if ((SectionHeader->Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
+ *(UINT64 *) &SectionHeader->PointerToRelocations = NewPe32BaseAddress;
+ break;
+ }
+ }
+
+ //
+ // BaseAddress is set to section header.
+ //
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RebaseImage (
+ IN CHAR8 *FileName,
+ IN OUT UINT8 *FileBuffer,
+ IN UINT64 NewPe32BaseAddress
+ )
+/*++
+
+Routine Description:
+
+ Set new base address into PeImage, and fix up PeImage based on new address.
+
+Arguments:
+
+ FileName - Name of file
+ FileBuffer - Pointer to PeImage.
+ NewPe32BaseAddress - New Base Address for PE image.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - BaseAddress is not valid.
+ EFI_SUCCESS - Update PeImage is correctly.
+
+--*/
+{
+ EFI_STATUS Status;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ UINTN Index;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
+ UINT8 *MemoryImagePointer;
+ EFI_IMAGE_SECTION_HEADER *SectionHeader;
+
+ //
+ // Initialize context
+ //
+ memset (&ImageContext, 0, sizeof (ImageContext));
+ ImageContext.Handle = (VOID *) FileBuffer;
+ ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);
+ return Status;
+ }
+
+ if (ImageContext.RelocationsStripped) {
+ Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);
+ return Status;
+ }
+
+ //
+ // Get PeHeader pointer
+ //
+ ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);
+
+ //
+ // Load and Relocate Image Data
+ //
+ MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
+ if (MemoryImagePointer == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
+ ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((INT64)ImageContext.SectionAlignment - 1));
+
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);
+ free ((VOID *) MemoryImagePointer);
+ return Status;
+ }
+
+ ImageContext.DestinationAddress = NewPe32BaseAddress;
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName);
+ free ((VOID *) MemoryImagePointer);
+ return Status;
+ }
+
+ //
+ // Copy Relocated data to raw image file.
+ //
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
+ (UINTN) ImgHdr +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
+ ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
+ );
+
+ for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
+ CopyMem (
+ FileBuffer + SectionHeader->PointerToRawData,
+ (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),
+ SectionHeader->SizeOfRawData < SectionHeader->Misc.VirtualSize ? SectionHeader->SizeOfRawData : SectionHeader->Misc.VirtualSize
+ );
+ }
+
+ free ((VOID *) MemoryImagePointer);
+
+ //
+ // Update Image Base Address
+ //
+ if (ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;
+ } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;
+ } else {
+ Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
+ ImgHdr->Pe32.OptionalHeader.Magic,
+ FileName
+ );
+ return EFI_ABORTED;
+ }
+
+ //
+ // Set new base address into section header
+ //
+ Status = SetAddressToSectionHeader (FileName, FileBuffer, NewPe32BaseAddress);
+
+ return Status;
+}
+
+int
+main (
+ int argc,
+ char *argv[]
+ )
+/*++
+
+Routine Description:
+
+ Main function.
+
+Arguments:
+
+ argc - Number of command line parameters.
+ argv - Array of pointers to command line parameter strings.
+
+Returns:
+ STATUS_SUCCESS - Utility exits successfully.
+ STATUS_ERROR - Some error occurred during execution.
+
+--*/
+{
+ UINT32 Type;
+ UINT32 InputFileNum;
+ CHAR8 **InputFileName;
+ char *OutImageName;
+ char *ModuleType;
+ CHAR8 *TimeStamp;
+ FILE *fpIn;
+ FILE *fpOut;
+ FILE *fpInOut;
+ UINT32 Data;
+ UINT32 *DataPointer;
+ UINT32 *OldDataPointer;
+ UINT32 CheckSum;
+ UINT32 Index;
+ UINT32 Index1;
+ UINT32 Index2;
+ UINT64 Temp64;
+ UINT32 MciAlignment;
+ UINT8 MciPadValue;
+ UINT32 AllignedRelocSize;
+ UINT8 *FileBuffer;
+ UINT32 FileLength;
+ UINT8 *OutputFileBuffer;
+ UINT32 OutputFileLength;
+ UINT8 *InputFileBuffer;
+ UINT32 InputFileLength;
+ RUNTIME_FUNCTION *RuntimeFunction;
+ UNWIND_INFO *UnwindInfo;
+ STATUS Status;
+ BOOLEAN ReplaceFlag;
+ BOOLEAN KeepExceptionTableFlag;
+ BOOLEAN KeepOptionalHeaderFlag;
+ BOOLEAN KeepZeroPendingFlag;
+ UINT64 LogLevel;
+ EFI_TE_IMAGE_HEADER TEImageHeader;
+ EFI_TE_IMAGE_HEADER *TeHdr;
+ EFI_IMAGE_SECTION_HEADER *SectionHeader;
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr;
+ EFI_IMAGE_OPTIONAL_HEADER32 *Optional32;
+ EFI_IMAGE_OPTIONAL_HEADER64 *Optional64;
+ EFI_IMAGE_DOS_HEADER BackupDosHdr;
+ MICROCODE_IMAGE_HEADER *MciHeader;
+ UINT8 *HiiPackageListBuffer;
+ UINT8 *HiiPackageDataPointer;
+ EFI_GUID HiiPackageListGuid;
+ EFI_HII_PACKAGE_LIST_HEADER HiiPackageListHeader;
+ EFI_HII_PACKAGE_HEADER HiiPackageHeader;
+ EFI_IFR_FORM_SET IfrFormSet;
+ UINT8 NumberOfFormPackage;
+ EFI_HII_PACKAGE_HEADER EndPackage;
+ UINT32 HiiSectionHeaderSize;
+ UINT8 *HiiSectionHeader;
+ UINT64 NewBaseAddress;
+ BOOLEAN NegativeAddr;
+ FILE *ReportFile;
+ CHAR8 *ReportFileName;
+ UINTN FileLen;
+ time_t InputFileTime;
+ time_t OutputFileTime;
+ struct stat Stat_Buf;
+ BOOLEAN ZeroDebugFlag;
+
+ SetUtilityName (UTILITY_NAME);
+
+ //
+ // Assign to fix compile warning
+ //
+ FileLen = 0;
+ InputFileNum = 0;
+ InputFileName = NULL;
+ mInImageName = NULL;
+ OutImageName = NULL;
+ ModuleType = NULL;
+ Type = 0;
+ Status = STATUS_SUCCESS;
+ FileBuffer = NULL;
+ fpIn = NULL;
+ fpOut = NULL;
+ fpInOut = NULL;
+ TimeStamp = NULL;
+ MciAlignment = DEFAULT_MC_ALIGNMENT;
+ MciPadValue = DEFAULT_MC_PAD_BYTE_VALUE;
+ FileLength = 0;
+ MciHeader = NULL;
+ CheckSum = 0;
+ ReplaceFlag = FALSE;
+ LogLevel = 0;
+ OutputFileBuffer = NULL;
+ OutputFileLength = 0;
+ InputFileBuffer = NULL;
+ InputFileLength = 0;
+ Optional32 = NULL;
+ Optional64 = NULL;
+ KeepExceptionTableFlag = FALSE;
+ KeepOptionalHeaderFlag = FALSE;
+ KeepZeroPendingFlag = FALSE;
+ NumberOfFormPackage = 0;
+ HiiPackageListBuffer = NULL;
+ HiiPackageDataPointer = NULL;
+ EndPackage.Length = sizeof (EFI_HII_PACKAGE_HEADER);
+ EndPackage.Type = EFI_HII_PACKAGE_END;
+ memset (&HiiPackageListGuid, 0, sizeof (HiiPackageListGuid));
+ HiiSectionHeaderSize = 0;
+ HiiSectionHeader = NULL;
+ NewBaseAddress = 0;
+ NegativeAddr = FALSE;
+ InputFileTime = 0;
+ OutputFileTime = 0;
+ ZeroDebugFlag = FALSE;
+
+ if (argc == 1) {
+ Error (NULL, 0, 1001, "Missing options", "No input options.");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ argc --;
+ argv ++;
+
+ if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
+ Version ();
+ Usage ();
+ return STATUS_SUCCESS;
+ }
+
+ if (stricmp (argv[0], "--version") == 0) {
+ Version ();
+ return STATUS_SUCCESS;
+ }
+
+ while (argc > 0) {
+ if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {
+ if (argv[1] == NULL || argv[1][0] == '-') {
+ Error (NULL, 0, 1003, "Invalid option value", "Output file name is missing for -o option");
+ goto Finish;
+ }
+ OutImageName = argv[1];
+ argc -= 2;
+ argv += 2;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-e") == 0) || (stricmp (argv[0], "--efiImage") == 0)) {
+ if (argv[1] == NULL || argv[1][0] == '-') {
+ Error (NULL, 0, 1003, "Invalid option value", "Module Type is missing for -o option");
+ goto Finish;
+ }
+ ModuleType = argv[1];
+ if (mOutImageType == FW_ZERO_DEBUG_IMAGE) {
+ ZeroDebugFlag = TRUE;
+ }
+ if (mOutImageType != FW_TE_IMAGE) {
+ mOutImageType = FW_EFI_IMAGE;
+ }
+ argc -= 2;
+ argv += 2;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--stripped") == 0)) {
+ mOutImageType = FW_RELOC_STRIPEED_IMAGE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--acpi") == 0)) {
+ mOutImageType = FW_ACPI_IMAGE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--terse") == 0)) {
+ if (mOutImageType == FW_ZERO_DEBUG_IMAGE) {
+ ZeroDebugFlag = TRUE;
+ }
+ mOutImageType = FW_TE_IMAGE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-u") == 0) || (stricmp (argv[0], "--dump") == 0)) {
+ mOutImageType = DUMP_TE_HEADER;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--exe2bin") == 0)) {
+ mOutImageType = FW_BIN_IMAGE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-z") == 0) || (stricmp (argv[0], "--zero") == 0)) {
+ if (mOutImageType == FW_DUMMY_IMAGE) {
+ mOutImageType = FW_ZERO_DEBUG_IMAGE;
+ }
+ if (mOutImageType == FW_TE_IMAGE || mOutImageType == FW_EFI_IMAGE) {
+ ZeroDebugFlag = TRUE;
+ }
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--stamp") == 0)) {
+ mOutImageType = FW_SET_STAMP_IMAGE;
+ if (argv[1] == NULL || argv[1][0] == '-') {
+ Error (NULL, 0, 1003, "Invalid option value", "time stamp is missing for -s option");
+ goto Finish;
+ }
+ TimeStamp = argv[1];
+ argc -= 2;
+ argv += 2;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--replace") == 0)) {
+ ReplaceFlag = TRUE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if (stricmp (argv[0], "--keepexceptiontable") == 0) {
+ KeepExceptionTableFlag = TRUE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if (stricmp(argv[0], "--keepoptionalheader") == 0) {
+ KeepOptionalHeaderFlag = TRUE;
+ argc--;
+ argv++;
+ continue;
+ }
+
+ if (stricmp (argv[0], "--keepzeropending") == 0) {
+ KeepZeroPendingFlag = TRUE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--mcifile") == 0)) {
+ mOutImageType = FW_MCI_IMAGE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--join") == 0)) {
+ mOutImageType = FW_MERGE_IMAGE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--align") == 0)) {
+ if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {
+ Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
+ goto Finish;
+ }
+ MciAlignment = (UINT32) Temp64;
+ argc -= 2;
+ argv += 2;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "--rebase") == 0)) {
+ if (argv[1][0] == '-') {
+ NegativeAddr = TRUE;
+ Status = AsciiStringToUint64 (argv[1] + 1, FALSE, &Temp64);
+ } else {
+ NegativeAddr = FALSE;
+ Status = AsciiStringToUint64 (argv[1], FALSE, &Temp64);
+ }
+ if (Status != EFI_SUCCESS) {
+ Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
+ goto Finish;
+ }
+ mOutImageType = FW_REBASE_IMAGE;
+ NewBaseAddress = (UINT64) Temp64;
+ argc -= 2;
+ argv += 2;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "--address") == 0)) {
+ if (argv[1][0] == '-') {
+ NegativeAddr = TRUE;
+ Status = AsciiStringToUint64 (argv[1] + 1, FALSE, &Temp64);
+ } else {
+ NegativeAddr = FALSE;
+ Status = AsciiStringToUint64 (argv[1], FALSE, &Temp64);
+ }
+ if (Status != EFI_SUCCESS) {
+ Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
+ goto Finish;
+ }
+ mOutImageType = FW_SET_ADDRESS_IMAGE;
+ NewBaseAddress = (UINT64) Temp64;
+ argc -= 2;
+ argv += 2;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--pad") == 0)) {
+ if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {
+ Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
+ goto Finish;
+ }
+ MciPadValue = (UINT8) Temp64;
+ argc -= 2;
+ argv += 2;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
+ SetPrintLevel (VERBOSE_LOG_LEVEL);
+ VerboseMsg ("Verbose output Mode Set!");
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
+ SetPrintLevel (KEY_LOG_LEVEL);
+ KeyMsg ("Quiet output Mode Set!");
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
+ Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
+ goto Finish;
+ }
+ if (LogLevel > 9) {
+ Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel);
+ goto Finish;
+ }
+ SetPrintLevel (LogLevel);
+ DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
+ argc -= 2;
+ argv += 2;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--hiiguid") == 0)) {
+ Status = StringToGuid (argv[1], &HiiPackageListGuid);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
+ goto Finish;
+ }
+ argc -= 2;
+ argv += 2;
+ continue;
+ }
+
+ if (stricmp (argv[0], "--hiipackage") == 0) {
+ mOutImageType = FW_HII_PACKAGE_LIST_RCIMAGE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if (stricmp (argv[0], "--hiibinpackage") == 0) {
+ mOutImageType = FW_HII_PACKAGE_LIST_BINIMAGE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if (argv[0][0] == '-') {
+ Error (NULL, 0, 1000, "Unknown option", argv[0]);
+ goto Finish;
+ }
+ //
+ // Get Input file name
+ //
+ if ((InputFileNum == 0) && (InputFileName == NULL)) {
+ InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));
+ if (InputFileName == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+ goto Finish;
+ }
+
+ memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
+ } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {
+ //
+ // InputFileName buffer too small, need to realloc
+ //
+ InputFileName = (CHAR8 **) realloc (
+ InputFileName,
+ (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)
+ );
+
+ if (InputFileName == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+ goto Finish;
+ }
+
+ memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
+ }
+
+ InputFileName [InputFileNum ++] = argv[0];
+ argc --;
+ argv ++;
+ }
+
+ VerboseMsg ("%s tool start.", UTILITY_NAME);
+
+ if (mOutImageType == FW_DUMMY_IMAGE) {
+ 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!");
+ if (ReplaceFlag) {
+ 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.");
+ }
+ goto Finish;
+ }
+
+ //
+ // check input files
+ //
+ if (InputFileNum == 0) {
+ Error (NULL, 0, 1001, "Missing option", "Input files");
+ goto Finish;
+ }
+
+ //
+ // Combine MciBinary files to one file
+ //
+ if ((mOutImageType == FW_MERGE_IMAGE) && ReplaceFlag) {
+ Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");
+ goto Finish;
+ }
+
+ //
+ // Combine HiiBinary packages to a single package list
+ //
+ if ((mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) && ReplaceFlag) {
+ Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option.");
+ goto Finish;
+ }
+
+ if ((mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) && ReplaceFlag) {
+ Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiibinpackage merge files option.");
+ goto Finish;
+ }
+
+ //
+ // Input image file
+ //
+ mInImageName = InputFileName [InputFileNum - 1];
+ VerboseMsg ("the input file name is %s", mInImageName);
+
+ //
+ // Action will be taken for the input file.
+ //
+ switch (mOutImageType) {
+ case FW_EFI_IMAGE:
+ VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType);
+ break;
+ case FW_TE_IMAGE:
+ VerboseMsg ("Create Te Image based on the input PE image.");
+ break;
+ case FW_ACPI_IMAGE:
+ VerboseMsg ("Get acpi table data from the input PE image.");
+ break;
+ case FW_RELOC_STRIPEED_IMAGE:
+ VerboseMsg ("Remove relocation section from Pe or Te image.");
+ break;
+ case FW_BIN_IMAGE:
+ VerboseMsg ("Convert the input EXE to the output BIN file.");
+ break;
+ case FW_ZERO_DEBUG_IMAGE:
+ VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");
+ break;
+ case FW_SET_STAMP_IMAGE:
+ VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp);
+ break;
+ case DUMP_TE_HEADER:
+ VerboseMsg ("Dump the TE header information of the input TE image.");
+ break;
+ case FW_MCI_IMAGE:
+ VerboseMsg ("Convert input MicroCode.txt file to MicroCode.bin file.");
+ break;
+ case FW_MERGE_IMAGE:
+ VerboseMsg ("Combine the input multi microcode bin files to one bin file.");
+ break;
+ case FW_HII_PACKAGE_LIST_RCIMAGE:
+ VerboseMsg ("Combine the input multi hii bin packages to one text package list RC file.");
+ break;
+ case FW_HII_PACKAGE_LIST_BINIMAGE:
+ VerboseMsg ("Combine the input multi hii bin packages to one binary package list file.");
+ break;
+ case FW_REBASE_IMAGE:
+ VerboseMsg ("Rebase the input image to new base address.");
+ break;
+ case FW_SET_ADDRESS_IMAGE:
+ VerboseMsg ("Set the preferred address into the section header of the input image");
+ break;
+ default:
+ break;
+ }
+
+ if (ReplaceFlag) {
+ VerboseMsg ("Overwrite the input file with the output content.");
+ }
+
+ //
+ // Open output file and Write image into the output file.
+ //
+ if (OutImageName != NULL) {
+ fpOut = fopen (LongFilePath (OutImageName), "rb");
+ if (fpOut != NULL) {
+ //
+ // Get Output file time stamp
+ //
+ fstat(fileno (fpOut), &Stat_Buf);
+ OutputFileTime = Stat_Buf.st_mtime;
+ //
+ // Get Output file data
+ //
+ OutputFileLength = _filelength (fileno (fpOut));
+ OutputFileBuffer = malloc (OutputFileLength);
+ if (OutputFileBuffer == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+ fclose (fpOut);
+ fpOut = NULL;
+ goto Finish;
+ }
+ fread (OutputFileBuffer, 1, OutputFileLength, fpOut);
+ fclose (fpOut);
+ fpOut = NULL;
+ }
+ VerboseMsg ("Output file name is %s", OutImageName);
+ } else if (!ReplaceFlag && mOutImageType != DUMP_TE_HEADER) {
+ Error (NULL, 0, 1001, "Missing option", "output file");
+ goto Finish;
+ }
+
+ //
+ // Open input file and read file data into file buffer.
+ //
+ fpIn = fopen (LongFilePath (mInImageName), "rb");
+ if (fpIn == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", mInImageName);
+ goto Finish;
+ }
+ //
+ // Get Iutput file time stamp
+ //
+ fstat(fileno (fpIn), &Stat_Buf);
+ InputFileTime = Stat_Buf.st_mtime;
+ //
+ // Get Input file data
+ //
+ InputFileLength = _filelength (fileno (fpIn));
+ InputFileBuffer = malloc (InputFileLength);
+ if (InputFileBuffer == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+ fclose (fpIn);
+ goto Finish;
+ }
+ fread (InputFileBuffer, 1, InputFileLength, fpIn);
+ fclose (fpIn);
+ DebugMsg (NULL, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) InputFileLength);
+
+ //
+ // Combine multi binary HII package files.
+ //
+ if (mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE || mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) {
+ //
+ // Open output file handle.
+ //
+ fpOut = fopen (LongFilePath (OutImageName), "wb");
+ if (!fpOut) {
+ Error (NULL, 0, 0001, "Error opening output file", OutImageName);
+ goto Finish;
+ }
+ //
+ // Get hii package list length
+ //
+ HiiPackageListHeader.PackageLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+ for (Index = 0; Index < InputFileNum; Index ++) {
+ fpIn = fopen (LongFilePath (InputFileName [Index]), "rb");
+ if (fpIn == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);
+ goto Finish;
+ }
+ FileLength = _filelength (fileno (fpIn));
+ fread (&HiiPackageHeader, 1, sizeof (HiiPackageHeader), fpIn);
+ if (HiiPackageHeader.Type == EFI_HII_PACKAGE_FORM) {
+ if (HiiPackageHeader.Length != FileLength) {
+ Error (NULL, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName [Index]);
+ fclose (fpIn);
+ goto Finish;
+ }
+ if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) {
+ fread (&IfrFormSet, 1, sizeof (IfrFormSet), fpIn);
+ memcpy (&HiiPackageListGuid, &IfrFormSet.Guid, sizeof (EFI_GUID));
+ }
+ NumberOfFormPackage ++;
+ }
+ HiiPackageListHeader.PackageLength += FileLength;
+ fclose (fpIn);
+ }
+ HiiPackageListHeader.PackageLength += sizeof (EndPackage);
+ //
+ // Check whether hii packages are valid
+ //
+ if (NumberOfFormPackage > 1) {
+ Error (NULL, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package");
+ goto Finish;
+ }
+ if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) {
+ Error (NULL, 0, 3000, "Invalid", "HII package list guid is not specified!");
+ goto Finish;
+ }
+ memcpy (&HiiPackageListHeader.PackageListGuid, &HiiPackageListGuid, sizeof (EFI_GUID));
+ //
+ // read hii packages
+ //
+ HiiPackageListBuffer = malloc (HiiPackageListHeader.PackageLength);
+ if (HiiPackageListBuffer == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+ goto Finish;
+ }
+ memcpy (HiiPackageListBuffer, &HiiPackageListHeader, sizeof (HiiPackageListHeader));
+ HiiPackageDataPointer = HiiPackageListBuffer + sizeof (HiiPackageListHeader);
+ for (Index = 0; Index < InputFileNum; Index ++) {
+ fpIn = fopen (LongFilePath (InputFileName [Index]), "rb");
+ if (fpIn == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);
+ free (HiiPackageListBuffer);
+ goto Finish;
+ }
+
+ FileLength = _filelength (fileno (fpIn));
+ fread (HiiPackageDataPointer, 1, FileLength, fpIn);
+ fclose (fpIn);
+ HiiPackageDataPointer = HiiPackageDataPointer + FileLength;
+ }
+ memcpy (HiiPackageDataPointer, &EndPackage, sizeof (EndPackage));
+
+ //
+ // write the hii package into the binary package list file with the resource section header
+ //
+ if (mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) {
+ //
+ // Create the resource section header
+ //
+ HiiSectionHeader = CreateHiiResouceSectionHeader (&HiiSectionHeaderSize, HiiPackageListHeader.PackageLength);
+ if (HiiSectionHeader == NULL) {
+ free (HiiPackageListBuffer);
+ goto Finish;
+ }
+ //
+ // Wrtie section header and HiiData into File.
+ //
+ fwrite (HiiSectionHeader, 1, HiiSectionHeaderSize, fpOut);
+ fwrite (HiiPackageListBuffer, 1, HiiPackageListHeader.PackageLength, fpOut);
+ //
+ // Free allocated resources.
+ //
+ free (HiiSectionHeader);
+ free (HiiPackageListBuffer);
+ //
+ // Done successfully
+ //
+ goto Finish;
+ }
+
+ //
+ // write the hii package into the text package list rc file.
+ //
+ if (mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) {
+ for (Index = 0; gHiiPackageRCFileHeader[Index] != NULL; Index++) {
+ fprintf (fpOut, "%s\n", gHiiPackageRCFileHeader[Index]);
+ }
+ fprintf (fpOut, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX, HII_RESOURCE_SECTION_NAME);
+
+ HiiPackageDataPointer = HiiPackageListBuffer;
+ for (Index = 0; Index + 2 < HiiPackageListHeader.PackageLength; Index += 2) {
+ if (Index % 16 == 0) {
+ fprintf (fpOut, "\n ");
+ }
+ fprintf (fpOut, " 0x%04X,", *(UINT16 *) HiiPackageDataPointer);
+ HiiPackageDataPointer += 2;
+ }
+
+ if (Index % 16 == 0) {
+ fprintf (fpOut, "\n ");
+ }
+ if ((Index + 2) == HiiPackageListHeader.PackageLength) {
+ fprintf (fpOut, " 0x%04X\n}\n", *(UINT16 *) HiiPackageDataPointer);
+ }
+ if ((Index + 1) == HiiPackageListHeader.PackageLength) {
+ fprintf (fpOut, " 0x%04X\n}\n", *(UINT8 *) HiiPackageDataPointer);
+ }
+ free (HiiPackageListBuffer);
+ //
+ // Done successfully
+ //
+ goto Finish;
+ }
+ }
+
+ //
+ // Combine MciBinary files to one file
+ //
+ if (mOutImageType == FW_MERGE_IMAGE) {
+ //
+ // Open output file handle.
+ //
+ fpOut = fopen (LongFilePath (OutImageName), "wb");
+ if (!fpOut) {
+ Error (NULL, 0, 0001, "Error opening output file", OutImageName);
+ goto Finish;
+ }
+ for (Index = 0; Index < InputFileNum; Index ++) {
+ fpIn = fopen (LongFilePath (InputFileName [Index]), "rb");
+ if (!fpIn) {
+ Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);
+ goto Finish;
+ }
+
+ FileLength = _filelength (fileno (fpIn));
+ FileBuffer = malloc (FileLength);
+ if (FileBuffer == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+ fclose (fpIn);
+ goto Finish;
+ }
+
+ fread (FileBuffer, 1, FileLength, fpIn);
+ fclose (fpIn);
+ //
+ // write input file to out file
+ //
+ fwrite (FileBuffer, 1, FileLength, fpOut);
+ //
+ // write pad value to out file.
+ //
+ while (FileLength ++ % MciAlignment != 0) {
+ fwrite (&MciPadValue, 1, 1, fpOut);
+ }
+ //
+ // free allocated memory space
+ //
+ free (FileBuffer);
+ FileBuffer = NULL;
+ }
+ //
+ // Done successfully
+ //
+ goto Finish;
+ }
+
+ //
+ // Convert MicroCode.txt file to MicroCode.bin file
+ //
+ if (mOutImageType == FW_MCI_IMAGE) {
+ fpIn = fopen (LongFilePath (mInImageName), "r");
+ if (fpIn == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", mInImageName);
+ goto Finish;
+ }
+
+ //
+ // The first pass is to determine
+ // how much data is in the file so we can allocate a working buffer.
+ //
+ FileLength = 0;
+ do {
+ Status = MicrocodeReadData (fpIn, &Data);
+ if (Status == STATUS_SUCCESS) {
+ FileLength += sizeof (Data);
+ }
+ if (Status == STATUS_IGNORE) {
+ Status = STATUS_SUCCESS;
+ }
+ } while (Status == STATUS_SUCCESS);
+ //
+ // Error if no data.
+ //
+ if (FileLength == 0) {
+ Error (NULL, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName);
+ goto Finish;
+ }
+ if (FileLength < sizeof (MICROCODE_IMAGE_HEADER)) {
+ Error (NULL, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName);
+ goto Finish;
+ }
+
+ //
+ // Allocate a buffer for the data
+ //
+ FileBuffer = malloc (FileLength);
+ if (FileBuffer == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+ goto Finish;
+ }
+ //
+ // Re-read the file, storing the data into our buffer
+ //
+ fseek (fpIn, 0, SEEK_SET);
+ DataPointer = (UINT32 *) FileBuffer;
+ OldDataPointer = DataPointer;
+ do {
+ OldDataPointer = DataPointer;
+ Status = MicrocodeReadData (fpIn, DataPointer++);
+ if (Status == STATUS_IGNORE) {
+ DataPointer = OldDataPointer;
+ Status = STATUS_SUCCESS;
+ }
+ } while (Status == STATUS_SUCCESS);
+ //
+ // close input file after read data
+ //
+ fclose (fpIn);
+
+ //
+ // Can't do much checking on the header because, per the spec, the
+ // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
+ // and the TotalSize field is invalid (actually missing). Thus we can't
+ // even verify the Reserved fields are 0.
+ //
+ MciHeader = (MICROCODE_IMAGE_HEADER *) FileBuffer;
+ if (MciHeader->DataSize == 0) {
+ Index = 2048;
+ } else {
+ Index = MciHeader->TotalSize;
+ }
+
+ if (Index != FileLength) {
+ Error (NULL, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName, (unsigned) FileLength, (unsigned) Index);
+ goto Finish;
+ }
+
+ //
+ // Checksum the contents
+ //
+ DataPointer = (UINT32 *) FileBuffer;
+ CheckSum = 0;
+ Index = 0;
+ while (Index < FileLength) {
+ CheckSum += *DataPointer;
+ DataPointer ++;
+ Index += sizeof (*DataPointer);
+ }
+ if (CheckSum != 0) {
+ Error (NULL, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum, mInImageName);
+ goto Finish;
+ }
+ //
+ // Open the output file and write the buffer contents
+ //
+ VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
+ goto WriteFile;
+ }
+
+ //
+ // Open input file and read file data into file buffer.
+ //
+ FileLength = InputFileLength;
+ FileBuffer = malloc (FileLength);
+ if (FileBuffer == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+ goto Finish;
+ }
+ memcpy (FileBuffer, InputFileBuffer, InputFileLength);
+
+ //
+ // Dump TeImage Header into output file.
+ //
+ if (mOutImageType == DUMP_TE_HEADER) {
+ memcpy (&TEImageHeader, FileBuffer, sizeof (TEImageHeader));
+ if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {
+ Error (NULL, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName);
+ goto Finish;
+ }
+ //
+ // Open the output file handle.
+ //
+ if (ReplaceFlag) {
+ fpInOut = fopen (LongFilePath (mInImageName), "wb");
+ if (fpInOut == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", mInImageName);
+ goto Finish;
+ }
+ } else {
+ if (OutImageName != NULL) {
+ fpOut = fopen (LongFilePath (OutImageName), "wb");
+ } else {
+ fpOut = stdout;
+ }
+ if (fpOut == NULL) {
+ Error (NULL, 0, 0001, "Error opening output file", OutImageName);
+ goto Finish;
+ }
+ }
+ if (fpInOut != NULL) {
+ fprintf (fpInOut, "Dump of file %s\n\n", mInImageName);
+ fprintf (fpInOut, "TE IMAGE HEADER VALUES\n");
+ fprintf (fpInOut, "%17X machine\n", TEImageHeader.Machine);
+ fprintf (fpInOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);
+ fprintf (fpInOut, "%17X subsystems\n", TEImageHeader.Subsystem);
+ fprintf (fpInOut, "%17X stripped size\n", TEImageHeader.StrippedSize);
+ fprintf (fpInOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint);
+ fprintf (fpInOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode);
+ fprintf (fpInOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase);
+ fprintf (fpInOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size);
+ fprintf (fpInOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size);
+ }
+ if (fpOut != NULL) {
+ fprintf (fpOut, "Dump of file %s\n\n", mInImageName);
+ fprintf (fpOut, "TE IMAGE HEADER VALUES\n");
+ fprintf (fpOut, "%17X machine\n", TEImageHeader.Machine);
+ fprintf (fpOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);
+ fprintf (fpOut, "%17X subsystems\n", TEImageHeader.Subsystem);
+ fprintf (fpOut, "%17X stripped size\n", TEImageHeader.StrippedSize);
+ fprintf (fpOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint);
+ fprintf (fpOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode);
+ fprintf (fpOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase);
+ fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size);
+ fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size);
+ }
+ goto Finish;
+ }
+
+ //
+ // Following code to convert dll to efi image or te image.
+ // Get new image type
+ //
+ if ((mOutImageType == FW_EFI_IMAGE) || (mOutImageType == FW_TE_IMAGE)) {
+ if (ModuleType == NULL) {
+ if (mOutImageType == FW_EFI_IMAGE) {
+ Error (NULL, 0, 1001, "Missing option", "EFI_FILETYPE");
+ goto Finish;
+ } else if (mOutImageType == FW_TE_IMAGE) {
+ //
+ // Default TE Image Type is Boot service driver
+ //
+ Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
+ VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
+ }
+ } else {
+ if (stricmp (ModuleType, "BASE") == 0 ||
+ stricmp (ModuleType, "SEC") == 0 ||
+ stricmp (ModuleType, "SECURITY_CORE") == 0 ||
+ stricmp (ModuleType, "PEI_CORE") == 0 ||
+ stricmp (ModuleType, "PEIM") == 0 ||
+ stricmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0 ||
+ stricmp (ModuleType, "PIC_PEIM") == 0 ||
+ stricmp (ModuleType, "RELOCATABLE_PEIM") == 0 ||
+ stricmp (ModuleType, "DXE_CORE") == 0 ||
+ stricmp (ModuleType, "BS_DRIVER") == 0 ||
+ stricmp (ModuleType, "DXE_DRIVER") == 0 ||
+ stricmp (ModuleType, "DXE_SMM_DRIVER") == 0 ||
+ stricmp (ModuleType, "UEFI_DRIVER") == 0 ||
+ stricmp (ModuleType, "SMM_CORE") == 0 ||
+ stricmp (ModuleType, "MM_STANDALONE") == 0 ||
+ stricmp (ModuleType, "MM_CORE_STANDALONE") == 0) {
+ Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
+ VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
+
+ } else if (stricmp (ModuleType, "UEFI_APPLICATION") == 0 ||
+ stricmp (ModuleType, "APPLICATION") == 0) {
+ Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;
+ VerboseMsg ("Efi Image subsystem type is efi application.");
+
+ } else if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0 ||
+ stricmp (ModuleType, "RT_DRIVER") == 0) {
+ Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;
+ VerboseMsg ("Efi Image subsystem type is efi runtime driver.");
+
+ } else if (stricmp (ModuleType, "DXE_SAL_DRIVER") == 0 ||
+ stricmp (ModuleType, "SAL_RT_DRIVER") == 0) {
+ Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;
+ VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");
+
+ } else {
+ Error (NULL, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType);
+ goto Finish;
+ }
+ }
+ }
+
+ //
+ // Convert ELF image to PeImage
+ //
+ if (IsElfHeader(FileBuffer)) {
+ VerboseMsg ("Convert %s from ELF to PE/COFF.", mInImageName);
+ if (!ConvertElf(&FileBuffer, &FileLength)) {
+ Error (NULL, 0, 3000, "Invalid", "Unable to convert %s from ELF to PE/COFF.", mInImageName);
+ goto Finish;
+ }
+ }
+
+ //
+ // Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP
+ // XIP == eXecute In Place
+ //
+ PeCoffConvertImageToXip (&FileBuffer, &FileLength);
+
+ //
+ // Remove reloc section from PE or TE image
+ //
+ if (mOutImageType == FW_RELOC_STRIPEED_IMAGE) {
+ //
+ // Check TeImage
+ //
+ TeHdr = (EFI_TE_IMAGE_HEADER *) FileBuffer;
+ if (TeHdr->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TeHdr + 1);
+ for (Index = 0; Index < TeHdr->NumberOfSections; Index ++, SectionHeader ++) {
+ if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) {
+ //
+ // Check the reloc section is in the end of image.
+ //
+ if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) ==
+ (FileLength + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER))) {
+ //
+ // Remove .reloc section and update TeImage Header
+ //
+ FileLength = FileLength - SectionHeader->SizeOfRawData;
+ SectionHeader->SizeOfRawData = 0;
+ SectionHeader->Misc.VirtualSize = 0;
+ TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
+ TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
+ break;
+ }
+ }
+ }
+ } else {
+ //
+ // Check PE Image
+ //
+ DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;
+ if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer);
+ if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
+ Error (NULL, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName);
+ goto Finish;
+ }
+ DosHdr = NULL;
+ } else {
+ PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew);
+ if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
+ Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);
+ goto Finish;
+ }
+ }
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
+ for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
+ if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) {
+ //
+ // Check the reloc section is in the end of image.
+ //
+ if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == FileLength) {
+ //
+ // Remove .reloc section and update PeImage Header
+ //
+ FileLength = FileLength - SectionHeader->SizeOfRawData;
+
+ PeHdr->Pe32.FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED;
+ if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;
+ Optional32->SizeOfImage -= SectionHeader->SizeOfRawData;
+ Optional32->SizeOfInitializedData -= SectionHeader->SizeOfRawData;
+ if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
+ Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
+ }
+ }
+ if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
+ Optional64->SizeOfImage -= SectionHeader->SizeOfRawData;
+ Optional64->SizeOfInitializedData -= SectionHeader->SizeOfRawData;
+ if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
+ Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
+ }
+ }
+ SectionHeader->Misc.VirtualSize = 0;
+ SectionHeader->SizeOfRawData = 0;
+ break;
+ }
+ }
+ }
+ }
+ //
+ // Write file
+ //
+ goto WriteFile;
+ }
+ //
+ // Read the dos & pe hdrs of the image
+ //
+ DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
+ if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ // NO DOS header, check for PE/COFF header
+ PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer);
+ if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
+ Error (NULL, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName);
+ goto Finish;
+ }
+ DosHdr = NULL;
+ } else {
+
+ PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew);
+ if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
+ Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);
+ goto Finish;
+ }
+ }
+
+ if (PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM) {
+ // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
+ // so patch back to the official UEFI value.
+ PeHdr->Pe32.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMT;
+ }
+
+ //
+ // Set new base address into image
+ //
+ if (mOutImageType == FW_REBASE_IMAGE || mOutImageType == FW_SET_ADDRESS_IMAGE) {
+ if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ if (NewBaseAddress >= 0x100000000ULL) {
+ Error (NULL, 0, 3000, "Invalid", "New base address is larger than 4G for 32bit PE image");
+ goto Finish;
+ }
+ }
+
+ if (NegativeAddr) {
+ //
+ // Set Base Address to a negative value.
+ //
+ NewBaseAddress = (UINT64) (0 - NewBaseAddress);
+ }
+ if (mOutImageType == FW_REBASE_IMAGE) {
+ Status = RebaseImage (mInImageName, FileBuffer, NewBaseAddress);
+ } else {
+ Status = SetAddressToSectionHeader (mInImageName, FileBuffer, NewBaseAddress);
+ }
+ if (EFI_ERROR (Status)) {
+ if (NegativeAddr) {
+ Error (NULL, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address -0x%llx can't success", mInImageName, 0 - NewBaseAddress);
+ } else {
+ Error (NULL, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address 0x%llx can't success", mInImageName, NewBaseAddress);
+ }
+ goto Finish;
+ }
+
+ //
+ // Write file
+ //
+ goto WriteFile;
+ }
+
+ //
+ // Extract bin data from Pe image.
+ //
+ if (mOutImageType == FW_BIN_IMAGE) {
+ if (FileLength < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) {
+ Error (NULL, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName);
+ goto Finish;
+ }
+ //
+ // Output bin data from exe file
+ //
+ FileLength = FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders;
+ memmove (FileBuffer, FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, FileLength);
+ VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
+ goto WriteFile;
+ }
+
+ //
+ // Zero Debug Information of Pe Image
+ //
+ if (mOutImageType == FW_ZERO_DEBUG_IMAGE) {
+ Status = ZeroDebugData (FileBuffer, TRUE);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status);
+ goto Finish;
+ }
+
+ //
+ // Write the updated Image
+ //
+ VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
+ goto WriteFile;
+ }
+
+ //
+ // Set Time Stamp of Pe Image
+ //
+ if (mOutImageType == FW_SET_STAMP_IMAGE) {
+ Status = SetStamp (FileBuffer, TimeStamp);
+ if (EFI_ERROR (Status)) {
+ goto Finish;
+ }
+
+ //
+ // Write the updated Image
+ //
+ VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
+ goto WriteFile;
+ }
+
+ //
+ // Extract acpi data from pe image.
+ //
+ if (mOutImageType == FW_ACPI_IMAGE) {
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
+ for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
+ if (strcmp ((char *)SectionHeader->Name, ".data") == 0 || strcmp ((char *)SectionHeader->Name, ".sdata") == 0) {
+ //
+ // Check Acpi Table
+ //
+ if (SectionHeader->Misc.VirtualSize < SectionHeader->SizeOfRawData) {
+ FileLength = SectionHeader->Misc.VirtualSize;
+ } else {
+ FileLength = SectionHeader->SizeOfRawData;
+ }
+
+ if (CheckAcpiTable (FileBuffer + SectionHeader->PointerToRawData, FileLength) != STATUS_SUCCESS) {
+ Error (NULL, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName);
+ goto Finish;
+ }
+
+ //
+ // Output Apci data to file
+ //
+ memmove (FileBuffer, FileBuffer + SectionHeader->PointerToRawData, FileLength);
+ VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
+ goto WriteFile;
+ }
+ }
+ Error (NULL, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName);
+ goto Finish;
+ }
+ //
+ // Zero all unused fields of the DOS header
+ //
+ if (DosHdr != NULL) {
+ memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));
+ memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));
+ DosHdr->e_magic = BackupDosHdr.e_magic;
+ DosHdr->e_lfanew = BackupDosHdr.e_lfanew;
+
+ for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (UINT32 ) DosHdr->e_lfanew; Index++) {
+ FileBuffer[Index] = (UINT8) DosHdr->e_cp;
+ }
+ }
+
+ //
+ // Initialize TeImage Header
+ //
+ memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));
+ TEImageHeader.Signature = EFI_TE_IMAGE_HEADER_SIGNATURE;
+ TEImageHeader.Machine = PeHdr->Pe32.FileHeader.Machine;
+ TEImageHeader.NumberOfSections = (UINT8) PeHdr->Pe32.FileHeader.NumberOfSections;
+ TEImageHeader.StrippedSize = (UINT16) ((UINTN) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader) - (UINTN) FileBuffer);
+ TEImageHeader.Subsystem = (UINT8) Type;
+
+ //
+ // Patch the PE header
+ //
+ PeHdr->Pe32.OptionalHeader.Subsystem = (UINT16) Type;
+
+ if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;
+ if (!KeepOptionalHeaderFlag) {
+ Optional32->MajorOperatingSystemVersion = 0;
+ Optional32->MinorOperatingSystemVersion = 0;
+ Optional32->MajorImageVersion = 0;
+ Optional32->MinorImageVersion = 0;
+ Optional32->MajorSubsystemVersion = 0;
+ Optional32->MinorSubsystemVersion = 0;
+ Optional32->Win32VersionValue = 0;
+ Optional32->CheckSum = 0;
+ Optional32->SizeOfStackReserve = 0;
+ Optional32->SizeOfStackCommit = 0;
+ Optional32->SizeOfHeapReserve = 0;
+ Optional32->SizeOfHeapCommit = 0;
+ }
+ TEImageHeader.AddressOfEntryPoint = Optional32->AddressOfEntryPoint;
+ TEImageHeader.BaseOfCode = Optional32->BaseOfCode;
+ TEImageHeader.ImageBase = (UINT64) (Optional32->ImageBase);
+
+ if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
+ }
+
+ if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+ }
+
+ //
+ // Zero .pdata section data.
+ //
+ if (!KeepExceptionTableFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&
+ Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&
+ Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
+ for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
+ if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {
+ //
+ // Zero .pdata Section data
+ //
+ memset (FileBuffer + SectionHeader->PointerToRawData, 0, SectionHeader->SizeOfRawData);
+ //
+ // Zero .pdata Section header name
+ //
+ memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));
+ //
+ // Zero Exception Table
+ //
+ Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;
+ Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;
+ DebugMsg (NULL, 0, 9, "Zero the .pdata section for PE image", NULL);
+ break;
+ }
+ }
+ }
+
+ //
+ // Strip zero padding at the end of the .reloc section
+ //
+ if (!KeepZeroPendingFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ if (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
+ for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
+ //
+ // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
+ //
+ if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {
+ SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
+ AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));
+ //
+ // Check to see if there is zero padding at the end of the base relocations
+ //
+ if (AllignedRelocSize < SectionHeader->SizeOfRawData) {
+ //
+ // Check to see if the base relocations are at the end of the file
+ //
+ if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {
+ //
+ // All the required conditions are met to strip the zero padding of the end of the base relocations section
+ //
+ Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
+ Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
+ SectionHeader->SizeOfRawData = AllignedRelocSize;
+ FileLength = Optional32->SizeOfImage;
+ 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));
+ }
+ }
+ }
+ }
+ }
+ }
+ } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
+ if (!KeepOptionalHeaderFlag) {
+ Optional64->MajorOperatingSystemVersion = 0;
+ Optional64->MinorOperatingSystemVersion = 0;
+ Optional64->MajorImageVersion = 0;
+ Optional64->MinorImageVersion = 0;
+ Optional64->MajorSubsystemVersion = 0;
+ Optional64->MinorSubsystemVersion = 0;
+ Optional64->Win32VersionValue = 0;
+ Optional64->CheckSum = 0;
+ Optional64->SizeOfStackReserve = 0;
+ Optional64->SizeOfStackCommit = 0;
+ Optional64->SizeOfHeapReserve = 0;
+ Optional64->SizeOfHeapCommit = 0;
+ }
+ TEImageHeader.AddressOfEntryPoint = Optional64->AddressOfEntryPoint;
+ TEImageHeader.BaseOfCode = Optional64->BaseOfCode;
+ TEImageHeader.ImageBase = (UINT64) (Optional64->ImageBase);
+
+ if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
+ }
+
+ if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+ }
+
+ //
+ // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
+ // For Itaninum and X64 Image, remove .pdata section.
+ //
+ if ((!KeepExceptionTableFlag && PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_X64)) {
+ if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&
+ Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&
+ Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
+ for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
+ if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {
+ //
+ // Zero .pdata Section header name
+ //
+ memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));
+
+ RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);
+ for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
+ for (Index2 = 0; Index2 < PeHdr->Pe32.FileHeader.NumberOfSections; Index2++, SectionHeader++) {
+ if (RuntimeFunction->UnwindInfoAddress >= SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {
+ UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));
+ if (UnwindInfo->Version == 1) {
+ memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));
+ memset (UnwindInfo, 0, sizeof (UNWIND_INFO));
+ }
+ break;
+ }
+ }
+ memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));
+ }
+ //
+ // Zero Exception Table
+ //
+ Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;
+ Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;
+ DebugMsg (NULL, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL);
+ break;
+ }
+ }
+ }
+ }
+
+ //
+ // Strip zero padding at the end of the .reloc section
+ //
+ if (!KeepZeroPendingFlag && Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
+ if (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
+ for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
+ //
+ // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
+ //
+ if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {
+ SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
+ AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));
+ //
+ // Check to see if there is zero padding at the end of the base relocations
+ //
+ if (AllignedRelocSize < SectionHeader->SizeOfRawData) {
+ //
+ // Check to see if the base relocations are at the end of the file
+ //
+ if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {
+ //
+ // All the required conditions are met to strip the zero padding of the end of the base relocations section
+ //
+ Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
+ Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
+ SectionHeader->SizeOfRawData = AllignedRelocSize;
+ FileLength = Optional64->SizeOfImage;
+ 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));
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ Error (NULL, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr->Pe32.OptionalHeader.Magic, mInImageName);
+ goto Finish;
+ }
+
+ if (((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) == 0) && \
+ (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == 0) && \
+ (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size == 0)) {
+ //
+ // PeImage can be loaded into memory, but it has no relocation section.
+ // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
+ //
+ if (Optional32 != NULL) {
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);
+ } else if (Optional64 != NULL) {
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);
+ }
+ }
+
+ //
+ // Fill HII section data
+ //
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
+ for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) {
+ if (stricmp ((char *)SectionHeader[Index].Name, ".hii") == 0) {
+ //
+ // Update resource section header offset
+ //
+ SetHiiResourceHeader ((UINT8*) FileBuffer + SectionHeader[Index].PointerToRawData, SectionHeader[Index].VirtualAddress);
+ //
+ // Update resource section name
+ //
+ strcpy((char *) SectionHeader[Index].Name, ".rsrc");
+ //
+ // Update resource data directory.
+ //
+ if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;
+ Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress;
+ Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize;
+ } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
+ Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress;
+ Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize;
+ }
+ break;
+ }
+ }
+
+ //
+ // Zero ExceptionTable Xdata
+ //
+ if (!KeepExceptionTableFlag) {
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
+ for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) {
+ if (stricmp ((char *)SectionHeader[Index].Name, ".xdata") == 0) {
+ //
+ // zero .xdata section
+ //
+ memset (FileBuffer + SectionHeader[Index].PointerToRawData, 0, SectionHeader[Index].SizeOfRawData);
+ 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);
+ break;
+ }
+ }
+ }
+
+ //
+ // Zero Time/Data field
+ //
+ ZeroDebugData (FileBuffer, ZeroDebugFlag);
+
+ if (mOutImageType == FW_TE_IMAGE) {
+ if ((PeHdr->Pe32.FileHeader.NumberOfSections &~0xFF) || (Type &~0xFF)) {
+ //
+ // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
+ //
+ Error (NULL, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName);
+ goto Finish;
+ }
+
+ if ((PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment)) {
+ //
+ // TeImage has the same section alignment and file alignment.
+ //
+ Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName);
+ goto Finish;
+ }
+
+ 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",
+ TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, (unsigned) TEImageHeader.AddressOfEntryPoint, (unsigned) TEImageHeader.BaseOfCode, (unsigned long long) TEImageHeader.ImageBase);
+ //
+ // Update Image to TeImage
+ //
+ FileLength = FileLength - TEImageHeader.StrippedSize;
+ memmove (FileBuffer + sizeof (EFI_TE_IMAGE_HEADER), FileBuffer + TEImageHeader.StrippedSize, FileLength);
+ FileLength = FileLength + sizeof (EFI_TE_IMAGE_HEADER);
+ memcpy (FileBuffer, &TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER));
+ VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength));
+ } else {
+
+ //
+ // Following codes are to fix the objcopy's issue:
+ // objcopy in binutil 2.50.18 will set PE image's charactices to "RELOC_STRIPPED" if image has no ".reloc" section
+ // It cause issue for EFI image which has no ".reloc" sections.
+ // Following codes will be removed when objcopy in binutil fix this problem for PE image.
+ //
+ if ((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0) {
+ if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;
+ if (Optional32->ImageBase == 0) {
+ PeHdr->Pe32.FileHeader.Characteristics &= ~EFI_IMAGE_FILE_RELOCS_STRIPPED;
+ }
+ } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
+ if (Optional64->ImageBase == 0) {
+ PeHdr->Pe32.FileHeader.Characteristics &= ~EFI_IMAGE_FILE_RELOCS_STRIPPED;
+ }
+ }
+ }
+ }
+
+WriteFile:
+ //
+ // Update Image to EfiImage or TE image
+ //
+ if (ReplaceFlag) {
+ if ((FileLength != InputFileLength) || (memcmp (FileBuffer, InputFileBuffer, FileLength) != 0)) {
+ //
+ // Update File when File is changed.
+ //
+ fpInOut = fopen (LongFilePath (mInImageName), "wb");
+ if (fpInOut == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", mInImageName);
+ goto Finish;
+ }
+ fwrite (FileBuffer, 1, FileLength, fpInOut);
+ VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
+ }
+ } else {
+ if ((OutputFileTime < InputFileTime) || (FileLength != OutputFileLength) || (memcmp (FileBuffer, OutputFileBuffer, FileLength) != 0)) {
+ //
+ // Update File when File is changed or File is old.
+ //
+ fpOut = fopen (LongFilePath (OutImageName), "wb");
+ if (fpOut == NULL) {
+ Error (NULL, 0, 0001, "Error opening output file", OutImageName);
+ goto Finish;
+ }
+ fwrite (FileBuffer, 1, FileLength, fpOut);
+ VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
+ }
+ }
+ mImageSize = FileLength;
+
+Finish:
+ if (fpInOut != NULL) {
+ if (GetUtilityStatus () != STATUS_SUCCESS) {
+ //
+ // when file updates failed, original file is still recovered.
+ //
+ fwrite (InputFileBuffer, 1, InputFileLength, fpInOut);
+ }
+ //
+ // Write converted data into fpInOut file and close input file.
+ //
+ fclose (fpInOut);
+ }
+
+ if (FileBuffer != NULL) {
+ free (FileBuffer);
+ }
+
+ if (InputFileName != NULL) {
+ free (InputFileName);
+ }
+
+ if (fpOut != NULL) {
+ //
+ // Write converted data into fpOut file and close output file.
+ //
+ fclose (fpOut);
+ if (GetUtilityStatus () != STATUS_SUCCESS) {
+ if (OutputFileBuffer == NULL) {
+ remove (OutImageName);
+ } else {
+ fpOut = fopen (LongFilePath (OutImageName), "wb");
+ fwrite (OutputFileBuffer, 1, OutputFileLength, fpOut);
+ fclose (fpOut);
+ }
+ }
+ }
+
+ if (InputFileBuffer != NULL) {
+ free (InputFileBuffer);
+ }
+
+ if (OutputFileBuffer != NULL) {
+ free (OutputFileBuffer);
+ }
+
+ //
+ // Write module size and time stamp to report file.
+ //
+ if (OutImageName != NULL) {
+ FileLen = strlen (OutImageName);
+ }
+ if (FileLen >= 4 && strcmp (OutImageName + (FileLen - 4), ".efi") == 0) {
+ ReportFileName = (CHAR8 *) malloc (FileLen + 1);
+ if (ReportFileName != NULL) {
+ strcpy (ReportFileName, OutImageName);
+ strcpy (ReportFileName + (FileLen - 4), ".txt");
+ ReportFile = fopen (LongFilePath (ReportFileName), "w+");
+ if (ReportFile != NULL) {
+ fprintf (ReportFile, "MODULE_SIZE = %u\n", (unsigned) mImageSize);
+ fprintf (ReportFile, "TIME_STAMP = %u\n", (unsigned) mImageTimeStamp);
+ fclose(ReportFile);
+ }
+ free (ReportFileName);
+ }
+ }
+ VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
+
+ return GetUtilityStatus ();
+}
+
+STATIC
+EFI_STATUS
+ZeroDebugData (
+ IN OUT UINT8 *FileBuffer,
+ BOOLEAN ZeroDebugFlag
+ )
+/*++
+
+Routine Description:
+
+ Zero debug information in PeImage.
+
+Arguments:
+
+ FileBuffer - Pointer to PeImage.
+ ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp
+
+Returns:
+
+ EFI_ABORTED - PeImage is invalid.
+ EFI_SUCCESS - Zero debug data successfully.
+
+--*/
+{
+ UINT32 Index;
+ UINT32 DebugDirectoryEntryRva;
+ UINT32 DebugDirectoryEntrySize;
+ UINT32 DebugDirectoryEntryFileOffset;
+ UINT32 ExportDirectoryEntryRva;
+ UINT32 ExportDirectoryEntryFileOffset;
+ UINT32 ResourceDirectoryEntryRva;
+ UINT32 ResourceDirectoryEntryFileOffset;
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_IMAGE_FILE_HEADER *FileHdr;
+ EFI_IMAGE_OPTIONAL_HEADER32 *Optional32Hdr;
+ EFI_IMAGE_OPTIONAL_HEADER64 *Optional64Hdr;
+ EFI_IMAGE_SECTION_HEADER *SectionHeader;
+ EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
+ EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY *RsdsEntry;
+ UINT32 *NewTimeStamp;
+
+ //
+ // Init variable.
+ //
+ DebugDirectoryEntryRva = 0;
+ DebugDirectoryEntrySize = 0;
+ ExportDirectoryEntryRva = 0;
+ ResourceDirectoryEntryRva = 0;
+ DebugDirectoryEntryFileOffset = 0;
+ ExportDirectoryEntryFileOffset = 0;
+ ResourceDirectoryEntryFileOffset = 0;
+ DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;
+ FileHdr = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));
+
+
+ DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
+ if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ // NO DOS header, must start with PE/COFF header
+ FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32));
+ } else {
+ FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));
+ }
+
+ //
+ // Get Debug, Export and Resource EntryTable RVA address.
+ // Resource Directory entry need to review.
+ //
+ Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
+ Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
+ if (Optional32Hdr->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr + FileHdr->SizeOfOptionalHeader);
+ if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
+ Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
+ ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
+ }
+ if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
+ Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
+ ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
+ }
+ if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
+ Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
+ DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ DebugDirectoryEntrySize = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+ if (ZeroDebugFlag) {
+ Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;
+ Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;
+ }
+ }
+ } else {
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr + FileHdr->SizeOfOptionalHeader);
+ if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
+ Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
+ ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
+ }
+ if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
+ Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
+ ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
+ }
+ if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
+ Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
+ DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ DebugDirectoryEntrySize = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+ if (ZeroDebugFlag) {
+ Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;
+ Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;
+ }
+ }
+ }
+
+ //
+ // Get DirectoryEntryTable file offset.
+ //
+ for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {
+ if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&
+ DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
+ DebugDirectoryEntryFileOffset =
+ DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
+ }
+ if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&
+ ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
+ ExportDirectoryEntryFileOffset =
+ ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
+ }
+ if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&
+ ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
+ ResourceDirectoryEntryFileOffset =
+ ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
+ }
+ }
+
+ //
+ //Zero Debug Data and TimeStamp
+ //
+ FileHdr->TimeDateStamp = 0;
+ mImageTimeStamp = 0;
+ if (ExportDirectoryEntryFileOffset != 0) {
+ NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));
+ *NewTimeStamp = 0;
+ }
+
+ if (ResourceDirectoryEntryFileOffset != 0) {
+ NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));
+ *NewTimeStamp = 0;
+ }
+
+ if (DebugDirectoryEntryFileOffset != 0) {
+ DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset);
+ Index = 0;
+ for (Index=0; Index < DebugDirectoryEntrySize / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); Index ++, DebugEntry ++) {
+ DebugEntry->TimeDateStamp = 0;
+ if (mIsConvertXip) {
+ DebugEntry->FileOffset = DebugEntry->RVA;
+ }
+ if (ZeroDebugFlag || DebugEntry->Type != EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
+ memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);
+ memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
+ }
+ if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
+ RsdsEntry = (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY *) (FileBuffer + DebugEntry->FileOffset);
+ if (RsdsEntry->Signature == CODEVIEW_SIGNATURE_MTOC) {
+ // MTOC sets DebugDirectoryEntrySize to size of the .debug section, so fix it.
+ if (!ZeroDebugFlag) {
+ if (Optional32Hdr->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
+ } else {
+ Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+SetStamp (
+ IN OUT UINT8 *FileBuffer,
+ IN CHAR8 *TimeStamp
+ )
+/*++
+
+Routine Description:
+
+ Set new time stamp into PeImage FileHdr and Directory table:
+ Debug, Export and Resource.
+
+Arguments:
+
+ FileBuffer - Pointer to PeImage.
+ TimeStamp - Time stamp string.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - TimeStamp format is not recognized.
+ EFI_SUCCESS - Set new time stamp in this image successfully.
+
+--*/
+{
+ struct tm stime;
+ struct tm *ptime;
+ time_t newtime;
+ UINT32 Index;
+ UINT32 DebugDirectoryEntryRva;
+ UINT32 DebugDirectoryEntryFileOffset;
+ UINT32 ExportDirectoryEntryRva;
+ UINT32 ExportDirectoryEntryFileOffset;
+ UINT32 ResourceDirectoryEntryRva;
+ UINT32 ResourceDirectoryEntryFileOffset;
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_IMAGE_FILE_HEADER *FileHdr;
+ EFI_IMAGE_OPTIONAL_HEADER32 *Optional32Hdr;
+ EFI_IMAGE_OPTIONAL_HEADER64 *Optional64Hdr;
+ EFI_IMAGE_SECTION_HEADER *SectionHeader;
+ UINT32 *NewTimeStamp;
+
+ //
+ // Init variable.
+ //
+ DebugDirectoryEntryRva = 0;
+ DebugDirectoryEntryFileOffset = 0;
+ ExportDirectoryEntryRva = 0;
+ ExportDirectoryEntryFileOffset = 0;
+ ResourceDirectoryEntryRva = 0;
+ ResourceDirectoryEntryFileOffset = 0;
+ //
+ // Get time and date that will be set.
+ //
+ if (TimeStamp == NULL) {
+ Error (NULL, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // compare the value with "NOW", if yes, current system time is set.
+ //
+ if (stricmp (TimeStamp, "NOW") == 0) {
+ //
+ // get system current time and date
+ //
+ time (&newtime);
+ } else {
+ //
+ // Check Time Format strictly yyyy-mm-dd 00:00:00
+ //
+ for (Index = 0; TimeStamp[Index] != '\0' && Index < 20; Index ++) {
+ if (Index == 4 || Index == 7) {
+ if (TimeStamp[Index] == '-') {
+ continue;
+ }
+ } else if (Index == 13 || Index == 16) {
+ if (TimeStamp[Index] == ':') {
+ continue;
+ }
+ } else if (Index == 10 && TimeStamp[Index] == ' ') {
+ continue;
+ } else if ((TimeStamp[Index] < '0') || (TimeStamp[Index] > '9')) {
+ break;
+ }
+ }
+
+ if (Index < 19 || TimeStamp[19] != '\0') {
+ Error (NULL, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // get the date and time from TimeStamp
+ //
+ if (sscanf (TimeStamp, "%d-%d-%d %d:%d:%d",
+ &stime.tm_year,
+ &stime.tm_mon,
+ &stime.tm_mday,
+ &stime.tm_hour,
+ &stime.tm_min,
+ &stime.tm_sec
+ ) != 6) {
+ Error (NULL, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
+ //
+ if (stime.tm_mon <= 0 || stime.tm_mday <=0) {
+ Error (NULL, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp);
+ return EFI_INVALID_PARAMETER;
+ }
+ stime.tm_mon -= 1;
+
+ //
+ // in struct, Year (current year minus 1900)
+ // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
+ //
+ //
+ // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
+ //
+ if (stime.tm_year >= 1970 && stime.tm_year <= 2038) {
+ //
+ // convert 1970 -> 70, 2000 -> 100, ...
+ //
+ stime.tm_year -= 1900;
+ } else {
+ Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // convert the date and time to time_t format
+ //
+ newtime = mktime (&stime);
+ if (newtime == (time_t) - 1) {
+ Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ ptime = localtime (&newtime);
+ if (ptime != NULL) {
+ DebugMsg (NULL, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",
+ ptime->tm_year + 1900, ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min, ptime->tm_sec);
+ }
+ //
+ // Set new time and data into PeImage.
+ //
+ DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
+ if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ // NO DOS header, must start with PE/COFF header
+ FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32));
+ } else {
+ FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));
+ }
+
+ //
+ // Get Debug, Export and Resource EntryTable RVA address.
+ // Resource Directory entry need to review.
+ //
+ if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {
+ Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr + FileHdr->SizeOfOptionalHeader);
+ if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
+ Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
+ ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
+ }
+ if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
+ Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
+ ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
+ }
+ if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
+ Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
+ DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ }
+ } else {
+ Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr + FileHdr->SizeOfOptionalHeader);
+ if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
+ Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
+ ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
+ }
+ if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
+ Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
+ ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
+ }
+ if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
+ Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
+ DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ }
+ }
+
+ //
+ // Get DirectoryEntryTable file offset.
+ //
+ for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {
+ if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&
+ DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
+ DebugDirectoryEntryFileOffset =
+ DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
+ }
+ if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&
+ ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
+ ExportDirectoryEntryFileOffset =
+ ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
+ }
+ if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&
+ ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
+ ResourceDirectoryEntryFileOffset =
+ ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
+ }
+ }
+
+ //
+ // Set new stamp
+ //
+ FileHdr->TimeDateStamp = (UINT32) newtime;
+ mImageTimeStamp = (UINT32) newtime;
+ if (ExportDirectoryEntryRva != 0) {
+ NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));
+ *NewTimeStamp = (UINT32) newtime;
+ }
+
+ if (ResourceDirectoryEntryRva != 0) {
+ NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));
+ *NewTimeStamp = (UINT32) newtime;
+ }
+
+ if (DebugDirectoryEntryRva != 0) {
+ NewTimeStamp = (UINT32 *) (FileBuffer + DebugDirectoryEntryFileOffset + sizeof (UINT32));
+ *NewTimeStamp = (UINT32) newtime;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+STATUS
+MicrocodeReadData (
+ FILE *InFptr,
+ UINT32 *Data
+ )
+/*++
+
+Routine Description:
+ Read a 32-bit microcode data value from a text file and convert to raw binary form.
+
+Arguments:
+ InFptr - file pointer to input text file
+ Data - pointer to where to return the data parsed
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings, Data contains valid information
+ STATUS_ERROR - errors were encountered
+
+--*/
+{
+ CHAR8 Line[MAX_LINE_LEN];
+ CHAR8 *cptr;
+ int ScannedData = 0;
+
+ Line[MAX_LINE_LEN - 1] = 0;
+ while (1) {
+ if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {
+ return STATUS_ERROR;
+ }
+ //
+ // If it was a binary file, then it may have overwritten our null terminator
+ //
+ if (Line[MAX_LINE_LEN - 1] != 0) {
+ return STATUS_ERROR;
+ }
+
+ //
+ // strip space
+ //
+ for (cptr = Line; *cptr && isspace((int)*cptr); cptr++) {
+ }
+
+ // Skip Blank Lines and Comment Lines
+ if ((strlen(cptr) != 0) && (*cptr != ';')) {
+ break;
+ }
+ }
+
+ // Look for
+ // dd 000000001h ; comment
+ // dd XXXXXXXX
+ // DD XXXXXXXXX
+ // DD XXXXXXXXX
+ //
+ if ((tolower((int)cptr[0]) == 'd') && (tolower((int)cptr[1]) == 'd') && isspace ((int)cptr[2])) {
+ //
+ // Skip blanks and look for a hex digit
+ //
+ cptr += 3;
+ for (; *cptr && isspace((int)*cptr); cptr++) {
+ }
+ if (isxdigit ((int)*cptr)) {
+ if (sscanf (cptr, "%X", &ScannedData) != 1) {
+ return STATUS_ERROR;
+ }
+ }
+ *Data = (UINT32) ScannedData;
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_ERROR;
+}
diff --git a/efi_memtest/__JustForReference__Unused__/GenFw.h b/efi_memtest/__JustForReference__Unused__/GenFw.h
new file mode 100644
index 0000000..4690176
--- /dev/null
+++ b/efi_memtest/__JustForReference__Unused__/GenFw.h
@@ -0,0 +1,50 @@
+/** @file
+Header file for GenFw
+
+Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _GEN_FW_H_
+#define _GEN_FW_H_
+
+//
+// Action for this tool.
+//
+#define FW_DUMMY_IMAGE 0
+#define FW_EFI_IMAGE 1
+#define FW_TE_IMAGE 2
+#define FW_ACPI_IMAGE 3
+#define FW_BIN_IMAGE 4
+#define FW_ZERO_DEBUG_IMAGE 5
+#define FW_SET_STAMP_IMAGE 6
+#define FW_MCI_IMAGE 7
+#define FW_MERGE_IMAGE 8
+#define FW_RELOC_STRIPEED_IMAGE 9
+#define FW_HII_PACKAGE_LIST_RCIMAGE 10
+#define FW_HII_PACKAGE_LIST_BINIMAGE 11
+#define FW_REBASE_IMAGE 12
+#define FW_SET_ADDRESS_IMAGE 13
+
+#define DUMP_TE_HEADER 0x11
+
+VOID
+SetHiiResourceHeader (
+ UINT8 *HiiBinData,
+ UINT32 OffsetToFile
+ );
+
+INTN
+IsElfHeader (
+ UINT8 *FileBuffer
+ );
+
+BOOLEAN
+ConvertElf (
+ UINT8 **FileBuffer,
+ UINT32 *FileLength
+ );
+
+#endif