From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- .../BaseTools/Source/C/GenFw/Elf32Convert.c | 1177 +++++++ .../BaseTools/Source/C/GenFw/Elf32Convert.h | 19 + .../BaseTools/Source/C/GenFw/Elf64Convert.c | 1668 ++++++++++ .../BaseTools/Source/C/GenFw/Elf64Convert.h | 19 + .../Firmware/BaseTools/Source/C/GenFw/ElfConvert.c | 245 ++ .../Firmware/BaseTools/Source/C/GenFw/ElfConvert.h | 81 + .../Firmware/BaseTools/Source/C/GenFw/GNUmakefile | 23 + .../EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.c | 3255 ++++++++++++++++++++ .../EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.h | 50 + .../EFI/Firmware/BaseTools/Source/C/GenFw/Makefile | 18 + .../Firmware/BaseTools/Source/C/GenFw/Makefile.kmk | 49 + .../EFI/Firmware/BaseTools/Source/C/GenFw/elf32.h | 252 ++ .../EFI/Firmware/BaseTools/Source/C/GenFw/elf64.h | 254 ++ .../Firmware/BaseTools/Source/C/GenFw/elf_common.h | 1045 +++++++ 14 files changed, 8155 insertions(+) create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/ElfConvert.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/ElfConvert.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GNUmakefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Makefile.kmk create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf32.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf64.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf_common.h (limited to 'src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw') diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.c new file mode 100644 index 00000000..f93eeb47 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.c @@ -0,0 +1,1177 @@ +/** @file +Elf32 Convert solution + +Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.
+Portions copyright (c) 2013, ARM Ltd. All rights reserved.
+Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "WinNtInclude.h" + +#ifndef __GNUC__ +#include +#include +#endif +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "PeCoffLib.h" +#include "EfiUtilityMsgs.h" + +#include "GenFw.h" +#include "ElfConvert.h" +#include "Elf32Convert.h" + +STATIC +VOID +ScanSections32 ( + VOID + ); + +STATIC +BOOLEAN +WriteSections32 ( + SECTION_FILTER_TYPES FilterType + ); + +STATIC +VOID +WriteRelocations32 ( + VOID + ); + +STATIC +VOID +WriteDebug32 ( + VOID + ); + +STATIC +VOID +SetImageSize32 ( + VOID + ); + +STATIC +VOID +CleanUp32 ( + VOID + ); + +// +// Rename ELF32 structures to common names to help when porting to ELF64. +// +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. +// +STATIC Elf_Ehdr *mEhdr; +STATIC Elf_Shdr *mShdrBase; +STATIC Elf_Phdr *mPhdrBase; + +// +// Coff information +// +STATIC UINT32 mCoffAlignment = 0x20; + +// +// PE section alignment. +// +STATIC const UINT16 mCoffNbrSections = 4; + +// +// ELF sections to offset in Coff file. +// +STATIC UINT32 *mCoffSectionsOffset = NULL; + +// +// Offsets in COFF file +// +STATIC UINT32 mNtHdrOffset; +STATIC UINT32 mTextOffset; +STATIC UINT32 mDataOffset; +STATIC UINT32 mHiiRsrcOffset; +STATIC UINT32 mRelocOffset; +STATIC UINT32 mDebugOffset; + +// +// Initialization Function +// +BOOLEAN +InitializeElf32 ( + UINT8 *FileBuffer, + ELF_FUNCTION_TABLE *ElfFunctions + ) +{ + // + // Initialize data pointer and structures. + // + mEhdr = (Elf_Ehdr*) FileBuffer; + + // + // Check the ELF32 specific header information. + // + if (mEhdr->e_ident[EI_CLASS] != ELFCLASS32) { + Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFCLASS32"); + return FALSE; + } + if (mEhdr->e_ident[EI_DATA] != ELFDATA2LSB) { + Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB"); + return FALSE; + } + if ((mEhdr->e_type != ET_EXEC) && (mEhdr->e_type != ET_DYN)) { + Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN"); + return FALSE; + } + if (!((mEhdr->e_machine == EM_386) || (mEhdr->e_machine == EM_ARM) || (mEhdr->e_machine == EM_RISCV))) { + Warning (NULL, 0, 3000, "Unsupported", "ELF e_machine is not Elf32 machine."); + } + if (mEhdr->e_version != EV_CURRENT) { + Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) mEhdr->e_version, EV_CURRENT); + return FALSE; + } + + // + // Update section header pointers + // + mShdrBase = (Elf_Shdr *)((UINT8 *)mEhdr + mEhdr->e_shoff); + mPhdrBase = (Elf_Phdr *)((UINT8 *)mEhdr + mEhdr->e_phoff); + + // + // Create COFF Section offset buffer and zero. + // + mCoffSectionsOffset = (UINT32 *)malloc(mEhdr->e_shnum * sizeof (UINT32)); + if (mCoffSectionsOffset == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return FALSE; + } + memset(mCoffSectionsOffset, 0, mEhdr->e_shnum * sizeof(UINT32)); + + // + // Fill in function pointers. + // + ElfFunctions->ScanSections = ScanSections32; + ElfFunctions->WriteSections = WriteSections32; + ElfFunctions->WriteRelocations = WriteRelocations32; + ElfFunctions->WriteDebug = WriteDebug32; + ElfFunctions->SetImageSize = SetImageSize32; + ElfFunctions->CleanUp = CleanUp32; + + return TRUE; +} + + +// +// Header by Index functions +// +STATIC +Elf_Shdr* +GetShdrByIndex ( + UINT32 Num + ) +{ + if (Num >= mEhdr->e_shnum) { + Error (NULL, 0, 3000, "Invalid", "GetShdrByIndex: Index %u is too high.", Num); + exit(EXIT_FAILURE); + } + + return (Elf_Shdr*)((UINT8*)mShdrBase + Num * mEhdr->e_shentsize); +} + +STATIC +Elf_Phdr* +GetPhdrByIndex ( + UINT32 num + ) +{ + if (num >= mEhdr->e_phnum) { + Error (NULL, 0, 3000, "Invalid", "GetPhdrByIndex: Index %u is too high.", num); + exit(EXIT_FAILURE); + } + + return (Elf_Phdr *)((UINT8*)mPhdrBase + num * mEhdr->e_phentsize); +} + +STATIC +UINT32 +CoffAlign ( + UINT32 Offset + ) +{ + return (Offset + mCoffAlignment - 1) & ~(mCoffAlignment - 1); +} + +STATIC +UINT32 +DebugRvaAlign ( + UINT32 Offset + ) +{ + return (Offset + 3) & ~3; +} + +// +// filter functions +// +STATIC +BOOLEAN +IsTextShdr ( + Elf_Shdr *Shdr + ) +{ + return (BOOLEAN) ((Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC); +} + +STATIC +BOOLEAN +IsHiiRsrcShdr ( + Elf_Shdr *Shdr + ) +{ + Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx); + + return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0); +} + +STATIC +BOOLEAN +IsDataShdr ( + Elf_Shdr *Shdr + ) +{ + if (IsHiiRsrcShdr(Shdr)) { + return FALSE; + } + return (BOOLEAN) (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE); +} + +STATIC +BOOLEAN +IsStrtabShdr ( + Elf_Shdr *Shdr + ) +{ + Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx); + + return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_STRTAB_SECTION_NAME) == 0); +} + +STATIC +Elf_Shdr * +FindStrtabShdr ( + VOID + ) +{ + UINT32 i; + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (IsStrtabShdr(shdr)) { + return shdr; + } + } + return NULL; +} + +STATIC +const UINT8 * +GetSymName ( + Elf_Sym *Sym + ) +{ + Elf_Shdr *StrtabShdr; + UINT8 *StrtabContents; + BOOLEAN foundEnd; + UINT32 i; + + if (Sym->st_name == 0) { + return NULL; + } + + StrtabShdr = FindStrtabShdr(); + if (StrtabShdr == NULL) { + return NULL; + } + + assert(Sym->st_name < StrtabShdr->sh_size); + + StrtabContents = (UINT8*)mEhdr + StrtabShdr->sh_offset; + + foundEnd = FALSE; + for (i = Sym->st_name; (i < StrtabShdr->sh_size) && !foundEnd; i++) { + foundEnd = (BOOLEAN)(StrtabContents[i] == 0); + } + assert(foundEnd); + + return StrtabContents + Sym->st_name; +} + +// +// Elf functions interface implementation +// + +STATIC +VOID +ScanSections32 ( + VOID + ) +{ + UINT32 i; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + UINT32 CoffEntry; + UINT32 SectionCount; + BOOLEAN FoundSection; + + CoffEntry = 0; + mCoffOffset = 0; + + // + // Coff file start with a DOS header. + // + mCoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40; + mNtHdrOffset = mCoffOffset; + switch (mEhdr->e_machine) { + case EM_386: + case EM_ARM: + mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32); + break; + default: + VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)mEhdr->e_machine); + mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32); + break; + } + + mTableOffset = mCoffOffset; + mCoffOffset += mCoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER); + + // + // Set mCoffAlignment to the maximum alignment of the input sections + // we care about + // + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (shdr->sh_addralign <= mCoffAlignment) { + continue; + } + if (IsTextShdr(shdr) || IsDataShdr(shdr) || IsHiiRsrcShdr(shdr)) { + mCoffAlignment = (UINT32)shdr->sh_addralign; + } + } + + // + // Check if mCoffAlignment is larger than MAX_COFF_ALIGNMENT + // + if (mCoffAlignment > MAX_COFF_ALIGNMENT) { + Error (NULL, 0, 3000, "Invalid", "Section alignment is larger than MAX_COFF_ALIGNMENT."); + assert (FALSE); + } + + // + // Move the PE/COFF header right before the first section. This will help us + // save space when converting to TE. + // + if (mCoffAlignment > mCoffOffset) { + mNtHdrOffset += mCoffAlignment - mCoffOffset; + mTableOffset += mCoffAlignment - mCoffOffset; + mCoffOffset = mCoffAlignment; + } + + // + // First text sections. + // + mCoffOffset = CoffAlign(mCoffOffset); + mTextOffset = mCoffOffset; + FoundSection = FALSE; + SectionCount = 0; + for (i = 0; i < mEhdr->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 + mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1); + } else { + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment."); + } + } + + /* Relocate entry. */ + if ((mEhdr->e_entry >= shdr->sh_addr) && + (mEhdr->e_entry < shdr->sh_addr + shdr->sh_size)) { + CoffEntry = mCoffOffset + mEhdr->e_entry - shdr->sh_addr; + } + + // + // Set mTextOffset with the offset of the first '.text' section + // + if (!FoundSection) { + mTextOffset = mCoffOffset; + FoundSection = TRUE; + } + + mCoffSectionsOffset[i] = mCoffOffset; + mCoffOffset += shdr->sh_size; + SectionCount ++; + } + } + + if (!FoundSection) { + Error (NULL, 0, 3000, "Invalid", "Did not find any '.text' section."); + assert (FALSE); + } + + mDebugOffset = DebugRvaAlign(mCoffOffset); + mCoffOffset = CoffAlign(mCoffOffset); + + if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) { + Warning (NULL, 0, 0, NULL, "Multiple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName); + } + + // + // Then data sections. + // + mDataOffset = mCoffOffset; + FoundSection = FALSE; + SectionCount = 0; + for (i = 0; i < mEhdr->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 + mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1); + } else { + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment."); + } + } + + // + // Set mDataOffset with the offset of the first '.data' section + // + if (!FoundSection) { + mDataOffset = mCoffOffset; + FoundSection = TRUE; + } + + mCoffSectionsOffset[i] = mCoffOffset; + mCoffOffset += shdr->sh_size; + SectionCount ++; + } + } + + if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) { + Warning (NULL, 0, 0, NULL, "Multiple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName); + } + + // + // Make room for .debug data in .data (or .text if .data is empty) instead of + // putting it in a section of its own. This is explicitly allowed by the + // PE/COFF spec, and prevents bloat in the binary when using large values for + // section alignment. + // + if (SectionCount > 0) { + mDebugOffset = DebugRvaAlign(mCoffOffset); + } + mCoffOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) + + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + + strlen(mInImageName) + 1; + + mCoffOffset = CoffAlign(mCoffOffset); + if (SectionCount == 0) { + mDataOffset = mCoffOffset; + } + + // + // The HII resource sections. + // + mHiiRsrcOffset = mCoffOffset; + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (IsHiiRsrcShdr(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 + mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1); + } else { + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment."); + } + } + if (shdr->sh_size != 0) { + mHiiRsrcOffset = mCoffOffset; + mCoffSectionsOffset[i] = mCoffOffset; + mCoffOffset += shdr->sh_size; + mCoffOffset = CoffAlign(mCoffOffset); + SetHiiResourceHeader ((UINT8*) mEhdr + shdr->sh_offset, mHiiRsrcOffset); + } + break; + } + } + + mRelocOffset = mCoffOffset; + + // + // Allocate base Coff file. Will be expanded later for relocations. + // + mCoffFile = (UINT8 *)malloc(mCoffOffset); + if (mCoffFile == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + } + assert (mCoffFile != NULL); + memset(mCoffFile, 0, mCoffOffset); + + // + // Fill headers. + // + DosHdr = (EFI_IMAGE_DOS_HEADER *)mCoffFile; + DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE; + DosHdr->e_lfanew = mNtHdrOffset; + + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(mCoffFile + mNtHdrOffset); + + NtHdr->Pe32.Signature = EFI_IMAGE_NT_SIGNATURE; + + switch (mEhdr->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_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 %hu. Assume IA-32", mInImageName, mEhdr->e_machine); + NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32; + NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + } + + NtHdr->Pe32.FileHeader.NumberOfSections = mCoffNbrSections; + NtHdr->Pe32.FileHeader.TimeDateStamp = (UINT32) time(NULL); + mImageTimeStamp = NtHdr->Pe32.FileHeader.TimeDateStamp; + 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 = mDataOffset - mTextOffset; + NtHdr->Pe32.OptionalHeader.SizeOfInitializedData = mRelocOffset - mDataOffset; + NtHdr->Pe32.OptionalHeader.SizeOfUninitializedData = 0; + NtHdr->Pe32.OptionalHeader.AddressOfEntryPoint = CoffEntry; + + NtHdr->Pe32.OptionalHeader.BaseOfCode = mTextOffset; + + NtHdr->Pe32.OptionalHeader.BaseOfData = mDataOffset; + NtHdr->Pe32.OptionalHeader.ImageBase = 0; + NtHdr->Pe32.OptionalHeader.SectionAlignment = mCoffAlignment; + NtHdr->Pe32.OptionalHeader.FileAlignment = mCoffAlignment; + NtHdr->Pe32.OptionalHeader.SizeOfImage = 0; + + NtHdr->Pe32.OptionalHeader.SizeOfHeaders = mTextOffset; + NtHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES; + + // + // Section headers. + // + if ((mDataOffset - mTextOffset) > 0) { + CreateSectionHeader (".text", mTextOffset, mDataOffset - mTextOffset, + 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 ((mHiiRsrcOffset - mDataOffset) > 0) { + CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset, + 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--; + } + + if ((mRelocOffset - mHiiRsrcOffset) > 0) { + CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset, + EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + | EFI_IMAGE_SCN_MEM_READ); + + NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = mRelocOffset - mHiiRsrcOffset; + NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = mHiiRsrcOffset; + } else { + // Don't make a section of size 0. + NtHdr->Pe32.FileHeader.NumberOfSections--; + } + +} + +STATIC +BOOLEAN +WriteSections32 ( + SECTION_FILTER_TYPES FilterType + ) +{ + UINT32 Idx; + Elf_Shdr *SecShdr; + UINT32 SecOffset; + BOOLEAN (*Filter)(Elf_Shdr *); + + // + // Initialize filter pointer + // + switch (FilterType) { + case SECTION_TEXT: + Filter = IsTextShdr; + break; + case SECTION_HII: + Filter = IsHiiRsrcShdr; + break; + case SECTION_DATA: + Filter = IsDataShdr; + break; + default: + return FALSE; + } + + // + // First: copy sections. + // + for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) { + Elf_Shdr *Shdr = GetShdrByIndex(Idx); + if ((*Filter)(Shdr)) { + switch (Shdr->sh_type) { + case SHT_PROGBITS: + /* Copy. */ + if (Shdr->sh_offset + Shdr->sh_size > mFileBufferSize) { + return FALSE; + } + memcpy(mCoffFile + mCoffSectionsOffset[Idx], + (UINT8*)mEhdr + Shdr->sh_offset, + Shdr->sh_size); + break; + + case SHT_NOBITS: + memset(mCoffFile + mCoffSectionsOffset[Idx], 0, Shdr->sh_size); + break; + + default: + // + // Ignore for unknown section type. + // + VerboseMsg ("%s unknown section type %x. We ignore this unknown section type.", mInImageName, (unsigned)Shdr->sh_type); + break; + } + } + } + + // + // Second: apply relocations. + // + for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) { + // + // Determine if this is a relocation section. + // + Elf_Shdr *RelShdr = GetShdrByIndex(Idx); + if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) { + continue; + } + + // + // Relocation section found. Now extract section information that the relocations + // apply to in the ELF data and the new COFF data. + // + SecShdr = GetShdrByIndex(RelShdr->sh_info); + SecOffset = mCoffSectionsOffset[RelShdr->sh_info]; + + // + // Only process relocations for the current filter type. + // + if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) { + UINT32 RelOffset; + + // + // Determine the symbol table referenced by the relocation data. + // + Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link); + UINT8 *Symtab = (UINT8*)mEhdr + SymtabShdr->sh_offset; + + // + // Process all relocation entries for this section. + // + for (RelOffset = 0; RelOffset < RelShdr->sh_size; RelOffset += RelShdr->sh_entsize) { + // + // Set pointer to relocation entry + // + Elf_Rel *Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelOffset); + + // + // Set pointer to symbol table entry associated with the relocation entry. + // + Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize); + + Elf_Shdr *SymShdr; + UINT8 *Targ; + UINT16 Address; + + // + // Check section header index found in symbol table and get the section + // header location. + // + if (Sym->st_shndx == SHN_UNDEF + || Sym->st_shndx >= mEhdr->e_shnum) { + const UINT8 *SymName = GetSymName(Sym); + if (SymName == NULL) { + SymName = (const UINT8 *)""; + } + + Error (NULL, 0, 3000, "Invalid", + "%s: Bad definition for symbol '%s'@%#x or unsupported symbol type. " + "For example, absolute and undefined symbols are not supported.", + mInImageName, SymName, Sym->st_value); + + exit(EXIT_FAILURE); + } + SymShdr = GetShdrByIndex(Sym->st_shndx); + + // + // Convert the relocation data to a pointer into the coff file. + // + // Note: + // r_offset is the virtual address of the storage unit to be relocated. + // sh_addr is the virtual address for the base of the section. + // + Targ = mCoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr); + + // + // Determine how to handle each relocation type based on the machine type. + // + if (mEhdr->e_machine == EM_386) { + switch (ELF_R_TYPE(Rel->r_info)) { + case R_386_NONE: + break; + case R_386_32: + // + // Absolute relocation. + // Converts Targ from a absolute virtual address to the absolute + // COFF address. + // + *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + + mCoffSectionsOffset[Sym->st_shndx]; + break; + case R_386_PC32: + // + // Relative relocation: Symbol - Ip + Addend + // + *(UINT32 *)Targ = *(UINT32 *)Targ + + (mCoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr) + - (SecOffset - SecShdr->sh_addr); + break; + default: + Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } + } else if (mEhdr->e_machine == EM_ARM) { + switch (ELF32_R_TYPE(Rel->r_info)) { + case R_ARM_RBASE: + // No relocation - no action required + // break skipped + + case R_ARM_PC24: + case R_ARM_REL32: + case R_ARM_XPC25: + case R_ARM_THM_PC22: + case R_ARM_THM_JUMP19: + case R_ARM_CALL: + case R_ARM_JMP24: + case R_ARM_THM_JUMP24: + case R_ARM_PREL31: + case R_ARM_MOVW_PREL_NC: + case R_ARM_MOVT_PREL: + case R_ARM_THM_MOVW_PREL_NC: + case R_ARM_THM_MOVT_PREL: + case R_ARM_THM_JMP6: + case R_ARM_THM_ALU_PREL_11_0: + case R_ARM_THM_PC12: + case R_ARM_REL32_NOI: + case R_ARM_ALU_PC_G0_NC: + case R_ARM_ALU_PC_G0: + case R_ARM_ALU_PC_G1_NC: + case R_ARM_ALU_PC_G1: + case R_ARM_ALU_PC_G2: + case R_ARM_LDR_PC_G1: + case R_ARM_LDR_PC_G2: + case R_ARM_LDRS_PC_G0: + case R_ARM_LDRS_PC_G1: + case R_ARM_LDRS_PC_G2: + case R_ARM_LDC_PC_G0: + case R_ARM_LDC_PC_G1: + case R_ARM_LDC_PC_G2: + case R_ARM_THM_JUMP11: + case R_ARM_THM_JUMP8: + case R_ARM_TLS_GD32: + case R_ARM_TLS_LDM32: + case R_ARM_TLS_IE32: + // Thease are all PC-relative relocations and don't require modification + // GCC does not seem to have the concept of a application that just needs to get relocated. + break; + + case R_ARM_THM_MOVW_ABS_NC: + // MOVW is only lower 16-bits of the addres + Address = (UINT16)(Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]); + ThumbMovtImmediatePatch ((UINT16 *)Targ, Address); + break; + + case R_ARM_THM_MOVT_ABS: + // MOVT is only upper 16-bits of the addres + Address = (UINT16)((Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]) >> 16); + ThumbMovtImmediatePatch ((UINT16 *)Targ, Address); + break; + + case R_ARM_ABS32: + case R_ARM_RABS32: + // + // Absolute relocation. + // + *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + break; + + default: + Error (NULL, 0, 3000, "Invalid", "WriteSections (): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info)); + } + } + } + } + } + + return TRUE; +} + +UINTN gMovwOffset = 0; + +STATIC +VOID +WriteRelocations32 ( + 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; + Elf32_Phdr *DynamicSegment; + + for (Index = 0, FoundRelocations = FALSE; Index < mEhdr->e_shnum; Index++) { + Elf_Shdr *RelShdr = GetShdrByIndex(Index); + if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) { + 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) { + Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx); + + if (mEhdr->e_machine == EM_386) { + switch (ELF_R_TYPE(Rel->r_info)) { + case R_386_NONE: + case R_386_PC32: + // + // No fixup entry required. + // + break; + case R_386_32: + // + // Creates a relative relocation entry from the absolute entry. + // + CoffAddFixup(mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr), + EFI_IMAGE_REL_BASED_HIGHLOW); + break; + default: + Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } + } else if (mEhdr->e_machine == EM_ARM) { + switch (ELF32_R_TYPE(Rel->r_info)) { + case R_ARM_RBASE: + // No relocation - no action required + // break skipped + + case R_ARM_PC24: + case R_ARM_REL32: + case R_ARM_XPC25: + case R_ARM_THM_PC22: + case R_ARM_THM_JUMP19: + case R_ARM_CALL: + case R_ARM_JMP24: + case R_ARM_THM_JUMP24: + case R_ARM_PREL31: + case R_ARM_MOVW_PREL_NC: + case R_ARM_MOVT_PREL: + case R_ARM_THM_MOVW_PREL_NC: + case R_ARM_THM_MOVT_PREL: + case R_ARM_THM_JMP6: + case R_ARM_THM_ALU_PREL_11_0: + case R_ARM_THM_PC12: + case R_ARM_REL32_NOI: + case R_ARM_ALU_PC_G0_NC: + case R_ARM_ALU_PC_G0: + case R_ARM_ALU_PC_G1_NC: + case R_ARM_ALU_PC_G1: + case R_ARM_ALU_PC_G2: + case R_ARM_LDR_PC_G1: + case R_ARM_LDR_PC_G2: + case R_ARM_LDRS_PC_G0: + case R_ARM_LDRS_PC_G1: + case R_ARM_LDRS_PC_G2: + case R_ARM_LDC_PC_G0: + case R_ARM_LDC_PC_G1: + case R_ARM_LDC_PC_G2: + case R_ARM_THM_JUMP11: + case R_ARM_THM_JUMP8: + case R_ARM_TLS_GD32: + case R_ARM_TLS_LDM32: + case R_ARM_TLS_IE32: + // Thease are all PC-relative relocations and don't require modification + break; + + case R_ARM_THM_MOVW_ABS_NC: + CoffAddFixup ( + mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr), + EFI_IMAGE_REL_BASED_ARM_MOV32T + ); + + // PE/COFF treats MOVW/MOVT relocation as single 64-bit instruction + // Track this address so we can log an error for unsupported sequence of MOVW/MOVT + gMovwOffset = mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr); + break; + + case R_ARM_THM_MOVT_ABS: + if ((gMovwOffset + 4) != (mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr))) { + Error (NULL, 0, 3000, "Not Supported", "PE/COFF requires MOVW+MOVT instruction sequence %x +4 != %x.", gMovwOffset, mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)); + } + break; + + case R_ARM_ABS32: + case R_ARM_RABS32: + CoffAddFixup ( + mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr), + EFI_IMAGE_REL_BASED_HIGHLOW + ); + break; + + default: + Error (NULL, 0, 3000, "Invalid", "WriteRelocations(): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info)); + } + } else { + Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) mEhdr->e_machine); + } + } + } + } + } + + if (!FoundRelocations && (mEhdr->e_machine == EM_ARM)) { + /* Try again, but look for PT_DYNAMIC instead of SHT_REL */ + + for (Index = 0; Index < mEhdr->e_phnum; Index++) { + RelElementSize = 0; + RelSize = 0; + RelOffset = 0; + + DynamicSegment = GetPhdrByIndex (Index); + + if (DynamicSegment->p_type == PT_DYNAMIC) { + Dyn = (Elf32_Dyn *) ((UINT8 *)mEhdr + 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; + + default: + break; + } + Dyn++; + } + if (( RelOffset == 0 ) || ( RelSize == 0 ) || ( RelElementSize == 0 )) { + Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName); + } + + for (Index = 0; Index < mEhdr->e_shnum; Index++) { + Elf_Shdr *shdr = GetShdrByIndex(Index); + + // + // The PT_DYNAMIC section contains DT_REL relocations whose r_offset + // field is relative to the base of a segment (or the entire image), + // and not to the base of an ELF input section as is the case for + // SHT_REL sections. This means that we cannot fix up such relocations + // unless we cross-reference ELF sections and segments, considering + // that the output placement recorded in mCoffSectionsOffset[] is + // section based, not segment based. + // + // Fortunately, there is a simple way around this: we require that the + // in-memory layout of the ELF and PE/COFF versions of the binary is + // identical. That way, r_offset will retain its validity as a PE/COFF + // image offset, and we can record it in the COFF fixup table + // unmodified. + // + if (shdr->sh_addr != mCoffSectionsOffset[Index]) { + Error (NULL, 0, 3000, + "Invalid", "%s: PT_DYNAMIC relocations require identical ELF and PE/COFF section offsets.", + mInImageName); + } + } + + for (K = 0; K < RelSize; K += RelElementSize) { + + if (DynamicSegment->p_paddr == 0) { + // Older versions of the ARM ELF (SWS ESPC 0003 B-02) specification define DT_REL + // as an offset in the dynamic segment. p_paddr is defined to be zero for ARM tools + Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + DynamicSegment->p_offset + RelOffset + K); + } else { + // This is how it reads in the generic ELF specification + Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + RelOffset + K); + } + + switch (ELF32_R_TYPE (Rel->r_info)) { + case R_ARM_RBASE: + break; + + case R_ARM_RABS32: + CoffAddFixup (Rel->r_offset, EFI_IMAGE_REL_BASED_HIGHLOW); + break; + + default: + Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unknown type %d.", mInImageName, ELF32_R_TYPE (Rel->r_info)); + break; + } + } + break; + } + } + } + + // + // Pad by adding empty entries. + // + while (mCoffOffset & (mCoffAlignment - 1)) { + CoffAddFixupEntry(0); + } + + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset); + Dir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + Dir->Size = mCoffOffset - mRelocOffset; + 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 = mRelocOffset; + CreateSectionHeader (".reloc", mRelocOffset, mCoffOffset - mRelocOffset, + EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + | EFI_IMAGE_SCN_MEM_DISCARDABLE + | EFI_IMAGE_SCN_MEM_READ); + } + +} + +STATIC +VOID +WriteDebug32 ( + VOID + ) +{ + UINT32 Len; + 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; + + Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(mCoffFile + mDebugOffset); + Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW; + Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len; + Dir->RVA = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Dir->FileOffset = mDebugOffset + 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 *)(mCoffFile + mNtHdrOffset); + DataDir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]; + DataDir->VirtualAddress = mDebugOffset; + DataDir->Size = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); +} + +STATIC +VOID +SetImageSize32 ( + VOID + ) +{ + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + + // + // Set image size + // + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset); + NtHdr->Pe32.OptionalHeader.SizeOfImage = mCoffOffset; +} + +STATIC +VOID +CleanUp32 ( + VOID + ) +{ + if (mCoffSectionsOffset != NULL) { + free (mCoffSectionsOffset); + } +} + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.h new file mode 100644 index 00000000..d1b15123 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.h @@ -0,0 +1,19 @@ +/** @file +Header file for Elf32 Convert solution + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _ELF_32_CONVERT_ +#define _ELF_32_CONVERT_ + +BOOLEAN +InitializeElf32 ( + UINT8 *FileBuffer, + ELF_FUNCTION_TABLE *ElfFunctions + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.c new file mode 100644 index 00000000..989c1fa8 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.c @@ -0,0 +1,1668 @@ +/** @file +Elf64 convert solution + +Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.
+Portions copyright (c) 2013-2014, ARM Ltd. All rights reserved.
+Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "WinNtInclude.h" + +#ifndef __GNUC__ +#include +#include +#endif +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "PeCoffLib.h" +#include "EfiUtilityMsgs.h" + +#include "GenFw.h" +#include "ElfConvert.h" +#include "Elf64Convert.h" + +STATIC +VOID +ScanSections64 ( + VOID + ); + +STATIC +BOOLEAN +WriteSections64 ( + SECTION_FILTER_TYPES FilterType + ); + +STATIC +VOID +WriteRelocations64 ( + VOID + ); + +STATIC +VOID +WriteDebug64 ( + VOID + ); + +STATIC +VOID +SetImageSize64 ( + VOID + ); + +STATIC +VOID +CleanUp64 ( + VOID + ); + +// +// Rename ELF32 structures to common names to help when porting to ELF64. +// +typedef Elf64_Shdr Elf_Shdr; +typedef Elf64_Ehdr Elf_Ehdr; +typedef Elf64_Rel Elf_Rel; +typedef Elf64_Rela Elf_Rela; +typedef Elf64_Sym Elf_Sym; +typedef Elf64_Phdr Elf_Phdr; +typedef Elf64_Dyn Elf_Dyn; +#define ELFCLASS ELFCLASS64 +#define ELF_R_TYPE(r) ELF64_R_TYPE(r) +#define ELF_R_SYM(r) ELF64_R_SYM(r) + +// +// Well known ELF structures. +// +STATIC Elf_Ehdr *mEhdr; +STATIC Elf_Shdr *mShdrBase; +STATIC Elf_Phdr *mPhdrBase; + +// +// GOT information +// +STATIC Elf_Shdr *mGOTShdr = NULL; +STATIC UINT32 mGOTShindex = 0; +STATIC UINT32 *mGOTCoffEntries = NULL; +STATIC UINT32 mGOTMaxCoffEntries = 0; +STATIC UINT32 mGOTNumCoffEntries = 0; + +// +// Coff information +// +STATIC UINT32 mCoffAlignment = 0x20; + +// +// PE section alignment. +// +STATIC const UINT16 mCoffNbrSections = 4; + +// +// ELF sections to offset in Coff file. +// +STATIC UINT32 *mCoffSectionsOffset = NULL; + +// +// Offsets in COFF file +// +STATIC UINT32 mNtHdrOffset; +STATIC UINT32 mTextOffset; +STATIC UINT32 mDataOffset; +STATIC UINT32 mHiiRsrcOffset; +STATIC UINT32 mRelocOffset; +STATIC UINT32 mDebugOffset; + +// +// Used for RISC-V relocations. +// +STATIC UINT8 *mRiscVPass1Targ = NULL; +STATIC Elf_Shdr *mRiscVPass1Sym = NULL; +STATIC Elf64_Half mRiscVPass1SymSecIndex = 0; + +// +// Initialization Function +// +BOOLEAN +InitializeElf64 ( + UINT8 *FileBuffer, + ELF_FUNCTION_TABLE *ElfFunctions + ) +{ + // + // Initialize data pointer and structures. + // + VerboseMsg ("Set EHDR"); + mEhdr = (Elf_Ehdr*) FileBuffer; + + // + // Check the ELF64 specific header information. + // + VerboseMsg ("Check ELF64 Header Information"); + if (mEhdr->e_ident[EI_CLASS] != ELFCLASS64) { + Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFCLASS64"); + return FALSE; + } + if (mEhdr->e_ident[EI_DATA] != ELFDATA2LSB) { + Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB"); + return FALSE; + } + if ((mEhdr->e_type != ET_EXEC) && (mEhdr->e_type != ET_DYN)) { + Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN"); + return FALSE; + } + if (!((mEhdr->e_machine == EM_X86_64) || (mEhdr->e_machine == EM_AARCH64) || (mEhdr->e_machine == EM_RISCV64))) { + Warning (NULL, 0, 3000, "Unsupported", "ELF e_machine is not Elf64 machine."); + } + if (mEhdr->e_version != EV_CURRENT) { + Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) mEhdr->e_version, EV_CURRENT); + return FALSE; + } + + // + // Update section header pointers + // + VerboseMsg ("Update Header Pointers"); + mShdrBase = (Elf_Shdr *)((UINT8 *)mEhdr + mEhdr->e_shoff); + mPhdrBase = (Elf_Phdr *)((UINT8 *)mEhdr + mEhdr->e_phoff); + + // + // Create COFF Section offset buffer and zero. + // + VerboseMsg ("Create COFF Section Offset Buffer"); + mCoffSectionsOffset = (UINT32 *)malloc(mEhdr->e_shnum * sizeof (UINT32)); + if (mCoffSectionsOffset == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return FALSE; + } + memset(mCoffSectionsOffset, 0, mEhdr->e_shnum * sizeof(UINT32)); + + // + // Fill in function pointers. + // + VerboseMsg ("Fill in Function Pointers"); + ElfFunctions->ScanSections = ScanSections64; + ElfFunctions->WriteSections = WriteSections64; + ElfFunctions->WriteRelocations = WriteRelocations64; + ElfFunctions->WriteDebug = WriteDebug64; + ElfFunctions->SetImageSize = SetImageSize64; + ElfFunctions->CleanUp = CleanUp64; + + return TRUE; +} + + +// +// Header by Index functions +// +STATIC +Elf_Shdr* +GetShdrByIndex ( + UINT32 Num + ) +{ + if (Num >= mEhdr->e_shnum) { + Error (NULL, 0, 3000, "Invalid", "GetShdrByIndex: Index %u is too high.", Num); + exit(EXIT_FAILURE); + } + + return (Elf_Shdr*)((UINT8*)mShdrBase + Num * mEhdr->e_shentsize); +} + +STATIC +UINT32 +CoffAlign ( + UINT32 Offset + ) +{ + return (Offset + mCoffAlignment - 1) & ~(mCoffAlignment - 1); +} + +STATIC +UINT32 +DebugRvaAlign ( + UINT32 Offset + ) +{ + return (Offset + 3) & ~3; +} + +// +// filter functions +// +STATIC +BOOLEAN +IsTextShdr ( + Elf_Shdr *Shdr + ) +{ + return (BOOLEAN) ((Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC); +} + +STATIC +BOOLEAN +IsHiiRsrcShdr ( + Elf_Shdr *Shdr + ) +{ + Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx); + + return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0); +} + +STATIC +BOOLEAN +IsDataShdr ( + Elf_Shdr *Shdr + ) +{ + if (IsHiiRsrcShdr(Shdr)) { + return FALSE; + } + return (BOOLEAN) (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE); +} + +STATIC +BOOLEAN +IsStrtabShdr ( + Elf_Shdr *Shdr + ) +{ + Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx); + + return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_STRTAB_SECTION_NAME) == 0); +} + +STATIC +Elf_Shdr * +FindStrtabShdr ( + VOID + ) +{ + UINT32 i; + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (IsStrtabShdr(shdr)) { + return shdr; + } + } + return NULL; +} + +STATIC +const UINT8 * +GetSymName ( + Elf_Sym *Sym + ) +{ + Elf_Shdr *StrtabShdr; + UINT8 *StrtabContents; + BOOLEAN foundEnd; + UINT32 i; + + if (Sym->st_name == 0) { + return NULL; + } + + StrtabShdr = FindStrtabShdr(); + if (StrtabShdr == NULL) { + return NULL; + } + + assert(Sym->st_name < StrtabShdr->sh_size); + + StrtabContents = (UINT8*)mEhdr + StrtabShdr->sh_offset; + + foundEnd = FALSE; + for (i= Sym->st_name; (i < StrtabShdr->sh_size) && !foundEnd; i++) { + foundEnd = (BOOLEAN)(StrtabContents[i] == 0); + } + assert(foundEnd); + + return StrtabContents + Sym->st_name; +} + +// +// Find the ELF section hosting the GOT from an ELF Rva +// of a single GOT entry. Normally, GOT is placed in +// ELF .text section, so assume once we find in which +// section the GOT is, all GOT entries are there, and +// just verify this. +// +STATIC +VOID +FindElfGOTSectionFromGOTEntryElfRva ( + Elf64_Addr GOTEntryElfRva + ) +{ + UINT32 i; + if (mGOTShdr != NULL) { + if (GOTEntryElfRva >= mGOTShdr->sh_addr && + GOTEntryElfRva < mGOTShdr->sh_addr + mGOTShdr->sh_size) { + return; + } + Error (NULL, 0, 3000, "Unsupported", "FindElfGOTSectionFromGOTEntryElfRva: GOT entries found in multiple sections."); + exit(EXIT_FAILURE); + } + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (GOTEntryElfRva >= shdr->sh_addr && + GOTEntryElfRva < shdr->sh_addr + shdr->sh_size) { + mGOTShdr = shdr; + mGOTShindex = i; + return; + } + } + Error (NULL, 0, 3000, "Invalid", "FindElfGOTSectionFromGOTEntryElfRva: ElfRva 0x%016LX for GOT entry not found in any section.", GOTEntryElfRva); + exit(EXIT_FAILURE); +} + +// +// Stores locations of GOT entries in COFF image. +// Returns TRUE if GOT entry is new. +// Simple implementation as number of GOT +// entries is expected to be low. +// + +STATIC +BOOLEAN +AccumulateCoffGOTEntries ( + UINT32 GOTCoffEntry + ) +{ + UINT32 i; + if (mGOTCoffEntries != NULL) { + for (i = 0; i < mGOTNumCoffEntries; i++) { + if (mGOTCoffEntries[i] == GOTCoffEntry) { + return FALSE; + } + } + } + if (mGOTCoffEntries == NULL) { + mGOTCoffEntries = (UINT32*)malloc(5 * sizeof *mGOTCoffEntries); + if (mGOTCoffEntries == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + } + assert (mGOTCoffEntries != NULL); + mGOTMaxCoffEntries = 5; + mGOTNumCoffEntries = 0; + } else if (mGOTNumCoffEntries == mGOTMaxCoffEntries) { + mGOTCoffEntries = (UINT32*)realloc(mGOTCoffEntries, 2 * mGOTMaxCoffEntries * sizeof *mGOTCoffEntries); + if (mGOTCoffEntries == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + } + assert (mGOTCoffEntries != NULL); + mGOTMaxCoffEntries += mGOTMaxCoffEntries; + } + mGOTCoffEntries[mGOTNumCoffEntries++] = GOTCoffEntry; + return TRUE; +} + +// +// 32-bit Unsigned integer comparator for qsort. +// +STATIC +int +UINT32Comparator ( + const void* lhs, + const void* rhs + ) +{ + if (*(const UINT32*)lhs < *(const UINT32*)rhs) { + return -1; + } + return *(const UINT32*)lhs > *(const UINT32*)rhs; +} + +// +// Emit accumulated Coff GOT entry relocations into +// Coff image. This function performs its job +// once and then releases the entry list, so +// it can safely be called multiple times. +// +STATIC +VOID +EmitGOTRelocations ( + VOID + ) +{ + UINT32 i; + if (mGOTCoffEntries == NULL) { + return; + } + // + // Emit Coff relocations with Rvas ordered. + // + qsort( + mGOTCoffEntries, + mGOTNumCoffEntries, + sizeof *mGOTCoffEntries, + UINT32Comparator); + for (i = 0; i < mGOTNumCoffEntries; i++) { + VerboseMsg ("EFI_IMAGE_REL_BASED_DIR64 Offset: 0x%08X", mGOTCoffEntries[i]); + CoffAddFixup( + mGOTCoffEntries[i], + EFI_IMAGE_REL_BASED_DIR64); + } + free(mGOTCoffEntries); + mGOTCoffEntries = NULL; + mGOTMaxCoffEntries = 0; + mGOTNumCoffEntries = 0; +} +// +// RISC-V 64 specific Elf WriteSection function. +// +STATIC +VOID +WriteSectionRiscV64 ( + Elf_Rela *Rel, + UINT8 *Targ, + Elf_Shdr *SymShdr, + Elf_Sym *Sym + ) +{ + UINT32 Value; + UINT32 Value2; + + switch (ELF_R_TYPE(Rel->r_info)) { + case R_RISCV_NONE: + break; + + case R_RISCV_32: + *(UINT32 *)Targ = (UINT32)((UINT64)(*(UINT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]); + break; + + case R_RISCV_64: + *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + break; + + case R_RISCV_HI20: + mRiscVPass1Targ = Targ; + mRiscVPass1Sym = SymShdr; + mRiscVPass1SymSecIndex = Sym->st_shndx; + break; + + case R_RISCV_LO12_I: + if (mRiscVPass1Sym == SymShdr && mRiscVPass1Targ != NULL && mRiscVPass1SymSecIndex == Sym->st_shndx && mRiscVPass1SymSecIndex != 0) { + Value = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20) << 12); + Value2 = (UINT32)(RV_X(*(UINT32 *)Targ, 20, 12)); + if (Value2 & (RISCV_IMM_REACH/2)) { + Value2 |= ~(RISCV_IMM_REACH-1); + } + Value += Value2; + Value = Value - (UINT32)SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + Value2 = RISCV_CONST_HIGH_PART (Value); + *(UINT32 *)mRiscVPass1Targ = (RV_X (Value2, 12, 20) << 12) | \ + (RV_X (*(UINT32 *)mRiscVPass1Targ, 0, 12)); + *(UINT32 *)Targ = (RV_X (Value, 0, 12) << 20) | \ + (RV_X (*(UINT32 *)Targ, 0, 20)); + } + mRiscVPass1Sym = NULL; + mRiscVPass1Targ = NULL; + mRiscVPass1SymSecIndex = 0; + break; + + case R_RISCV_LO12_S: + if (mRiscVPass1Sym == SymShdr && mRiscVPass1Targ != NULL && mRiscVPass1SymSecIndex == Sym->st_shndx && mRiscVPass1SymSecIndex != 0) { + Value = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20) << 12); + Value2 = (UINT32)(RV_X(*(UINT32 *)Targ, 7, 5) | (RV_X(*(UINT32 *)Targ, 25, 7) << 5)); + if (Value2 & (RISCV_IMM_REACH/2)) { + Value2 |= ~(RISCV_IMM_REACH-1); + } + Value += Value2; + Value = Value - (UINT32)SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + Value2 = RISCV_CONST_HIGH_PART (Value); + *(UINT32 *)mRiscVPass1Targ = (RV_X (Value2, 12, 20) << 12) | \ + (RV_X (*(UINT32 *)mRiscVPass1Targ, 0, 12)); + Value2 = *(UINT32 *)Targ & 0x01fff07f; + Value &= RISCV_IMM_REACH - 1; + *(UINT32 *)Targ = Value2 | (UINT32)(((RV_X(Value, 0, 5) << 7) | (RV_X(Value, 5, 7) << 25))); + } + mRiscVPass1Sym = NULL; + mRiscVPass1Targ = NULL; + mRiscVPass1SymSecIndex = 0; + break; + + case R_RISCV_PCREL_HI20: + mRiscVPass1Targ = Targ; + mRiscVPass1Sym = SymShdr; + mRiscVPass1SymSecIndex = Sym->st_shndx; + + Value = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20)); + break; + + case R_RISCV_PCREL_LO12_I: + if (mRiscVPass1Targ != NULL && mRiscVPass1Sym != NULL && mRiscVPass1SymSecIndex != 0) { + int i; + Value2 = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20)); + Value = (UINT32)(RV_X(*(UINT32 *)Targ, 20, 12)); + if(Value & (RISCV_IMM_REACH/2)) { + Value |= ~(RISCV_IMM_REACH-1); + } + Value = Value - (UINT32)mRiscVPass1Sym->sh_addr + mCoffSectionsOffset[mRiscVPass1SymSecIndex]; + if(-2048 > (INT32)Value) { + i = (((INT32)Value * -1) / 4096); + Value2 -= i; + Value += 4096 * i; + if(-2048 > (INT32)Value) { + Value2 -= 1; + Value += 4096; + } + } + else if( 2047 < (INT32)Value) { + i = (Value / 4096); + Value2 += i; + Value -= 4096 * i; + if(2047 < (INT32)Value) { + Value2 += 1; + Value -= 4096; + } + } + + *(UINT32 *)Targ = (RV_X(Value, 0, 12) << 20) | (RV_X(*(UINT32*)Targ, 0, 20)); + *(UINT32 *)mRiscVPass1Targ = (RV_X(Value2, 0, 20)<<12) | (RV_X(*(UINT32 *)mRiscVPass1Targ, 0, 12)); + } + mRiscVPass1Sym = NULL; + mRiscVPass1Targ = NULL; + mRiscVPass1SymSecIndex = 0; + break; + + case R_RISCV_ADD64: + case R_RISCV_SUB64: + case R_RISCV_ADD32: + case R_RISCV_SUB32: + case R_RISCV_BRANCH: + case R_RISCV_JAL: + case R_RISCV_GPREL_I: + case R_RISCV_GPREL_S: + case R_RISCV_CALL: + case R_RISCV_RVC_BRANCH: + case R_RISCV_RVC_JUMP: + case R_RISCV_RELAX: + case R_RISCV_SUB6: + case R_RISCV_SET6: + case R_RISCV_SET8: + case R_RISCV_SET16: + case R_RISCV_SET32: + break; + + default: + Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_RISCV64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } +} + +// +// Elf functions interface implementation +// + +STATIC +VOID +ScanSections64 ( + VOID + ) +{ + UINT32 i; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + UINT32 CoffEntry; + UINT32 SectionCount; + BOOLEAN FoundSection; + + CoffEntry = 0; + mCoffOffset = 0; + + // + // Coff file start with a DOS header. + // + mCoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40; + mNtHdrOffset = mCoffOffset; + switch (mEhdr->e_machine) { + case EM_X86_64: + case EM_AARCH64: + case EM_RISCV64: + mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS64); + break; + default: + VerboseMsg ("%s unknown e_machine type %hu. Assume X64", mInImageName, mEhdr->e_machine); + mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS64); + break; + } + + mTableOffset = mCoffOffset; + mCoffOffset += mCoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER); + + // + // Set mCoffAlignment to the maximum alignment of the input sections + // we care about + // + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (shdr->sh_addralign <= mCoffAlignment) { + continue; + } + if (IsTextShdr(shdr) || IsDataShdr(shdr) || IsHiiRsrcShdr(shdr)) { + mCoffAlignment = (UINT32)shdr->sh_addralign; + } + } + + // + // Check if mCoffAlignment is larger than MAX_COFF_ALIGNMENT + // + if (mCoffAlignment > MAX_COFF_ALIGNMENT) { + Error (NULL, 0, 3000, "Invalid", "Section alignment is larger than MAX_COFF_ALIGNMENT."); + assert (FALSE); + } + + + // + // Move the PE/COFF header right before the first section. This will help us + // save space when converting to TE. + // + if (mCoffAlignment > mCoffOffset) { + mNtHdrOffset += mCoffAlignment - mCoffOffset; + mTableOffset += mCoffAlignment - mCoffOffset; + mCoffOffset = mCoffAlignment; + } + + // + // First text sections. + // + mCoffOffset = CoffAlign(mCoffOffset); + mTextOffset = mCoffOffset; + FoundSection = FALSE; + SectionCount = 0; + for (i = 0; i < mEhdr->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 + mCoffOffset = (UINT32) ((mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1)); + } else { +#ifdef VBOX + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment. sec#%i addr=%#llx align=%#llx", i, shdr->sh_addr, shdr->sh_addralign); +#else + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment."); +#endif + } + } + + /* Relocate entry. */ + if ((mEhdr->e_entry >= shdr->sh_addr) && + (mEhdr->e_entry < shdr->sh_addr + shdr->sh_size)) { + CoffEntry = (UINT32) (mCoffOffset + mEhdr->e_entry - shdr->sh_addr); + } + + // + // Set mTextOffset with the offset of the first '.text' section + // + if (!FoundSection) { + mTextOffset = mCoffOffset; + FoundSection = TRUE; + } + + mCoffSectionsOffset[i] = mCoffOffset; + mCoffOffset += (UINT32) shdr->sh_size; + SectionCount ++; + } + } + + if (!FoundSection) { + Error (NULL, 0, 3000, "Invalid", "Did not find any '.text' section."); + assert (FALSE); + } + + mDebugOffset = DebugRvaAlign(mCoffOffset); + mCoffOffset = CoffAlign(mCoffOffset); + + if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) { + Warning (NULL, 0, 0, NULL, "Multiple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName); + } + + // + // Then data sections. + // + mDataOffset = mCoffOffset; + FoundSection = FALSE; + SectionCount = 0; + for (i = 0; i < mEhdr->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 + mCoffOffset = (UINT32) ((mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1)); + } else { +#ifdef VBOX + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment. sec#%i addr=%#llx align=%#llx", i, shdr->sh_addr, shdr->sh_addralign); +#else + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment."); +#endif + } + } + + // + // Set mDataOffset with the offset of the first '.data' section + // + if (!FoundSection) { + mDataOffset = mCoffOffset; + FoundSection = TRUE; + } + mCoffSectionsOffset[i] = mCoffOffset; + mCoffOffset += (UINT32) shdr->sh_size; + SectionCount ++; + } + } + + // + // Make room for .debug data in .data (or .text if .data is empty) instead of + // putting it in a section of its own. This is explicitly allowed by the + // PE/COFF spec, and prevents bloat in the binary when using large values for + // section alignment. + // + if (SectionCount > 0) { + mDebugOffset = DebugRvaAlign(mCoffOffset); + } + mCoffOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) + + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + + strlen(mInImageName) + 1; + + mCoffOffset = CoffAlign(mCoffOffset); + if (SectionCount == 0) { + mDataOffset = mCoffOffset; + } + + if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) { + Warning (NULL, 0, 0, NULL, "Multiple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName); + } + + // + // The HII resource sections. + // + mHiiRsrcOffset = mCoffOffset; + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (IsHiiRsrcShdr(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 + mCoffOffset = (UINT32) ((mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1)); + } else { +#ifdef VBOX + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment. sec#%i addr=%#llx align=%#llx", i, shdr->sh_addr, shdr->sh_addralign); +#else + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment."); +#endif + } + } + if (shdr->sh_size != 0) { + mHiiRsrcOffset = mCoffOffset; + mCoffSectionsOffset[i] = mCoffOffset; + mCoffOffset += (UINT32) shdr->sh_size; + mCoffOffset = CoffAlign(mCoffOffset); + SetHiiResourceHeader ((UINT8*) mEhdr + shdr->sh_offset, mHiiRsrcOffset); + } + break; + } + } + + mRelocOffset = mCoffOffset; + + // + // Allocate base Coff file. Will be expanded later for relocations. + // + mCoffFile = (UINT8 *)malloc(mCoffOffset); + if (mCoffFile == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + } + assert (mCoffFile != NULL); + memset(mCoffFile, 0, mCoffOffset); + + // + // Fill headers. + // + DosHdr = (EFI_IMAGE_DOS_HEADER *)mCoffFile; + DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE; + DosHdr->e_lfanew = mNtHdrOffset; + + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(mCoffFile + mNtHdrOffset); + + NtHdr->Pe32Plus.Signature = EFI_IMAGE_NT_SIGNATURE; + + switch (mEhdr->e_machine) { + case EM_X86_64: + NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_X64; + NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + break; + case EM_AARCH64: + NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_AARCH64; + NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + break; + case EM_RISCV64: + NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_RISCV64; + NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + break; + + default: + VerboseMsg ("%s unknown e_machine type. Assume X64", (UINTN)mEhdr->e_machine); + NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_X64; + NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + } + + NtHdr->Pe32Plus.FileHeader.NumberOfSections = mCoffNbrSections; + NtHdr->Pe32Plus.FileHeader.TimeDateStamp = (UINT32) time(NULL); + mImageTimeStamp = NtHdr->Pe32Plus.FileHeader.TimeDateStamp; + NtHdr->Pe32Plus.FileHeader.PointerToSymbolTable = 0; + NtHdr->Pe32Plus.FileHeader.NumberOfSymbols = 0; + NtHdr->Pe32Plus.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32Plus.OptionalHeader); + NtHdr->Pe32Plus.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE + | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED + | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED + | EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE; + + NtHdr->Pe32Plus.OptionalHeader.SizeOfCode = mDataOffset - mTextOffset; + NtHdr->Pe32Plus.OptionalHeader.SizeOfInitializedData = mRelocOffset - mDataOffset; + NtHdr->Pe32Plus.OptionalHeader.SizeOfUninitializedData = 0; + NtHdr->Pe32Plus.OptionalHeader.AddressOfEntryPoint = CoffEntry; + + NtHdr->Pe32Plus.OptionalHeader.BaseOfCode = mTextOffset; + + NtHdr->Pe32Plus.OptionalHeader.ImageBase = 0; + NtHdr->Pe32Plus.OptionalHeader.SectionAlignment = mCoffAlignment; + NtHdr->Pe32Plus.OptionalHeader.FileAlignment = mCoffAlignment; + NtHdr->Pe32Plus.OptionalHeader.SizeOfImage = 0; + + NtHdr->Pe32Plus.OptionalHeader.SizeOfHeaders = mTextOffset; + NtHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES; + + // + // Section headers. + // + if ((mDataOffset - mTextOffset) > 0) { + CreateSectionHeader (".text", mTextOffset, mDataOffset - mTextOffset, + 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->Pe32Plus.FileHeader.NumberOfSections--; + } + + if ((mHiiRsrcOffset - mDataOffset) > 0) { + CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset, + 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->Pe32Plus.FileHeader.NumberOfSections--; + } + + if ((mRelocOffset - mHiiRsrcOffset) > 0) { + CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset, + EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + | EFI_IMAGE_SCN_MEM_READ); + + NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = mRelocOffset - mHiiRsrcOffset; + NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = mHiiRsrcOffset; + } else { + // Don't make a section of size 0. + NtHdr->Pe32Plus.FileHeader.NumberOfSections--; + } + +} + +STATIC +BOOLEAN +WriteSections64 ( + SECTION_FILTER_TYPES FilterType + ) +{ + UINT32 Idx; + Elf_Shdr *SecShdr; + UINT32 SecOffset; + BOOLEAN (*Filter)(Elf_Shdr *); + Elf64_Addr GOTEntryRva; + + // + // Initialize filter pointer + // + switch (FilterType) { + case SECTION_TEXT: + Filter = IsTextShdr; + break; + case SECTION_HII: + Filter = IsHiiRsrcShdr; + break; + case SECTION_DATA: + Filter = IsDataShdr; + break; + default: + return FALSE; + } + + // + // First: copy sections. + // + for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) { + Elf_Shdr *Shdr = GetShdrByIndex(Idx); + if ((*Filter)(Shdr)) { + switch (Shdr->sh_type) { + case SHT_PROGBITS: + /* Copy. */ + if (Shdr->sh_offset + Shdr->sh_size > mFileBufferSize) { + return FALSE; + } + memcpy(mCoffFile + mCoffSectionsOffset[Idx], + (UINT8*)mEhdr + Shdr->sh_offset, + (size_t) Shdr->sh_size); + break; + + case SHT_NOBITS: + memset(mCoffFile + mCoffSectionsOffset[Idx], 0, (size_t) Shdr->sh_size); + break; + + default: + // + // Ignore for unknown section type. + // + VerboseMsg ("%s unknown section type %x. We ignore this unknown section type.", mInImageName, (unsigned)Shdr->sh_type); + break; + } + } + } + + // + // Second: apply relocations. + // + VerboseMsg ("Applying Relocations..."); + for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) { + // + // Determine if this is a relocation section. + // + Elf_Shdr *RelShdr = GetShdrByIndex(Idx); + if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) { + continue; + } + + // + // If this is a ET_DYN (PIE) executable, we will encounter a dynamic SHT_RELA + // section that applies to the entire binary, and which will have its section + // index set to #0 (which is a NULL section with the SHF_ALLOC bit cleared). + // + // In the absence of GOT based relocations, + // this RELA section will contain redundant R_xxx_RELATIVE relocations, one + // for every R_xxx_xx64 relocation appearing in the per-section RELA sections. + // (i.e., .rela.text and .rela.data) + // + if (RelShdr->sh_info == 0) { + continue; + } + + // + // Relocation section found. Now extract section information that the relocations + // apply to in the ELF data and the new COFF data. + // + SecShdr = GetShdrByIndex(RelShdr->sh_info); + SecOffset = mCoffSectionsOffset[RelShdr->sh_info]; + + // + // Only process relocations for the current filter type. + // + if (RelShdr->sh_type == SHT_RELA && (*Filter)(SecShdr)) { + UINT64 RelIdx; + + // + // Determine the symbol table referenced by the relocation data. + // + Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link); + UINT8 *Symtab = (UINT8*)mEhdr + SymtabShdr->sh_offset; + + // + // Process all relocation entries for this section. + // + for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += (UINT32) RelShdr->sh_entsize) { + + // + // Set pointer to relocation entry + // + Elf_Rela *Rel = (Elf_Rela *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx); + + // + // Set pointer to symbol table entry associated with the relocation entry. + // + Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize); + + Elf_Shdr *SymShdr; + UINT8 *Targ; + + // + // Check section header index found in symbol table and get the section + // header location. + // + if (Sym->st_shndx == SHN_UNDEF + || Sym->st_shndx >= mEhdr->e_shnum) { + const UINT8 *SymName = GetSymName(Sym); + if (SymName == NULL) { + SymName = (const UINT8 *)""; + } + + // + // Skip error on EM_RISCV64 becasue no symble name is built + // from RISC-V toolchain. + // + if (mEhdr->e_machine != EM_RISCV64) { + Error (NULL, 0, 3000, "Invalid", + "%s: Bad definition for symbol '%s'@%#llx or unsupported symbol type. " + "For example, absolute and undefined symbols are not supported.", + mInImageName, SymName, Sym->st_value); + + exit(EXIT_FAILURE); + } + } + SymShdr = GetShdrByIndex(Sym->st_shndx); + + // + // Convert the relocation data to a pointer into the coff file. + // + // Note: + // r_offset is the virtual address of the storage unit to be relocated. + // sh_addr is the virtual address for the base of the section. + // + // r_offset in a memory address. + // Convert it to a pointer in the coff file. + // + Targ = mCoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr); + + // + // Determine how to handle each relocation type based on the machine type. + // + if (mEhdr->e_machine == EM_X86_64) { + switch (ELF_R_TYPE(Rel->r_info)) { + case R_X86_64_NONE: + break; + case R_X86_64_64: + // + // Absolute relocation. + // + VerboseMsg ("R_X86_64_64"); + VerboseMsg ("Offset: 0x%08X, Addend: 0x%016LX", + (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), + *(UINT64 *)Targ); + *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + VerboseMsg ("Relocation: 0x%016LX", *(UINT64*)Targ); + break; + case R_X86_64_32: + VerboseMsg ("R_X86_64_32"); + VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", + (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), + *(UINT32 *)Targ); + *(UINT32 *)Targ = (UINT32)((UINT64)(*(UINT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]); + VerboseMsg ("Relocation: 0x%08X", *(UINT32*)Targ); + break; + case R_X86_64_32S: + VerboseMsg ("R_X86_64_32S"); + VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", + (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), + *(UINT32 *)Targ); + *(INT32 *)Targ = (INT32)((INT64)(*(INT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]); + VerboseMsg ("Relocation: 0x%08X", *(UINT32*)Targ); + break; + + case R_X86_64_PLT32: + // + // Treat R_X86_64_PLT32 relocations as R_X86_64_PC32: this is + // possible since we know all code symbol references resolve to + // definitions in the same module (UEFI has no shared libraries), + // and so there is never a reason to jump via a PLT entry, + // allowing us to resolve the reference using the symbol directly. + // + VerboseMsg ("Treating R_X86_64_PLT32 as R_X86_64_PC32 ..."); + /* fall through */ + case R_X86_64_PC32: + // + // Relative relocation: Symbol - Ip + Addend + // + VerboseMsg ("R_X86_64_PC32"); + VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", + (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), + *(UINT32 *)Targ); + *(UINT32 *)Targ = (UINT32) (*(UINT32 *)Targ + + (mCoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr) + - (SecOffset - SecShdr->sh_addr)); + VerboseMsg ("Relocation: 0x%08X", *(UINT32 *)Targ); + break; + case R_X86_64_GOTPCREL: + case R_X86_64_GOTPCRELX: + case R_X86_64_REX_GOTPCRELX: + VerboseMsg ("R_X86_64_GOTPCREL family"); + VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", + (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), + *(UINT32 *)Targ); + GOTEntryRva = Rel->r_offset - Rel->r_addend + *(INT32 *)Targ; + FindElfGOTSectionFromGOTEntryElfRva(GOTEntryRva); + *(UINT32 *)Targ = (UINT32) (*(UINT32 *)Targ + + (mCoffSectionsOffset[mGOTShindex] - mGOTShdr->sh_addr) + - (SecOffset - SecShdr->sh_addr)); + VerboseMsg ("Relocation: 0x%08X", *(UINT32 *)Targ); + GOTEntryRva += (mCoffSectionsOffset[mGOTShindex] - mGOTShdr->sh_addr); // ELF Rva -> COFF Rva + if (AccumulateCoffGOTEntries((UINT32)GOTEntryRva)) { + // + // Relocate GOT entry if it's the first time we run into it + // + Targ = mCoffFile + GOTEntryRva; + // + // Limitation: The following three statements assume memory + // at *Targ is valid because the section containing the GOT + // has already been copied from the ELF image to the Coff image. + // This pre-condition presently holds because the GOT is placed + // in section .text, and the ELF text sections are all copied + // prior to reaching this point. + // If the pre-condition is violated in the future, this fixup + // either needs to be deferred after the GOT section is copied + // to the Coff image, or the fixup should be performed on the + // source Elf image instead of the destination Coff image. + // + VerboseMsg ("Offset: 0x%08X, Addend: 0x%016LX", + (UINT32)GOTEntryRva, + *(UINT64 *)Targ); + *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + VerboseMsg ("Relocation: 0x%016LX", *(UINT64*)Targ); + } + break; + default: + Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_X86_64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } + } else if (mEhdr->e_machine == EM_AARCH64) { + + switch (ELF_R_TYPE(Rel->r_info)) { + INT64 Offset; + + case R_AARCH64_LD64_GOT_LO12_NC: + // + // Convert into an ADD instruction - see R_AARCH64_ADR_GOT_PAGE below. + // + *(UINT32 *)Targ &= 0x3ff; + *(UINT32 *)Targ |= 0x91000000 | ((Sym->st_value & 0xfff) << 10); + break; + + case R_AARCH64_ADR_GOT_PAGE: + // + // This relocation points to the GOT entry that contains the absolute + // address of the symbol we are referring to. Since EDK2 only uses + // fully linked binaries, we can avoid the indirection, and simply + // refer to the symbol directly. This implies having to patch the + // subsequent LDR instruction (covered by a R_AARCH64_LD64_GOT_LO12_NC + // relocation) into an ADD instruction - this is handled above. + // + Offset = (Sym->st_value - (Rel->r_offset & ~0xfff)) >> 12; + + *(UINT32 *)Targ &= 0x9000001f; + *(UINT32 *)Targ |= ((Offset & 0x1ffffc) << (5 - 2)) | ((Offset & 0x3) << 29); + + /* fall through */ + + case R_AARCH64_ADR_PREL_PG_HI21: + // + // In order to handle Cortex-A53 erratum #843419, the LD linker may + // convert ADRP instructions into ADR instructions, but without + // updating the static relocation type, and so we may end up here + // while the instruction in question is actually ADR. So let's + // just disregard it: the section offset check we apply below to + // ADR instructions will trigger for its R_AARCH64_xxx_ABS_LO12_NC + // companion instruction as well, so it is safe to omit it here. + // + if ((*(UINT32 *)Targ & BIT31) == 0) { + break; + } + + // + // AArch64 PG_H21 relocations are typically paired with ABS_LO12 + // relocations, where a PC-relative reference with +/- 4 GB range is + // split into a relative high part and an absolute low part. Since + // the absolute low part represents the offset into a 4 KB page, we + // either have to convert the ADRP into an ADR instruction, or we + // need to use a section alignment of at least 4 KB, so that the + // binary appears at a correct offset at runtime. In any case, we + // have to make sure that the 4 KB relative offsets of both the + // section containing the reference as well as the section to which + // it refers have not been changed during PE/COFF conversion (i.e., + // in ScanSections64() above). + // + if (mCoffAlignment < 0x1000) { + // + // Attempt to convert the ADRP into an ADR instruction. + // This is only possible if the symbol is within +/- 1 MB. + // + + // Decode the ADRP instruction + Offset = (INT32)((*(UINT32 *)Targ & 0xffffe0) << 8); + Offset = (Offset << (6 - 5)) | ((*(UINT32 *)Targ & 0x60000000) >> (29 - 12)); + + // + // ADRP offset is relative to the previous page boundary, + // whereas ADR offset is relative to the instruction itself. + // So fix up the offset so it points to the page containing + // the symbol. + // + Offset -= (UINTN)(Targ - mCoffFile) & 0xfff; + + if (Offset < -0x100000 || Offset > 0xfffff) { + Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s due to its size (> 1 MB), this module requires 4 KB section alignment.", + mInImageName); + break; + } + + // Re-encode the offset as an ADR instruction + *(UINT32 *)Targ &= 0x1000001f; + *(UINT32 *)Targ |= ((Offset & 0x1ffffc) << (5 - 2)) | ((Offset & 0x3) << 29); + } + /* fall through */ + + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_LDST8_ABS_LO12_NC: + case R_AARCH64_LDST16_ABS_LO12_NC: + case R_AARCH64_LDST32_ABS_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: + case R_AARCH64_LDST128_ABS_LO12_NC: + if (((SecShdr->sh_addr ^ SecOffset) & 0xfff) != 0 || + ((SymShdr->sh_addr ^ mCoffSectionsOffset[Sym->st_shndx]) & 0xfff) != 0) { + Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s AARCH64 small code model requires identical ELF and PE/COFF section offsets modulo 4 KB.", + mInImageName); + break; + } + /* fall through */ + + case R_AARCH64_ADR_PREL_LO21: + case R_AARCH64_CONDBR19: + case R_AARCH64_LD_PREL_LO19: + case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: + case R_AARCH64_PREL64: + case R_AARCH64_PREL32: + case R_AARCH64_PREL16: + // + // The GCC toolchains (i.e., binutils) may corrupt section relative + // relocations when emitting relocation sections into fully linked + // binaries. More specifically, they tend to fail to take into + // account the fact that a '.rodata + XXX' relocation needs to have + // its addend recalculated once .rodata is merged into the .text + // section, and the relocation emitted into the .rela.text section. + // + // We cannot really recover from this loss of information, so the + // only workaround is to prevent having to recalculate any relative + // relocations at all, by using a linker script that ensures that + // the offset between the Place and the Symbol is the same in both + // the ELF and the PE/COFF versions of the binary. + // + if ((SymShdr->sh_addr - SecShdr->sh_addr) != + (mCoffSectionsOffset[Sym->st_shndx] - SecOffset)) { + Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s AARCH64 relative relocations require identical ELF and PE/COFF section offsets", + mInImageName); + } + break; + + // Absolute relocations. + case R_AARCH64_ABS64: + *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + break; + + default: + Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_AARCH64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } + } else if (mEhdr->e_machine == EM_RISCV64) { + // + // Write section for RISC-V 64 architecture. + // + WriteSectionRiscV64 (Rel, Targ, SymShdr, Sym); + } else { + Error (NULL, 0, 3000, "Invalid", "Not a supported machine type"); + } + } + } + } + + return TRUE; +} + +STATIC +VOID +WriteRelocations64 ( + VOID + ) +{ + UINT32 Index; + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + EFI_IMAGE_DATA_DIRECTORY *Dir; + UINT32 RiscVRelType; + + for (Index = 0; Index < mEhdr->e_shnum; Index++) { + Elf_Shdr *RelShdr = GetShdrByIndex(Index); + if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) { + Elf_Shdr *SecShdr = GetShdrByIndex (RelShdr->sh_info); + if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) { + UINT64 RelIdx; + + for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) { + Elf_Rela *Rel = (Elf_Rela *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx); + + if (mEhdr->e_machine == EM_X86_64) { + switch (ELF_R_TYPE(Rel->r_info)) { + case R_X86_64_NONE: + case R_X86_64_PC32: + case R_X86_64_PLT32: + case R_X86_64_GOTPCREL: + case R_X86_64_GOTPCRELX: + case R_X86_64_REX_GOTPCRELX: + break; + case R_X86_64_64: + VerboseMsg ("EFI_IMAGE_REL_BASED_DIR64 Offset: 0x%08X", + mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)); + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_DIR64); + break; + // + // R_X86_64_32 and R_X86_64_32S are ELF64 relocations emitted when using + // the SYSV X64 ABI small non-position-independent code model. + // R_X86_64_32 is used for unsigned 32-bit immediates with a 32-bit operand + // size. The value is either not extended, or zero-extended to 64 bits. + // R_X86_64_32S is used for either signed 32-bit non-rip-relative displacements + // or signed 32-bit immediates with a 64-bit operand size. The value is + // sign-extended to 64 bits. + // EFI_IMAGE_REL_BASED_HIGHLOW is a PE relocation that uses 32-bit arithmetic + // for rebasing an image. + // EFI PE binaries declare themselves EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE and + // may load above 2GB. If an EFI PE binary with a converted R_X86_64_32S + // relocation is loaded above 2GB, the value will get sign-extended to the + // negative part of the 64-bit address space. The negative part of the 64-bit + // address space is unmapped, so accessing such an address page-faults. + // In order to support R_X86_64_32S, it is necessary to unset + // EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE, and the EFI PE loader must implement + // this flag and abstain from loading such a PE binary above 2GB. + // Since this feature is not supported, support for R_X86_64_32S (and hence + // the small non-position-independent code model) is disabled. + // + // case R_X86_64_32S: + case R_X86_64_32: + VerboseMsg ("EFI_IMAGE_REL_BASED_HIGHLOW Offset: 0x%08X", + mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)); + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_HIGHLOW); + break; + default: + Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_X86_64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } + } else if (mEhdr->e_machine == EM_AARCH64) { + + switch (ELF_R_TYPE(Rel->r_info)) { + case R_AARCH64_ADR_PREL_LO21: + case R_AARCH64_CONDBR19: + case R_AARCH64_LD_PREL_LO19: + case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: + case R_AARCH64_PREL64: + case R_AARCH64_PREL32: + case R_AARCH64_PREL16: + case R_AARCH64_ADR_PREL_PG_HI21: + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_LDST8_ABS_LO12_NC: + case R_AARCH64_LDST16_ABS_LO12_NC: + case R_AARCH64_LDST32_ABS_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: + case R_AARCH64_LDST128_ABS_LO12_NC: + case R_AARCH64_ADR_GOT_PAGE: + case R_AARCH64_LD64_GOT_LO12_NC: + // + // No fixups are required for relative relocations, provided that + // the relative offsets between sections have been preserved in + // the ELF to PE/COFF conversion. We have already asserted that + // this is the case in WriteSections64 (). + // + break; + + case R_AARCH64_ABS64: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_DIR64); + break; + + case R_AARCH64_ABS32: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_HIGHLOW); + break; + + default: + Error (NULL, 0, 3000, "Invalid", "WriteRelocations64(): %s unsupported ELF EM_AARCH64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } + } else if (mEhdr->e_machine == EM_RISCV64) { + RiscVRelType = ELF_R_TYPE(Rel->r_info); + switch (RiscVRelType) { + case R_RISCV_NONE: + break; + + case R_RISCV_32: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_HIGHLOW); + break; + + case R_RISCV_64: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_DIR64); + break; + + case R_RISCV_HI20: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_RISCV_HI20); + break; + + case R_RISCV_LO12_I: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_RISCV_LOW12I); + break; + + case R_RISCV_LO12_S: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_RISCV_LOW12S); + break; + + case R_RISCV_ADD64: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_SUB64: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_ADD32: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_SUB32: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_BRANCH: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_JAL: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_GPREL_I: + case R_RISCV_GPREL_S: + case R_RISCV_CALL: + case R_RISCV_RVC_BRANCH: + case R_RISCV_RVC_JUMP: + case R_RISCV_RELAX: + case R_RISCV_SUB6: + case R_RISCV_SET6: + case R_RISCV_SET8: + case R_RISCV_SET16: + case R_RISCV_SET32: + case R_RISCV_PCREL_HI20: + case R_RISCV_PCREL_LO12_I: + break; + + default: + Error (NULL, 0, 3000, "Invalid", "WriteRelocations64(): %s unsupported ELF EM_RISCV64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } + } else { + Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) mEhdr->e_machine); + } + } + if (mEhdr->e_machine == EM_X86_64 && RelShdr->sh_info == mGOTShindex) { + // + // Tack relocations for GOT entries after other relocations for + // the section the GOT is in, as it's usually found at the end + // of the section. This is done in order to maintain Rva order + // of Coff relocations. + // + EmitGOTRelocations(); + } + } + } + } + + if (mEhdr->e_machine == EM_X86_64) { + // + // This is a safety net just in case the GOT is in a section + // with no other relocations and the first invocation of + // EmitGOTRelocations() above was skipped. This invocation + // does not maintain Rva order of Coff relocations. + // At present, with a single text section, all references to + // the GOT and the GOT itself reside in section .text, so + // if there's a GOT at all, the first invocation above + // is executed. + // + EmitGOTRelocations(); + } + // + // Pad by adding empty entries. + // + while (mCoffOffset & (mCoffAlignment - 1)) { + CoffAddFixupEntry(0); + } + + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset); + Dir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + Dir->Size = mCoffOffset - mRelocOffset; + if (Dir->Size == 0) { + // If no relocations, null out the directory entry and don't add the .reloc section + Dir->VirtualAddress = 0; + NtHdr->Pe32Plus.FileHeader.NumberOfSections--; + } else { + Dir->VirtualAddress = mRelocOffset; + CreateSectionHeader (".reloc", mRelocOffset, mCoffOffset - mRelocOffset, + EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + | EFI_IMAGE_SCN_MEM_DISCARDABLE + | EFI_IMAGE_SCN_MEM_READ); + } +} + +STATIC +VOID +WriteDebug64 ( + VOID + ) +{ + UINT32 Len; + 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; + + Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(mCoffFile + mDebugOffset); + Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW; + Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len; + Dir->RVA = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Dir->FileOffset = mDebugOffset + 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 *)(mCoffFile + mNtHdrOffset); + DataDir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]; + DataDir->VirtualAddress = mDebugOffset; + DataDir->Size = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); +} + +STATIC +VOID +SetImageSize64 ( + VOID + ) +{ + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + + // + // Set image size + // + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset); + NtHdr->Pe32Plus.OptionalHeader.SizeOfImage = mCoffOffset; +} + +STATIC +VOID +CleanUp64 ( + VOID + ) +{ + if (mCoffSectionsOffset != NULL) { + free (mCoffSectionsOffset); + } +} + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.h new file mode 100644 index 00000000..69746f4e --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.h @@ -0,0 +1,19 @@ +/** @file +Header file for Elf64 convert solution + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _ELF_64_CONVERT_ +#define _ELF_64_CONVERT_ + +BOOLEAN +InitializeElf64 ( + UINT8 *FileBuffer, + ELF_FUNCTION_TABLE *ElfFunctions + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/ElfConvert.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/ElfConvert.c new file mode 100644 index 00000000..1dfc947f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/ElfConvert.c @@ -0,0 +1,245 @@ +/** @file +Elf convert solution + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "WinNtInclude.h" + +#ifndef __GNUC__ +#include +#include +#endif +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "EfiUtilityMsgs.h" + +#include "GenFw.h" +#include "ElfConvert.h" +#include "Elf32Convert.h" +#include "Elf64Convert.h" + +// +// Result Coff file in memory. +// +UINT8 *mCoffFile = NULL; + +// +// COFF relocation data +// +EFI_IMAGE_BASE_RELOCATION *mCoffBaseRel; +UINT16 *mCoffEntryRel; + +// +// Current offset in coff file. +// +UINT32 mCoffOffset; + +// +// Offset in Coff file of headers and sections. +// +UINT32 mTableOffset; + +// +//mFileBufferSize +// +UINT32 mFileBufferSize; + +// +//***************************************************************************** +// Common ELF Functions +//***************************************************************************** +// + +VOID +CoffAddFixupEntry( + UINT16 Val + ) +{ + *mCoffEntryRel = Val; + mCoffEntryRel++; + mCoffBaseRel->SizeOfBlock += 2; + mCoffOffset += 2; +} + +VOID +CoffAddFixup( + UINT32 Offset, + UINT8 Type + ) +{ + if (mCoffBaseRel == NULL + || mCoffBaseRel->VirtualAddress != (Offset & ~0xfff)) { + if (mCoffBaseRel != NULL) { + // + // Add a null entry (is it required ?) + // + CoffAddFixupEntry (0); + + // + // Pad for alignment. + // + if (mCoffOffset % 4 != 0) + CoffAddFixupEntry (0); + } + + mCoffFile = realloc ( + mCoffFile, + mCoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2 * MAX_COFF_ALIGNMENT + ); + if (mCoffFile == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + } + assert (mCoffFile != NULL); + memset ( + mCoffFile + mCoffOffset, 0, + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2 * MAX_COFF_ALIGNMENT + ); + + mCoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(mCoffFile + mCoffOffset); + mCoffBaseRel->VirtualAddress = Offset & ~0xfff; + mCoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION); + + mCoffEntryRel = (UINT16 *)(mCoffBaseRel + 1); + mCoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION); + } + + // + // Fill the entry. + // + CoffAddFixupEntry((UINT16) ((Type << 12) | (Offset & 0xfff))); +} + +VOID +CreateSectionHeader ( + const CHAR8 *Name, + UINT32 Offset, + UINT32 Size, + UINT32 Flags + ) +{ + EFI_IMAGE_SECTION_HEADER *Hdr; + Hdr = (EFI_IMAGE_SECTION_HEADER*)(mCoffFile + mTableOffset); + + 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; + + mTableOffset += sizeof (EFI_IMAGE_SECTION_HEADER); +} + +// +//***************************************************************************** +// Functions called from GenFw main code. +//***************************************************************************** +// + +INTN +IsElfHeader ( + UINT8 *FileBuffer +) +{ + return (FileBuffer[EI_MAG0] == ELFMAG0 && + FileBuffer[EI_MAG1] == ELFMAG1 && + FileBuffer[EI_MAG2] == ELFMAG2 && + FileBuffer[EI_MAG3] == ELFMAG3); +} + +BOOLEAN +ConvertElf ( + UINT8 **FileBuffer, + UINT32 *FileLength + ) +{ + ELF_FUNCTION_TABLE ElfFunctions; + UINT8 EiClass; + + mFileBufferSize = *FileLength; + // + // Determine ELF type and set function table pointer correctly. + // + VerboseMsg ("Check Elf Image Header"); + EiClass = (*FileBuffer)[EI_CLASS]; + if (EiClass == ELFCLASS32) { + if (!InitializeElf32 (*FileBuffer, &ElfFunctions)) { + return FALSE; + } + } else if (EiClass == ELFCLASS64) { + if (!InitializeElf64 (*FileBuffer, &ElfFunctions)) { + return FALSE; + } + } else { + Error (NULL, 0, 3000, "Unsupported", "ELF EI_CLASS not supported."); + return FALSE; + } + + // + // Compute sections new address. + // + VerboseMsg ("Compute sections new address."); + ElfFunctions.ScanSections (); + + // + // Write and relocate sections. + // + VerboseMsg ("Write and relocate sections."); + if (!ElfFunctions.WriteSections (SECTION_TEXT)) { + return FALSE; + } + if (!ElfFunctions.WriteSections (SECTION_DATA)) { + return FALSE; + } + if (!ElfFunctions.WriteSections (SECTION_HII)) { + return FALSE; + } + + // + // Translate and write relocations. + // + VerboseMsg ("Translate and write relocations."); + ElfFunctions.WriteRelocations (); + + // + // Write debug info. + // + VerboseMsg ("Write debug info."); + ElfFunctions.WriteDebug (); + + // + // Make sure image size is correct before returning the new image. + // + VerboseMsg ("Set image size."); + ElfFunctions.SetImageSize (); + + // + // Replace. + // + free (*FileBuffer); + *FileBuffer = mCoffFile; + *FileLength = mCoffOffset; + + // + // Free resources used by ELF functions. + // + ElfFunctions.CleanUp (); + + return TRUE; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/ElfConvert.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/ElfConvert.h new file mode 100644 index 00000000..27917942 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/ElfConvert.h @@ -0,0 +1,81 @@ +/** @file +Header file for Elf convert solution + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _ELF_CONVERT_H_ +#define _ELF_CONVERT_H_ + +#include "elf_common.h" +#include "elf32.h" +#include "elf64.h" + +// +// Externally defined variables +// +extern UINT32 mCoffOffset; +extern CHAR8 *mInImageName; +extern UINT32 mImageTimeStamp; +extern UINT8 *mCoffFile; +extern UINT32 mTableOffset; +extern UINT32 mOutImageType; +extern UINT32 mFileBufferSize; + +// +// Common EFI specific data. +// +#define ELF_HII_SECTION_NAME ".hii" +#define ELF_STRTAB_SECTION_NAME ".strtab" +#define MAX_COFF_ALIGNMENT 0x10000 + +// +// Filter Types +// +typedef enum { + SECTION_TEXT, + SECTION_HII, + SECTION_DATA + +} SECTION_FILTER_TYPES; + +// +// FunctionTable +// +typedef struct { + VOID (*ScanSections) (); + BOOLEAN (*WriteSections) (SECTION_FILTER_TYPES FilterType); + VOID (*WriteRelocations) (); + VOID (*WriteDebug) (); + VOID (*SetImageSize) (); + VOID (*CleanUp) (); + +} ELF_FUNCTION_TABLE; + +// +// Common functions +// +VOID +CoffAddFixup ( + UINT32 Offset, + UINT8 Type + ); + +VOID +CoffAddFixupEntry ( + UINT16 Val + ); + + +VOID +CreateSectionHeader ( + const CHAR8 *Name, + UINT32 Offset, + UINT32 Size, + UINT32 Flags + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GNUmakefile new file mode 100644 index 00000000..79916b4f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GNUmakefile @@ -0,0 +1,23 @@ +## @file +# GNU/Linux makefile for 'GenFw' module build. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +MAKEROOT ?= .. + +APPNAME = GenFw + +OBJECTS = GenFw.o ElfConvert.o Elf32Convert.o Elf64Convert.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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.c new file mode 100644 index 00000000..4faf329b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.c @@ -0,0 +1,3255 @@ +/** @file +Converts a pe32+ image to an FW, Te image type, or other specific image. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "WinNtInclude.h" + +#ifndef __GNUC__ +#include +#include +#include +#include +#endif +#include +#include +#include +#include +#include + +#include +#include +#include + +// +// Acpi Table definition +// +#include +#include +#include +#include +#include + +#include "CommonLib.h" +#include "PeCoffLib.h" +#include "ParseInf.h" +#include "EfiUtilityMsgs.h" + +#include "GenFw.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wlogical-op" +#endif + +// +// Version of this utility +// +#define UTILITY_NAME "GenFw" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 2 + +#define HII_RESOURCE_SECTION_INDEX 1 +#define HII_RESOURCE_SECTION_NAME "HII" + +#define DEFAULT_MC_PAD_BYTE_VALUE 0xFF +#define DEFAULT_MC_ALIGNMENT 16 + +#define STATUS_IGNORE 0xA +// +// Structure definition for a microcode header +// +typedef struct { + UINT32 HeaderVersion; + UINT32 PatchId; + UINT32 Date; + UINT32 CpuId; + UINT32 Checksum; + UINT32 LoaderVersion; + UINT32 PlatformId; + UINT32 DataSize; // if 0, then TotalSize = 2048, and TotalSize field is invalid + UINT32 TotalSize; // number of bytes + UINT32 Reserved[3]; +} MICROCODE_IMAGE_HEADER; + +static EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; + +static const char *gHiiPackageRCFileHeader[] = { + "//", + "// DO NOT EDIT -- auto-generated file", + "//", + NULL +}; + +// +// Module image information +// +CHAR8 *mInImageName; +UINT32 mImageTimeStamp = 0; +UINT32 mImageSize = 0; +UINT32 mOutImageType = FW_DUMMY_IMAGE; +BOOLEAN mIsConvertXip = FALSE; + + +STATIC +EFI_STATUS +ZeroDebugData ( + IN OUT UINT8 *FileBuffer, + BOOLEAN ZeroDebug + ); + +STATIC +EFI_STATUS +SetStamp ( + IN OUT UINT8 *FileBuffer, + IN CHAR8 *TimeStamp + ); + +STATIC +STATUS +MicrocodeReadData ( + FILE *InFptr, + UINT32 *Data + ); + +STATIC +VOID +Version ( + VOID + ) +/*++ + +Routine Description: + + Print out version information for this utility. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION); +} + +STATIC +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Print Help message. + +Arguments: + + VOID + +Returns: + + None + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "\nUsage: %s [options] \n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " -o FileName, --outputfile FileName\n\ + File will be created to store the output content.\n"); + fprintf (stdout, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\ + Create Efi Image. EFI_FILETYPE is one of BASE,SMM_CORE,\n\ + PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\ + SEC, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER,\n\ + DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER,\n\ + MM_STANDALONE, MM_CORE_STANDALONE,\n\ + PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\ + APPLICATION, SAL_RT_DRIVER to support all module types\n\ + It can only be used together with --keepexceptiontable,\n\ + --keepzeropending, --keepoptionalheader, -r, -o option.\n\ + It is a action option. If it is combined with other action options,\n\ + the later input action option will override the previous one.\n"); + fprintf (stdout, " -c, --acpi Create Acpi table.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -t, --terse Create Te Image.\n\ + It can only be used together with --keepexceptiontable,\n\ + --keepzeropending, --keepoptionalheader, -r, -o option.\n\ + It is a action option. If it is combined with other action options,\n\ + the later input action option will override the previous one.\n"); + fprintf (stdout, " -u, --dump Dump TeImage Header.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\ + It also zeros the time stamp fields.\n\ + This option can be used to compare the binary efi image.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n");; + fprintf (stdout, " -l, --stripped Strip off the relocation info from PE or TE image.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -s timedate, --stamp timedate\n\ + timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\ + is set to NOW, current system time is used. The support\n\ + date scope is 1970-01-01 00+timezone:00:00\n\ + ~ 2038-01-19 03+timezone:14:07\n\ + The scope is adjusted according to the different zones.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\ + It can't be combined with other action options\n\ + except for -o option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -j, --join Combine multi microcode bin files to one file.\n\ + It can be specified with -a, -p, -o option.\n\ + No other options can be combined with it.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\ + This option is only used together with -j option.\n"); + fprintf (stdout, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\ + This option is only used together with -j option.\n"); + fprintf (stdout, " --keepexceptiontable Don't clear exception table.\n\ + This option can be used together with -e or -t.\n\ + It doesn't work for other options.\n"); + fprintf (stdout, " --keepoptionalheader Don't zero PE/COFF optional header fields.\n\ + This option can be used together with -e or -t.\n\ + It doesn't work for other options.\n"); + fprintf (stdout, " --keepzeropending Don't strip zero pending of .reloc.\n\ + This option can be used together with -e or -t.\n\ + It doesn't work for other options.\n"); + fprintf (stdout, " -r, --replace Overwrite the input file with the output content.\n\ + If more input files are specified,\n\ + the last input file will be as the output file.\n"); + fprintf (stdout, " -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\ + Guid is used to specify hii package list guid.\n\ + Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\ + If not specified, the first Form FormSet guid is used.\n"); + fprintf (stdout, " --hiipackage Combine all input binary hii packages into \n\ + a single package list as the text resource data(RC).\n\ + It can't be combined with other action options\n\ + except for -o option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " --hiibinpackage Combine all input binary hii packages into \n\ + a single package list as the binary resource section.\n\ + It can't be combined with other action options\n\ + except for -o option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " --rebase NewAddress Rebase image to new base address. New address \n\ + is also set to the first none code section header.\n\ + It can't be combined with other action options\n\ + except for -o or -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " --address NewAddress Set new address into the first none code \n\ + section header of the input image.\n\ + It can't be combined with other action options\n\ + except for -o or -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n"); + fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n"); + fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n"); + fprintf (stdout, " --version Show program's version number and exit\n"); + fprintf (stdout, " -h, --help Show this help message and exit\n"); +} + +STATIC +STATUS +CheckAcpiTable ( + VOID *AcpiTable, + UINT32 Length + ) +/*++ + +Routine Description: + + Check Acpi Table + +Arguments: + + AcpiTable Buffer for AcpiSection + Length AcpiSection Length + +Returns: + + 0 success + non-zero otherwise + +--*/ +{ + EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader; + EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; + UINT32 ExpectedLength; + + AcpiHeader = (EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable; + + // + // Generic check for AcpiTable length. + // + if (AcpiHeader->Length > Length) { + Error (NULL, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL); + return STATUS_ERROR; + } + + // + // Currently, we only check must-have tables: FADT, FACS, DSDT, + // and some important tables: MADT, MCFG. + // + switch (AcpiHeader->Signature) { + + // + // "FACP" Fixed ACPI Description Table + // + case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE: + switch (AcpiHeader->Revision) { + case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION: + ExpectedLength = sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE); + break; + case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION: + ExpectedLength = sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE); + break; + case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION: + ExpectedLength = sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE); + break; + default: + if (AcpiHeader->Revision > EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) { + ExpectedLength = AcpiHeader->Length; + break; + } + Error (NULL, 0, 3000, "Invalid", "FACP revision check failed."); + return STATUS_ERROR; + } + if (ExpectedLength != AcpiHeader->Length) { + Error (NULL, 0, 3000, "Invalid", "FACP length check failed."); + return STATUS_ERROR; + } + break; + + // + // "FACS" Firmware ACPI Control Structure + // + case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE: + Facs = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)AcpiTable; + if (Facs->Version > EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) { + break; + } + if ((Facs->Version != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) && + (Facs->Version != EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) && + (Facs->Version != EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)){ + Error (NULL, 0, 3000, "Invalid", "FACS version check failed."); + return STATUS_ERROR; + } + if ((Facs->Length != sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) && + (Facs->Length != sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) && + (Facs->Length != sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))) { + Error (NULL, 0, 3000, "Invalid", "FACS length check failed."); + return STATUS_ERROR; + } + break; + + // + // "DSDT" Differentiated System Description Table + // + case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE: + if (AcpiHeader->Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION) { + break; + } + if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER)) { + Error (NULL, 0, 3000, "Invalid", "DSDT length check failed."); + return STATUS_ERROR; + } + break; + + // + // "APIC" Multiple APIC Description Table + // + case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE: + if (AcpiHeader->Revision > EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) { + break; + } + if ((AcpiHeader->Revision != EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) && + (AcpiHeader->Revision != EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) && + (AcpiHeader->Revision != EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)) { + Error (NULL, 0, 3000, "Invalid", "APIC revision check failed."); + return STATUS_ERROR; + } + if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT32) + sizeof(UINT32)) { + Error (NULL, 0, 3000, "Invalid", "APIC length check failed."); + return STATUS_ERROR; + } + break; + + // + // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table + // + case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE: + if (AcpiHeader->Revision > EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) { + break; + } + if (AcpiHeader->Revision != EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) { + Error (NULL, 0, 3000, "Invalid", "MCFG revision check failed."); + return STATUS_ERROR; + } + if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64)) { + Error (NULL, 0, 3000, "Invalid", "MCFG length check failed."); + return STATUS_ERROR; + } + break; + + // + // Other table pass check + // + default: + break; + } + + return STATUS_SUCCESS; +} + +VOID +SetHiiResourceHeader ( + UINT8 *HiiBinData, + UINT32 OffsetToFile + ) +{ + UINT32 Index; + EFI_IMAGE_RESOURCE_DIRECTORY *ResourceDirectory; + EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *ResourceDirectoryEntry; + EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString; + EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry; + + // + // Fill Resource section entry + // + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData); + ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1); + for (Index = 0; Index < ResourceDirectory->NumberOfNamedEntries; Index ++) { + if (ResourceDirectoryEntry->u1.s.NameIsString) { + ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiBinData + ResourceDirectoryEntry->u1.s.NameOffset); + + if (ResourceDirectoryString->Length == 3 && + ResourceDirectoryString->String[0] == L'H' && + ResourceDirectoryString->String[1] == L'I' && + ResourceDirectoryString->String[2] == L'I') { + // + // Resource Type "HII" found + // + if (ResourceDirectoryEntry->u2.s.DataIsDirectory) { + // + // Move to next level - resource Name + // + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData + ResourceDirectoryEntry->u2.s.OffsetToDirectory); + ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1); + + if (ResourceDirectoryEntry->u2.s.DataIsDirectory) { + // + // Move to next level - resource Language + // + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData + ResourceDirectoryEntry->u2.s.OffsetToDirectory); + ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1); + } + } + + // + // Now it ought to be resource Data and update its OffsetToData value + // + if (!ResourceDirectoryEntry->u2.s.DataIsDirectory) { + ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (HiiBinData + ResourceDirectoryEntry->u2.OffsetToData); + ResourceDataEntry->OffsetToData = ResourceDataEntry->OffsetToData + OffsetToFile; + break; + } + } + } + ResourceDirectoryEntry++; + } + + return; +} + +EFI_IMAGE_OPTIONAL_HEADER_UNION * +GetPeCoffHeader ( + void *Data + ) +{ + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr; + + // + // Read the dos & pe hdrs of the image + // + DosHdr = (EFI_IMAGE_DOS_HEADER *)Data; + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + // NO DOS header, check for PE/COFF header + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(Data); + if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + return NULL; + } + } else { + + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(((UINT8 *)Data) + DosHdr->e_lfanew); + if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + return NULL; + } + } + + return PeHdr; +} + +void +PeCoffConvertImageToXip ( + UINT8 **FileBuffer, + UINT32 *FileLength + ) +{ + EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr; + EFI_IMAGE_OPTIONAL_HEADER_UNION *NewPeHdr; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + UINTN TotalNecessaryFileSize; + UINTN SectionSize; + UINT8 *XipFile; + UINT32 XipLength; + UINTN Index; + UINTN FirstSectionOffset; + BOOLEAN ConversionNeeded; + + PeHdr = GetPeCoffHeader ((void *) *FileBuffer); + if (PeHdr == NULL) { + return; + } + + if (PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment) { + // + // The only reason to expand zero fill sections is to make them compatible with XIP images. + // If SectionAlignment is not equal to FileAlignment then it is not an XIP type image. + // + return; + } + + // + // Calculate size of XIP file, and determine if the conversion is needed. + // + ConversionNeeded = FALSE; + XipLength = 0; + FirstSectionOffset = *FileLength; + TotalNecessaryFileSize = 0; + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + SectionSize = MAX (SectionHeader->Misc.VirtualSize, SectionHeader->SizeOfRawData); + TotalNecessaryFileSize += SectionSize; + if (SectionSize > 0) { + FirstSectionOffset = MIN (FirstSectionOffset, SectionHeader->VirtualAddress); + XipLength = MAX (XipLength, SectionHeader->VirtualAddress + SectionSize); + if (SectionHeader->VirtualAddress != SectionHeader->PointerToRawData) { + ConversionNeeded = TRUE; + } + } + if (SectionHeader->Misc.VirtualSize > SectionHeader->SizeOfRawData) { + ConversionNeeded = TRUE; + } + } + + if (FirstSectionOffset < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) { + // + // If one of the sections should be loaded to an offset overlapping with + // the executable header, then it cannot be made into an XIP image. + // + VerboseMsg ("PE/COFF conversion to XIP is impossible due to overlap"); + VerboseMsg ("of section data with the executable header."); + return; + } + + if (FirstSectionOffset == *FileLength) { + // + // If we never found a section with a non-zero size, then we + // skip the conversion. + // + return; + } + + TotalNecessaryFileSize += FirstSectionOffset; + + if (!ConversionNeeded) { + return; + } + + if (XipLength > (2 * TotalNecessaryFileSize)) { + VerboseMsg ("PE/COFF conversion to XIP appears to be larger than necessary."); + VerboseMsg ("The image linking process may have left unused memory ranges."); + } + + if (PeHdr->Pe32.FileHeader.PointerToSymbolTable != 0) { + // + // This field is obsolete and should be zero + // + PeHdr->Pe32.FileHeader.PointerToSymbolTable = 0; + } + + // + // Allocate the extra space that we need to grow the image + // + XipFile = malloc (XipLength); + if (XipFile == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return; + } + memset (XipFile, 0, XipLength); + + // + // Copy the file headers + // + memcpy (XipFile, *FileBuffer, PeHdr->Pe32.OptionalHeader.SizeOfHeaders); + + NewPeHdr = GetPeCoffHeader ((void *)XipFile); + if (NewPeHdr == NULL) { + free (XipFile); + return; + } + + // + // Copy the section data over to the appropriate XIP offsets + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(NewPeHdr->Pe32.OptionalHeader) + NewPeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + if (SectionHeader->SizeOfRawData > 0) { + memcpy ( + XipFile + SectionHeader->VirtualAddress, + *FileBuffer + SectionHeader->PointerToRawData, + SectionHeader->SizeOfRawData + ); + } + // + // Make the size of raw data in section header alignment. + // + SectionSize = (SectionHeader->Misc.VirtualSize + PeHdr->Pe32.OptionalHeader.FileAlignment - 1) & (~(PeHdr->Pe32.OptionalHeader.FileAlignment - 1)); + if (SectionSize < SectionHeader->SizeOfRawData) { + SectionHeader->SizeOfRawData = SectionSize; + } + + SectionHeader->PointerToRawData = SectionHeader->VirtualAddress; + } + + free (*FileBuffer); + *FileLength = XipLength; + *FileBuffer = XipFile; + + mIsConvertXip = TRUE; +} + +UINT8 * +CreateHiiResouceSectionHeader ( + UINT32 *pSectionHeaderSize, + UINT32 HiiDataSize + ) +/*++ + +Routine Description: + + Create COFF resource section header + +Arguments: + + pSectionHeaderSize - Pointer to section header size. + HiiDataSize - Size of the total HII data in section. + +Returns: + The created section header buffer. + +--*/ +{ + UINT32 HiiSectionHeaderSize; + UINT32 HiiSectionOffset; + UINT8 *HiiSectionHeader; + EFI_IMAGE_RESOURCE_DIRECTORY *ResourceDirectory; + EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *TypeResourceDirectoryEntry; + EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *NameResourceDirectoryEntry; + EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *LanguageResourceDirectoryEntry; + EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString; + EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry; + + // + // Calculate the total size for the resource header (include Type, Name and Language) + // then allocate memory for the resource header. + // + HiiSectionHeaderSize = 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY)) + + 3 * (sizeof (UINT16) + 3 * sizeof (CHAR16)) + + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY); + HiiSectionHeader = malloc (HiiSectionHeaderSize); + if (HiiSectionHeader == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return NULL; + } + memset (HiiSectionHeader, 0, HiiSectionHeaderSize); + + HiiSectionOffset = 0; + // + // Create Type entry + // + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset); + HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY); + ResourceDirectory->NumberOfNamedEntries = 1; + TypeResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset); + HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY); + TypeResourceDirectoryEntry->u1.s.NameIsString = 1; + TypeResourceDirectoryEntry->u2.s.DataIsDirectory = 1; + TypeResourceDirectoryEntry->u2.s.OffsetToDirectory = HiiSectionOffset; + // + // Create Name entry + // + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset); + HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY); + ResourceDirectory->NumberOfNamedEntries = 1; + NameResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset); + HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY); + NameResourceDirectoryEntry->u1.s.NameIsString = 1; + NameResourceDirectoryEntry->u2.s.DataIsDirectory = 1; + NameResourceDirectoryEntry->u2.s.OffsetToDirectory = HiiSectionOffset; + // + // Create Language entry + // + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset); + HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY); + ResourceDirectory->NumberOfNamedEntries = 1; + LanguageResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset); + HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY); + LanguageResourceDirectoryEntry->u1.s.NameIsString = 1; + // + // Create string entry for Type + // + TypeResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset; + ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset); + ResourceDirectoryString->Length = 3; + ResourceDirectoryString->String[0] = L'H'; + ResourceDirectoryString->String[1] = L'I'; + ResourceDirectoryString->String[2] = L'I'; + HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]); + // + // Create string entry for Name + // + NameResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset; + ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset); + ResourceDirectoryString->Length = 3; + ResourceDirectoryString->String[0] = L'E'; + ResourceDirectoryString->String[1] = L'F'; + ResourceDirectoryString->String[2] = L'I'; + HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]); + // + // Create string entry for Language + // + LanguageResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset; + ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset); + ResourceDirectoryString->Length = 3; + ResourceDirectoryString->String[0] = L'B'; + ResourceDirectoryString->String[1] = L'I'; + ResourceDirectoryString->String[2] = L'N'; + HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]); + // + // Create Leaf data + // + LanguageResourceDirectoryEntry->u2.OffsetToData = HiiSectionOffset; + ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (HiiSectionHeader + HiiSectionOffset); + HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY); + ResourceDataEntry->OffsetToData = HiiSectionOffset; + ResourceDataEntry->Size = HiiDataSize; + + *pSectionHeaderSize = HiiSectionHeaderSize; + return HiiSectionHeader; +} + +EFI_STATUS +RebaseImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINT32 *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + + FileOffset - The offset, in bytes, into the file to read + + ReadSize - The number of bytes to read from the file starting at FileOffset + + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + UINT32 Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +SetAddressToSectionHeader ( + IN CHAR8 *FileName, + IN OUT UINT8 *FileBuffer, + IN UINT64 NewPe32BaseAddress + ) +/*++ + +Routine Description: + + Set new base address into the section header of PeImage + +Arguments: + + FileName - Name of file + FileBuffer - Pointer to PeImage. + NewPe32BaseAddress - New Base Address for PE image. + +Returns: + + EFI_SUCCESS Set new base address into this image successfully. + +--*/ +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + UINTN Index; + EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + + // + // Initialize context + // + memset (&ImageContext, 0, sizeof (ImageContext)); + ImageContext.Handle = (VOID *) FileBuffer; + ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead; + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName); + return Status; + } + + if (ImageContext.RelocationsStripped) { + Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName); + return Status; + } + + // + // Get PeHeader pointer + // + ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset); + + // + // Get section header list + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN) ImgHdr + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader + ); + + // + // Set base address into the first section header that doesn't point to code section. + // + for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + if ((SectionHeader->Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) { + *(UINT64 *) &SectionHeader->PointerToRelocations = NewPe32BaseAddress; + break; + } + } + + // + // BaseAddress is set to section header. + // + return EFI_SUCCESS; +} + +EFI_STATUS +RebaseImage ( + IN CHAR8 *FileName, + IN OUT UINT8 *FileBuffer, + IN UINT64 NewPe32BaseAddress + ) +/*++ + +Routine Description: + + Set new base address into PeImage, and fix up PeImage based on new address. + +Arguments: + + FileName - Name of file + FileBuffer - Pointer to PeImage. + NewPe32BaseAddress - New Base Address for PE image. + +Returns: + + EFI_INVALID_PARAMETER - BaseAddress is not valid. + EFI_SUCCESS - Update PeImage is correctly. + +--*/ +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + UINTN Index; + EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; + UINT8 *MemoryImagePointer; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + + // + // Initialize context + // + memset (&ImageContext, 0, sizeof (ImageContext)); + ImageContext.Handle = (VOID *) FileBuffer; + ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead; + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName); + return Status; + } + + if (ImageContext.RelocationsStripped) { + Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName); + return Status; + } + + // + // Get PeHeader pointer + // + ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset); + + // + // Load and Relocate Image Data + // + MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment); + if (MemoryImagePointer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName); + return EFI_OUT_OF_RESOURCES; + } + memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment); + ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((INT64)ImageContext.SectionAlignment - 1)); + + Status = PeCoffLoaderLoadImage (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName); + free ((VOID *) MemoryImagePointer); + return Status; + } + + ImageContext.DestinationAddress = NewPe32BaseAddress; + Status = PeCoffLoaderRelocateImage (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName); + free ((VOID *) MemoryImagePointer); + return Status; + } + + // + // Copy Relocated data to raw image file. + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN) ImgHdr + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader + ); + + for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + CopyMem ( + FileBuffer + SectionHeader->PointerToRawData, + (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), + SectionHeader->SizeOfRawData < SectionHeader->Misc.VirtualSize ? SectionHeader->SizeOfRawData : SectionHeader->Misc.VirtualSize + ); + } + + free ((VOID *) MemoryImagePointer); + + // + // Update Image Base Address + // + if (ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress; + } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress; + } else { + Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s", + ImgHdr->Pe32.OptionalHeader.Magic, + FileName + ); + return EFI_ABORTED; + } + + // + // Set new base address into section header + // + Status = SetAddressToSectionHeader (FileName, FileBuffer, NewPe32BaseAddress); + + return Status; +} + +int +main ( + int argc, + char *argv[] + ) +/*++ + +Routine Description: + + Main function. + +Arguments: + + argc - Number of command line parameters. + argv - Array of pointers to command line parameter strings. + +Returns: + STATUS_SUCCESS - Utility exits successfully. + STATUS_ERROR - Some error occurred during execution. + +--*/ +{ + UINT32 Type; + UINT32 InputFileNum; + CHAR8 **InputFileName; + char *OutImageName; + char *ModuleType; + CHAR8 *TimeStamp; + FILE *fpIn; + FILE *fpOut; + FILE *fpInOut; + UINT32 Data; + UINT32 *DataPointer; + UINT32 *OldDataPointer; + UINT32 CheckSum; + UINT32 Index; + UINT32 Index1; + UINT32 Index2; + UINT64 Temp64; + UINT32 MciAlignment; + UINT8 MciPadValue; + UINT32 AllignedRelocSize; + UINT8 *FileBuffer; + UINT32 FileLength; + UINT8 *OutputFileBuffer; + UINT32 OutputFileLength; + UINT8 *InputFileBuffer; + UINT32 InputFileLength; + RUNTIME_FUNCTION *RuntimeFunction; + UNWIND_INFO *UnwindInfo; + STATUS Status; + BOOLEAN ReplaceFlag; + BOOLEAN KeepExceptionTableFlag; + BOOLEAN KeepOptionalHeaderFlag; + BOOLEAN KeepZeroPendingFlag; + UINT64 LogLevel; + EFI_TE_IMAGE_HEADER TEImageHeader; + EFI_TE_IMAGE_HEADER *TeHdr; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr; + EFI_IMAGE_OPTIONAL_HEADER32 *Optional32; + EFI_IMAGE_OPTIONAL_HEADER64 *Optional64; + EFI_IMAGE_DOS_HEADER BackupDosHdr; + MICROCODE_IMAGE_HEADER *MciHeader; + UINT8 *HiiPackageListBuffer; + UINT8 *HiiPackageDataPointer; + EFI_GUID HiiPackageListGuid; + EFI_HII_PACKAGE_LIST_HEADER HiiPackageListHeader; + EFI_HII_PACKAGE_HEADER HiiPackageHeader; + EFI_IFR_FORM_SET IfrFormSet; + UINT8 NumberOfFormPackage; + EFI_HII_PACKAGE_HEADER EndPackage; + UINT32 HiiSectionHeaderSize; + UINT8 *HiiSectionHeader; + UINT64 NewBaseAddress; + BOOLEAN NegativeAddr; + FILE *ReportFile; + CHAR8 *ReportFileName; + UINTN FileLen; + time_t InputFileTime; + time_t OutputFileTime; + struct stat Stat_Buf; + BOOLEAN ZeroDebugFlag; + + SetUtilityName (UTILITY_NAME); + + // + // Assign to fix compile warning + // + FileLen = 0; + InputFileNum = 0; + InputFileName = NULL; + mInImageName = NULL; + OutImageName = NULL; + ModuleType = NULL; + Type = 0; + Status = STATUS_SUCCESS; + FileBuffer = NULL; + fpIn = NULL; + fpOut = NULL; + fpInOut = NULL; + TimeStamp = NULL; + MciAlignment = DEFAULT_MC_ALIGNMENT; + MciPadValue = DEFAULT_MC_PAD_BYTE_VALUE; + FileLength = 0; + MciHeader = NULL; + CheckSum = 0; + ReplaceFlag = FALSE; + LogLevel = 0; + OutputFileBuffer = NULL; + OutputFileLength = 0; + InputFileBuffer = NULL; + InputFileLength = 0; + Optional32 = NULL; + Optional64 = NULL; + KeepExceptionTableFlag = FALSE; + KeepOptionalHeaderFlag = FALSE; + KeepZeroPendingFlag = FALSE; + NumberOfFormPackage = 0; + HiiPackageListBuffer = NULL; + HiiPackageDataPointer = NULL; + EndPackage.Length = sizeof (EFI_HII_PACKAGE_HEADER); + EndPackage.Type = EFI_HII_PACKAGE_END; + memset (&HiiPackageListGuid, 0, sizeof (HiiPackageListGuid)); + HiiSectionHeaderSize = 0; + HiiSectionHeader = NULL; + NewBaseAddress = 0; + NegativeAddr = FALSE; + InputFileTime = 0; + OutputFileTime = 0; + ZeroDebugFlag = FALSE; + + if (argc == 1) { + Error (NULL, 0, 1001, "Missing options", "No input options."); + Usage (); + return STATUS_ERROR; + } + + argc --; + argv ++; + + if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { + Version (); + Usage (); + return STATUS_SUCCESS; + } + + if (stricmp (argv[0], "--version") == 0) { + Version (); + return STATUS_SUCCESS; + } + + while (argc > 0) { + if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Output file name is missing for -o option"); + goto Finish; + } + OutImageName = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-e") == 0) || (stricmp (argv[0], "--efiImage") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Module Type is missing for -o option"); + goto Finish; + } + ModuleType = argv[1]; + if (mOutImageType == FW_ZERO_DEBUG_IMAGE) { + ZeroDebugFlag = TRUE; + } + if (mOutImageType != FW_TE_IMAGE) { + mOutImageType = FW_EFI_IMAGE; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--stripped") == 0)) { + mOutImageType = FW_RELOC_STRIPEED_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--acpi") == 0)) { + mOutImageType = FW_ACPI_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--terse") == 0)) { + if (mOutImageType == FW_ZERO_DEBUG_IMAGE) { + ZeroDebugFlag = TRUE; + } + mOutImageType = FW_TE_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-u") == 0) || (stricmp (argv[0], "--dump") == 0)) { + mOutImageType = DUMP_TE_HEADER; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--exe2bin") == 0)) { + mOutImageType = FW_BIN_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-z") == 0) || (stricmp (argv[0], "--zero") == 0)) { + if (mOutImageType == FW_DUMMY_IMAGE) { + mOutImageType = FW_ZERO_DEBUG_IMAGE; + } + if (mOutImageType == FW_TE_IMAGE || mOutImageType == FW_EFI_IMAGE) { + ZeroDebugFlag = TRUE; + } + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--stamp") == 0)) { + mOutImageType = FW_SET_STAMP_IMAGE; + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "time stamp is missing for -s option"); + goto Finish; + } + TimeStamp = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--replace") == 0)) { + ReplaceFlag = TRUE; + argc --; + argv ++; + continue; + } + + if (stricmp (argv[0], "--keepexceptiontable") == 0) { + KeepExceptionTableFlag = TRUE; + argc --; + argv ++; + continue; + } + + if (stricmp(argv[0], "--keepoptionalheader") == 0) { + KeepOptionalHeaderFlag = TRUE; + argc--; + argv++; + continue; + } + + if (stricmp (argv[0], "--keepzeropending") == 0) { + KeepZeroPendingFlag = TRUE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--mcifile") == 0)) { + mOutImageType = FW_MCI_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--join") == 0)) { + mOutImageType = FW_MERGE_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--align") == 0)) { + if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + MciAlignment = (UINT32) Temp64; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "--rebase") == 0)) { + if (argv[1][0] == '-') { + NegativeAddr = TRUE; + Status = AsciiStringToUint64 (argv[1] + 1, FALSE, &Temp64); + } else { + NegativeAddr = FALSE; + Status = AsciiStringToUint64 (argv[1], FALSE, &Temp64); + } + if (Status != EFI_SUCCESS) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + mOutImageType = FW_REBASE_IMAGE; + NewBaseAddress = (UINT64) Temp64; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "--address") == 0)) { + if (argv[1][0] == '-') { + NegativeAddr = TRUE; + Status = AsciiStringToUint64 (argv[1] + 1, FALSE, &Temp64); + } else { + NegativeAddr = FALSE; + Status = AsciiStringToUint64 (argv[1], FALSE, &Temp64); + } + if (Status != EFI_SUCCESS) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + mOutImageType = FW_SET_ADDRESS_IMAGE; + NewBaseAddress = (UINT64) Temp64; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--pad") == 0)) { + if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + MciPadValue = (UINT8) Temp64; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) { + SetPrintLevel (VERBOSE_LOG_LEVEL); + VerboseMsg ("Verbose output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + SetPrintLevel (KEY_LOG_LEVEL); + KeyMsg ("Quiet output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + if (LogLevel > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel); + goto Finish; + } + SetPrintLevel (LogLevel); + DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]); + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--hiiguid") == 0)) { + Status = StringToGuid (argv[1], &HiiPackageListGuid); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if (stricmp (argv[0], "--hiipackage") == 0) { + mOutImageType = FW_HII_PACKAGE_LIST_RCIMAGE; + argc --; + argv ++; + continue; + } + + if (stricmp (argv[0], "--hiibinpackage") == 0) { + mOutImageType = FW_HII_PACKAGE_LIST_BINIMAGE; + argc --; + argv ++; + continue; + } + + if (argv[0][0] == '-') { + Error (NULL, 0, 1000, "Unknown option", argv[0]); + goto Finish; + } + // + // Get Input file name + // + if ((InputFileNum == 0) && (InputFileName == NULL)) { + InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)); + if (InputFileName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + goto Finish; + } + + memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *))); + } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) { + // + // InputFileName buffer too small, need to realloc + // + InputFileName = (CHAR8 **) realloc ( + InputFileName, + (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *) + ); + + if (InputFileName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + goto Finish; + } + + memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *))); + } + + InputFileName [InputFileNum ++] = argv[0]; + argc --; + argv ++; + } + + VerboseMsg ("%s tool start.", UTILITY_NAME); + + if (mOutImageType == FW_DUMMY_IMAGE) { + Error (NULL, 0, 1001, "Missing option", "No create file action specified; pls specify -e, -c or -t option to create efi image, or acpi table or TeImage!"); + if (ReplaceFlag) { + Error (NULL, 0, 1001, "Missing option", "-r option is not supported as the independent option. It can be used together with other create file option specified at the above."); + } + goto Finish; + } + + // + // check input files + // + if (InputFileNum == 0) { + Error (NULL, 0, 1001, "Missing option", "Input files"); + goto Finish; + } + + // + // Combine MciBinary files to one file + // + if ((mOutImageType == FW_MERGE_IMAGE) && ReplaceFlag) { + Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option."); + goto Finish; + } + + // + // Combine HiiBinary packages to a single package list + // + if ((mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) && ReplaceFlag) { + Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option."); + goto Finish; + } + + if ((mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) && ReplaceFlag) { + Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiibinpackage merge files option."); + goto Finish; + } + + // + // Input image file + // + mInImageName = InputFileName [InputFileNum - 1]; + VerboseMsg ("the input file name is %s", mInImageName); + + // + // Action will be taken for the input file. + // + switch (mOutImageType) { + case FW_EFI_IMAGE: + VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType); + break; + case FW_TE_IMAGE: + VerboseMsg ("Create Te Image based on the input PE image."); + break; + case FW_ACPI_IMAGE: + VerboseMsg ("Get acpi table data from the input PE image."); + break; + case FW_RELOC_STRIPEED_IMAGE: + VerboseMsg ("Remove relocation section from Pe or Te image."); + break; + case FW_BIN_IMAGE: + VerboseMsg ("Convert the input EXE to the output BIN file."); + break; + case FW_ZERO_DEBUG_IMAGE: + VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image."); + break; + case FW_SET_STAMP_IMAGE: + VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp); + break; + case DUMP_TE_HEADER: + VerboseMsg ("Dump the TE header information of the input TE image."); + break; + case FW_MCI_IMAGE: + VerboseMsg ("Convert input MicroCode.txt file to MicroCode.bin file."); + break; + case FW_MERGE_IMAGE: + VerboseMsg ("Combine the input multi microcode bin files to one bin file."); + break; + case FW_HII_PACKAGE_LIST_RCIMAGE: + VerboseMsg ("Combine the input multi hii bin packages to one text package list RC file."); + break; + case FW_HII_PACKAGE_LIST_BINIMAGE: + VerboseMsg ("Combine the input multi hii bin packages to one binary package list file."); + break; + case FW_REBASE_IMAGE: + VerboseMsg ("Rebase the input image to new base address."); + break; + case FW_SET_ADDRESS_IMAGE: + VerboseMsg ("Set the preferred address into the section header of the input image"); + break; + default: + break; + } + + if (ReplaceFlag) { + VerboseMsg ("Overwrite the input file with the output content."); + } + + // + // Open output file and Write image into the output file. + // + if (OutImageName != NULL) { + fpOut = fopen (LongFilePath (OutImageName), "rb"); + if (fpOut != NULL) { + // + // Get Output file time stamp + // + fstat(fileno (fpOut), &Stat_Buf); + OutputFileTime = Stat_Buf.st_mtime; + // + // Get Output file data + // + OutputFileLength = _filelength (fileno (fpOut)); + OutputFileBuffer = malloc (OutputFileLength); + if (OutputFileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + fclose (fpOut); + fpOut = NULL; + goto Finish; + } + fread (OutputFileBuffer, 1, OutputFileLength, fpOut); + fclose (fpOut); + fpOut = NULL; + } + VerboseMsg ("Output file name is %s", OutImageName); + } else if (!ReplaceFlag && mOutImageType != DUMP_TE_HEADER) { + Error (NULL, 0, 1001, "Missing option", "output file"); + goto Finish; + } + + // + // Open input file and read file data into file buffer. + // + fpIn = fopen (LongFilePath (mInImageName), "rb"); + if (fpIn == NULL) { + Error (NULL, 0, 0001, "Error opening file", mInImageName); + goto Finish; + } + // + // Get Iutput file time stamp + // + fstat(fileno (fpIn), &Stat_Buf); + InputFileTime = Stat_Buf.st_mtime; + // + // Get Input file data + // + InputFileLength = _filelength (fileno (fpIn)); + InputFileBuffer = malloc (InputFileLength); + if (InputFileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + fclose (fpIn); + goto Finish; + } + fread (InputFileBuffer, 1, InputFileLength, fpIn); + fclose (fpIn); + DebugMsg (NULL, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) InputFileLength); + + // + // Combine multi binary HII package files. + // + if (mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE || mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) { + // + // Open output file handle. + // + fpOut = fopen (LongFilePath (OutImageName), "wb"); + if (!fpOut) { + Error (NULL, 0, 0001, "Error opening output file", OutImageName); + goto Finish; + } + // + // Get hii package list length + // + HiiPackageListHeader.PackageLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER); + for (Index = 0; Index < InputFileNum; Index ++) { + fpIn = fopen (LongFilePath (InputFileName [Index]), "rb"); + if (fpIn == NULL) { + Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]); + goto Finish; + } + FileLength = _filelength (fileno (fpIn)); + fread (&HiiPackageHeader, 1, sizeof (HiiPackageHeader), fpIn); + if (HiiPackageHeader.Type == EFI_HII_PACKAGE_FORM) { + if (HiiPackageHeader.Length != FileLength) { + Error (NULL, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName [Index]); + fclose (fpIn); + goto Finish; + } + if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) { + fread (&IfrFormSet, 1, sizeof (IfrFormSet), fpIn); + memcpy (&HiiPackageListGuid, &IfrFormSet.Guid, sizeof (EFI_GUID)); + } + NumberOfFormPackage ++; + } + HiiPackageListHeader.PackageLength += FileLength; + fclose (fpIn); + } + HiiPackageListHeader.PackageLength += sizeof (EndPackage); + // + // Check whether hii packages are valid + // + if (NumberOfFormPackage > 1) { + Error (NULL, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package"); + goto Finish; + } + if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) { + Error (NULL, 0, 3000, "Invalid", "HII package list guid is not specified!"); + goto Finish; + } + memcpy (&HiiPackageListHeader.PackageListGuid, &HiiPackageListGuid, sizeof (EFI_GUID)); + // + // read hii packages + // + HiiPackageListBuffer = malloc (HiiPackageListHeader.PackageLength); + if (HiiPackageListBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + goto Finish; + } + memcpy (HiiPackageListBuffer, &HiiPackageListHeader, sizeof (HiiPackageListHeader)); + HiiPackageDataPointer = HiiPackageListBuffer + sizeof (HiiPackageListHeader); + for (Index = 0; Index < InputFileNum; Index ++) { + fpIn = fopen (LongFilePath (InputFileName [Index]), "rb"); + if (fpIn == NULL) { + Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]); + free (HiiPackageListBuffer); + goto Finish; + } + + FileLength = _filelength (fileno (fpIn)); + fread (HiiPackageDataPointer, 1, FileLength, fpIn); + fclose (fpIn); + HiiPackageDataPointer = HiiPackageDataPointer + FileLength; + } + memcpy (HiiPackageDataPointer, &EndPackage, sizeof (EndPackage)); + + // + // write the hii package into the binary package list file with the resource section header + // + if (mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) { + // + // Create the resource section header + // + HiiSectionHeader = CreateHiiResouceSectionHeader (&HiiSectionHeaderSize, HiiPackageListHeader.PackageLength); + if (HiiSectionHeader == NULL) { + free (HiiPackageListBuffer); + goto Finish; + } + // + // Wrtie section header and HiiData into File. + // + fwrite (HiiSectionHeader, 1, HiiSectionHeaderSize, fpOut); + fwrite (HiiPackageListBuffer, 1, HiiPackageListHeader.PackageLength, fpOut); + // + // Free allocated resources. + // + free (HiiSectionHeader); + free (HiiPackageListBuffer); + // + // Done successfully + // + goto Finish; + } + + // + // write the hii package into the text package list rc file. + // + if (mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) { + for (Index = 0; gHiiPackageRCFileHeader[Index] != NULL; Index++) { + fprintf (fpOut, "%s\n", gHiiPackageRCFileHeader[Index]); + } + fprintf (fpOut, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX, HII_RESOURCE_SECTION_NAME); + + HiiPackageDataPointer = HiiPackageListBuffer; + for (Index = 0; Index + 2 < HiiPackageListHeader.PackageLength; Index += 2) { + if (Index % 16 == 0) { + fprintf (fpOut, "\n "); + } + fprintf (fpOut, " 0x%04X,", *(UINT16 *) HiiPackageDataPointer); + HiiPackageDataPointer += 2; + } + + if (Index % 16 == 0) { + fprintf (fpOut, "\n "); + } + if ((Index + 2) == HiiPackageListHeader.PackageLength) { + fprintf (fpOut, " 0x%04X\n}\n", *(UINT16 *) HiiPackageDataPointer); + } + if ((Index + 1) == HiiPackageListHeader.PackageLength) { + fprintf (fpOut, " 0x%04X\n}\n", *(UINT8 *) HiiPackageDataPointer); + } + free (HiiPackageListBuffer); + // + // Done successfully + // + goto Finish; + } + } + + // + // Combine MciBinary files to one file + // + if (mOutImageType == FW_MERGE_IMAGE) { + // + // Open output file handle. + // + fpOut = fopen (LongFilePath (OutImageName), "wb"); + if (!fpOut) { + Error (NULL, 0, 0001, "Error opening output file", OutImageName); + goto Finish; + } + for (Index = 0; Index < InputFileNum; Index ++) { + fpIn = fopen (LongFilePath (InputFileName [Index]), "rb"); + if (!fpIn) { + Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]); + goto Finish; + } + + FileLength = _filelength (fileno (fpIn)); + FileBuffer = malloc (FileLength); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + fclose (fpIn); + goto Finish; + } + + fread (FileBuffer, 1, FileLength, fpIn); + fclose (fpIn); + // + // write input file to out file + // + fwrite (FileBuffer, 1, FileLength, fpOut); + // + // write pad value to out file. + // + while (FileLength ++ % MciAlignment != 0) { + fwrite (&MciPadValue, 1, 1, fpOut); + } + // + // free allocated memory space + // + free (FileBuffer); + FileBuffer = NULL; + } + // + // Done successfully + // + goto Finish; + } + + // + // Convert MicroCode.txt file to MicroCode.bin file + // + if (mOutImageType == FW_MCI_IMAGE) { + fpIn = fopen (LongFilePath (mInImageName), "r"); + if (fpIn == NULL) { + Error (NULL, 0, 0001, "Error opening file", mInImageName); + goto Finish; + } + + // + // The first pass is to determine + // how much data is in the file so we can allocate a working buffer. + // + FileLength = 0; + do { + Status = MicrocodeReadData (fpIn, &Data); + if (Status == STATUS_SUCCESS) { + FileLength += sizeof (Data); + } + if (Status == STATUS_IGNORE) { + Status = STATUS_SUCCESS; + } + } while (Status == STATUS_SUCCESS); + // + // Error if no data. + // + if (FileLength == 0) { + Error (NULL, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName); + goto Finish; + } + if (FileLength < sizeof (MICROCODE_IMAGE_HEADER)) { + Error (NULL, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName); + goto Finish; + } + + // + // Allocate a buffer for the data + // + FileBuffer = malloc (FileLength); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + goto Finish; + } + // + // Re-read the file, storing the data into our buffer + // + fseek (fpIn, 0, SEEK_SET); + DataPointer = (UINT32 *) FileBuffer; + OldDataPointer = DataPointer; + do { + OldDataPointer = DataPointer; + Status = MicrocodeReadData (fpIn, DataPointer++); + if (Status == STATUS_IGNORE) { + DataPointer = OldDataPointer; + Status = STATUS_SUCCESS; + } + } while (Status == STATUS_SUCCESS); + // + // close input file after read data + // + fclose (fpIn); + + // + // Can't do much checking on the header because, per the spec, the + // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K, + // and the TotalSize field is invalid (actually missing). Thus we can't + // even verify the Reserved fields are 0. + // + MciHeader = (MICROCODE_IMAGE_HEADER *) FileBuffer; + if (MciHeader->DataSize == 0) { + Index = 2048; + } else { + Index = MciHeader->TotalSize; + } + + if (Index != FileLength) { + Error (NULL, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName, (unsigned) FileLength, (unsigned) Index); + goto Finish; + } + + // + // Checksum the contents + // + DataPointer = (UINT32 *) FileBuffer; + CheckSum = 0; + Index = 0; + while (Index < FileLength) { + CheckSum += *DataPointer; + DataPointer ++; + Index += sizeof (*DataPointer); + } + if (CheckSum != 0) { + Error (NULL, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum, mInImageName); + goto Finish; + } + // + // Open the output file and write the buffer contents + // + VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength); + goto WriteFile; + } + + // + // Open input file and read file data into file buffer. + // + FileLength = InputFileLength; + FileBuffer = malloc (FileLength); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + goto Finish; + } + memcpy (FileBuffer, InputFileBuffer, InputFileLength); + + // + // Dump TeImage Header into output file. + // + if (mOutImageType == DUMP_TE_HEADER) { + memcpy (&TEImageHeader, FileBuffer, sizeof (TEImageHeader)); + if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName); + goto Finish; + } + // + // Open the output file handle. + // + if (ReplaceFlag) { + fpInOut = fopen (LongFilePath (mInImageName), "wb"); + if (fpInOut == NULL) { + Error (NULL, 0, 0001, "Error opening file", mInImageName); + goto Finish; + } + } else { + if (OutImageName != NULL) { + fpOut = fopen (LongFilePath (OutImageName), "wb"); + } else { + fpOut = stdout; + } + if (fpOut == NULL) { + Error (NULL, 0, 0001, "Error opening output file", OutImageName); + goto Finish; + } + } + if (fpInOut != NULL) { + fprintf (fpInOut, "Dump of file %s\n\n", mInImageName); + fprintf (fpInOut, "TE IMAGE HEADER VALUES\n"); + fprintf (fpInOut, "%17X machine\n", TEImageHeader.Machine); + fprintf (fpInOut, "%17X number of sections\n", TEImageHeader.NumberOfSections); + fprintf (fpInOut, "%17X subsystems\n", TEImageHeader.Subsystem); + fprintf (fpInOut, "%17X stripped size\n", TEImageHeader.StrippedSize); + fprintf (fpInOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint); + fprintf (fpInOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode); + fprintf (fpInOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase); + fprintf (fpInOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size); + fprintf (fpInOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size); + } + if (fpOut != NULL) { + fprintf (fpOut, "Dump of file %s\n\n", mInImageName); + fprintf (fpOut, "TE IMAGE HEADER VALUES\n"); + fprintf (fpOut, "%17X machine\n", TEImageHeader.Machine); + fprintf (fpOut, "%17X number of sections\n", TEImageHeader.NumberOfSections); + fprintf (fpOut, "%17X subsystems\n", TEImageHeader.Subsystem); + fprintf (fpOut, "%17X stripped size\n", TEImageHeader.StrippedSize); + fprintf (fpOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint); + fprintf (fpOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode); + fprintf (fpOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase); + fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size); + fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size); + } + goto Finish; + } + + // + // Following code to convert dll to efi image or te image. + // Get new image type + // + if ((mOutImageType == FW_EFI_IMAGE) || (mOutImageType == FW_TE_IMAGE)) { + if (ModuleType == NULL) { + if (mOutImageType == FW_EFI_IMAGE) { + Error (NULL, 0, 1001, "Missing option", "EFI_FILETYPE"); + goto Finish; + } else if (mOutImageType == FW_TE_IMAGE) { + // + // Default TE Image Type is Boot service driver + // + Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; + VerboseMsg ("Efi Image subsystem type is efi boot service driver."); + } + } else { + if (stricmp (ModuleType, "BASE") == 0 || + stricmp (ModuleType, "SEC") == 0 || + stricmp (ModuleType, "SECURITY_CORE") == 0 || + stricmp (ModuleType, "PEI_CORE") == 0 || + stricmp (ModuleType, "PEIM") == 0 || + stricmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0 || + stricmp (ModuleType, "PIC_PEIM") == 0 || + stricmp (ModuleType, "RELOCATABLE_PEIM") == 0 || + stricmp (ModuleType, "DXE_CORE") == 0 || + stricmp (ModuleType, "BS_DRIVER") == 0 || + stricmp (ModuleType, "DXE_DRIVER") == 0 || + stricmp (ModuleType, "DXE_SMM_DRIVER") == 0 || + stricmp (ModuleType, "UEFI_DRIVER") == 0 || + stricmp (ModuleType, "SMM_CORE") == 0 || + stricmp (ModuleType, "MM_STANDALONE") == 0 || + stricmp (ModuleType, "MM_CORE_STANDALONE") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; + VerboseMsg ("Efi Image subsystem type is efi boot service driver."); + + } else if (stricmp (ModuleType, "UEFI_APPLICATION") == 0 || + stricmp (ModuleType, "APPLICATION") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION; + VerboseMsg ("Efi Image subsystem type is efi application."); + + } else if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0 || + stricmp (ModuleType, "RT_DRIVER") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER; + VerboseMsg ("Efi Image subsystem type is efi runtime driver."); + + } else if (stricmp (ModuleType, "DXE_SAL_DRIVER") == 0 || + stricmp (ModuleType, "SAL_RT_DRIVER") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER; + VerboseMsg ("Efi Image subsystem type is efi sal runtime driver."); + + } else { + Error (NULL, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType); + goto Finish; + } + } + } + + // + // Convert ELF image to PeImage + // + if (IsElfHeader(FileBuffer)) { + VerboseMsg ("Convert %s from ELF to PE/COFF.", mInImageName); + if (!ConvertElf(&FileBuffer, &FileLength)) { + Error (NULL, 0, 3000, "Invalid", "Unable to convert %s from ELF to PE/COFF.", mInImageName); + goto Finish; + } + } + + // + // Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP + // XIP == eXecute In Place + // + PeCoffConvertImageToXip (&FileBuffer, &FileLength); + + // + // Remove reloc section from PE or TE image + // + if (mOutImageType == FW_RELOC_STRIPEED_IMAGE) { + // + // Check TeImage + // + TeHdr = (EFI_TE_IMAGE_HEADER *) FileBuffer; + if (TeHdr->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TeHdr + 1); + for (Index = 0; Index < TeHdr->NumberOfSections; Index ++, SectionHeader ++) { + if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) { + // + // Check the reloc section is in the end of image. + // + if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == + (FileLength + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER))) { + // + // Remove .reloc section and update TeImage Header + // + FileLength = FileLength - SectionHeader->SizeOfRawData; + SectionHeader->SizeOfRawData = 0; + SectionHeader->Misc.VirtualSize = 0; + TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0; + TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0; + break; + } + } + } + } else { + // + // Check PE Image + // + DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer; + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer); + if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName); + goto Finish; + } + DosHdr = NULL; + } else { + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew); + if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName); + goto Finish; + } + } + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) { + // + // Check the reloc section is in the end of image. + // + if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == FileLength) { + // + // Remove .reloc section and update PeImage Header + // + FileLength = FileLength - SectionHeader->SizeOfRawData; + + PeHdr->Pe32.FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED; + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader; + Optional32->SizeOfImage -= SectionHeader->SizeOfRawData; + Optional32->SizeOfInitializedData -= SectionHeader->SizeOfRawData; + if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0; + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0; + } + } + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader; + Optional64->SizeOfImage -= SectionHeader->SizeOfRawData; + Optional64->SizeOfInitializedData -= SectionHeader->SizeOfRawData; + if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0; + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0; + } + } + SectionHeader->Misc.VirtualSize = 0; + SectionHeader->SizeOfRawData = 0; + break; + } + } + } + } + // + // Write file + // + goto WriteFile; + } + // + // Read the dos & pe hdrs of the image + // + DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer; + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + // NO DOS header, check for PE/COFF header + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer); + if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName); + goto Finish; + } + DosHdr = NULL; + } else { + + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew); + if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName); + goto Finish; + } + } + + if (PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM) { + // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2) + // so patch back to the official UEFI value. + PeHdr->Pe32.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMT; + } + + // + // Set new base address into image + // + if (mOutImageType == FW_REBASE_IMAGE || mOutImageType == FW_SET_ADDRESS_IMAGE) { + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + if (NewBaseAddress >= 0x100000000ULL) { + Error (NULL, 0, 3000, "Invalid", "New base address is larger than 4G for 32bit PE image"); + goto Finish; + } + } + + if (NegativeAddr) { + // + // Set Base Address to a negative value. + // + NewBaseAddress = (UINT64) (0 - NewBaseAddress); + } + if (mOutImageType == FW_REBASE_IMAGE) { + Status = RebaseImage (mInImageName, FileBuffer, NewBaseAddress); + } else { + Status = SetAddressToSectionHeader (mInImageName, FileBuffer, NewBaseAddress); + } + if (EFI_ERROR (Status)) { + if (NegativeAddr) { + Error (NULL, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address -0x%llx can't success", mInImageName, 0 - NewBaseAddress); + } else { + Error (NULL, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address 0x%llx can't success", mInImageName, NewBaseAddress); + } + goto Finish; + } + + // + // Write file + // + goto WriteFile; + } + + // + // Extract bin data from Pe image. + // + if (mOutImageType == FW_BIN_IMAGE) { + if (FileLength < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) { + Error (NULL, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName); + goto Finish; + } + // + // Output bin data from exe file + // + FileLength = FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders; + memmove (FileBuffer, FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, FileLength); + VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength); + goto WriteFile; + } + + // + // Zero Debug Information of Pe Image + // + if (mOutImageType == FW_ZERO_DEBUG_IMAGE) { + Status = ZeroDebugData (FileBuffer, TRUE); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status); + goto Finish; + } + + // + // Write the updated Image + // + VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength); + goto WriteFile; + } + + // + // Set Time Stamp of Pe Image + // + if (mOutImageType == FW_SET_STAMP_IMAGE) { + Status = SetStamp (FileBuffer, TimeStamp); + if (EFI_ERROR (Status)) { + goto Finish; + } + + // + // Write the updated Image + // + VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength); + goto WriteFile; + } + + // + // Extract acpi data from pe image. + // + if (mOutImageType == FW_ACPI_IMAGE) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + if (strcmp ((char *)SectionHeader->Name, ".data") == 0 || strcmp ((char *)SectionHeader->Name, ".sdata") == 0) { + // + // Check Acpi Table + // + if (SectionHeader->Misc.VirtualSize < SectionHeader->SizeOfRawData) { + FileLength = SectionHeader->Misc.VirtualSize; + } else { + FileLength = SectionHeader->SizeOfRawData; + } + + if (CheckAcpiTable (FileBuffer + SectionHeader->PointerToRawData, FileLength) != STATUS_SUCCESS) { + Error (NULL, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName); + goto Finish; + } + + // + // Output Apci data to file + // + memmove (FileBuffer, FileBuffer + SectionHeader->PointerToRawData, FileLength); + VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength); + goto WriteFile; + } + } + Error (NULL, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName); + goto Finish; + } + // + // Zero all unused fields of the DOS header + // + if (DosHdr != NULL) { + memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER)); + memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER)); + DosHdr->e_magic = BackupDosHdr.e_magic; + DosHdr->e_lfanew = BackupDosHdr.e_lfanew; + + for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (UINT32 ) DosHdr->e_lfanew; Index++) { + FileBuffer[Index] = (UINT8) DosHdr->e_cp; + } + } + + // + // Initialize TeImage Header + // + memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER)); + TEImageHeader.Signature = EFI_TE_IMAGE_HEADER_SIGNATURE; + TEImageHeader.Machine = PeHdr->Pe32.FileHeader.Machine; + TEImageHeader.NumberOfSections = (UINT8) PeHdr->Pe32.FileHeader.NumberOfSections; + TEImageHeader.StrippedSize = (UINT16) ((UINTN) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader) - (UINTN) FileBuffer); + TEImageHeader.Subsystem = (UINT8) Type; + + // + // Patch the PE header + // + PeHdr->Pe32.OptionalHeader.Subsystem = (UINT16) Type; + + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader; + if (!KeepOptionalHeaderFlag) { + Optional32->MajorOperatingSystemVersion = 0; + Optional32->MinorOperatingSystemVersion = 0; + Optional32->MajorImageVersion = 0; + Optional32->MinorImageVersion = 0; + Optional32->MajorSubsystemVersion = 0; + Optional32->MinorSubsystemVersion = 0; + Optional32->Win32VersionValue = 0; + Optional32->CheckSum = 0; + Optional32->SizeOfStackReserve = 0; + Optional32->SizeOfStackCommit = 0; + Optional32->SizeOfHeapReserve = 0; + Optional32->SizeOfHeapCommit = 0; + } + TEImageHeader.AddressOfEntryPoint = Optional32->AddressOfEntryPoint; + TEImageHeader.BaseOfCode = Optional32->BaseOfCode; + TEImageHeader.ImageBase = (UINT64) (Optional32->ImageBase); + + if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; + } + + if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size; + } + + // + // Zero .pdata section data. + // + if (!KeepExceptionTableFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION && + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 && + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) { + if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) { + // + // Zero .pdata Section data + // + memset (FileBuffer + SectionHeader->PointerToRawData, 0, SectionHeader->SizeOfRawData); + // + // Zero .pdata Section header name + // + memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name)); + // + // Zero Exception Table + // + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0; + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0; + DebugMsg (NULL, 0, 9, "Zero the .pdata section for PE image", NULL); + break; + } + } + } + + // + // Strip zero padding at the end of the .reloc section + // + if (!KeepZeroPendingFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + if (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) { + // + // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory + // + if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) { + SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; + AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1)); + // + // Check to see if there is zero padding at the end of the base relocations + // + if (AllignedRelocSize < SectionHeader->SizeOfRawData) { + // + // Check to see if the base relocations are at the end of the file + // + if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) { + // + // All the required conditions are met to strip the zero padding of the end of the base relocations section + // + Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize); + Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize); + SectionHeader->SizeOfRawData = AllignedRelocSize; + FileLength = Optional32->SizeOfImage; + DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader->SizeOfRawData - AllignedRelocSize)); + } + } + } + } + } + } + } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader; + if (!KeepOptionalHeaderFlag) { + Optional64->MajorOperatingSystemVersion = 0; + Optional64->MinorOperatingSystemVersion = 0; + Optional64->MajorImageVersion = 0; + Optional64->MinorImageVersion = 0; + Optional64->MajorSubsystemVersion = 0; + Optional64->MinorSubsystemVersion = 0; + Optional64->Win32VersionValue = 0; + Optional64->CheckSum = 0; + Optional64->SizeOfStackReserve = 0; + Optional64->SizeOfStackCommit = 0; + Optional64->SizeOfHeapReserve = 0; + Optional64->SizeOfHeapCommit = 0; + } + TEImageHeader.AddressOfEntryPoint = Optional64->AddressOfEntryPoint; + TEImageHeader.BaseOfCode = Optional64->BaseOfCode; + TEImageHeader.ImageBase = (UINT64) (Optional64->ImageBase); + + if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; + } + + if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size; + } + + // + // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty + // For Itaninum and X64 Image, remove .pdata section. + // + if ((!KeepExceptionTableFlag && PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_X64)) { + if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION && + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 && + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) { + if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) { + // + // Zero .pdata Section header name + // + memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name)); + + RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData); + for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index2 = 0; Index2 < PeHdr->Pe32.FileHeader.NumberOfSections; Index2++, SectionHeader++) { + if (RuntimeFunction->UnwindInfoAddress >= SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) { + UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress)); + if (UnwindInfo->Version == 1) { + memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16)); + memset (UnwindInfo, 0, sizeof (UNWIND_INFO)); + } + break; + } + } + memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION)); + } + // + // Zero Exception Table + // + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0; + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0; + DebugMsg (NULL, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL); + break; + } + } + } + } + + // + // Strip zero padding at the end of the .reloc section + // + if (!KeepZeroPendingFlag && Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + if (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) { + // + // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory + // + if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) { + SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; + AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1)); + // + // Check to see if there is zero padding at the end of the base relocations + // + if (AllignedRelocSize < SectionHeader->SizeOfRawData) { + // + // Check to see if the base relocations are at the end of the file + // + if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) { + // + // All the required conditions are met to strip the zero padding of the end of the base relocations section + // + Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize); + Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize); + SectionHeader->SizeOfRawData = AllignedRelocSize; + FileLength = Optional64->SizeOfImage; + DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader->SizeOfRawData - AllignedRelocSize)); + } + } + } + } + } + } + } else { + Error (NULL, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr->Pe32.OptionalHeader.Magic, mInImageName); + goto Finish; + } + + if (((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) == 0) && \ + (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == 0) && \ + (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size == 0)) { + // + // PeImage can be loaded into memory, but it has no relocation section. + // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero. + // + if (Optional32 != NULL) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION); + } else if (Optional64 != NULL) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION); + } + } + + // + // Fill HII section data + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) { + if (stricmp ((char *)SectionHeader[Index].Name, ".hii") == 0) { + // + // Update resource section header offset + // + SetHiiResourceHeader ((UINT8*) FileBuffer + SectionHeader[Index].PointerToRawData, SectionHeader[Index].VirtualAddress); + // + // Update resource section name + // + strcpy((char *) SectionHeader[Index].Name, ".rsrc"); + // + // Update resource data directory. + // + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader; + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress; + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize; + } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader; + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress; + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize; + } + break; + } + } + + // + // Zero ExceptionTable Xdata + // + if (!KeepExceptionTableFlag) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) { + if (stricmp ((char *)SectionHeader[Index].Name, ".xdata") == 0) { + // + // zero .xdata section + // + memset (FileBuffer + SectionHeader[Index].PointerToRawData, 0, SectionHeader[Index].SizeOfRawData); + DebugMsg (NULL, 0, 9, NULL, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", (unsigned) SectionHeader[Index].PointerToRawData, (unsigned) SectionHeader[Index].SizeOfRawData); + break; + } + } + } + + // + // Zero Time/Data field + // + ZeroDebugData (FileBuffer, ZeroDebugFlag); + + if (mOutImageType == FW_TE_IMAGE) { + if ((PeHdr->Pe32.FileHeader.NumberOfSections &~0xFF) || (Type &~0xFF)) { + // + // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both. + // + Error (NULL, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName); + goto Finish; + } + + if ((PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment)) { + // + // TeImage has the same section alignment and file alignment. + // + Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName); + goto Finish; + } + + DebugMsg (NULL, 0, 9, "TeImage Header Info", "Machine type is %X, Number of sections is %X, Stripped size is %X, EntryPoint is %X, BaseOfCode is %X, ImageBase is %llX", + TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, (unsigned) TEImageHeader.AddressOfEntryPoint, (unsigned) TEImageHeader.BaseOfCode, (unsigned long long) TEImageHeader.ImageBase); + // + // Update Image to TeImage + // + FileLength = FileLength - TEImageHeader.StrippedSize; + memmove (FileBuffer + sizeof (EFI_TE_IMAGE_HEADER), FileBuffer + TEImageHeader.StrippedSize, FileLength); + FileLength = FileLength + sizeof (EFI_TE_IMAGE_HEADER); + memcpy (FileBuffer, &TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER)); + VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength)); + } else { + + // + // Following codes are to fix the objcopy's issue: + // objcopy in binutil 2.50.18 will set PE image's charactices to "RELOC_STRIPPED" if image has no ".reloc" section + // It cause issue for EFI image which has no ".reloc" sections. + // Following codes will be removed when objcopy in binutil fix this problem for PE image. + // + if ((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0) { + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader; + if (Optional32->ImageBase == 0) { + PeHdr->Pe32.FileHeader.Characteristics &= ~EFI_IMAGE_FILE_RELOCS_STRIPPED; + } + } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader; + if (Optional64->ImageBase == 0) { + PeHdr->Pe32.FileHeader.Characteristics &= ~EFI_IMAGE_FILE_RELOCS_STRIPPED; + } + } + } + } + +WriteFile: + // + // Update Image to EfiImage or TE image + // + if (ReplaceFlag) { + if ((FileLength != InputFileLength) || (memcmp (FileBuffer, InputFileBuffer, FileLength) != 0)) { + // + // Update File when File is changed. + // + fpInOut = fopen (LongFilePath (mInImageName), "wb"); + if (fpInOut == NULL) { + Error (NULL, 0, 0001, "Error opening file", mInImageName); + goto Finish; + } + fwrite (FileBuffer, 1, FileLength, fpInOut); + VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength); + } + } else { + if ((OutputFileTime < InputFileTime) || (FileLength != OutputFileLength) || (memcmp (FileBuffer, OutputFileBuffer, FileLength) != 0)) { + // + // Update File when File is changed or File is old. + // + fpOut = fopen (LongFilePath (OutImageName), "wb"); + if (fpOut == NULL) { + Error (NULL, 0, 0001, "Error opening output file", OutImageName); + goto Finish; + } + fwrite (FileBuffer, 1, FileLength, fpOut); + VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength); + } + } + mImageSize = FileLength; + +Finish: + if (fpInOut != NULL) { + if (GetUtilityStatus () != STATUS_SUCCESS) { + // + // when file updates failed, original file is still recovered. + // + fwrite (InputFileBuffer, 1, InputFileLength, fpInOut); + } + // + // Write converted data into fpInOut file and close input file. + // + fclose (fpInOut); + } + + if (FileBuffer != NULL) { + free (FileBuffer); + } + + if (InputFileName != NULL) { + free (InputFileName); + } + + if (fpOut != NULL) { + // + // Write converted data into fpOut file and close output file. + // + fclose (fpOut); + if (GetUtilityStatus () != STATUS_SUCCESS) { + if (OutputFileBuffer == NULL) { + remove (OutImageName); + } else { + fpOut = fopen (LongFilePath (OutImageName), "wb"); + fwrite (OutputFileBuffer, 1, OutputFileLength, fpOut); + fclose (fpOut); + } + } + } + + if (InputFileBuffer != NULL) { + free (InputFileBuffer); + } + + if (OutputFileBuffer != NULL) { + free (OutputFileBuffer); + } + + // + // Write module size and time stamp to report file. + // + if (OutImageName != NULL) { + FileLen = strlen (OutImageName); + } + if (FileLen >= 4 && strcmp (OutImageName + (FileLen - 4), ".efi") == 0) { + ReportFileName = (CHAR8 *) malloc (FileLen + 1); + if (ReportFileName != NULL) { + strcpy (ReportFileName, OutImageName); + strcpy (ReportFileName + (FileLen - 4), ".txt"); + ReportFile = fopen (LongFilePath (ReportFileName), "w+"); + if (ReportFile != NULL) { + fprintf (ReportFile, "MODULE_SIZE = %u\n", (unsigned) mImageSize); + fprintf (ReportFile, "TIME_STAMP = %u\n", (unsigned) mImageTimeStamp); + fclose(ReportFile); + } + free (ReportFileName); + } + } + VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ()); + + return GetUtilityStatus (); +} + +STATIC +EFI_STATUS +ZeroDebugData ( + IN OUT UINT8 *FileBuffer, + BOOLEAN ZeroDebugFlag + ) +/*++ + +Routine Description: + + Zero debug information in PeImage. + +Arguments: + + FileBuffer - Pointer to PeImage. + ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp + +Returns: + + EFI_ABORTED - PeImage is invalid. + EFI_SUCCESS - Zero debug data successfully. + +--*/ +{ + UINT32 Index; + UINT32 DebugDirectoryEntryRva; + UINT32 DebugDirectoryEntrySize; + UINT32 DebugDirectoryEntryFileOffset; + UINT32 ExportDirectoryEntryRva; + UINT32 ExportDirectoryEntryFileOffset; + UINT32 ResourceDirectoryEntryRva; + UINT32 ResourceDirectoryEntryFileOffset; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_FILE_HEADER *FileHdr; + EFI_IMAGE_OPTIONAL_HEADER32 *Optional32Hdr; + EFI_IMAGE_OPTIONAL_HEADER64 *Optional64Hdr; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY *RsdsEntry; + UINT32 *NewTimeStamp; + + // + // Init variable. + // + DebugDirectoryEntryRva = 0; + DebugDirectoryEntrySize = 0; + ExportDirectoryEntryRva = 0; + ResourceDirectoryEntryRva = 0; + DebugDirectoryEntryFileOffset = 0; + ExportDirectoryEntryFileOffset = 0; + ResourceDirectoryEntryFileOffset = 0; + DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer; + FileHdr = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32)); + + + DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer; + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + // NO DOS header, must start with PE/COFF header + FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32)); + } else { + FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32)); + } + + // + // Get Debug, Export and Resource EntryTable RVA address. + // Resource Directory entry need to review. + // + Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER)); + Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER)); + if (Optional32Hdr->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr + FileHdr->SizeOfOptionalHeader); + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) { + ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + } + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) { + ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + } + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) { + DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + DebugDirectoryEntrySize = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size; + if (ZeroDebugFlag) { + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0; + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0; + } + } + } else { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr + FileHdr->SizeOfOptionalHeader); + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) { + ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + } + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) { + ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + } + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) { + DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + DebugDirectoryEntrySize = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size; + if (ZeroDebugFlag) { + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0; + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0; + } + } + } + + // + // Get DirectoryEntryTable file offset. + // + for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) { + if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress && + DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = + DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress && + ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + ExportDirectoryEntryFileOffset = + ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress && + ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + ResourceDirectoryEntryFileOffset = + ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + } + + // + //Zero Debug Data and TimeStamp + // + FileHdr->TimeDateStamp = 0; + mImageTimeStamp = 0; + if (ExportDirectoryEntryFileOffset != 0) { + NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32)); + *NewTimeStamp = 0; + } + + if (ResourceDirectoryEntryFileOffset != 0) { + NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32)); + *NewTimeStamp = 0; + } + + if (DebugDirectoryEntryFileOffset != 0) { + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset); + Index = 0; + for (Index=0; Index < DebugDirectoryEntrySize / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); Index ++, DebugEntry ++) { + DebugEntry->TimeDateStamp = 0; + if (mIsConvertXip) { + DebugEntry->FileOffset = DebugEntry->RVA; + } + if (ZeroDebugFlag || DebugEntry->Type != EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData); + memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)); + } + if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + RsdsEntry = (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY *) (FileBuffer + DebugEntry->FileOffset); + if (RsdsEntry->Signature == CODEVIEW_SIGNATURE_MTOC) { + // MTOC sets DebugDirectoryEntrySize to size of the .debug section, so fix it. + if (!ZeroDebugFlag) { + if (Optional32Hdr->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + } else { + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + } + } + break; + } + } + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SetStamp ( + IN OUT UINT8 *FileBuffer, + IN CHAR8 *TimeStamp + ) +/*++ + +Routine Description: + + Set new time stamp into PeImage FileHdr and Directory table: + Debug, Export and Resource. + +Arguments: + + FileBuffer - Pointer to PeImage. + TimeStamp - Time stamp string. + +Returns: + + EFI_INVALID_PARAMETER - TimeStamp format is not recognized. + EFI_SUCCESS - Set new time stamp in this image successfully. + +--*/ +{ + struct tm stime; + struct tm *ptime; + time_t newtime; + UINT32 Index; + UINT32 DebugDirectoryEntryRva; + UINT32 DebugDirectoryEntryFileOffset; + UINT32 ExportDirectoryEntryRva; + UINT32 ExportDirectoryEntryFileOffset; + UINT32 ResourceDirectoryEntryRva; + UINT32 ResourceDirectoryEntryFileOffset; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_FILE_HEADER *FileHdr; + EFI_IMAGE_OPTIONAL_HEADER32 *Optional32Hdr; + EFI_IMAGE_OPTIONAL_HEADER64 *Optional64Hdr; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + UINT32 *NewTimeStamp; + + // + // Init variable. + // + DebugDirectoryEntryRva = 0; + DebugDirectoryEntryFileOffset = 0; + ExportDirectoryEntryRva = 0; + ExportDirectoryEntryFileOffset = 0; + ResourceDirectoryEntryRva = 0; + ResourceDirectoryEntryFileOffset = 0; + // + // Get time and date that will be set. + // + if (TimeStamp == NULL) { + Error (NULL, 0, 3000, "Invalid", "TimeStamp cannot be NULL."); + return EFI_INVALID_PARAMETER; + } + // + // compare the value with "NOW", if yes, current system time is set. + // + if (stricmp (TimeStamp, "NOW") == 0) { + // + // get system current time and date + // + time (&newtime); + } else { + // + // Check Time Format strictly yyyy-mm-dd 00:00:00 + // + for (Index = 0; TimeStamp[Index] != '\0' && Index < 20; Index ++) { + if (Index == 4 || Index == 7) { + if (TimeStamp[Index] == '-') { + continue; + } + } else if (Index == 13 || Index == 16) { + if (TimeStamp[Index] == ':') { + continue; + } + } else if (Index == 10 && TimeStamp[Index] == ' ') { + continue; + } else if ((TimeStamp[Index] < '0') || (TimeStamp[Index] > '9')) { + break; + } + } + + if (Index < 19 || TimeStamp[19] != '\0') { + Error (NULL, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp); + return EFI_INVALID_PARAMETER; + } + + // + // get the date and time from TimeStamp + // + if (sscanf (TimeStamp, "%d-%d-%d %d:%d:%d", + &stime.tm_year, + &stime.tm_mon, + &stime.tm_mday, + &stime.tm_hour, + &stime.tm_min, + &stime.tm_sec + ) != 6) { + Error (NULL, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp); + return EFI_INVALID_PARAMETER; + } + + // + // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it + // + if (stime.tm_mon <= 0 || stime.tm_mday <=0) { + Error (NULL, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp); + return EFI_INVALID_PARAMETER; + } + stime.tm_mon -= 1; + + // + // in struct, Year (current year minus 1900) + // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038 + // + // + // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038) + // + if (stime.tm_year >= 1970 && stime.tm_year <= 2038) { + // + // convert 1970 -> 70, 2000 -> 100, ... + // + stime.tm_year -= 1900; + } else { + Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp); + return EFI_INVALID_PARAMETER; + } + + // + // convert the date and time to time_t format + // + newtime = mktime (&stime); + if (newtime == (time_t) - 1) { + Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp); + return EFI_INVALID_PARAMETER; + } + } + + ptime = localtime (&newtime); + if (ptime != NULL) { + DebugMsg (NULL, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d", + ptime->tm_year + 1900, ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min, ptime->tm_sec); + } + // + // Set new time and data into PeImage. + // + DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer; + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + // NO DOS header, must start with PE/COFF header + FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32)); + } else { + FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32)); + } + + // + // Get Debug, Export and Resource EntryTable RVA address. + // Resource Directory entry need to review. + // + if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) { + Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER)); + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr + FileHdr->SizeOfOptionalHeader); + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) { + ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + } + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) { + ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + } + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) { + DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + } + } else { + Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER)); + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr + FileHdr->SizeOfOptionalHeader); + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) { + ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + } + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) { + ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + } + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) { + DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + } + } + + // + // Get DirectoryEntryTable file offset. + // + for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) { + if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress && + DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = + DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress && + ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + ExportDirectoryEntryFileOffset = + ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress && + ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + ResourceDirectoryEntryFileOffset = + ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + } + + // + // Set new stamp + // + FileHdr->TimeDateStamp = (UINT32) newtime; + mImageTimeStamp = (UINT32) newtime; + if (ExportDirectoryEntryRva != 0) { + NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32)); + *NewTimeStamp = (UINT32) newtime; + } + + if (ResourceDirectoryEntryRva != 0) { + NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32)); + *NewTimeStamp = (UINT32) newtime; + } + + if (DebugDirectoryEntryRva != 0) { + NewTimeStamp = (UINT32 *) (FileBuffer + DebugDirectoryEntryFileOffset + sizeof (UINT32)); + *NewTimeStamp = (UINT32) newtime; + } + + return EFI_SUCCESS; +} + +STATIC +STATUS +MicrocodeReadData ( + FILE *InFptr, + UINT32 *Data + ) +/*++ + +Routine Description: + Read a 32-bit microcode data value from a text file and convert to raw binary form. + +Arguments: + InFptr - file pointer to input text file + Data - pointer to where to return the data parsed + +Returns: + STATUS_SUCCESS - no errors or warnings, Data contains valid information + STATUS_ERROR - errors were encountered + +--*/ +{ + CHAR8 Line[MAX_LINE_LEN]; + CHAR8 *cptr; + int ScannedData = 0; + + Line[MAX_LINE_LEN - 1] = 0; + while (1) { + if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) { + return STATUS_ERROR; + } + // + // If it was a binary file, then it may have overwritten our null terminator + // + if (Line[MAX_LINE_LEN - 1] != 0) { + return STATUS_ERROR; + } + + // + // strip space + // + for (cptr = Line; *cptr && isspace((int)*cptr); cptr++) { + } + + // Skip Blank Lines and Comment Lines + if ((strlen(cptr) != 0) && (*cptr != ';')) { + break; + } + } + + // Look for + // dd 000000001h ; comment + // dd XXXXXXXX + // DD XXXXXXXXX + // DD XXXXXXXXX + // + if ((tolower((int)cptr[0]) == 'd') && (tolower((int)cptr[1]) == 'd') && isspace ((int)cptr[2])) { + // + // Skip blanks and look for a hex digit + // + cptr += 3; + for (; *cptr && isspace((int)*cptr); cptr++) { + } + if (isxdigit ((int)*cptr)) { + if (sscanf (cptr, "%X", &ScannedData) != 1) { + return STATUS_ERROR; + } + } + *Data = (UINT32) ScannedData; + return STATUS_SUCCESS; + } + + return STATUS_ERROR; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.h new file mode 100644 index 00000000..ff206497 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.h @@ -0,0 +1,50 @@ +/** @file +Header file for GenFw + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _GEN_FW_H_ +#define _GEN_FW_H_ + +// +// Action for this tool. +// +#define FW_DUMMY_IMAGE 0 +#define FW_EFI_IMAGE 1 +#define FW_TE_IMAGE 2 +#define FW_ACPI_IMAGE 3 +#define FW_BIN_IMAGE 4 +#define FW_ZERO_DEBUG_IMAGE 5 +#define FW_SET_STAMP_IMAGE 6 +#define FW_MCI_IMAGE 7 +#define FW_MERGE_IMAGE 8 +#define FW_RELOC_STRIPEED_IMAGE 9 +#define FW_HII_PACKAGE_LIST_RCIMAGE 10 +#define FW_HII_PACKAGE_LIST_BINIMAGE 11 +#define FW_REBASE_IMAGE 12 +#define FW_SET_ADDRESS_IMAGE 13 + +#define DUMP_TE_HEADER 0x11 + +VOID +SetHiiResourceHeader ( + UINT8 *HiiBinData, + UINT32 OffsetToFile + ); + +INTN +IsElfHeader ( + UINT8 *FileBuffer + ); + +BOOLEAN +ConvertElf ( + UINT8 **FileBuffer, + UINT32 *FileLength + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Makefile new file mode 100644 index 00000000..193bf3dc --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Makefile @@ -0,0 +1,18 @@ +## @file +# Windows makefile for 'GenFw' module build. +# +# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenFw + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = GenFw.obj ElfConvert.obj Elf32Convert.obj Elf64Convert.obj + +#CFLAGS = $(CFLAGS) /nodefaultlib:libc.lib + +!INCLUDE ..\Makefiles\ms.app + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Makefile.kmk new file mode 100644 index 00000000..5beae65a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Makefile.kmk @@ -0,0 +1,49 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-makefile for the EFI GenFw build tool. +# + +# +# Copyright (C) 2013-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +SUB_DEPTH = ../../../../../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +BLDPROGS += GenFw +GenFw_TEMPLATE = VBoxEfiBldProg +GenFw_SOURCES = \ + GenFw.c \ + ElfConvert.c \ + Elf32Convert.c \ + Elf64Convert.c + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf32.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf32.h new file mode 100644 index 00000000..8795fab4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf32.h @@ -0,0 +1,252 @@ +/** @file +Ported ELF include files from FreeBSD + +Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ +/*- + * 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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf64.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf64.h new file mode 100644 index 00000000..8dc10f6b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf64.h @@ -0,0 +1,254 @@ +/** @file +Ported ELF include files from FreeBSD + +Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +/*- + * 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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf_common.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf_common.h new file mode 100644 index 00000000..8bbf7596 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf_common.h @@ -0,0 +1,1045 @@ +/** @file +Ported ELF include files from FreeBSD + +Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.
+Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+Portion Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ +/*- + * 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_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) */ +#define EM_AARCH64 183 /* ARM 64bit Architecture */ +#define EM_RISCV64 243 /* 64bit RISC-V Architecture */ +#define EM_RISCV 244 /* 32bit RISC-V Architecture */ + +/* 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 */ + +/* Null relocation */ +#define R_AARCH64_NONE 256 /* No relocation */ +/* Static AArch64 relocations */ + /* Static data relocations */ +#define R_AARCH64_ABS64 257 /* S + A */ +#define R_AARCH64_ABS32 258 /* S + A */ +#define R_AARCH64_ABS16 259 /* S + A */ +#define R_AARCH64_PREL64 260 /* S + A - P */ +#define R_AARCH64_PREL32 261 /* S + A - P */ +#define R_AARCH64_PREL16 262 /* S + A - P */ + /* Group relocations to create a 16, 32, 48, or 64 bit unsigned data value or address inline */ +#define R_AARCH64_MOVW_UABS_G0 263 /* S + A */ +#define R_AARCH64_MOVW_UABS_G0_NC 264 /* S + A */ +#define R_AARCH64_MOVW_UABS_G1 265 /* S + A */ +#define R_AARCH64_MOVW_UABS_G1_NC 266 /* S + A */ +#define R_AARCH64_MOVW_UABS_G2 267 /* S + A */ +#define R_AARCH64_MOVW_UABS_G2_NC 268 /* S + A */ +#define R_AARCH64_MOVW_UABS_G3 269 /* S + A */ + /* Group relocations to create a 16, 32, 48, or 64 bit signed data or offset value inline */ +#define R_AARCH64_MOVW_SABS_G0 270 /* S + A */ +#define R_AARCH64_MOVW_SABS_G1 271 /* S + A */ +#define R_AARCH64_MOVW_SABS_G2 272 /* S + A */ + /* Relocations to generate 19, 21 and 33 bit PC-relative addresses */ +#define R_AARCH64_LD_PREL_LO19 273 /* S + A - P */ +#define R_AARCH64_ADR_PREL_LO21 274 /* S + A - P */ +#define R_AARCH64_ADR_PREL_PG_HI21 275 /* Page(S+A) - Page(P) */ +#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 /* Page(S+A) - Page(P) */ +#define R_AARCH64_ADD_ABS_LO12_NC 277 /* S + A */ +#define R_AARCH64_LDST8_ABS_LO12_NC 278 /* S + A */ +#define R_AARCH64_LDST16_ABS_LO12_NC 284 /* S + A */ +#define R_AARCH64_LDST32_ABS_LO12_NC 285 /* S + A */ +#define R_AARCH64_LDST64_ABS_LO12_NC 286 /* S + A */ +#define R_AARCH64_LDST128_ABS_LO12_NC 299 /* S + A */ + /* Relocations for control-flow instructions - all offsets are a multiple of 4 */ +#define R_AARCH64_TSTBR14 279 /* S+A-P */ +#define R_AARCH64_CONDBR19 280 /* S+A-P */ +#define R_AARCH64_JUMP26 282 /* S+A-P */ +#define R_AARCH64_CALL26 283 /* S+A-P */ + /* Group relocations to create a 16, 32, 48, or 64 bit PC-relative offset inline */ +#define R_AARCH64_MOVW_PREL_G0 287 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G0_NC 288 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G1 289 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G1_NC 290 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G2 291 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G2_NC 292 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G3 293 /* S+A-P */ + /* Group relocations to create a 16, 32, 48, or 64 bit GOT-relative offsets inline */ +#define R_AARCH64_MOVW_GOTOFF_G0 300 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G0_NC 301 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G1 302 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G1_NC 303 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G2 304 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G2_NC 305 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G3 306 /* G(S)-GOT */ + /* GOT-relative data relocations */ +#define R_AARCH64_GOTREL64 307 /* S+A-GOT */ +#define R_AARCH64_GOTREL32 308 /* S+A-GOT */ + /* GOT-relative instruction relocations */ +#define R_AARCH64_GOT_LD_PREL19 309 /* G(S)-P */ +#define R_AARCH64_LD64_GOTOFF_LO15 310 /* G(S)-GOT */ +#define R_AARCH64_ADR_GOT_PAGE 311 /* Page(G(S))-Page(P) */ +#define R_AARCH64_LD64_GOT_LO12_NC 312 /* G(S) */ +#define R_AARCH64_LD64_GOTPAGE_LO15 313 /* G(S)-Page(GOT) */ +/* Relocations for thread-local storage */ + /* General Dynamic TLS relocations */ +#define R_AARCH64_TLSGD_ADR_PREL21 512 /* G(TLSIDX(S+A)) - P */ +#define R_AARCH64_TLSGD_ADR_PAGE21 513 /* Page(G(TLSIDX(S+A))) - Page(P) */ +#define R_AARCH64_TLSGD_ADD_LO12_NC 514 /* G(TLSIDX(S+A)) */ +#define R_AARCH64_TLSGD_MOVW_G1 515 /* G(TLSIDX(S+A)) - GOT */ +#define R_AARCH64_TLSGD_MOVW_G0_NC 516 /* G(TLSIDX(S+A)) - GOT */ + /* Local Dynamic TLS relocations */ +#define R_AARCH64_TLSLD_ADR_PREL21 517 /* G(LDM(S))) - P */ +#define R_AARCH64_TLSLD_ADR_PAGE21 518 /* Page(G(LDM(S)))-Page(P) */ +#define R_AARCH64_TLSLD_ADD_LO12_NC 519 /* G(LDM(S)) */ +#define R_AARCH64_TLSLD_MOVW_G1 520 /* G(LDM(S)) - GOT */ +#define R_AARCH64_TLSLD_MOVW_G0_NC 521 /* G(LDM(S)) - GOT */ +#define R_AARCH64_TLSLD_LD_PREL19 522 /* G(LDM(S)) - P */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 /* DTPREL(S+A) */ + /* Initial Exec TLS relocations */ +#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 /* G(TPREL(S+A)) - GOT */ +#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 /* G(TPREL(S+A)) - GOT */ +#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 /* Page(G(TPREL(S+A))) - Page(P) */ +#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 /* G(TPREL(S+A)) */ +#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 /* G(TPREL(S+A)) - P */ + /* Local Exec TLS relocations */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559 /* TPREL(S+A) */ +/* Dynamic relocations */ + /* Dynamic relocations */ +#define R_AARCH64_COPY 1024 +#define R_AARCH64_GLOB_DAT 1025 /* S + A */ +#define R_AARCH64_JUMP_SLOT 1026 /* S + A */ +#define R_AARCH64_RELATIVE 1027 /* Delta(S) + A , Delta(P) + A */ +#define R_AARCH64_TLS_DTPREL64 1028 /* DTPREL(S+A) */ +#define R_AARCH64_TLS_DTPMOD64 1029 /* LDM(S) */ +#define R_AARCH64_TLS_TPREL64 1030 /* TPREL(S+A) */ +#define R_AARCH64_TLS_DTPREL32 1031 /* DTPREL(S+A) */ +#define R_AARCH64_TLS_DTPMOD32 1032 /* LDM(S) */ +#define R_AARCH64_TLS_TPREL32 1033 /* DTPREL(S+A) */ + +#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_CALL 28 +#define R_ARM_JMP24 29 +#define R_ARM_THM_MOVW_ABS_NC 47 +#define R_ARM_THM_MOVT_ABS 48 + +// Block of PC-relative relocations added to work around gcc putting +// object relocations in static executables. +#define R_ARM_THM_JUMP24 30 +#define R_ARM_PREL31 42 +#define R_ARM_MOVW_PREL_NC 45 +#define R_ARM_MOVT_PREL 46 +#define R_ARM_THM_MOVW_PREL_NC 49 +#define R_ARM_THM_MOVT_PREL 50 +#define R_ARM_THM_JMP6 52 +#define R_ARM_THM_ALU_PREL_11_0 53 +#define R_ARM_THM_PC12 54 +#define R_ARM_REL32_NOI 56 +#define R_ARM_ALU_PC_G0_NC 57 +#define R_ARM_ALU_PC_G0 58 +#define R_ARM_ALU_PC_G1_NC 59 +#define R_ARM_ALU_PC_G1 60 +#define R_ARM_ALU_PC_G2 61 +#define R_ARM_LDR_PC_G1 62 +#define R_ARM_LDR_PC_G2 63 +#define R_ARM_LDRS_PC_G0 64 +#define R_ARM_LDRS_PC_G1 65 +#define R_ARM_LDRS_PC_G2 66 +#define R_ARM_LDC_PC_G0 67 +#define R_ARM_LDC_PC_G1 68 +#define R_ARM_LDC_PC_G2 69 +#define R_ARM_GOT_PREL 96 +#define R_ARM_THM_JUMP11 102 +#define R_ARM_THM_JUMP8 103 +#define R_ARM_TLS_GD32 104 +#define R_ARM_TLS_LDM32 105 +#define R_ARM_TLS_IE32 107 + +#define R_ARM_THM_JUMP19 51 +#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 + +#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 */ +#define R_X86_64_PC64 24 /* PC relative 64 bit */ +#define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */ +#define R_X86_64_GOTPC3 26 /* 32 bit signed pc relative offset to GOT */ +#define R_X86_64_GOT64 27 /* 64-bit GOT entry offset */ +#define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset to GOT entry */ +#define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT */ +#define R_X86_64_GOTPLT64 30 /* like GOT64, says PLT entry needed */ +#define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset to PLT entry */ +#define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend */ +#define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend */ +#define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */ +#define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS descriptor. */ +#define R_X86_64_TLSDESC 36 /* TLS descriptor. */ +#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ +#define R_X86_64_RELATIVE64 38 /* 64-bit adjust by program base */ +#define R_X86_64_GOTPCRELX 41 /* Load from 32 bit signed pc relative offset to GOT entry without REX prefix, relaxable. */ +#define R_X86_64_REX_GOTPCRELX 42 /* Load from 32 bit signed pc relative offset to GOT entry with REX prefix, relaxable. */ + +/* + * RISC-V relocation types + */ + +/* Relocation types used by the dynamic linker */ +#define R_RISCV_NONE 0 +#define R_RISCV_32 1 +#define R_RISCV_64 2 +#define R_RISCV_RELATIVE 3 +#define R_RISCV_COPY 4 +#define R_RISCV_JUMP_SLOT 5 +#define R_RISCV_TLS_DTPMOD32 6 +#define R_RISCV_TLS_DTPMOD64 7 +#define R_RISCV_TLS_DTPREL32 8 +#define R_RISCV_TLS_DTPREL64 9 +#define R_RISCV_TLS_TPREL32 10 +#define R_RISCV_TLS_TPREL64 11 + +/* Relocation types not used by the dynamic linker */ +#define R_RISCV_BRANCH 16 +#define R_RISCV_JAL 17 +#define R_RISCV_CALL 18 +#define R_RISCV_CALL_PLT 19 +#define R_RISCV_GOT_HI20 20 +#define R_RISCV_TLS_GOT_HI20 21 +#define R_RISCV_TLS_GD_HI20 22 +#define R_RISCV_PCREL_HI20 23 +#define R_RISCV_PCREL_LO12_I 24 +#define R_RISCV_PCREL_LO12_S 25 +#define R_RISCV_HI20 26 +#define R_RISCV_LO12_I 27 +#define R_RISCV_LO12_S 28 +#define R_RISCV_TPREL_HI20 29 +#define R_RISCV_TPREL_LO12_I 30 +#define R_RISCV_TPREL_LO12_S 31 +#define R_RISCV_TPREL_ADD 32 +#define R_RISCV_ADD8 33 +#define R_RISCV_ADD16 34 +#define R_RISCV_ADD32 35 +#define R_RISCV_ADD64 36 +#define R_RISCV_SUB8 37 +#define R_RISCV_SUB16 38 +#define R_RISCV_SUB32 39 +#define R_RISCV_SUB64 40 +#define R_RISCV_GNU_VTINHERIT 41 +#define R_RISCV_GNU_VTENTRY 42 +#define R_RISCV_ALIGN 43 +#define R_RISCV_RVC_BRANCH 44 +#define R_RISCV_RVC_JUMP 45 +#define R_RISCV_RVC_LUI 46 +#define R_RISCV_GPREL_I 47 +#define R_RISCV_GPREL_S 48 +#define R_RISCV_TPREL_I 49 +#define R_RISCV_TPREL_S 50 +#define R_RISCV_RELAX 51 +#define R_RISCV_SUB6 52 +#define R_RISCV_SET6 53 +#define R_RISCV_SET8 54 +#define R_RISCV_SET16 55 +#define R_RISCV_SET32 56 +#endif /* !_SYS_ELF_COMMON_H_ */ -- cgit v1.2.3