Squash commits for public release
This commit is contained in:
144
boot/libboot/elf/elf_lite.c
Normal file
144
boot/libboot/elf/elf_lite.c
Normal file
@@ -0,0 +1,144 @@
|
||||
#include "elf_lite.h"
|
||||
#include <libboot/crypto/sha256.h>
|
||||
#include <libboot/log/log.h>
|
||||
#include <libboot/mem/alloc.h>
|
||||
#include <libboot/mem/mem.h>
|
||||
|
||||
// #define DEBUG_ELF
|
||||
|
||||
int elf_init_ctx(drive_desc_t* drive_desc, fs_desc_t* fs_desc, const char* path, elfctx_t* elfctx)
|
||||
{
|
||||
elfctx->drive_desc = drive_desc;
|
||||
elfctx->fs_desc = fs_desc;
|
||||
fs_desc->get_inode(drive_desc, path, &elfctx->file_inode);
|
||||
fs_desc->read_from_inode(drive_desc, &elfctx->file_inode, (void*)&elfctx->header, 0, sizeof(elfctx->header));
|
||||
|
||||
if (elfctx->header.e_ident[EI_MAG0] != 0x7F || elfctx->header.e_ident[EI_MAG1] != 0x45 || elfctx->header.e_ident[EI_MAG2] != 0x4c || elfctx->header.e_ident[EI_MAG3] != 0x46) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int elf_read_program_header(elfctx_t* elfctx, size_t id, elf_program_header_32_t* program_header)
|
||||
{
|
||||
uintptr_t offset = elfctx->header.e_phoff + id * elfctx->header.e_phentsize;
|
||||
return elfctx->fs_desc->read_from_inode(elfctx->drive_desc, &elfctx->file_inode, (void*)program_header, offset, sizeof(*program_header));
|
||||
}
|
||||
|
||||
int elf_read_section_header(elfctx_t* elfctx, uint32_t id, elf_section_header_32_t* section_header)
|
||||
{
|
||||
uintptr_t offset = elfctx->header.e_shoff + id * elfctx->header.e_shentsize;
|
||||
return elfctx->fs_desc->read_from_inode(elfctx->drive_desc, &elfctx->file_inode, (void*)section_header, offset, sizeof(*section_header));
|
||||
}
|
||||
|
||||
#ifdef BITS32
|
||||
int elf_load_kernel(drive_desc_t* drive_desc, fs_desc_t* fs_desc, const char* path, size_t* kernel_vaddr, size_t* kernel_paddr, size_t* kernel_size)
|
||||
{
|
||||
elfctx_t elfctx;
|
||||
int err = elf_init_ctx(drive_desc, fs_desc, path, &elfctx);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
size_t vaddr = -1;
|
||||
size_t paddr = -1;
|
||||
size_t vaddr_end = 0;
|
||||
|
||||
for (uint32_t i = 0; i < elfctx.header.e_phnum; i++) {
|
||||
elf_program_header_32_t program_header;
|
||||
elf_read_program_header(&elfctx, i, &program_header);
|
||||
|
||||
if (program_header.p_type == PT_LOAD) {
|
||||
paddr = min(paddr, program_header.p_paddr);
|
||||
vaddr = min(vaddr, program_header.p_vaddr);
|
||||
fs_desc->read(drive_desc, path, (void*)program_header.p_paddr, program_header.p_offset, program_header.p_filesz);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < elfctx.header.e_shnum; i++) {
|
||||
elf_section_header_32_t section_header;
|
||||
elf_read_section_header(&elfctx, i, §ion_header);
|
||||
|
||||
if ((section_header.sh_flags & SHF_ALLOC) == SHF_ALLOC) {
|
||||
vaddr_end = max(vaddr_end, section_header.sh_addr + section_header.sh_size);
|
||||
}
|
||||
}
|
||||
|
||||
*kernel_vaddr = vaddr;
|
||||
*kernel_paddr = paddr;
|
||||
*kernel_size = vaddr_end - vaddr;
|
||||
return 0;
|
||||
}
|
||||
// #endif
|
||||
#else
|
||||
size_t elf_get_kernel_size(void* elffile)
|
||||
{
|
||||
elf_header_64_t* header = (elf_header_64_t*)elffile;
|
||||
if (header->e_ident[EI_MAG0] != 0x7F || header->e_ident[EI_MAG1] != 0x45 || header->e_ident[EI_MAG2] != 0x4c || header->e_ident[EI_MAG3] != 0x46) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t vaddr = 0xffffffffffffffff;
|
||||
size_t vaddr_end = 0;
|
||||
|
||||
for (size_t i = 0; i < header->e_phnum; i++) {
|
||||
uintptr_t offset = header->e_phoff + i * header->e_phentsize;
|
||||
elf_program_header_64_t* program_header = (elf_program_header_64_t*)((uintptr_t)elffile + offset);
|
||||
if (program_header->p_type == PT_LOAD) {
|
||||
vaddr = min(vaddr, program_header->p_vaddr);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < header->e_shnum; i++) {
|
||||
uintptr_t offset = header->e_shoff + i * header->e_shentsize;
|
||||
elf_section_header_64_t* section_header = (elf_section_header_64_t*)((uintptr_t)elffile + offset);
|
||||
|
||||
if ((section_header->sh_flags & SHF_ALLOC) == SHF_ALLOC) {
|
||||
vaddr_end = max(vaddr_end, section_header->sh_addr + section_header->sh_size);
|
||||
}
|
||||
}
|
||||
|
||||
return vaddr_end - vaddr;
|
||||
}
|
||||
|
||||
int elf_load_kernel(void* elffile, size_t size, uintptr_t* kernel_vaddr, uintptr_t* kernel_paddr)
|
||||
{
|
||||
elf_header_64_t* header = (elf_header_64_t*)elffile;
|
||||
if (header->e_ident[EI_MAG0] != 0x7F || header->e_ident[EI_MAG1] != 0x45 || header->e_ident[EI_MAG2] != 0x4c || header->e_ident[EI_MAG3] != 0x46) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t vaddr = 0xffffffffffffffff;
|
||||
for (size_t i = 0; i < header->e_phnum; i++) {
|
||||
uintptr_t offset = header->e_phoff + i * header->e_phentsize;
|
||||
elf_program_header_64_t* program_header = (elf_program_header_64_t*)((uintptr_t)elffile + offset);
|
||||
if (program_header->p_type == PT_LOAD) {
|
||||
vaddr = min(vaddr, program_header->p_vaddr);
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t paddr = (uintptr_t)palloc(size);
|
||||
if (!paddr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < header->e_phnum; i++) {
|
||||
uintptr_t offset = header->e_phoff + i * header->e_phentsize;
|
||||
elf_program_header_64_t* program_header = (elf_program_header_64_t*)((uintptr_t)elffile + offset);
|
||||
if (program_header->p_type == PT_LOAD) {
|
||||
uintptr_t data_paddr = (program_header->p_vaddr - vaddr) + paddr;
|
||||
uintptr_t data_offset = (uintptr_t)elffile + program_header->p_offset;
|
||||
|
||||
#ifdef DEBUG_ELF
|
||||
log("copying elf %lx %lx %lx", data_paddr, data_offset, program_header->p_filesz);
|
||||
#endif
|
||||
memcpy((void*)data_paddr, (void*)data_offset, program_header->p_filesz);
|
||||
}
|
||||
}
|
||||
|
||||
*kernel_vaddr = vaddr;
|
||||
*kernel_paddr = paddr;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
196
boot/libboot/elf/elf_lite.h
Normal file
196
boot/libboot/elf/elf_lite.h
Normal file
@@ -0,0 +1,196 @@
|
||||
#ifndef _BOOT_LIBBOOT_ELF_ELF_LITE
|
||||
#define _BOOT_LIBBOOT_ELF_ELF_LITE
|
||||
|
||||
#include <libboot/abi/drivers.h>
|
||||
#include <libboot/fs/ext2_lite.h>
|
||||
#include <libboot/types.h>
|
||||
|
||||
enum E_IDENT_FIELDS {
|
||||
EI_MAG0,
|
||||
EI_MAG1,
|
||||
EI_MAG2,
|
||||
EI_MAG3,
|
||||
EI_CLASS,
|
||||
EI_DATA,
|
||||
EI_VERSION,
|
||||
EI_OSABI,
|
||||
EI_ABIVERSION,
|
||||
};
|
||||
|
||||
enum E_TYPE_FIELDS {
|
||||
ET_NONE,
|
||||
ET_REL,
|
||||
ET_EXEC,
|
||||
ET_DYN,
|
||||
ET_CORE,
|
||||
};
|
||||
|
||||
enum E_MACHINE_FIELDS {
|
||||
EM_NONE,
|
||||
EM_386 = 3,
|
||||
EM_PPC = 20,
|
||||
EM_PPC64 = 21,
|
||||
EM_X86_64 = 62,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t e_ident[16];
|
||||
uint16_t e_type;
|
||||
uint16_t e_machine;
|
||||
uint32_t e_version;
|
||||
uint32_t e_entry;
|
||||
uint32_t e_phoff;
|
||||
uint32_t e_shoff;
|
||||
uint32_t e_flags;
|
||||
uint16_t e_ehsize;
|
||||
uint16_t e_phentsize;
|
||||
uint16_t e_phnum;
|
||||
uint16_t e_shentsize;
|
||||
uint16_t e_shnum;
|
||||
uint16_t e_shstrndx;
|
||||
} elf_header_32_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t e_ident[16];
|
||||
uint16_t e_type;
|
||||
uint16_t e_machine;
|
||||
uint32_t e_version;
|
||||
uint64_t e_entry;
|
||||
uint64_t e_phoff;
|
||||
uint64_t e_shoff;
|
||||
uint32_t e_flags;
|
||||
uint16_t e_ehsize;
|
||||
uint16_t e_phentsize;
|
||||
uint16_t e_phnum;
|
||||
uint16_t e_shentsize;
|
||||
uint16_t e_shnum;
|
||||
uint16_t e_shstrndx;
|
||||
} elf_header_64_t;
|
||||
|
||||
enum P_TYPE_FIELDS {
|
||||
PT_NULL,
|
||||
PT_LOAD,
|
||||
PT_DYNAMIC,
|
||||
PT_INTERP,
|
||||
PT_NOTE,
|
||||
PT_SHLIB,
|
||||
PT_PHDR,
|
||||
PT_TLS,
|
||||
PT_LOOS = 0x60000000,
|
||||
PT_HIOS = 0x6FFFFFFF,
|
||||
PT_LOPROC = 0x70000000,
|
||||
PT_HIPROC = 0x7FFFFFFF,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t p_type;
|
||||
uint32_t p_offset;
|
||||
uint32_t p_vaddr;
|
||||
uint32_t p_paddr;
|
||||
uint32_t p_filesz;
|
||||
uint16_t p_memsz;
|
||||
uint16_t p_flags;
|
||||
uint16_t p_align;
|
||||
} elf_program_header_32_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t p_type;
|
||||
uint32_t p_flags;
|
||||
uint64_t p_offset;
|
||||
uint64_t p_vaddr;
|
||||
uint64_t p_paddr;
|
||||
uint64_t p_filesz;
|
||||
uint64_t p_memsz;
|
||||
uint64_t p_align;
|
||||
} elf_program_header_64_t;
|
||||
|
||||
enum SH_TYPE_FIELDS {
|
||||
SHT_NULL,
|
||||
SHT_PROGBITS,
|
||||
SHT_SYMTAB,
|
||||
SHT_STRTAB,
|
||||
SHT_RELA,
|
||||
SHT_HASH,
|
||||
SHT_DYNAMIC,
|
||||
SHT_NOTE,
|
||||
SHT_NOBITS,
|
||||
SHT_REL,
|
||||
SHT_SHLIB,
|
||||
SHT_DYNSYM,
|
||||
SHT_INIT_ARRAY,
|
||||
SHT_FINI_ARRAY,
|
||||
SHT_PREINIT_ARRAY,
|
||||
SHT_GROUP,
|
||||
SHT_SYMTAB_SHNDX,
|
||||
|
||||
SHT_LOOS = 1610612736,
|
||||
SHT_HIOS = 1879048191,
|
||||
SHT_LOPROC = 1879048192,
|
||||
SHT_HIPROC = 2147483647,
|
||||
SHT_LOUSER = 2147483648,
|
||||
SHT_HIUSER = 4294967295,
|
||||
};
|
||||
|
||||
enum SH_FLAGS_FIELDS {
|
||||
SHF_WRITE = 0x1,
|
||||
SHF_ALLOC = 0x2,
|
||||
SHF_EXECINSTR = 0x4,
|
||||
SHF_MERGE = 0x10,
|
||||
SHF_STRINGS = 0x20,
|
||||
|
||||
SHF_INFO_LINK = 0x40,
|
||||
SHF_LINK_ORDER = 0x80,
|
||||
SHF_OS_NONCONFORMING = 0x100,
|
||||
SHF_GROUP = 0x200,
|
||||
SHF_TLS = 0x400,
|
||||
SHF_COMPRESSED = 0x800,
|
||||
SHF_MASKOS = 0x0ff00000,
|
||||
SHF_MASKPROC = 0xf0000000
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t sh_name;
|
||||
uint32_t sh_type;
|
||||
uint32_t sh_flags;
|
||||
uint32_t sh_addr;
|
||||
uint32_t sh_offset;
|
||||
uint32_t sh_size;
|
||||
uint32_t sh_link;
|
||||
uint32_t sh_info;
|
||||
uint32_t sh_addralign;
|
||||
uint32_t sh_entsize;
|
||||
} elf_section_header_32_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t sh_name;
|
||||
uint32_t sh_type;
|
||||
uint64_t sh_flags;
|
||||
uint64_t sh_addr;
|
||||
uint64_t sh_offset;
|
||||
uint64_t sh_size;
|
||||
uint32_t sh_link;
|
||||
uint32_t sh_info;
|
||||
uint64_t sh_addralign;
|
||||
uint64_t sh_entsize;
|
||||
} elf_section_header_64_t;
|
||||
|
||||
struct elfctx {
|
||||
drive_desc_t* drive_desc;
|
||||
fs_desc_t* fs_desc;
|
||||
inode_t file_inode;
|
||||
elf_header_32_t header;
|
||||
};
|
||||
typedef struct elfctx elfctx_t;
|
||||
|
||||
int elf_init_ctx(drive_desc_t* drive_desc, fs_desc_t* fs_desc, const char* path, elfctx_t* elfctx);
|
||||
int elf_read_program_header(elfctx_t* elfctx, size_t id, elf_program_header_32_t* program_header);
|
||||
int elf_read_section_header(elfctx_t* elfctx, uint32_t id, elf_section_header_32_t* section_header);
|
||||
|
||||
#ifdef BITS32
|
||||
int elf_load_kernel(drive_desc_t* drive_desc, fs_desc_t* fs_desc, const char* path, size_t* kernel_vaddr, size_t* kernel_paddr, size_t* kernel_size);
|
||||
#else
|
||||
size_t elf_get_kernel_size(void* elffile);
|
||||
int elf_load_kernel(void* elffile, size_t size, uintptr_t* kernel_vaddr, uintptr_t* kernel_paddr);
|
||||
#endif
|
||||
|
||||
#endif // _BOOT_LIBBOOT_ELF_ELF_LITE
|
||||
Reference in New Issue
Block a user