/** @file
Elf convert solution
Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#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 ();
//
// For PRM Driver to Write export info.
//
if (mExportFlag) {
VerboseMsg ("Write export info.");
ElfFunctions.WriteExport ();
}
//
// 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;
}