Support ELF32/64 format payloads regardless of operation mode
This allows to load and execute ELF32 or ELF64 format payloads regardless of Ia32 or X64 SBL operation modes. Signed-off-by: Aiden Park <aiden.park@intel.com>
This commit is contained in:
parent
3a02cd0f45
commit
236a800284
|
@ -10,6 +10,7 @@
|
|||
#define __ELF_LIB_H__
|
||||
|
||||
#include <Uefi/UefiBaseType.h>
|
||||
#include <IndustryStandard/PeImage.h>
|
||||
|
||||
/**
|
||||
Check if the image is a bootable ELF image.
|
||||
|
@ -40,9 +41,28 @@ IsElfImage (
|
|||
@retval EFI_SUCCESS ELF binary is loaded successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
LoadElfImage (
|
||||
IN CONST VOID *ImageBase,
|
||||
OUT VOID **EntryPoint
|
||||
);
|
||||
|
||||
/**
|
||||
Extract and return the machine type from ELF image.
|
||||
|
||||
@param[in] ImageBase Memory address of an image.
|
||||
@param[out] MachinePtr The pointer to machine type to return.
|
||||
|
||||
@retval EFI_SUCCESS Machine was returned successfully.
|
||||
@retval EFI_UNSUPPORTED Unsupported image format.
|
||||
@retval EFI_INVALID_PARAMETER The ImageBase pointer is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetElfMachine (
|
||||
IN VOID *ImageBase,
|
||||
OUT UINT16 *MachinePtr OPTIONAL
|
||||
);
|
||||
|
||||
#endif /* __ELF_LIB_H__ */
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
|
||||
#include "ElfLibInternal.h"
|
||||
|
||||
#define ELF_CR(Record, TYPE, Field) (((TYPE *) Record)->Field)
|
||||
#define ELF_CLASS_CR(Record, TYPE, Field, IsElf64) \
|
||||
IsElf64 ? ELF_CR(Record,Elf64_##TYPE,Field) : ELF_CR(Record,Elf32_##TYPE,Field)
|
||||
|
||||
/**
|
||||
Check if the image has ELF Header
|
||||
|
||||
|
@ -30,7 +34,31 @@ IsElfHeader (
|
|||
}
|
||||
|
||||
/**
|
||||
Check if the image is 32-bit ELF Format
|
||||
Check if the image is 64-bit ELF Format
|
||||
|
||||
@param[in] ImageBase Memory address of an image.
|
||||
|
||||
@retval TRUE if ELF32, otherwise FALSE
|
||||
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
IsElf64Format (
|
||||
IN CONST UINT8 *ImageBase
|
||||
)
|
||||
{
|
||||
Elf32_Ehdr *ElfHdr;
|
||||
|
||||
ElfHdr = (Elf32_Ehdr *)ImageBase;
|
||||
if (ElfHdr->e_ident[EI_CLASS] == ELFCLASS64) {
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Check if the image is ELF Format
|
||||
|
||||
@param[in] ImageBase Memory address of an image.
|
||||
|
||||
|
@ -43,46 +71,54 @@ IsElfFormat (
|
|||
IN CONST UINT8 *ImageBase
|
||||
)
|
||||
{
|
||||
Elf_Ehdr *ElfHdr;
|
||||
Elf32_Ehdr *ElfHdr;
|
||||
UINT16 Data16;
|
||||
UINT32 Data32;
|
||||
BOOLEAN IsElf64;
|
||||
|
||||
if (ImageBase == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ElfHdr = (Elf_Ehdr *)ImageBase;
|
||||
ElfHdr = (Elf32_Ehdr *)ImageBase;
|
||||
|
||||
//
|
||||
// Check 32/64-bit architecture
|
||||
//
|
||||
if (ElfHdr->e_ident[EI_CLASS] != ELFCLASS) {
|
||||
return FALSE;
|
||||
}
|
||||
IsElf64 = IsElf64Format (ImageBase);
|
||||
|
||||
//
|
||||
// Support little-endian only
|
||||
//
|
||||
if (ElfHdr->e_ident[EI_DATA] != ELFDATA2LSB) {
|
||||
DEBUG ((DEBUG_VERBOSE, "IsElfFormat: Not Little-Endian!\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Support intel architecture only for now
|
||||
//
|
||||
if (ElfHdr->e_machine != ELF_EM) {
|
||||
Data16 = (UINT16)ELF_CLASS_CR (ImageBase, Ehdr, e_machine, IsElf64);
|
||||
if ((Data16 != EM_386) && (Data16 != EM_X86_64)) {
|
||||
DEBUG ((DEBUG_VERBOSE, "IsElfFormat: Not Intel Architecture!\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Support ELF types: EXEC (Executable file), DYN (Shared object file)
|
||||
//
|
||||
if ((ElfHdr->e_type != ET_EXEC) && (ElfHdr->e_type != ET_DYN)) {
|
||||
Data16 = (UINT16)ELF_CLASS_CR (ImageBase, Ehdr, e_type, IsElf64);
|
||||
if ((Data16 != ET_EXEC) && (Data16 != ET_DYN)) {
|
||||
DEBUG ((DEBUG_VERBOSE, "IsElfFormat: Not Support ELF types(%d)!\n", Data16));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Support current ELF version only
|
||||
//
|
||||
if (ElfHdr->e_version != EV_CURRENT) {
|
||||
Data32 = (UINT32)ELF_CLASS_CR (ImageBase, Ehdr, e_version, IsElf64);
|
||||
if (Data32 != EV_CURRENT) {
|
||||
DEBUG ((DEBUG_VERBOSE, "IsElfFormat: Not Support ELF version(0x%08X)!\n", Data32));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -106,41 +142,59 @@ LoadElfSegments (
|
|||
OUT VOID **EntryPoint
|
||||
)
|
||||
{
|
||||
Elf_Ehdr *ElfHdr;
|
||||
Elf_Phdr *ProgramHdr;
|
||||
Elf_Phdr *ProgramHdrBase;
|
||||
VOID *ProgramHdr;
|
||||
UINT8 *ProgramHdrBase;
|
||||
BOOLEAN IsElf64;
|
||||
UINT16 Index;
|
||||
UINT16 ProgramHdrNum;
|
||||
UINT16 ProgramHdrEntSize;
|
||||
UINT32 ProgramHdrType;
|
||||
UINT64 ProgramHdrOffset;
|
||||
UINT64 ProgramHdrFileOffset;
|
||||
UINT64 ProgramHdrFileSize;
|
||||
UINT64 ProgramHdrMemSize;
|
||||
UINT64 ProgramHdrPaddr;
|
||||
UINT64 ElfEntry;
|
||||
|
||||
if ((ImageBase == NULL) || (EntryPoint == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ElfHdr = (Elf_Ehdr *)ImageBase;
|
||||
ProgramHdrBase = (Elf_Phdr *)(ImageBase + ElfHdr->e_phoff);
|
||||
for (Index = 0; Index < ElfHdr->e_phnum; Index++) {
|
||||
ProgramHdr = (Elf_Phdr *)((UINT8 *)ProgramHdrBase + Index * ElfHdr->e_phentsize);
|
||||
IsElf64 = IsElf64Format (ImageBase);
|
||||
ProgramHdrOffset = ELF_CLASS_CR (ImageBase, Ehdr, e_phoff, IsElf64);
|
||||
ProgramHdrBase = (UINT8 *)ImageBase + ProgramHdrOffset;
|
||||
ProgramHdrNum = ELF_CLASS_CR (ImageBase, Ehdr, e_phnum, IsElf64);
|
||||
ProgramHdrEntSize = ELF_CLASS_CR (ImageBase, Ehdr, e_phentsize, IsElf64);
|
||||
for (Index = 0; Index < ProgramHdrNum; Index++) {
|
||||
ProgramHdr = (VOID *)(ProgramHdrBase + Index * ProgramHdrEntSize);
|
||||
|
||||
if ((ProgramHdr->p_type != PT_LOAD) ||
|
||||
(ProgramHdr->p_memsz == 0) ||
|
||||
(ProgramHdr->p_offset == 0)) {
|
||||
ProgramHdrType = ELF_CLASS_CR (ProgramHdr, Phdr, p_type, IsElf64);
|
||||
ProgramHdrFileOffset = ELF_CLASS_CR (ProgramHdr, Phdr, p_offset, IsElf64);
|
||||
ProgramHdrMemSize = ELF_CLASS_CR (ProgramHdr, Phdr, p_memsz, IsElf64);
|
||||
if ((ProgramHdrType != PT_LOAD) ||
|
||||
(ProgramHdrMemSize == 0) ||
|
||||
(ProgramHdrFileOffset == 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ProgramHdr->p_filesz > ProgramHdr->p_memsz) {
|
||||
ProgramHdrFileSize = ELF_CLASS_CR (ProgramHdr, Phdr, p_filesz, IsElf64);
|
||||
if (ProgramHdrFileSize > ProgramHdrMemSize) {
|
||||
return EFI_LOAD_ERROR;
|
||||
}
|
||||
|
||||
CopyMem ((VOID *)(UINTN)ProgramHdr->p_paddr,
|
||||
ImageBase + ProgramHdr->p_offset,
|
||||
(UINTN)ProgramHdr->p_filesz);
|
||||
ProgramHdrPaddr = ELF_CLASS_CR (ProgramHdr, Phdr, p_paddr, IsElf64);
|
||||
CopyMem ((VOID *)(UINTN)ProgramHdrPaddr,
|
||||
(VOID *)(UINTN)(ImageBase + ProgramHdrFileOffset),
|
||||
(UINTN)ProgramHdrFileSize);
|
||||
|
||||
if (ProgramHdr->p_memsz > ProgramHdr->p_filesz) {
|
||||
ZeroMem ((VOID *)(UINTN)(ProgramHdr->p_paddr + ProgramHdr->p_filesz),
|
||||
(UINTN)(ProgramHdr->p_memsz - ProgramHdr->p_filesz));
|
||||
if (ProgramHdrMemSize > ProgramHdrFileSize) {
|
||||
ZeroMem ((VOID *)(UINTN)(ProgramHdrPaddr + ProgramHdrFileSize),
|
||||
(UINTN)(ProgramHdrMemSize - ProgramHdrFileSize));
|
||||
}
|
||||
}
|
||||
|
||||
*EntryPoint = (VOID *)(UINTN)ElfHdr->e_entry;
|
||||
ElfEntry = ELF_CLASS_CR (ImageBase, Ehdr, e_entry, IsElf64);
|
||||
*EntryPoint = (VOID *)(UINTN)ElfEntry;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@ -170,7 +224,7 @@ IsElfImage (
|
|||
This function loads ELF image segments into memory address specified
|
||||
in ELF program header.
|
||||
|
||||
@param[in] ImageBase Memory address of an image.
|
||||
@param[in] ElfBuffer Memory address of an image.
|
||||
@param[out] EntryPoint The entry point of loaded ELF image.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Input parameters are not valid.
|
||||
|
@ -179,6 +233,7 @@ IsElfImage (
|
|||
@retval EFI_SUCCESS ELF binary is loaded successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
LoadElfImage (
|
||||
IN CONST VOID *ElfBuffer,
|
||||
OUT VOID **EntryPoint
|
||||
|
@ -202,3 +257,40 @@ LoadElfImage (
|
|||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Extract and return the machine type from ELF image.
|
||||
|
||||
@param[in] ElfBuffer Memory address of an image.
|
||||
@param[out] MachinePtr The pointer to machine type to return.
|
||||
|
||||
@retval EFI_SUCCESS Machine was returned successfully.
|
||||
@retval EFI_UNSUPPORTED Unsupported image format.
|
||||
@retval EFI_INVALID_PARAMETER The ElfBuffer pointer is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetElfMachine (
|
||||
IN VOID *ElfBuffer,
|
||||
OUT UINT16 *MachinePtr OPTIONAL
|
||||
)
|
||||
{
|
||||
if (ElfBuffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!IsElfImage (ElfBuffer)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (MachinePtr != NULL) {
|
||||
if (IsElf64Format (ElfBuffer)) {
|
||||
*MachinePtr = IMAGE_FILE_MACHINE_X64;
|
||||
} else {
|
||||
*MachinePtr = IMAGE_FILE_MACHINE_I386;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <Library/BaseLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <IndustryStandard/PeImage.h>
|
||||
#include "ElfCommon.h"
|
||||
#include "Elf32.h"
|
||||
#include "Elf64.h"
|
||||
|
|
|
@ -183,7 +183,10 @@ NormalBootPath (
|
|||
UefiSig = Dst[0];
|
||||
Status = LoadFvImage (Dst, Stage2Param->PayloadActualLength, (VOID **)&PldEntry, &PldMachine);
|
||||
} else if (IsElfImage (Dst)) {
|
||||
Status = LoadElfImage (Dst, (VOID *)&PldEntry);
|
||||
Status = GetElfMachine (Dst, &PldMachine);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
Status = LoadElfImage (Dst, (VOID *)&PldEntry);
|
||||
}
|
||||
} else {
|
||||
if (FeaturePcdGet (PcdLinuxPayloadEnabled)) {
|
||||
if (IsBzImage (Dst)) {
|
||||
|
|
Loading…
Reference in New Issue