summaryrefslogtreecommitdiff
path: root/BaseTools/Source/C/GenFw
diff options
context:
space:
mode:
Diffstat (limited to 'BaseTools/Source/C/GenFw')
-rw-r--r--BaseTools/Source/C/GenFw/GNUmakefile18
-rw-r--r--BaseTools/Source/C/GenFw/GenFw.c3073
-rw-r--r--BaseTools/Source/C/GenFw/Makefile12
-rw-r--r--BaseTools/Source/C/GenFw/elf32.h244
-rw-r--r--BaseTools/Source/C/GenFw/elf64.h247
-rw-r--r--BaseTools/Source/C/GenFw/elf_common.h872
-rw-r--r--BaseTools/Source/C/GenFw/elf_generic.h88
7 files changed, 4554 insertions, 0 deletions
diff --git a/BaseTools/Source/C/GenFw/GNUmakefile b/BaseTools/Source/C/GenFw/GNUmakefile
new file mode 100644
index 0000000000..decae9e9ba
--- /dev/null
+++ b/BaseTools/Source/C/GenFw/GNUmakefile
@@ -0,0 +1,18 @@
+ARCH ?= IA32
+MAKEROOT ?= ..
+
+APPNAME = GenFw
+
+OBJECTS = GenFw.o
+
+include $(MAKEROOT)/Makefiles/app.makefile
+
+LIBS = -lCommon
+ifeq ($(CYGWIN), CYGWIN)
+ LIBS += -L/lib/e2fsprogs -luuid
+endif
+
+ifeq ($(LINUX), Linux)
+ LIBS += -luuid
+endif
+
diff --git a/BaseTools/Source/C/GenFw/GenFw.c b/BaseTools/Source/C/GenFw/GenFw.c
new file mode 100644
index 0000000000..2278948b3d
--- /dev/null
+++ b/BaseTools/Source/C/GenFw/GenFw.c
@@ -0,0 +1,3073 @@
+/** @file
+
+Copyright (c) 2004 - 2009, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenFw.c
+
+Abstract:
+
+ Converts a pe32+ image to an FW, Te image type, or other specific image.
+
+**/
+
+#include "WinNtInclude.h"
+
+#ifndef __GNUC__
+#include <windows.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>
+
+//
+// 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 "EfiUtilityMsgs.h"
+
+#include "elf_common.h"
+#include "elf32.h"
+#include "elf64.h"
+
+
+//
+// Version of this utility
+//
+#define UTILITY_NAME "GenFw"
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 2
+
+//
+// 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 DUMP_TE_HEADER 0x11
+
+#define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
+#define DEFAULT_MC_ALIGNMENT 16
+
+#ifndef _MAX_PATH
+#define _MAX_PATH 500
+#endif
+
+#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 CHAR8 *mInImageName;
+
+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\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_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, 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 ouput content.\n");
+ fprintf (stdout, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\
+ Create Efi Image. EFI_FILETYPE is one of BASE, SEC,\n\
+ PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\
+ DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER, \n\
+ DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER, \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, -r, -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, " -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, -r, -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, " -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 Relocation info stripped from the input 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-1-1 8:0:0 ~ 2038-1-19 3:14:07\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, " --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, " -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:
+ 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 != 0) &&
+ (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) {
+ Error (NULL, 0, 3000, "Invalid", "DSDT revision check failed.");
+ return STATUS_ERROR;
+ }
+ 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_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) {
+ 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;
+}
+
+
+INTN
+IsElfHeader(
+ UINT8 *FileBuffer
+)
+{
+ return (FileBuffer[EI_MAG0] == ELFMAG0
+ && FileBuffer[EI_MAG1] == ELFMAG1
+ && FileBuffer[EI_MAG2] == ELFMAG2
+ && FileBuffer[EI_MAG3] == ELFMAG3);
+}
+
+typedef Elf32_Shdr Elf_Shdr;
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Rel Elf_Rel;
+typedef Elf32_Sym Elf_Sym;
+typedef Elf32_Phdr Elf_Phdr;
+typedef Elf32_Dyn Elf_Dyn;
+
+#define ELFCLASS ELFCLASS32
+#define ELF_R_TYPE(r) ELF32_R_TYPE(r)
+#define ELF_R_SYM(r) ELF32_R_SYM(r)
+
+//
+// Well known ELF structures.
+//
+Elf_Ehdr *Ehdr;
+Elf_Shdr *ShdrBase;
+Elf_Phdr *gPhdrBase;
+
+//
+// PE section alignment.
+//
+const UINT32 CoffAlignment = 0x20;
+const UINT32 CoffNbrSections = 4;
+
+//
+// Current offset in coff file.
+//
+UINT32 CoffOffset;
+
+//
+// Result Coff file in memory.
+//
+UINT8 *CoffFile = NULL;
+//
+// ELF sections to offset in Coff file.
+//
+UINT32 *CoffSectionsOffset = NULL;
+
+//
+// Offset in Coff file of headers and sections.
+//
+UINT32 NtHdrOffset;
+UINT32 TableOffset;
+UINT32 TextOffset;
+UINT32 DataOffset;
+UINT32 RelocOffset;
+
+EFI_IMAGE_BASE_RELOCATION *CoffBaseRel;
+UINT16 *CoffEntryRel;
+
+UINT32
+CoffAlign(
+ UINT32 Offset
+ )
+{
+ return (Offset + CoffAlignment - 1) & ~(CoffAlignment - 1);
+}
+
+Elf_Shdr *
+GetShdrByIndex(
+ UINT32 Num
+ )
+{
+ if (Num >= Ehdr->e_shnum)
+ return NULL;
+ return (Elf_Shdr*)((UINT8*)ShdrBase + Num * Ehdr->e_shentsize);
+}
+
+INTN
+CheckElfHeader(
+ VOID
+ )
+{
+ //
+ // Note: Magic has already been tested.
+ //
+ if (Ehdr->e_ident[EI_CLASS] != ELFCLASS) {
+ Error (NULL, 0, 3000, "Unsupported", "%s needs to be ported for 64-bit ELF.", mInImageName);
+ return 0;
+ }
+ if (Ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
+ Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");
+ return 0;
+ }
+ if ((Ehdr->e_type != ET_EXEC) && (Ehdr->e_type != ET_DYN)) {
+ Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");
+ return 0;
+ }
+ if (!((Ehdr->e_machine == EM_386) || (Ehdr->e_machine == EM_ARM))) {
+ Error (NULL, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM");
+ return 0;
+ }
+ if (Ehdr->e_version != EV_CURRENT) {
+ Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%d) not EV_CURRENT (%d)", Ehdr->e_version, EV_CURRENT);
+ return 0;
+ }
+
+ //
+ // Find the section header table
+ //
+ ShdrBase = (Elf_Shdr *)((UINT8 *)Ehdr + Ehdr->e_shoff);
+ gPhdrBase = (Elf_Phdr *)((UINT8 *)Ehdr + Ehdr->e_phoff);
+
+ CoffSectionsOffset = (UINT32 *)malloc(Ehdr->e_shnum * sizeof (UINT32));
+
+ memset(CoffSectionsOffset, 0, Ehdr->e_shnum * sizeof(UINT32));
+ return 1;
+}
+
+int
+IsTextShdr(
+ Elf_Shdr *Shdr
+ )
+{
+ return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC;
+}
+
+int
+IsDataShdr(
+ Elf_Shdr *Shdr
+ )
+{
+ return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE);
+}
+
+VOID
+CreateSectionHeader(
+ const CHAR8 *Name,
+ UINT32 Offset,
+ UINT32 Size,
+ UINT32 Flags
+ )
+{
+ EFI_IMAGE_SECTION_HEADER *Hdr;
+ Hdr = (EFI_IMAGE_SECTION_HEADER*)(CoffFile + TableOffset);
+
+ strcpy((char *)Hdr->Name, Name);
+ Hdr->Misc.VirtualSize = Size;
+ Hdr->VirtualAddress = Offset;
+ Hdr->SizeOfRawData = Size;
+ Hdr->PointerToRawData = Offset;
+ Hdr->PointerToRelocations = 0;
+ Hdr->PointerToLinenumbers = 0;
+ Hdr->NumberOfRelocations = 0;
+ Hdr->NumberOfLinenumbers = 0;
+ Hdr->Characteristics = Flags;
+
+ TableOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
+}
+
+VOID
+ScanSections(
+ VOID
+ )
+{
+ UINT32 i;
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
+ UINT32 CoffEntry;
+
+ CoffEntry = 0;
+ CoffOffset = 0;
+
+ //
+ // Coff file start with a DOS header.
+ //
+ CoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40;
+ NtHdrOffset = CoffOffset;
+ CoffOffset += sizeof(EFI_IMAGE_OPTIONAL_HEADER_UNION);
+ TableOffset = CoffOffset;
+ CoffOffset += CoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER);
+
+ //
+ // First text sections.
+ //
+ CoffOffset = CoffAlign(CoffOffset);
+ TextOffset = CoffOffset;
+ for (i = 0; i < Ehdr->e_shnum; i++) {
+ Elf_Shdr *shdr = GetShdrByIndex(i);
+ if (IsTextShdr(shdr)) {
+ if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {
+ // the alignment field is valid
+ if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {
+ // if the section address is aligned we must align PE/COFF
+ CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);
+ } else if ((shdr->sh_addr % shdr->sh_addralign) != (CoffOffset % shdr->sh_addralign)) {
+ // ARM RVCT tools have behavior outside of the ELF specification to try
+ // and make images smaller. If sh_addr is not aligned to sh_addralign
+ // then the section needs to preserve sh_addr MOD sh_addralign.
+ // Normally doing nothing here works great.
+ Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");
+ }
+ }
+
+ /* Relocate entry. */
+ if ((Ehdr->e_entry >= shdr->sh_addr) &&
+ (Ehdr->e_entry < shdr->sh_addr + shdr->sh_size)) {
+ CoffEntry = CoffOffset + Ehdr->e_entry - shdr->sh_addr;
+ }
+ CoffSectionsOffset[i] = CoffOffset;
+ CoffOffset += shdr->sh_size;
+ }
+ }
+
+ if (Ehdr->e_machine != EM_ARM) {
+ CoffOffset = CoffAlign(CoffOffset);
+ }
+
+ //
+ // Then data sections.
+ //
+ DataOffset = CoffOffset;
+ for (i = 0; i < Ehdr->e_shnum; i++) {
+ Elf_Shdr *shdr = GetShdrByIndex(i);
+ if (IsDataShdr(shdr)) {
+ if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {
+ // the alignment field is valid
+ if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {
+ // if the section address is aligned we must align PE/COFF
+ CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);
+ } else if ((shdr->sh_addr % shdr->sh_addralign) != (CoffOffset % shdr->sh_addralign)) {
+ // ARM RVCT tools have behavior outside of the ELF specification to try
+ // and make images smaller. If sh_addr is not aligned to sh_addralign
+ // then the section needs to preserve sh_addr MOD sh_addralign.
+ // Normally doing nothing here works great.
+ Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");
+ }
+ }
+
+ CoffSectionsOffset[i] = CoffOffset;
+ CoffOffset += shdr->sh_size;
+ }
+ }
+ CoffOffset = CoffAlign(CoffOffset);
+
+ RelocOffset = CoffOffset;
+
+ //
+ // Allocate base Coff file. Will be expanded later for relocations.
+ //
+ CoffFile = (UINT8 *)malloc(CoffOffset);
+ memset(CoffFile, 0, CoffOffset);
+
+ //
+ // Fill headers.
+ //
+ DosHdr = (EFI_IMAGE_DOS_HEADER *)CoffFile;
+ DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;
+ DosHdr->e_lfanew = NtHdrOffset;
+
+ NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(CoffFile + NtHdrOffset);
+
+ NtHdr->Pe32.Signature = EFI_IMAGE_NT_SIGNATURE;
+
+ switch (Ehdr->e_machine) {
+ case EM_386:
+ NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;
+ NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
+ break;
+ case EM_X86_64:
+ NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_X64;
+ NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+ break;
+ case EM_IA_64:
+ NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IPF;
+ NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+ break;
+ case EM_ARM:
+ NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_ARMT;
+ NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
+ break;
+ default:
+ VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)Ehdr->e_machine);
+ NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;
+ NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
+ }
+
+ NtHdr->Pe32.FileHeader.NumberOfSections = CoffNbrSections;
+ NtHdr->Pe32.FileHeader.TimeDateStamp = time(NULL);
+ NtHdr->Pe32.FileHeader.PointerToSymbolTable = 0;
+ NtHdr->Pe32.FileHeader.NumberOfSymbols = 0;
+ NtHdr->Pe32.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32.OptionalHeader);
+ NtHdr->Pe32.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE
+ | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED
+ | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED
+ | EFI_IMAGE_FILE_32BIT_MACHINE;
+
+ NtHdr->Pe32.OptionalHeader.SizeOfCode = DataOffset - TextOffset;
+ NtHdr->Pe32.OptionalHeader.SizeOfInitializedData = RelocOffset - DataOffset;
+ NtHdr->Pe32.OptionalHeader.SizeOfUninitializedData = 0;
+ NtHdr->Pe32.OptionalHeader.AddressOfEntryPoint = CoffEntry;
+
+ NtHdr->Pe32.OptionalHeader.BaseOfCode = TextOffset;
+
+ NtHdr->Pe32.OptionalHeader.BaseOfData = DataOffset;
+ NtHdr->Pe32.OptionalHeader.ImageBase = 0;
+ NtHdr->Pe32.OptionalHeader.SectionAlignment = CoffAlignment;
+ NtHdr->Pe32.OptionalHeader.FileAlignment = CoffAlignment;
+ NtHdr->Pe32.OptionalHeader.SizeOfImage = 0;
+
+ NtHdr->Pe32.OptionalHeader.SizeOfHeaders = TextOffset;
+ NtHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;
+
+ //
+ // Section headers.
+ //
+ if ((DataOffset - TextOffset) > 0) {
+ CreateSectionHeader (".text", TextOffset, DataOffset - TextOffset,
+ EFI_IMAGE_SCN_CNT_CODE
+ | EFI_IMAGE_SCN_MEM_EXECUTE
+ | EFI_IMAGE_SCN_MEM_READ);
+ } else {
+ // Don't make a section of size 0.
+ NtHdr->Pe32.FileHeader.NumberOfSections--;
+ }
+
+ if ((RelocOffset - TextOffset) > 0) {
+ CreateSectionHeader (".data", DataOffset, RelocOffset - DataOffset,
+ EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
+ | EFI_IMAGE_SCN_MEM_WRITE
+ | EFI_IMAGE_SCN_MEM_READ);
+ } else {
+ // Don't make a section of size 0.
+ NtHdr->Pe32.FileHeader.NumberOfSections--;
+ }
+}
+
+VOID
+WriteSections(
+ int (*Filter)(Elf_Shdr *)
+ )
+{
+ UINT32 Idx;
+ Elf_Shdr *SecShdr;
+ UINT32 SecOffset;
+
+ //
+ // First: copy sections.
+ //
+ for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {
+ Elf_Shdr *Shdr = GetShdrByIndex(Idx);
+ if ((*Filter)(Shdr)) {
+ switch (Shdr->sh_type) {
+ case SHT_PROGBITS:
+ /* Copy. */
+ memcpy(CoffFile + CoffSectionsOffset[Idx],
+ (UINT8*)Ehdr + Shdr->sh_offset,
+ Shdr->sh_size);
+ break;
+
+ case SHT_NOBITS:
+ memset(CoffFile + CoffSectionsOffset[Idx], 0, Shdr->sh_size);
+ break;
+
+ default:
+ //
+ // Ignore for unkown section type.
+ //
+ VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (UINTN)Shdr->sh_type);
+ break;
+ }
+ }
+ }
+
+ //
+ // Second: apply relocations.
+ //
+ for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {
+ Elf_Shdr *RelShdr = GetShdrByIndex(Idx);
+ if (RelShdr->sh_type != SHT_REL)
+ continue;
+ SecShdr = GetShdrByIndex(RelShdr->sh_info);
+ SecOffset = CoffSectionsOffset[RelShdr->sh_info];
+ if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) {
+ UINT32 RelIdx;
+ Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);
+ UINT8 *Symtab = (UINT8*)Ehdr + SymtabShdr->sh_offset;
+
+ for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {
+ Elf_Rel *Rel = (Elf_Rel *)((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);
+ Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);
+ Elf_Shdr *SymShdr;
+ UINT8 *Targ;
+
+ if (Sym->st_shndx == SHN_UNDEF
+ || Sym->st_shndx == SHN_ABS
+ || Sym->st_shndx > Ehdr->e_shnum) {
+ Error (NULL, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName);
+ }
+ SymShdr = GetShdrByIndex(Sym->st_shndx);
+
+ //
+ // Note: r_offset in a memory address.
+ // Convert it to a pointer in the coff file.
+ //
+ Targ = CoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);
+
+ if (Ehdr->e_machine == EM_386) {
+ switch (ELF_R_TYPE(Rel->r_info)) {
+ case R_386_NONE:
+ break;
+ case R_386_32:
+ //
+ // Absolute relocation.
+ //
+ *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr
+ + CoffSectionsOffset[Sym->st_shndx];
+ break;
+ case R_386_PC32:
+ //
+ // Relative relocation: Symbol - Ip + Addend
+ //
+ *(UINT32 *)Targ = *(UINT32 *)Targ
+ + (CoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)
+ - (SecOffset - SecShdr->sh_addr);
+ break;
+ default:
+ Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF_R_TYPE(Rel->r_info));
+ }
+ } else if (Ehdr->e_machine == EM_ARM) {
+ switch (ELF32_R_TYPE(Rel->r_info)) {
+ case R_ARM_RBASE: // No relocation - no action required
+ case R_ARM_PC24: // PC-relative relocations don't require modification
+ case R_ARM_XPC25: // PC-relative relocations don't require modification
+ break;
+ case R_ARM_ABS32:
+ case R_ARM_RABS32:
+ //
+ // Absolute relocation.
+ //
+ *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + CoffSectionsOffset[Sym->st_shndx];
+ break;
+ default:
+ Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF32_R_TYPE(Rel->r_info));
+ }
+ }
+ }
+ }
+ }
+}
+
+VOID
+CoffAddFixupEntry(
+ UINT16 Val
+ )
+{
+ *CoffEntryRel = Val;
+ CoffEntryRel++;
+ CoffBaseRel->SizeOfBlock += 2;
+ CoffOffset += 2;
+}
+
+VOID
+CoffAddFixup(
+ UINT32 Offset,
+ UINT8 Type
+ )
+{
+ if (CoffBaseRel == NULL
+ || CoffBaseRel->VirtualAddress != (Offset & ~0xfff)) {
+ if (CoffBaseRel != NULL) {
+ //
+ // Add a null entry (is it required ?)
+ //
+ CoffAddFixupEntry (0);
+ //
+ // Pad for alignment.
+ //
+ if (CoffOffset % 4 != 0)
+ CoffAddFixupEntry (0);
+ }
+
+ CoffFile = realloc
+ (CoffFile,
+ CoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);
+ memset(CoffFile + CoffOffset, 0,
+ sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);
+
+ CoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(CoffFile + CoffOffset);
+ CoffBaseRel->VirtualAddress = Offset & ~0xfff;
+ CoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION);
+
+ CoffEntryRel = (UINT16 *)(CoffBaseRel + 1);
+ CoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION);
+ }
+
+ //
+ // Fill the entry.
+ //
+ CoffAddFixupEntry((Type << 12) | (Offset & 0xfff));
+}
+
+
+Elf_Phdr *
+GetPhdrByIndex (
+ UINT32 num
+ )
+{
+ if (num >= Ehdr->e_phnum) {
+ return NULL;
+ }
+
+ return (Elf32_Phdr *)((UINT8*)gPhdrBase + num * Ehdr->e_phentsize);
+}
+
+
+VOID
+WriteRelocations(
+ VOID
+ )
+{
+ UINT32 Index;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
+ EFI_IMAGE_DATA_DIRECTORY *Dir;
+ BOOLEAN FoundRelocations;
+ Elf_Dyn *Dyn;
+ Elf_Rel *Rel;
+ UINTN RelElementSize;
+ UINTN RelSize;
+ UINTN RelOffset;
+ UINTN K;
+ UINT8 *Targ;
+ Elf32_Phdr *DynamicSegment;
+ Elf32_Phdr *TargetSegment;
+
+ for (Index = 0, FoundRelocations = FALSE; Index < Ehdr->e_shnum; Index++) {
+ Elf_Shdr *RelShdr = GetShdrByIndex(Index);
+ if (RelShdr->sh_type == SHT_REL) {
+ Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info);
+ if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {
+ UINT32 RelIdx;
+ FoundRelocations = TRUE;
+ for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {
+ Elf_Rel *Rel = (Elf_Rel *)
+ ((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);
+
+ if (Ehdr->e_machine == EM_386) {
+ switch (ELF_R_TYPE(Rel->r_info)) {
+ case R_386_NONE:
+ case R_386_PC32:
+ break;
+ case R_386_32:
+ CoffAddFixup(CoffSectionsOffset[RelShdr->sh_info]
+ + (Rel->r_offset - SecShdr->sh_addr),
+ EFI_IMAGE_REL_BASED_HIGHLOW);
+ break;
+ default:
+ Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF_R_TYPE(Rel->r_info));
+ }
+ } else if (Ehdr->e_machine == EM_ARM) {
+ switch (ELF32_R_TYPE(Rel->r_info)) {
+ case R_ARM_RBASE:
+ case R_ARM_PC24:
+ case R_ARM_XPC25:
+ break;
+ case R_ARM_ABS32:
+ case R_ARM_RABS32:
+ CoffAddFixup (
+ CoffSectionsOffset[RelShdr->sh_info]
+ + (Rel->r_offset - SecShdr->sh_addr),
+ EFI_IMAGE_REL_BASED_HIGHLOW
+ );
+ break;
+ default:
+ Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF32_R_TYPE(Rel->r_info));
+ }
+ } else {
+ Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %d (processor type).", Ehdr->e_machine);
+ }
+ }
+ }
+ }
+ }
+
+ if (!FoundRelocations && (Ehdr->e_machine == EM_ARM)) {
+ /* Try again, but look for PT_DYNAMIC instead of SHT_REL */
+
+ for (Index = 0; Index < Ehdr->e_phnum; Index++) {
+ RelElementSize = 0;
+ RelSize = 0;
+ RelOffset = 0;
+
+ DynamicSegment = GetPhdrByIndex (Index);
+
+ if (DynamicSegment->p_type == PT_DYNAMIC) {
+ Dyn = (Elf32_Dyn *) ((UINT8 *)Ehdr + DynamicSegment->p_offset);
+
+ while (Dyn->d_tag != DT_NULL) {
+ switch (Dyn->d_tag) {
+ case DT_REL:
+ RelOffset = Dyn->d_un.d_val;
+ break;
+
+ case DT_RELSZ:
+ RelSize = Dyn->d_un.d_val;
+ break;
+
+ case DT_RELENT:
+ RelElementSize = Dyn->d_un.d_val;
+ break;
+ }
+ Dyn++;
+ }
+ if (( RelOffset == 0 ) || ( RelSize == 0 ) || ( RelElementSize == 0 )) {
+ Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName);
+ }
+
+ for (K = 0; K < RelSize; K += RelElementSize) {
+
+ Rel = (Elf32_Rel *) ((UINT8 *) Ehdr + DynamicSegment->p_offset + RelOffset + K);
+
+ switch (ELF32_R_TYPE (Rel->r_info)) {
+ case R_ARM_RBASE:
+ break;
+ case R_ARM_RABS32:
+ TargetSegment = GetPhdrByIndex (ELF32_R_SYM (Rel->r_info) - 1);
+
+ // Note: r_offset in a memory address. Convert it to a pointer in the coff file.
+ Targ = CoffFile + CoffSectionsOffset[ ELF32_R_SYM( Rel->r_info ) ] + Rel->r_offset - TargetSegment->p_vaddr;
+
+ *(UINT32 *)Targ = *(UINT32 *)Targ + CoffSectionsOffset [ELF32_R_SYM( Rel->r_info )];
+
+ CoffAddFixup (CoffSectionsOffset[ELF32_R_SYM (Rel->r_info)] + (Rel->r_offset - TargetSegment->p_vaddr), EFI_IMAGE_REL_BASED_HIGHLOW);
+ break;
+ default:
+ Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type.", mInImageName);
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ //
+ // Pad by adding empty entries.
+ //
+ while (CoffOffset & (CoffAlignment - 1)) {
+ CoffAddFixupEntry(0);
+ }
+
+
+ NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset);
+ Dir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
+ Dir->Size = CoffOffset - RelocOffset;
+ if (Dir->Size == 0) {
+ // If no relocations, null out the directory entry and don't add the .reloc section
+ Dir->VirtualAddress = 0;
+ NtHdr->Pe32.FileHeader.NumberOfSections--;
+ } else {
+ Dir->VirtualAddress = RelocOffset;
+ CreateSectionHeader (".reloc", RelocOffset, CoffOffset - RelocOffset,
+ EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
+ | EFI_IMAGE_SCN_MEM_DISCARDABLE
+ | EFI_IMAGE_SCN_MEM_READ);
+ }
+
+}
+
+VOID
+WriteDebug(
+ VOID
+ )
+{
+ UINT32 Len;
+ UINT32 DebugOffset;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
+ EFI_IMAGE_DATA_DIRECTORY *DataDir;
+ EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir;
+ EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;
+
+ Len = strlen(mInImageName) + 1;
+ DebugOffset = CoffOffset;
+
+ CoffOffset += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)
+ + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)
+ + Len;
+ CoffOffset = CoffAlign(CoffOffset);
+
+ CoffFile = realloc(CoffFile, CoffOffset);
+ memset(CoffFile + DebugOffset, 0, CoffOffset - DebugOffset);
+
+ Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(CoffFile + DebugOffset);
+ Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;
+ Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len;
+ Dir->RVA = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
+ Dir->FileOffset = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
+
+ Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);
+ Nb10->Signature = CODEVIEW_SIGNATURE_NB10;
+ strcpy ((char *)(Nb10 + 1), mInImageName);
+
+
+ NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset);
+ DataDir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];
+ DataDir->VirtualAddress = DebugOffset;
+ DataDir->Size = CoffOffset - DebugOffset;
+ if (DataDir->Size == 0) {
+ // If no debug, null out the directory entry and don't add the .debug section
+ DataDir->VirtualAddress = 0;
+ NtHdr->Pe32.FileHeader.NumberOfSections--;
+ } else {
+ DataDir->VirtualAddress = DebugOffset;
+ CreateSectionHeader (".debug", DebugOffset, CoffOffset - DebugOffset,
+ EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
+ | EFI_IMAGE_SCN_MEM_DISCARDABLE
+ | EFI_IMAGE_SCN_MEM_READ);
+
+ }
+}
+
+VOID
+ConvertElf (
+ UINT8 **FileBuffer,
+ UINT32 *FileLength
+ )
+{
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
+
+ //
+ // Check header, read section table.
+ //
+ Ehdr = (Elf32_Ehdr*)*FileBuffer;
+ if (!CheckElfHeader())
+ return;
+
+ VerboseMsg ("Check Efl Image Header");
+ //
+ // Compute sections new address.
+ //
+ ScanSections();
+
+ VerboseMsg ("Compute sections new address.");
+
+ //
+ // Write and relocate sections.
+ //
+ WriteSections(IsTextShdr);
+ WriteSections(IsDataShdr);
+ VerboseMsg ("Write and relocate sections.");
+
+ //
+ // Translate and write relocations.
+ //
+ WriteRelocations();
+ VerboseMsg ("Translate and write relocations.");
+
+ //
+ // Write debug info.
+ //
+ WriteDebug();
+ VerboseMsg ("Write debug info.");
+
+ NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset);
+ NtHdr->Pe32.OptionalHeader.SizeOfImage = CoffOffset;
+
+ //
+ // Replace.
+ //
+ free(*FileBuffer);
+ *FileBuffer = CoffFile;
+ *FileLength = CoffOffset;
+
+ //
+ // Free memory space
+ //
+ if (CoffSectionsOffset != NULL) {
+ free (CoffSectionsOffset);
+ }
+}
+
+void
+ZeroXdataSection (
+ IN CHAR8 *ImageName,
+ IN OUT UINT8 *FileBuffer,
+ IN EFI_IMAGE_SECTION_HEADER *SectionHeader,
+ IN UINT32 SectionTotalNumber
+ )
+{
+ FILE *fpMapFile;
+ CHAR8 MapFileName[_MAX_PATH];
+ CHAR8 Line [MAX_LINE_LEN];
+ CHAR8 KeyWord [MAX_LINE_LEN];
+ CHAR8 SectionName [MAX_LINE_LEN];
+ UINT32 FunctionType = 0;
+ UINT32 SectionOffset;
+ UINT32 SectionLength;
+ UINT32 SectionNumber;
+ CHAR8 *PdbPointer;
+ INT32 Index = 0;
+
+ for (Index = 0; Index < SectionTotalNumber; Index ++) {
+ if (stricmp ((char *)SectionHeader[Index].Name, ".zdata") == 0) {
+ //
+ // try to zero the customized .zdata section, which is mapped to .xdata
+ //
+ 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", SectionHeader[Index].PointerToRawData, SectionHeader[Index].SizeOfRawData);
+ return;
+ }
+ }
+ //
+ // Try to get PDB file name
+ //
+ PdbPointer = (CHAR8 *) PeCoffLoaderGetPdbPointer (FileBuffer);
+ if (PdbPointer != NULL) {
+ strcpy (MapFileName, PdbPointer);
+ } else {
+ strcpy (MapFileName, ImageName);
+ }
+
+ //
+ // Construct map file name
+ //
+ Index = strlen (MapFileName) - 1;
+ while (Index >= 0 && MapFileName[Index] != '.') {
+ Index --;
+ }
+ if (Index < 0) {
+ //
+ // don't know how to costruct map file
+ //
+ return;
+ }
+
+ //
+ // fill map file postfix
+ //
+ MapFileName[Index + 1] = 'm';
+ MapFileName[Index + 2] = 'a';
+ MapFileName[Index + 3] = 'p';
+ MapFileName[Index + 4] = '\0';
+
+ //
+ // try opening Map File
+ //
+ fpMapFile = fopen (MapFileName, "r");
+ if (fpMapFile == NULL) {
+ //
+ // Can't open Map file. Maybe it doesn't exist.
+ //
+ return;
+ }
+
+ //
+ // Output Functions information into Fv Map file
+ //
+ while (fgets (Line, MAX_LINE_LEN, fpMapFile) != NULL) {
+ //
+ // Skip blank line
+ //
+ if (Line[0] == 0x0a) {
+ if (FunctionType != 0) {
+ //
+ // read all section table data
+ //
+ FunctionType = 0;
+ break;
+ }
+ FunctionType = 0;
+ continue;
+ }
+
+ //
+ // By Start keyword
+ //
+ if (FunctionType == 0) {
+ sscanf (Line, "%s", KeyWord);
+ if (stricmp (KeyWord, "Start") == 0) {
+ //
+ // function list
+ //
+ FunctionType = 1;
+ }
+ continue;
+ }
+ //
+ // Printf Function Information
+ //
+ if (FunctionType == 1) {
+ sscanf (Line, "%x:%x %xH %s", &SectionNumber, &SectionOffset, &SectionLength, SectionName);
+ if (stricmp (SectionName, ".xdata") == 0) {
+ FunctionType = 2;
+ break;
+ }
+ }
+ }
+
+ if (FunctionType != 2) {
+ //
+ // no .xdata section is found
+ //
+ fclose (fpMapFile);
+ return;
+ }
+
+ //
+ // Zero .xdata Section data
+ //
+ memset (FileBuffer + SectionHeader[SectionNumber-1].PointerToRawData + SectionOffset, 0, SectionLength);
+ DebugMsg (NULL, 0, 9, NULL, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", SectionHeader[SectionNumber-1].PointerToRawData + SectionOffset, SectionLength);
+ fclose (fpMapFile);
+ return;
+}
+
+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;
+ UINT32 OutImageType;
+ 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;
+ RUNTIME_FUNCTION *RuntimeFunction;
+ UNWIND_INFO *UnwindInfo;
+ STATUS Status;
+ BOOLEAN ReplaceFlag;
+ BOOLEAN KeepExceptionTableFlag;
+ 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;
+
+ SetUtilityName (UTILITY_NAME);
+
+ //
+ // Assign to fix compile warning
+ //
+ InputFileNum = 0;
+ InputFileName = NULL;
+ mInImageName = NULL;
+ OutImageName = NULL;
+ ModuleType = NULL;
+ OutImageType = FW_DUMMY_IMAGE;
+ 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;
+ Optional32 = NULL;
+ Optional64 = NULL;
+ KeepExceptionTableFlag = FALSE;
+ KeepZeroPendingFlag = 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 (OutImageType != FW_TE_IMAGE) {
+ OutImageType = FW_EFI_IMAGE;
+ }
+ argc -= 2;
+ argv += 2;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--stripped") == 0)) {
+ OutImageType = FW_RELOC_STRIPEED_IMAGE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--acpi") == 0)) {
+ OutImageType = FW_ACPI_IMAGE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--terse") == 0)) {
+ OutImageType = FW_TE_IMAGE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-u") == 0) || (stricmp (argv[0], "--dump") == 0)) {
+ OutImageType = DUMP_TE_HEADER;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--exe2bin") == 0)) {
+ OutImageType = FW_BIN_IMAGE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-z") == 0) || (stricmp (argv[0], "--zero") == 0)) {
+ OutImageType = FW_ZERO_DEBUG_IMAGE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--stamp") == 0)) {
+ OutImageType = 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], "--keepzeropending") == 0) {
+ KeepZeroPendingFlag = TRUE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--mcifile") == 0)) {
+ OutImageType = FW_MCI_IMAGE;
+ argc --;
+ argv ++;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--join") == 0)) {
+ OutImageType = 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], "-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, currnt input level is %d", 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 (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!");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ 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!");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
+ }
+
+ InputFileName [InputFileNum ++] = argv[0];
+ argc --;
+ argv ++;
+ }
+
+ VerboseMsg ("%s tool start.", UTILITY_NAME);
+
+ if (OutImageType == 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 ((OutImageType == FW_MERGE_IMAGE) && ReplaceFlag) {
+ Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j 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 (OutImageType) {
+ 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 ("Conver 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;
+ 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 (OutImageName, "rb");
+ if (fpOut != NULL) {
+ 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 = fopen (OutImageName, "wb");
+ if (!fpOut) {
+ Error (NULL, 0, 0001, "Error opening output file", OutImageName);
+ goto Finish;
+ }
+ VerboseMsg ("Output file name is %s", OutImageName);
+ } else if (!ReplaceFlag) {
+ if (OutImageType == DUMP_TE_HEADER) {
+ fpOut = stdout;
+ } else {
+ Error (NULL, 0, 1001, "Missing option", "output file");
+ goto Finish;
+ }
+ }
+
+ //
+ // Combine MciBinary files to one file
+ //
+ if (OutImageType == FW_MERGE_IMAGE) {
+ for (Index = 0; Index < InputFileNum; Index ++) {
+ fpIn = fopen (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 (OutImageType == FW_MCI_IMAGE) {
+ fpIn = fopen (mInImageName, "r");
+ if (!fpIn) {
+ 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, FileLength, 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.", CheckSum, mInImageName);
+ goto Finish;
+ }
+ //
+ // Open the output file and write the buffer contents
+ //
+ if (fpOut != NULL) {
+ if (fwrite (FileBuffer, FileLength, 1, fpOut) != 1) {
+ Error (NULL, 0, 0002, "Error writing file", OutImageName);
+ goto Finish;
+ }
+ }
+
+ if (ReplaceFlag) {
+ fpInOut = fopen (mInImageName, "wb");
+ if (fpInOut != NULL) {
+ Error (NULL, 0, 0001, "Error opening file", mInImageName);
+ goto Finish;
+ }
+ if (fwrite (FileBuffer, FileLength, 1, fpInOut) != 1) {
+ Error (NULL, 0, 0002, "Error writing file", mInImageName);
+ goto Finish;
+ }
+ }
+ VerboseMsg ("the size of output file is %d bytes", FileLength);
+ //
+ // Convert Mci.TXT to Mci.bin file successfully
+ //
+ goto Finish;
+ }
+
+ //
+ // Open input file and read file data into file buffer.
+ //
+ fpIn = fopen (mInImageName, "rb");
+ if (!fpIn) {
+ Error (NULL, 0, 0001, "Error opening file", mInImageName);
+ 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);
+
+ DebugMsg (NULL, 0, 9, "input file info", "the input file size is %d bytes", FileLength);
+
+ //
+ // Replace file
+ //
+ if (ReplaceFlag) {
+ fpInOut = fopen (mInImageName, "wb");
+ if (!fpInOut) {
+ Error (NULL, 0, 0001, "Error opening file", mInImageName);
+ goto Finish;
+ }
+ }
+ //
+ // Dump TeImage Header into output file.
+ //
+ if (OutImageType == 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;
+ }
+ 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", TEImageHeader.AddressOfEntryPoint);
+ fprintf (fpInOut, "%17X base of code\n", TEImageHeader.BaseOfCode);
+ fprintf (fpInOut, "%17lX image base\n", (long unsigned int)TEImageHeader.ImageBase);
+ fprintf (fpInOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader.DataDirectory[0].VirtualAddress, TEImageHeader.DataDirectory[0].Size);
+ fprintf (fpInOut, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader.DataDirectory[1].VirtualAddress, 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", TEImageHeader.AddressOfEntryPoint);
+ fprintf (fpOut, "%17X base of code\n", TEImageHeader.BaseOfCode);
+ fprintf (fpOut, "%17lX image base\n", (long unsigned int)TEImageHeader.ImageBase);
+ fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader.DataDirectory[0].VirtualAddress, TEImageHeader.DataDirectory[0].Size);
+ fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader.DataDirectory[1].VirtualAddress, TEImageHeader.DataDirectory[1].Size);
+ }
+ goto Finish;
+ }
+
+ //
+ // Following code to convert dll to efi image or te image.
+ // Get new image type
+ //
+ if ((OutImageType == FW_EFI_IMAGE) || (OutImageType == FW_TE_IMAGE)) {
+ if (ModuleType == NULL) {
+ if (OutImageType == FW_EFI_IMAGE) {
+ Error (NULL, 0, 1001, "Missing option", "EFI_FILETYPE");
+ goto Finish;
+ } else if (OutImageType == 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_DRIVER") == 0 ||
+ stricmp (ModuleType, "SMM_CORE") == 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 EFL image to PeImage
+ //
+ if (IsElfHeader(FileBuffer)) {
+ VerboseMsg ("Convert the input ELF Image to Pe Image");
+ ConvertElf(&FileBuffer, &FileLength);
+ }
+
+ //
+ // Remove reloc section from PE or TE image
+ //
+ if (OutImageType == 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 offical UEFI value.
+ PeHdr->Pe32.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMT;
+ }
+
+ //
+ // Extract bin data from Pe image.
+ //
+ if (OutImageType == 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
+ //
+ if (fpOut != NULL) {
+ fwrite (FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders, fpOut);
+ }
+ if (fpInOut != NULL) {
+ fwrite (FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders, fpInOut);
+ }
+ VerboseMsg ("the size of output file is %d bytes", FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders);
+ goto Finish;
+ }
+
+ //
+ // Zero Debug Information of Pe Image
+ //
+ if (OutImageType == FW_ZERO_DEBUG_IMAGE) {
+ Status = ZeroDebugData (FileBuffer, TRUE);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%lx", (UINTN) Status);
+ goto Finish;
+ }
+
+ if (fpOut != NULL) {
+ fwrite (FileBuffer, 1, FileLength, fpOut);
+ }
+ if (fpInOut != NULL) {
+ fwrite (FileBuffer, 1, FileLength, fpInOut);
+ }
+ VerboseMsg ("the size of output file is %d bytes", FileLength);
+ goto Finish;
+ }
+
+ //
+ // Set Time Stamp of Pe Image
+ //
+ if (OutImageType == FW_SET_STAMP_IMAGE) {
+ Status = SetStamp (FileBuffer, TimeStamp);
+ if (EFI_ERROR (Status)) {
+ goto Finish;
+ }
+
+ if (fpOut != NULL) {
+ fwrite (FileBuffer, 1, FileLength, fpOut);
+ }
+ if (fpInOut != NULL) {
+ fwrite (FileBuffer, 1, FileLength, fpInOut);
+ }
+ VerboseMsg ("the size of output file is %d bytes", FileLength);
+ goto Finish;
+ }
+
+ //
+ // Extract acpi data from pe image.
+ //
+ if (OutImageType == 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
+ //
+ if (fpOut != NULL) {
+ fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpOut);
+ }
+ if (fpInOut != NULL) {
+ fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpInOut);
+ }
+ VerboseMsg ("the size of output file is %d bytes", FileLength);
+ goto Finish;
+ }
+ }
+ 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] = 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;
+ Optional32->MajorLinkerVersion = 0;
+ Optional32->MinorLinkerVersion = 0;
+ 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 Execption 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 %d", SectionHeader->SizeOfRawData - AllignedRelocSize);
+ }
+ }
+ }
+ }
+ }
+ }
+ } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
+ Optional64->MajorLinkerVersion = 0;
+ Optional64->MinorLinkerVersion = 0;
+ 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) || PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_IA64) {
+ 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));
+ }
+ }
+ }
+ memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));
+ }
+ //
+ // Zero Execption 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 %d", 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);
+ }
+ }
+
+ //
+ // Zero ExceptionTable Xdata
+ //
+ if (!KeepExceptionTableFlag) {
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
+ ZeroXdataSection(mInImageName, FileBuffer, SectionHeader, PeHdr->Pe32.FileHeader.NumberOfSections);
+ }
+
+ //
+ // Zero Time/Data field
+ //
+ ZeroDebugData (FileBuffer, FALSE);
+
+ if (OutImageType == 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 %X",
+ TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, TEImageHeader.AddressOfEntryPoint, TEImageHeader.BaseOfCode, TEImageHeader.ImageBase);
+ //
+ // Update Image to TeImage
+ //
+ if (fpOut != NULL) {
+ fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpOut);
+ fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpOut);
+ }
+ if (fpInOut != NULL) {
+ fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpInOut);
+ fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpInOut);
+ }
+ VerboseMsg ("the size of output file is %d bytes", FileLength - TEImageHeader.StrippedSize);
+ goto Finish;
+ }
+WriteFile:
+ //
+ // Update Image to EfiImage
+ //
+ if (fpOut != NULL) {
+ fwrite (FileBuffer, 1, FileLength, fpOut);
+ }
+ if (fpInOut != NULL) {
+ fwrite (FileBuffer, 1, FileLength, fpInOut);
+ }
+ VerboseMsg ("the size of output file is %d bytes", FileLength);
+
+Finish:
+ if (fpInOut != NULL) {
+ if (GetUtilityStatus () != STATUS_SUCCESS) {
+ //
+ // when file updates failed, original file is still recoveried.
+ //
+ fwrite (FileBuffer, 1, FileLength, 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 (OutImageName, "wb");
+ fwrite (OutputFileBuffer, 1, OutputFileLength, fpOut);
+ fclose (fpOut);
+ free (OutputFileBuffer);
+ }
+ }
+ }
+
+ 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 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;
+ UINT32 *NewTimeStamp;
+
+ //
+ // Init variable.
+ //
+ DebugDirectoryEntryRva = 0;
+ ExportDirectoryEntryRva = 0;
+ ResourceDirectoryEntryRva = 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.
+ //
+ 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;
+ if (ZeroDebugFlag) {
+ Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;
+ Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;
+ }
+ }
+ } 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;
+ 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;
+
+ if (ExportDirectoryEntryRva != 0) {
+ NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));
+ *NewTimeStamp = 0;
+ }
+
+ if (ResourceDirectoryEntryRva != 0) {
+ NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));
+ *NewTimeStamp = 0;
+ }
+
+ if (DebugDirectoryEntryRva != 0) {
+ DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset);
+ DebugEntry->TimeDateStamp = 0;
+ if (ZeroDebugFlag) {
+ memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);
+ memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
+ }
+ }
+
+ 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;
+ ExportDirectoryEntryRva = 0;
+ ResourceDirectoryEntryRva = 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);
+ 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;
+
+ 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;
+
+ 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(*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(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) {
+ //
+ // Skip blanks and look for a hex digit
+ //
+ cptr += 3;
+ for (; *cptr && isspace(*cptr); cptr++) {
+ }
+ if (isxdigit (*cptr)) {
+ if (sscanf (cptr, "%X", Data) != 1) {
+ return STATUS_ERROR;
+ }
+ }
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_ERROR;
+}
diff --git a/BaseTools/Source/C/GenFw/Makefile b/BaseTools/Source/C/GenFw/Makefile
new file mode 100644
index 0000000000..35adfb1386
--- /dev/null
+++ b/BaseTools/Source/C/GenFw/Makefile
@@ -0,0 +1,12 @@
+!INCLUDE ..\Makefiles\ms.common
+
+APPNAME = GenFw
+
+LIBS = $(LIB_PATH)\Common.lib
+
+OBJECTS = GenFw.obj
+
+#CFLAGS = $(CFLAGS) /nodefaultlib:libc.lib
+
+!INCLUDE ..\Makefiles\ms.app
+
diff --git a/BaseTools/Source/C/GenFw/elf32.h b/BaseTools/Source/C/GenFw/elf32.h
new file mode 100644
index 0000000000..9e47123533
--- /dev/null
+++ b/BaseTools/Source/C/GenFw/elf32.h
@@ -0,0 +1,244 @@
+/*-
+ * Copyright (c) 1996-1998 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.2 2007/12/03 21:30:36 marius Exp $
+ */
+
+#ifndef _SYS_ELF32_H_
+#define _SYS_ELF32_H_ 1
+
+
+/*
+ * ELF definitions common to all 32-bit architectures.
+ */
+
+typedef UINT32 Elf32_Addr;
+typedef UINT16 Elf32_Half;
+typedef UINT32 Elf32_Off;
+typedef INT32 Elf32_Sword;
+typedef UINT32 Elf32_Word;
+typedef UINT64 Elf32_Lword;
+
+typedef Elf32_Word Elf32_Hashelt;
+
+/* Non-standard class-dependent datatype used for abstraction. */
+typedef Elf32_Word Elf32_Size;
+typedef Elf32_Sword Elf32_Ssize;
+
+/*
+ * ELF header.
+ */
+
+typedef struct {
+ unsigned char e_ident[EI_NIDENT]; /* File identification. */
+ Elf32_Half e_type; /* File type. */
+ Elf32_Half e_machine; /* Machine architecture. */
+ Elf32_Word e_version; /* ELF format version. */
+ Elf32_Addr e_entry; /* Entry point. */
+ Elf32_Off e_phoff; /* Program header file offset. */
+ Elf32_Off e_shoff; /* Section header file offset. */
+ Elf32_Word e_flags; /* Architecture-specific flags. */
+ Elf32_Half e_ehsize; /* Size of ELF header in bytes. */
+ Elf32_Half e_phentsize; /* Size of program header entry. */
+ Elf32_Half e_phnum; /* Number of program header entries. */
+ Elf32_Half e_shentsize; /* Size of section header entry. */
+ Elf32_Half e_shnum; /* Number of section header entries. */
+ Elf32_Half e_shstrndx; /* Section name strings section. */
+} Elf32_Ehdr;
+
+/*
+ * Section header.
+ */
+
+typedef struct {
+ Elf32_Word sh_name; /* Section name (index into the
+ section header string table). */
+ Elf32_Word sh_type; /* Section type. */
+ Elf32_Word sh_flags; /* Section flags. */
+ Elf32_Addr sh_addr; /* Address in memory image. */
+ Elf32_Off sh_offset; /* Offset in file. */
+ Elf32_Word sh_size; /* Size in bytes. */
+ Elf32_Word sh_link; /* Index of a related section. */
+ Elf32_Word sh_info; /* Depends on section type. */
+ Elf32_Word sh_addralign; /* Alignment in bytes. */
+ Elf32_Word sh_entsize; /* Size of each entry in section. */
+} Elf32_Shdr;
+
+/*
+ * Program header.
+ */
+
+typedef struct {
+ Elf32_Word p_type; /* Entry type. */
+ Elf32_Off p_offset; /* File offset of contents. */
+ Elf32_Addr p_vaddr; /* Virtual address in memory image. */
+ Elf32_Addr p_paddr; /* Physical address (not used). */
+ Elf32_Word p_filesz; /* Size of contents in file. */
+ Elf32_Word p_memsz; /* Size of contents in memory. */
+ Elf32_Word p_flags; /* Access permission flags. */
+ Elf32_Word p_align; /* Alignment in memory and file. */
+} Elf32_Phdr;
+
+/*
+ * Dynamic structure. The ".dynamic" section contains an array of them.
+ */
+
+typedef struct {
+ Elf32_Sword d_tag; /* Entry type. */
+ union {
+ Elf32_Word d_val; /* Integer value. */
+ Elf32_Addr d_ptr; /* Address value. */
+ } d_un;
+} Elf32_Dyn;
+
+/*
+ * Relocation entries.
+ */
+
+/* Relocations that don't need an addend field. */
+typedef struct {
+ Elf32_Addr r_offset; /* Location to be relocated. */
+ Elf32_Word r_info; /* Relocation type and symbol index. */
+} Elf32_Rel;
+
+/* Relocations that need an addend field. */
+typedef struct {
+ Elf32_Addr r_offset; /* Location to be relocated. */
+ Elf32_Word r_info; /* Relocation type and symbol index. */
+ Elf32_Sword r_addend; /* Addend. */
+} Elf32_Rela;
+
+/* Macros for accessing the fields of r_info. */
+#define ELF32_R_SYM(info) ((info) >> 8)
+#define ELF32_R_TYPE(info) ((unsigned char)(info))
+
+/* Macro for constructing r_info from field values. */
+#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type))
+
+/*
+ * Note entry header
+ */
+typedef Elf_Note Elf32_Nhdr;
+
+/*
+ * Move entry
+ */
+typedef struct {
+ Elf32_Lword m_value; /* symbol value */
+ Elf32_Word m_info; /* size + index */
+ Elf32_Word m_poffset; /* symbol offset */
+ Elf32_Half m_repeat; /* repeat count */
+ Elf32_Half m_stride; /* stride info */
+} Elf32_Move;
+
+/*
+ * The macros compose and decompose values for Move.r_info
+ *
+ * sym = ELF32_M_SYM(M.m_info)
+ * size = ELF32_M_SIZE(M.m_info)
+ * M.m_info = ELF32_M_INFO(sym, size)
+ */
+#define ELF32_M_SYM(info) ((info)>>8)
+#define ELF32_M_SIZE(info) ((unsigned char)(info))
+#define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size))
+
+/*
+ * Hardware/Software capabilities entry
+ */
+typedef struct {
+ Elf32_Word c_tag; /* how to interpret value */
+ union {
+ Elf32_Word c_val;
+ Elf32_Addr c_ptr;
+ } c_un;
+} Elf32_Cap;
+
+/*
+ * Symbol table entries.
+ */
+
+typedef struct {
+ Elf32_Word st_name; /* String table index of name. */
+ Elf32_Addr st_value; /* Symbol value. */
+ Elf32_Word st_size; /* Size of associated object. */
+ unsigned char st_info; /* Type and binding information. */
+ unsigned char st_other; /* Reserved (not used). */
+ Elf32_Half st_shndx; /* Section index of symbol. */
+} Elf32_Sym;
+
+/* Macros for accessing the fields of st_info. */
+#define ELF32_ST_BIND(info) ((info) >> 4)
+#define ELF32_ST_TYPE(info) ((info) & 0xf)
+
+/* Macro for constructing st_info from field values. */
+#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
+
+/* Macro for accessing the fields of st_other. */
+#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3)
+
+/* Structures used by Sun & GNU symbol versioning. */
+typedef struct
+{
+ Elf32_Half vd_version;
+ Elf32_Half vd_flags;
+ Elf32_Half vd_ndx;
+ Elf32_Half vd_cnt;
+ Elf32_Word vd_hash;
+ Elf32_Word vd_aux;
+ Elf32_Word vd_next;
+} Elf32_Verdef;
+
+typedef struct
+{
+ Elf32_Word vda_name;
+ Elf32_Word vda_next;
+} Elf32_Verdaux;
+
+typedef struct
+{
+ Elf32_Half vn_version;
+ Elf32_Half vn_cnt;
+ Elf32_Word vn_file;
+ Elf32_Word vn_aux;
+ Elf32_Word vn_next;
+} Elf32_Verneed;
+
+typedef struct
+{
+ Elf32_Word vna_hash;
+ Elf32_Half vna_flags;
+ Elf32_Half vna_other;
+ Elf32_Word vna_name;
+ Elf32_Word vna_next;
+} Elf32_Vernaux;
+
+typedef Elf32_Half Elf32_Versym;
+
+typedef struct {
+ Elf32_Half si_boundto; /* direct bindings - symbol bound to */
+ Elf32_Half si_flags; /* per symbol flags */
+} Elf32_Syminfo;
+
+#endif /* !_SYS_ELF32_H_ */
diff --git a/BaseTools/Source/C/GenFw/elf64.h b/BaseTools/Source/C/GenFw/elf64.h
new file mode 100644
index 0000000000..9960888940
--- /dev/null
+++ b/BaseTools/Source/C/GenFw/elf64.h
@@ -0,0 +1,247 @@
+/*-
+ * Copyright (c) 1996-1998 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.2 2007/12/03 21:30:36 marius Exp $
+ */
+
+#ifndef _SYS_ELF64_H_
+#define _SYS_ELF64_H_ 1
+
+
+/*
+ * ELF definitions common to all 64-bit architectures.
+ */
+
+typedef UINT64 Elf64_Addr;
+typedef UINT16 Elf64_Half;
+typedef UINT64 Elf64_Off;
+typedef INT32 Elf64_Sword;
+typedef INT64 Elf64_Sxword;
+typedef UINT32 Elf64_Word;
+typedef UINT64 Elf64_Lword;
+typedef UINT64 Elf64_Xword;
+
+/*
+ * Types of dynamic symbol hash table bucket and chain elements.
+ *
+ * This is inconsistent among 64 bit architectures, so a machine dependent
+ * typedef is required.
+ */
+
+typedef Elf64_Word Elf64_Hashelt;
+
+/* Non-standard class-dependent datatype used for abstraction. */
+typedef Elf64_Xword Elf64_Size;
+typedef Elf64_Sxword Elf64_Ssize;
+
+/*
+ * ELF header.
+ */
+
+typedef struct {
+ unsigned char e_ident[EI_NIDENT]; /* File identification. */
+ Elf64_Half e_type; /* File type. */
+ Elf64_Half e_machine; /* Machine architecture. */
+ Elf64_Word e_version; /* ELF format version. */
+ Elf64_Addr e_entry; /* Entry point. */
+ Elf64_Off e_phoff; /* Program header file offset. */
+ Elf64_Off e_shoff; /* Section header file offset. */
+ Elf64_Word e_flags; /* Architecture-specific flags. */
+ Elf64_Half e_ehsize; /* Size of ELF header in bytes. */
+ Elf64_Half e_phentsize; /* Size of program header entry. */
+ Elf64_Half e_phnum; /* Number of program header entries. */
+ Elf64_Half e_shentsize; /* Size of section header entry. */
+ Elf64_Half e_shnum; /* Number of section header entries. */
+ Elf64_Half e_shstrndx; /* Section name strings section. */
+} Elf64_Ehdr;
+
+/*
+ * Section header.
+ */
+
+typedef struct {
+ Elf64_Word sh_name; /* Section name (index into the
+ section header string table). */
+ Elf64_Word sh_type; /* Section type. */
+ Elf64_Xword sh_flags; /* Section flags. */
+ Elf64_Addr sh_addr; /* Address in memory image. */
+ Elf64_Off sh_offset; /* Offset in file. */
+ Elf64_Xword sh_size; /* Size in bytes. */
+ Elf64_Word sh_link; /* Index of a related section. */
+ Elf64_Word sh_info; /* Depends on section type. */
+ Elf64_Xword sh_addralign; /* Alignment in bytes. */
+ Elf64_Xword sh_entsize; /* Size of each entry in section. */
+} Elf64_Shdr;
+
+/*
+ * Program header.
+ */
+
+typedef struct {
+ Elf64_Word p_type; /* Entry type. */
+ Elf64_Word p_flags; /* Access permission flags. */
+ Elf64_Off p_offset; /* File offset of contents. */
+ Elf64_Addr p_vaddr; /* Virtual address in memory image. */
+ Elf64_Addr p_paddr; /* Physical address (not used). */
+ Elf64_Xword p_filesz; /* Size of contents in file. */
+ Elf64_Xword p_memsz; /* Size of contents in memory. */
+ Elf64_Xword p_align; /* Alignment in memory and file. */
+} Elf64_Phdr;
+
+/*
+ * Dynamic structure. The ".dynamic" section contains an array of them.
+ */
+
+typedef struct {
+ Elf64_Sxword d_tag; /* Entry type. */
+ union {
+ Elf64_Xword d_val; /* Integer value. */
+ Elf64_Addr d_ptr; /* Address value. */
+ } d_un;
+} Elf64_Dyn;
+
+/*
+ * Relocation entries.
+ */
+
+/* Relocations that don't need an addend field. */
+typedef struct {
+ Elf64_Addr r_offset; /* Location to be relocated. */
+ Elf64_Xword r_info; /* Relocation type and symbol index. */
+} Elf64_Rel;
+
+/* Relocations that need an addend field. */
+typedef struct {
+ Elf64_Addr r_offset; /* Location to be relocated. */
+ Elf64_Xword r_info; /* Relocation type and symbol index. */
+ Elf64_Sxword r_addend; /* Addend. */
+} Elf64_Rela;
+
+/* Macros for accessing the fields of r_info. */
+#define ELF64_R_SYM(info) ((info) >> 32)
+#define ELF64_R_TYPE(info) ((info) & 0xffffffffL)
+
+/* Macro for constructing r_info from field values. */
+#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL))
+
+#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40)
+#define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56)
+#define ELF64_R_TYPE_INFO(data, type) \
+ (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type))
+
+/*
+ * Note entry header
+ */
+typedef Elf_Note Elf64_Nhdr;
+
+/*
+ * Move entry
+ */
+typedef struct {
+ Elf64_Lword m_value; /* symbol value */
+ Elf64_Xword m_info; /* size + index */
+ Elf64_Xword m_poffset; /* symbol offset */
+ Elf64_Half m_repeat; /* repeat count */
+ Elf64_Half m_stride; /* stride info */
+} Elf64_Move;
+
+#define ELF64_M_SYM(info) ((info)>>8)
+#define ELF64_M_SIZE(info) ((unsigned char)(info))
+#define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size))
+
+/*
+ * Hardware/Software capabilities entry
+ */
+typedef struct {
+ Elf64_Xword c_tag; /* how to interpret value */
+ union {
+ Elf64_Xword c_val;
+ Elf64_Addr c_ptr;
+ } c_un;
+} Elf64_Cap;
+
+/*
+ * Symbol table entries.
+ */
+
+typedef struct {
+ Elf64_Word st_name; /* String table index of name. */
+ unsigned char st_info; /* Type and binding information. */
+ unsigned char st_other; /* Reserved (not used). */
+ Elf64_Half st_shndx; /* Section index of symbol. */
+ Elf64_Addr st_value; /* Symbol value. */
+ Elf64_Xword st_size; /* Size of associated object. */
+} Elf64_Sym;
+
+/* Macros for accessing the fields of st_info. */
+#define ELF64_ST_BIND(info) ((info) >> 4)
+#define ELF64_ST_TYPE(info) ((info) & 0xf)
+
+/* Macro for constructing st_info from field values. */
+#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
+
+/* Macro for accessing the fields of st_other. */
+#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3)
+
+/* Structures used by Sun & GNU-style symbol versioning. */
+typedef struct {
+ Elf64_Half vd_version;
+ Elf64_Half vd_flags;
+ Elf64_Half vd_ndx;
+ Elf64_Half vd_cnt;
+ Elf64_Word vd_hash;
+ Elf64_Word vd_aux;
+ Elf64_Word vd_next;
+} Elf64_Verdef;
+
+typedef struct {
+ Elf64_Word vda_name;
+ Elf64_Word vda_next;
+} Elf64_Verdaux;
+
+typedef struct {
+ Elf64_Half vn_version;
+ Elf64_Half vn_cnt;
+ Elf64_Word vn_file;
+ Elf64_Word vn_aux;
+ Elf64_Word vn_next;
+} Elf64_Verneed;
+
+typedef struct {
+ Elf64_Word vna_hash;
+ Elf64_Half vna_flags;
+ Elf64_Half vna_other;
+ Elf64_Word vna_name;
+ Elf64_Word vna_next;
+} Elf64_Vernaux;
+
+typedef Elf64_Half Elf64_Versym;
+
+typedef struct {
+ Elf64_Half si_boundto; /* direct bindings - symbol bound to */
+ Elf64_Half si_flags; /* per symbol flags */
+} Elf64_Syminfo;
+
+#endif /* !_SYS_ELF64_H_ */
diff --git a/BaseTools/Source/C/GenFw/elf_common.h b/BaseTools/Source/C/GenFw/elf_common.h
new file mode 100644
index 0000000000..471c2650a1
--- /dev/null
+++ b/BaseTools/Source/C/GenFw/elf_common.h
@@ -0,0 +1,872 @@
+/*-
+ * Copyright (c) 1998 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.2 2007/12/03 21:30:36 marius Exp $
+ */
+
+#ifndef _SYS_ELF_COMMON_H_
+#define _SYS_ELF_COMMON_H_ 1
+
+/*
+ * ELF definitions that are independent of architecture or word size.
+ */
+
+/*
+ * Note header. The ".note" section contains an array of notes. Each
+ * begins with this header, aligned to a word boundary. Immediately
+ * following the note header is n_namesz bytes of name, padded to the
+ * next word boundary. Then comes n_descsz bytes of descriptor, again
+ * padded to a word boundary. The values of n_namesz and n_descsz do
+ * not include the padding.
+ */
+
+typedef struct {
+ UINT32 n_namesz; /* Length of name. */
+ UINT32 n_descsz; /* Length of descriptor. */
+ UINT32 n_type; /* Type of this note. */
+} Elf_Note;
+
+/* Indexes into the e_ident array. Keep synced with
+ http://www.sco.com/developers/gabi/latest/ch4.eheader.html */
+#define EI_MAG0 0 /* Magic number, byte 0. */
+#define EI_MAG1 1 /* Magic number, byte 1. */
+#define EI_MAG2 2 /* Magic number, byte 2. */
+#define EI_MAG3 3 /* Magic number, byte 3. */
+#define EI_CLASS 4 /* Class of machine. */
+#define EI_DATA 5 /* Data format. */
+#define EI_VERSION 6 /* ELF format version. */
+#define EI_OSABI 7 /* Operating system / ABI identification */
+#define EI_ABIVERSION 8 /* ABI version */
+#define OLD_EI_BRAND 8 /* Start of architecture identification. */
+#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */
+#define EI_NIDENT 16 /* Size of e_ident array. */
+
+/* Values for the magic number bytes. */
+#define ELFMAG0 0x7f
+#define ELFMAG1 'E'
+#define ELFMAG2 'L'
+#define ELFMAG3 'F'
+#define ELFMAG "\177ELF" /* magic string */
+#define SELFMAG 4 /* magic string size */
+
+/* Values for e_ident[EI_VERSION] and e_version. */
+#define EV_NONE 0
+#define EV_CURRENT 1
+
+/* Values for e_ident[EI_CLASS]. */
+#define ELFCLASSNONE 0 /* Unknown class. */
+#define ELFCLASS32 1 /* 32-bit architecture. */
+#define ELFCLASS64 2 /* 64-bit architecture. */
+
+/* Values for e_ident[EI_DATA]. */
+#define ELFDATANONE 0 /* Unknown data format. */
+#define ELFDATA2LSB 1 /* 2's complement little-endian. */
+#define ELFDATA2MSB 2 /* 2's complement big-endian. */
+
+/* Values for e_ident[EI_OSABI]. */
+#define ELFOSABI_NONE 0 /* UNIX System V ABI */
+#define ELFOSABI_HPUX 1 /* HP-UX operating system */
+#define ELFOSABI_NETBSD 2 /* NetBSD */
+#define ELFOSABI_LINUX 3 /* GNU/Linux */
+#define ELFOSABI_HURD 4 /* GNU/Hurd */
+#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */
+#define ELFOSABI_SOLARIS 6 /* Solaris */
+#define ELFOSABI_AIX 7 /* AIX */
+#define ELFOSABI_IRIX 8 /* IRIX */
+#define ELFOSABI_FREEBSD 9 /* FreeBSD */
+#define ELFOSABI_TRU64 10 /* TRU64 UNIX */
+#define ELFOSABI_MODESTO 11 /* Novell Modesto */
+#define ELFOSABI_OPENBSD 12 /* OpenBSD */
+#define ELFOSABI_OPENVMS 13 /* Open VMS */
+#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */
+#define ELFOSABI_ARM 97 /* ARM */
+#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
+
+#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */
+#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */
+
+/* e_ident */
+#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
+ (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
+ (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
+ (ehdr).e_ident[EI_MAG3] == ELFMAG3)
+
+/* Values for e_type. */
+#define ET_NONE 0 /* Unknown type. */
+#define ET_REL 1 /* Relocatable. */
+#define ET_EXEC 2 /* Executable. */
+#define ET_DYN 3 /* Shared object. */
+#define ET_CORE 4 /* Core file. */
+#define ET_LOOS 0xfe00 /* First operating system specific. */
+#define ET_HIOS 0xfeff /* Last operating system-specific. */
+#define ET_LOPROC 0xff00 /* First processor-specific. */
+#define ET_HIPROC 0xffff /* Last processor-specific. */
+
+/* Values for e_machine. */
+#define EM_NONE 0 /* Unknown machine. */
+#define EM_M32 1 /* AT&T WE32100. */
+#define EM_SPARC 2 /* Sun SPARC. */
+#define EM_386 3 /* Intel i386. */
+#define EM_68K 4 /* Motorola 68000. */
+#define EM_88K 5 /* Motorola 88000. */
+#define EM_860 7 /* Intel i860. */
+#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */
+#define EM_S370 9 /* IBM System/370. */
+#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */
+#define EM_PARISC 15 /* HP PA-RISC. */
+#define EM_VPP500 17 /* Fujitsu VPP500. */
+#define EM_SPARC32PLUS 18 /* SPARC v8plus. */
+#define EM_960 19 /* Intel 80960. */
+#define EM_PPC 20 /* PowerPC 32-bit. */
+#define EM_PPC64 21 /* PowerPC 64-bit. */
+#define EM_S390 22 /* IBM System/390. */
+#define EM_V800 36 /* NEC V800. */
+#define EM_FR20 37 /* Fujitsu FR20. */
+#define EM_RH32 38 /* TRW RH-32. */
+#define EM_RCE 39 /* Motorola RCE. */
+#define EM_ARM 40 /* ARM. */
+#define EM_SH 42 /* Hitachi SH. */
+#define EM_SPARCV9 43 /* SPARC v9 64-bit. */
+#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */
+#define EM_ARC 45 /* Argonaut RISC Core. */
+#define EM_H8_300 46 /* Hitachi H8/300. */
+#define EM_H8_300H 47 /* Hitachi H8/300H. */
+#define EM_H8S 48 /* Hitachi H8S. */
+#define EM_H8_500 49 /* Hitachi H8/500. */
+#define EM_IA_64 50 /* Intel IA-64 Processor. */
+#define EM_MIPS_X 51 /* Stanford MIPS-X. */
+#define EM_COLDFIRE 52 /* Motorola ColdFire. */
+#define EM_68HC12 53 /* Motorola M68HC12. */
+#define EM_MMA 54 /* Fujitsu MMA. */
+#define EM_PCP 55 /* Siemens PCP. */
+#define EM_NCPU 56 /* Sony nCPU. */
+#define EM_NDR1 57 /* Denso NDR1 microprocessor. */
+#define EM_STARCORE 58 /* Motorola Star*Core processor. */
+#define EM_ME16 59 /* Toyota ME16 processor. */
+#define EM_ST100 60 /* STMicroelectronics ST100 processor. */
+#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */
+#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */
+#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */
+
+/* Non-standard or deprecated. */
+#define EM_486 6 /* Intel i486. */
+#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */
+#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */
+#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */
+
+/* Special section indexes. */
+#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */
+#define SHN_LORESERVE 0xff00 /* First of reserved range. */
+#define SHN_LOPROC 0xff00 /* First processor-specific. */
+#define SHN_HIPROC 0xff1f /* Last processor-specific. */
+#define SHN_LOOS 0xff20 /* First operating system-specific. */
+#define SHN_HIOS 0xff3f /* Last operating system-specific. */
+#define SHN_ABS 0xfff1 /* Absolute values. */
+#define SHN_COMMON 0xfff2 /* Common data. */
+#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */
+#define SHN_HIRESERVE 0xffff /* Last of reserved range. */
+
+/* sh_type */
+#define SHT_NULL 0 /* inactive */
+#define SHT_PROGBITS 1 /* program defined information */
+#define SHT_SYMTAB 2 /* symbol table section */
+#define SHT_STRTAB 3 /* string table section */
+#define SHT_RELA 4 /* relocation section with addends */
+#define SHT_HASH 5 /* symbol hash table section */
+#define SHT_DYNAMIC 6 /* dynamic section */
+#define SHT_NOTE 7 /* note section */
+#define SHT_NOBITS 8 /* no space section */
+#define SHT_REL 9 /* relocation section - no addends */
+#define SHT_SHLIB 10 /* reserved - purpose unknown */
+#define SHT_DYNSYM 11 /* dynamic symbol table section */
+#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */
+#define SHT_FINI_ARRAY 15 /* Termination function pointers. */
+#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */
+#define SHT_GROUP 17 /* Section group. */
+#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */
+#define SHT_LOOS 0x60000000 /* First of OS specific semantics */
+#define SHT_LOSUNW 0x6ffffff4
+#define SHT_SUNW_dof 0x6ffffff4
+#define SHT_SUNW_cap 0x6ffffff5
+#define SHT_SUNW_SIGNATURE 0x6ffffff6
+#define SHT_SUNW_ANNOTATE 0x6ffffff7
+#define SHT_SUNW_DEBUGSTR 0x6ffffff8
+#define SHT_SUNW_DEBUG 0x6ffffff9
+#define SHT_SUNW_move 0x6ffffffa
+#define SHT_SUNW_COMDAT 0x6ffffffb
+#define SHT_SUNW_syminfo 0x6ffffffc
+#define SHT_SUNW_verdef 0x6ffffffd
+#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */
+#define SHT_SUNW_verneed 0x6ffffffe
+#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */
+#define SHT_SUNW_versym 0x6fffffff
+#define SHT_GNU_versym 0x6fffffff /* Symbol version table */
+#define SHT_HISUNW 0x6fffffff
+#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */
+#define SHT_LOPROC 0x70000000 /* reserved range for processor */
+#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */
+#define SHT_HIPROC 0x7fffffff /* specific section header types */
+#define SHT_LOUSER 0x80000000 /* reserved range for application */
+#define SHT_HIUSER 0xffffffff /* specific indexes */
+
+/* Flags for sh_flags. */
+#define SHF_WRITE 0x1 /* Section contains writable data. */
+#define SHF_ALLOC 0x2 /* Section occupies memory. */
+#define SHF_EXECINSTR 0x4 /* Section contains instructions. */
+#define SHF_MERGE 0x10 /* Section may be merged. */
+#define SHF_STRINGS 0x20 /* Section contains strings. */
+#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */
+#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */
+#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */
+#define SHF_GROUP 0x200 /* Member of section group. */
+#define SHF_TLS 0x400 /* Section contains TLS data. */
+#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */
+#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */
+
+/* Values for p_type. */
+#define PT_NULL 0 /* Unused entry. */
+#define PT_LOAD 1 /* Loadable segment. */
+#define PT_DYNAMIC 2 /* Dynamic linking information segment. */
+#define PT_INTERP 3 /* Pathname of interpreter. */
+#define PT_NOTE 4 /* Auxiliary information. */
+#define PT_SHLIB 5 /* Reserved (not used). */
+#define PT_PHDR 6 /* Location of program header itself. */
+#define PT_TLS 7 /* Thread local storage segment */
+#define PT_LOOS 0x60000000 /* First OS-specific. */
+#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */
+#define PT_GNU_EH_FRAME 0x6474e550
+#define PT_LOSUNW 0x6ffffffa
+#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
+#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */
+#define PT_SUNWDTRACE 0x6ffffffc /* private */
+#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */
+#define PT_HISUNW 0x6fffffff
+#define PT_HIOS 0x6fffffff /* Last OS-specific. */
+#define PT_LOPROC 0x70000000 /* First processor-specific type. */
+#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */
+
+/* Values for p_flags. */
+#define PF_X 0x1 /* Executable. */
+#define PF_W 0x2 /* Writable. */
+#define PF_R 0x4 /* Readable. */
+#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */
+#define PF_MASKPROC 0xf0000000 /* Processor-specific. */
+
+/* Extended program header index. */
+#define PN_XNUM 0xffff
+
+/* Values for d_tag. */
+#define DT_NULL 0 /* Terminating entry. */
+#define DT_NEEDED 1 /* String table offset of a needed shared
+ library. */
+#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */
+#define DT_PLTGOT 3 /* Processor-dependent address. */
+#define DT_HASH 4 /* Address of symbol hash table. */
+#define DT_STRTAB 5 /* Address of string table. */
+#define DT_SYMTAB 6 /* Address of symbol table. */
+#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */
+#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */
+#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */
+#define DT_STRSZ 10 /* Size of string table. */
+#define DT_SYMENT 11 /* Size of each symbol table entry. */
+#define DT_INIT 12 /* Address of initialization function. */
+#define DT_FINI 13 /* Address of finalization function. */
+#define DT_SONAME 14 /* String table offset of shared object
+ name. */
+#define DT_RPATH 15 /* String table offset of library path. [sup] */
+#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */
+#define DT_REL 17 /* Address of ElfNN_Rel relocations. */
+#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */
+#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */
+#define DT_PLTREL 20 /* Type of relocation used for PLT. */
+#define DT_DEBUG 21 /* Reserved (not used). */
+#define DT_TEXTREL 22 /* Indicates there may be relocations in
+ non-writable segments. [sup] */
+#define DT_JMPREL 23 /* Address of PLT relocations. */
+#define DT_BIND_NOW 24 /* [sup] */
+#define DT_INIT_ARRAY 25 /* Address of the array of pointers to
+ initialization functions */
+#define DT_FINI_ARRAY 26 /* Address of the array of pointers to
+ termination functions */
+#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of
+ initialization functions. */
+#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of
+ terminationfunctions. */
+#define DT_RUNPATH 29 /* String table offset of a null-terminated
+ library search path string. */
+#define DT_FLAGS 30 /* Object specific flag values. */
+#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING
+ and less than DT_LOOS follow the rules for
+ the interpretation of the d_un union
+ as follows: even == 'd_ptr', even == 'd_val'
+ or none */
+#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to
+ pre-initialization functions. */
+#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of
+ pre-initialization functions. */
+#define DT_MAXPOSTAGS 34 /* number of positive tags */
+#define DT_LOOS 0x6000000d /* First OS-specific */
+#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */
+#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */
+#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */
+#define DT_SUNW_CAP 0x60000010 /* hardware/software */
+#define DT_HIOS 0x6ffff000 /* Last OS-specific */
+
+/*
+ * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
+ * Dyn.d_un.d_val field of the Elf*_Dyn structure.
+ */
+#define DT_VALRNGLO 0x6ffffd00
+#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */
+#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */
+#define DT_MOVEENT 0x6ffffdfa /* move table entry size */
+#define DT_MOVESZ 0x6ffffdfb /* move table size */
+#define DT_FEATURE_1 0x6ffffdfc /* feature holder */
+#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */
+ /* the following DT_* entry. */
+ /* See DF_P1_* definitions */
+#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */
+#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */
+#define DT_VALRNGHI 0x6ffffdff
+
+/*
+ * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
+ * Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
+ *
+ * If any adjustment is made to the ELF object after it has been
+ * built, these entries will need to be adjusted.
+ */
+#define DT_ADDRRNGLO 0x6ffffe00
+#define DT_CONFIG 0x6ffffefa /* configuration information */
+#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */
+#define DT_AUDIT 0x6ffffefc /* object auditing */
+#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */
+#define DT_MOVETAB 0x6ffffefe /* move table */
+#define DT_SYMINFO 0x6ffffeff /* syminfo table */
+#define DT_ADDRRNGHI 0x6ffffeff
+
+#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */
+#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */
+#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */
+#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */
+#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */
+#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */
+#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */
+#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */
+
+#define DT_LOPROC 0x70000000 /* First processor-specific type. */
+#define DT_DEPRECATED_SPARC_REGISTER 0x7000001
+#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */
+#define DT_USED 0x7ffffffe /* ignored - same as needed */
+#define DT_FILTER 0x7fffffff /* shared library filter name */
+#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */
+
+/* Values for DT_FLAGS */
+#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may
+ make reference to the $ORIGIN substitution
+ string */
+#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */
+#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in
+ non-writable segments. */
+#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should
+ process all relocations for the object
+ containing this entry before transferring
+ control to the program. */
+#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or
+ executable contains code using a static
+ thread-local storage scheme. */
+
+/* Values for n_type. Used in core files. */
+#define NT_PRSTATUS 1 /* Process status. */
+#define NT_FPREGSET 2 /* Floating point registers. */
+#define NT_PRPSINFO 3 /* Process state info. */
+
+/* Symbol Binding - ELFNN_ST_BIND - st_info */
+#define STB_LOCAL 0 /* Local symbol */
+#define STB_GLOBAL 1 /* Global symbol */
+#define STB_WEAK 2 /* like global - lower precedence */
+#define STB_LOOS 10 /* Reserved range for operating system */
+#define STB_HIOS 12 /* specific semantics. */
+#define STB_LOPROC 13 /* reserved range for processor */
+#define STB_HIPROC 15 /* specific semantics. */
+
+/* Symbol type - ELFNN_ST_TYPE - st_info */
+#define STT_NOTYPE 0 /* Unspecified type. */
+#define STT_OBJECT 1 /* Data object. */
+#define STT_FUNC 2 /* Function. */
+#define STT_SECTION 3 /* Section. */
+#define STT_FILE 4 /* Source file. */
+#define STT_COMMON 5 /* Uninitialized common block. */
+#define STT_TLS 6 /* TLS object. */
+#define STT_NUM 7
+#define STT_LOOS 10 /* Reserved range for operating system */
+#define STT_HIOS 12 /* specific semantics. */
+#define STT_LOPROC 13 /* reserved range for processor */
+#define STT_HIPROC 15 /* specific semantics. */
+
+/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */
+#define STV_DEFAULT 0x0 /* Default visibility (see binding). */
+#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */
+#define STV_HIDDEN 0x2 /* Not visible. */
+#define STV_PROTECTED 0x3 /* Visible but not preemptible. */
+
+/* Special symbol table indexes. */
+#define STN_UNDEF 0 /* Undefined symbol index. */
+
+/* Symbol versioning flags. */
+#define VER_DEF_CURRENT 1
+#define VER_DEF_IDX(x) VER_NDX(x)
+
+#define VER_FLG_BASE 0x01
+#define VER_FLG_WEAK 0x02
+
+#define VER_NEED_CURRENT 1
+#define VER_NEED_WEAK (1u << 15)
+#define VER_NEED_HIDDEN VER_NDX_HIDDEN
+#define VER_NEED_IDX(x) VER_NDX(x)
+
+#define VER_NDX_LOCAL 0
+#define VER_NDX_GLOBAL 1
+#define VER_NDX_GIVEN 2
+
+#define VER_NDX_HIDDEN (1u << 15)
+#define VER_NDX(x) ((x) & ~(1u << 15))
+
+#define CA_SUNW_NULL 0
+#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */
+#define CA_SUNW_SF_1 2 /* first software capabilities entry */
+
+/*
+ * Syminfo flag values
+ */
+#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */
+ /* to object containing defn. */
+#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */
+#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */
+#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */
+ /* lazily-loaded */
+#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */
+ /* object containing defn. */
+#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */
+ /* directly bind to this symbol */
+#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */
+#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */
+
+/*
+ * Syminfo.si_boundto values.
+ */
+#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */
+#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */
+#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */
+#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */
+#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */
+
+/*
+ * Syminfo version values.
+ */
+#define SYMINFO_NONE 0 /* Syminfo version */
+#define SYMINFO_CURRENT 1
+#define SYMINFO_NUM 2
+
+/*
+ * Relocation types.
+ *
+ * All machine architectures are defined here to allow tools on one to
+ * handle others.
+ */
+
+#define R_386_NONE 0 /* No relocation. */
+#define R_386_32 1 /* Add symbol value. */
+#define R_386_PC32 2 /* Add PC-relative symbol value. */
+#define R_386_GOT32 3 /* Add PC-relative GOT offset. */
+#define R_386_PLT32 4 /* Add PC-relative PLT offset. */
+#define R_386_COPY 5 /* Copy data from shared object. */
+#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */
+#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */
+#define R_386_RELATIVE 8 /* Add load address of shared object. */
+#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */
+#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */
+#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */
+#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */
+#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */
+#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */
+#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */
+#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */
+#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */
+#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */
+#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */
+#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */
+#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */
+#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */
+#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */
+#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */
+#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */
+#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */
+#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */
+#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */
+#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */
+#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */
+
+#define R_ALPHA_NONE 0 /* No reloc */
+#define R_ALPHA_REFLONG 1 /* Direct 32 bit */
+#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */
+#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */
+#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */
+#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */
+#define R_ALPHA_GPDISP 6 /* Add displacement to GP */
+#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */
+#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */
+#define R_ALPHA_SREL16 9 /* PC relative 16 bit */
+#define R_ALPHA_SREL32 10 /* PC relative 32 bit */
+#define R_ALPHA_SREL64 11 /* PC relative 64 bit */
+#define R_ALPHA_OP_PUSH 12 /* OP stack push */
+#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */
+#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */
+#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */
+#define R_ALPHA_GPVALUE 16
+#define R_ALPHA_GPRELHIGH 17
+#define R_ALPHA_GPRELLOW 18
+#define R_ALPHA_IMMED_GP_16 19
+#define R_ALPHA_IMMED_GP_HI32 20
+#define R_ALPHA_IMMED_SCN_HI32 21
+#define R_ALPHA_IMMED_BR_HI32 22
+#define R_ALPHA_IMMED_LO32 23
+#define R_ALPHA_COPY 24 /* Copy symbol at runtime */
+#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */
+#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */
+#define R_ALPHA_RELATIVE 27 /* Adjust by program base */
+
+#define R_ARM_NONE 0 /* No relocation. */
+#define R_ARM_PC24 1
+#define R_ARM_ABS32 2
+#define R_ARM_REL32 3
+#define R_ARM_PC13 4
+#define R_ARM_ABS16 5
+#define R_ARM_ABS12 6
+#define R_ARM_THM_ABS5 7
+#define R_ARM_ABS8 8
+#define R_ARM_SBREL32 9
+#define R_ARM_THM_PC22 10
+#define R_ARM_THM_PC8 11
+#define R_ARM_AMP_VCALL9 12
+#define R_ARM_SWI24 13
+#define R_ARM_THM_SWI8 14
+#define R_ARM_XPC25 15
+#define R_ARM_THM_XPC22 16
+#define R_ARM_COPY 20 /* Copy data from shared object. */
+#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */
+#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */
+#define R_ARM_RELATIVE 23 /* Add load address of shared object. */
+#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */
+#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */
+#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */
+#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */
+#define R_ARM_GNU_VTENTRY 100
+#define R_ARM_GNU_VTINHERIT 101
+#define R_ARM_RSBREL32 250
+#define R_ARM_THM_RPC22 251
+#define R_ARM_RREL32 252
+#define R_ARM_RABS32 253
+#define R_ARM_RPC24 254
+#define R_ARM_RBASE 255
+
+/* Name Value Field Calculation */
+#define R_IA_64_NONE 0 /* None */
+#define R_IA_64_IMM14 0x21 /* immediate14 S + A */
+#define R_IA_64_IMM22 0x22 /* immediate22 S + A */
+#define R_IA_64_IMM64 0x23 /* immediate64 S + A */
+#define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */
+#define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */
+#define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */
+#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */
+#define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */
+#define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */
+#define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */
+#define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */
+#define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */
+#define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */
+#define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */
+#define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */
+#define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */
+#define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */
+#define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */
+#define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */
+#define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */
+#define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */
+#define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */
+#define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */
+#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */
+#define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */
+#define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */
+#define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */
+#define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */
+#define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */
+#define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */
+#define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */
+#define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */
+#define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */
+#define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */
+#define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */
+#define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */
+#define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */
+#define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */
+#define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */
+#define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */
+#define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */
+#define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */
+#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */
+#define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */
+#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */
+#define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */
+#define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */
+#define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */
+#define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */
+#define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */
+#define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */
+#define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */
+#define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */
+#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */
+#define R_IA_64_SUB 0x85 /* immediate64 A - S */
+#define R_IA_64_LTOFF22X 0x86 /* immediate22 special */
+#define R_IA_64_LDXMOV 0x87 /* immediate22 special */
+#define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */
+#define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */
+#define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */
+#define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */
+#define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */
+#define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */
+#define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */
+#define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */
+#define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */
+#define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */
+#define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */
+#define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */
+#define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */
+#define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */
+#define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */
+#define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */
+#define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */
+
+#define R_PPC_NONE 0 /* No relocation. */
+#define R_PPC_ADDR32 1
+#define R_PPC_ADDR24 2
+#define R_PPC_ADDR16 3
+#define R_PPC_ADDR16_LO 4
+#define R_PPC_ADDR16_HI 5
+#define R_PPC_ADDR16_HA 6
+#define R_PPC_ADDR14 7
+#define R_PPC_ADDR14_BRTAKEN 8
+#define R_PPC_ADDR14_BRNTAKEN 9
+#define R_PPC_REL24 10
+#define R_PPC_REL14 11
+#define R_PPC_REL14_BRTAKEN 12
+#define R_PPC_REL14_BRNTAKEN 13
+#define R_PPC_GOT16 14
+#define R_PPC_GOT16_LO 15
+#define R_PPC_GOT16_HI 16
+#define R_PPC_GOT16_HA 17
+#define R_PPC_PLTREL24 18
+#define R_PPC_COPY 19
+#define R_PPC_GLOB_DAT 20
+#define R_PPC_JMP_SLOT 21
+#define R_PPC_RELATIVE 22
+#define R_PPC_LOCAL24PC 23
+#define R_PPC_UADDR32 24
+#define R_PPC_UADDR16 25
+#define R_PPC_REL32 26
+#define R_PPC_PLT32 27
+#define R_PPC_PLTREL32 28
+#define R_PPC_PLT16_LO 29
+#define R_PPC_PLT16_HI 30
+#define R_PPC_PLT16_HA 31
+#define R_PPC_SDAREL16 32
+#define R_PPC_SECTOFF 33
+#define R_PPC_SECTOFF_LO 34
+#define R_PPC_SECTOFF_HI 35
+#define R_PPC_SECTOFF_HA 36
+
+/*
+ * TLS relocations
+ */
+#define R_PPC_TLS 67
+#define R_PPC_DTPMOD32 68
+#define R_PPC_TPREL16 69
+#define R_PPC_TPREL16_LO 70
+#define R_PPC_TPREL16_HI 71
+#define R_PPC_TPREL16_HA 72
+#define R_PPC_TPREL32 73
+#define R_PPC_DTPREL16 74
+#define R_PPC_DTPREL16_LO 75
+#define R_PPC_DTPREL16_HI 76
+#define R_PPC_DTPREL16_HA 77
+#define R_PPC_DTPREL32 78
+#define R_PPC_GOT_TLSGD16 79
+#define R_PPC_GOT_TLSGD16_LO 80
+#define R_PPC_GOT_TLSGD16_HI 81
+#define R_PPC_GOT_TLSGD16_HA 82
+#define R_PPC_GOT_TLSLD16 83
+#define R_PPC_GOT_TLSLD16_LO 84
+#define R_PPC_GOT_TLSLD16_HI 85
+#define R_PPC_GOT_TLSLD16_HA 86
+#define R_PPC_GOT_TPREL16 87
+#define R_PPC_GOT_TPREL16_LO 88
+#define R_PPC_GOT_TPREL16_HI 89
+#define R_PPC_GOT_TPREL16_HA 90
+
+/*
+ * The remaining relocs are from the Embedded ELF ABI, and are not in the
+ * SVR4 ELF ABI.
+ */
+
+#define R_PPC_EMB_NADDR32 101
+#define R_PPC_EMB_NADDR16 102
+#define R_PPC_EMB_NADDR16_LO 103
+#define R_PPC_EMB_NADDR16_HI 104
+#define R_PPC_EMB_NADDR16_HA 105
+#define R_PPC_EMB_SDAI16 106
+#define R_PPC_EMB_SDA2I16 107
+#define R_PPC_EMB_SDA2REL 108
+#define R_PPC_EMB_SDA21 109
+#define R_PPC_EMB_MRKREF 110
+#define R_PPC_EMB_RELSEC16 111
+#define R_PPC_EMB_RELST_LO 112
+#define R_PPC_EMB_RELST_HI 113
+#define R_PPC_EMB_RELST_HA 114
+#define R_PPC_EMB_BIT_FLD 115
+#define R_PPC_EMB_RELSDA 116
+
+#define R_SPARC_NONE 0
+#define R_SPARC_8 1
+#define R_SPARC_16 2
+#define R_SPARC_32 3
+#define R_SPARC_DISP8 4
+#define R_SPARC_DISP16 5
+#define R_SPARC_DISP32 6
+#define R_SPARC_WDISP30 7
+#define R_SPARC_WDISP22 8
+#define R_SPARC_HI22 9
+#define R_SPARC_22 10
+#define R_SPARC_13 11
+#define R_SPARC_LO10 12
+#define R_SPARC_GOT10 13
+#define R_SPARC_GOT13 14
+#define R_SPARC_GOT22 15
+#define R_SPARC_PC10 16
+#define R_SPARC_PC22 17
+#define R_SPARC_WPLT30 18
+#define R_SPARC_COPY 19
+#define R_SPARC_GLOB_DAT 20
+#define R_SPARC_JMP_SLOT 21
+#define R_SPARC_RELATIVE 22
+#define R_SPARC_UA32 23
+#define R_SPARC_PLT32 24
+#define R_SPARC_HIPLT22 25
+#define R_SPARC_LOPLT10 26
+#define R_SPARC_PCPLT32 27
+#define R_SPARC_PCPLT22 28
+#define R_SPARC_PCPLT10 29
+#define R_SPARC_10 30
+#define R_SPARC_11 31
+#define R_SPARC_64 32
+#define R_SPARC_OLO10 33
+#define R_SPARC_HH22 34
+#define R_SPARC_HM10 35
+#define R_SPARC_LM22 36
+#define R_SPARC_PC_HH22 37
+#define R_SPARC_PC_HM10 38
+#define R_SPARC_PC_LM22 39
+#define R_SPARC_WDISP16 40
+#define R_SPARC_WDISP19 41
+#define R_SPARC_GLOB_JMP 42
+#define R_SPARC_7 43
+#define R_SPARC_5 44
+#define R_SPARC_6 45
+#define R_SPARC_DISP64 46
+#define R_SPARC_PLT64 47
+#define R_SPARC_HIX22 48
+#define R_SPARC_LOX10 49
+#define R_SPARC_H44 50
+#define R_SPARC_M44 51
+#define R_SPARC_L44 52
+#define R_SPARC_REGISTER 53
+#define R_SPARC_UA64 54
+#define R_SPARC_UA16 55
+#define R_SPARC_TLS_GD_HI22 56
+#define R_SPARC_TLS_GD_LO10 57
+#define R_SPARC_TLS_GD_ADD 58
+#define R_SPARC_TLS_GD_CALL 59
+#define R_SPARC_TLS_LDM_HI22 60
+#define R_SPARC_TLS_LDM_LO10 61
+#define R_SPARC_TLS_LDM_ADD 62
+#define R_SPARC_TLS_LDM_CALL 63
+#define R_SPARC_TLS_LDO_HIX22 64
+#define R_SPARC_TLS_LDO_LOX10 65
+#define R_SPARC_TLS_LDO_ADD 66
+#define R_SPARC_TLS_IE_HI22 67
+#define R_SPARC_TLS_IE_LO10 68
+#define R_SPARC_TLS_IE_LD 69
+#define R_SPARC_TLS_IE_LDX 70
+#define R_SPARC_TLS_IE_ADD 71
+#define R_SPARC_TLS_LE_HIX22 72
+#define R_SPARC_TLS_LE_LOX10 73
+#define R_SPARC_TLS_DTPMOD32 74
+#define R_SPARC_TLS_DTPMOD64 75
+#define R_SPARC_TLS_DTPOFF32 76
+#define R_SPARC_TLS_DTPOFF64 77
+#define R_SPARC_TLS_TPOFF32 78
+#define R_SPARC_TLS_TPOFF64 79
+
+#define R_X86_64_NONE 0 /* No relocation. */
+#define R_X86_64_64 1 /* Add 64 bit symbol value. */
+#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */
+#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */
+#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */
+#define R_X86_64_COPY 5 /* Copy data from shared object. */
+#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */
+#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */
+#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */
+#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */
+#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */
+#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */
+#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */
+#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */
+#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */
+#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */
+#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */
+#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */
+#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */
+#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */
+#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */
+#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */
+#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */
+#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */
+
+
+#endif /* !_SYS_ELF_COMMON_H_ */
diff --git a/BaseTools/Source/C/GenFw/elf_generic.h b/BaseTools/Source/C/GenFw/elf_generic.h
new file mode 100644
index 0000000000..dd4f8e14fd
--- /dev/null
+++ b/BaseTools/Source/C/GenFw/elf_generic.h
@@ -0,0 +1,88 @@
+/*-
+ * Copyright (c) 1998 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/sys/elf_generic.h,v 1.6.14.2 2007/12/03 21:30:36 marius Exp $
+ */
+
+#ifndef _SYS_ELF_GENERIC_H_
+#define _SYS_ELF_GENERIC_H_ 1
+
+#include <sys/cdefs.h>
+
+/*
+ * Definitions of generic ELF names which relieve applications from
+ * needing to know the word size.
+ */
+
+#if __ELF_WORD_SIZE != 32 && __ELF_WORD_SIZE != 64
+#error "__ELF_WORD_SIZE must be defined as 32 or 64"
+#endif
+
+#define ELF_CLASS __CONCAT(ELFCLASS,__ELF_WORD_SIZE)
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define ELF_DATA ELFDATA2LSB
+#elif BYTE_ORDER == BIG_ENDIAN
+#define ELF_DATA ELFDATA2MSB
+#else
+#error "Unknown byte order"
+#endif
+
+#define __elfN(x) __CONCAT(__CONCAT(__CONCAT(elf,__ELF_WORD_SIZE),_),x)
+#define __ElfN(x) __CONCAT(__CONCAT(__CONCAT(Elf,__ELF_WORD_SIZE),_),x)
+#define __ELFN(x) __CONCAT(__CONCAT(__CONCAT(ELF,__ELF_WORD_SIZE),_),x)
+#define __ElfType(x) typedef __ElfN(x) __CONCAT(Elf_,x)
+
+__ElfType(Addr);
+__ElfType(Half);
+__ElfType(Off);
+__ElfType(Sword);
+__ElfType(Word);
+__ElfType(Ehdr);
+__ElfType(Shdr);
+__ElfType(Phdr);
+__ElfType(Dyn);
+__ElfType(Rel);
+__ElfType(Rela);
+__ElfType(Sym);
+__ElfType(Verdef);
+__ElfType(Verdaux);
+__ElfType(Verneed);
+__ElfType(Vernaux);
+__ElfType(Versym);
+
+/* Non-standard ELF types. */
+__ElfType(Hashelt);
+__ElfType(Size);
+__ElfType(Ssize);
+
+#define ELF_R_SYM __ELFN(R_SYM)
+#define ELF_R_TYPE __ELFN(R_TYPE)
+#define ELF_R_INFO __ELFN(R_INFO)
+#define ELF_ST_BIND __ELFN(ST_BIND)
+#define ELF_ST_TYPE __ELFN(ST_TYPE)
+#define ELF_ST_INFO __ELFN(ST_INFO)
+
+#endif /* !_SYS_ELF_GENERIC_H_ */