/** @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; UINT32 mCoffOffsetMax; // // 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) { #ifndef JIEF_DEBUG // Some globals have the same name and that confuses the debugger. // So it's better not to link with Elf32Convert.o when debugging x64 if (!InitializeElf32 (*FileBuffer, &ElfFunctions)) { return FALSE; } #endif } 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; }