This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
portland-os/src/kernel/elf.c
Benji Dial e8c6577617 program loading, others
big kernel additions: paging, elf loading, separate kernel and user page allocation
it now properly loads and runs sd0:bin/init.elf
still need to determine which disk was booted from, and start the init on that disk
2020-09-06 00:48:07 -04:00

116 lines
No EOL
2.4 KiB
C

#include <stdint.h>
#include "drive.h"
#include "elf.h"
#include "task.h"
#include "util.h"
#include "paging.h"
#include "pmap.h"
#define ELF_MAGIC 0x464c457f
enum {
ELF_32 = 1,
ELF_64 = 2
};
enum {
LITTLE_ENDIAN = 1,
BIG_ENDIAN = 2
};
enum {
//...
ARCH_X86 = 0x03
//...
};
struct elf_header {
uint32_t magic;
uint8_t word_size;
uint8_t endianness;
uint8_t elf_version;
uint8_t target_os;//ignored
uint8_t os_abi_version;//should be zero
uint8_t reserved[7];
uint16_t object_type;//TODO
uint16_t architecture;//should be ARCH_X86
uint32_t elf_version_2;
uint32_t entry_vma;
uint32_t phtable_fa;
uint32_t shtable_fa;
uint32_t flags;
uint16_t eh_size;
uint16_t phentry_size;
uint16_t phtable_count;
uint16_t shentry_size;
uint16_t shtable_count;
uint16_t sh_names_entry;
} __attribute__ ((packed));
enum {
PT_UNUSED = 0,
PT_LOADME = 1,
PT_DYNLINK = 2,
PT_INTERP = 3,
PT_COMMENT = 4,
PT_SHARED = 5,
PT_PHTABLE = 6,
PT_TL_TMPL = 7
};
enum {
PH_WRITABLE = 0x02
};
struct ph_entry {
uint32_t type;
uint32_t fa;
uint32_t vma;//must be page-aligned
uint32_t pma;//ignored
uint32_t fs;
uint32_t vms;
uint32_t flags;
uint32_t align;
} __attribute__ ((packed));
bool try_elf_run(const struct drive *d, const char *path) {
file_id_t h = d->get_file(d, path);
if (!h)
return false;
struct elf_header ehead;
fmcpy(&ehead, d, h, 0, sizeof(struct elf_header));
if ((ehead.magic != ELF_MAGIC) ||
(ehead.word_size != ELF_32) ||
(ehead.endianness != LITTLE_ENDIAN) ||
ehead.os_abi_version) {
d->free_file(d, h);
return false;
}
uint32_t phtable_size = ehead.phentry_size * ehead.phtable_count;
uint16_t phtable_pages = (phtable_size - 1) / 4096 + 1;
void *phtable = allocate_kernel_pages(phtable_pages);
fmcpy(phtable, d, h, ehead.phtable_fa, phtable_size);
void *pd = new_task_pd();
for (uint32_t phi = 0; phi < ehead.phtable_count; ++phi) {
struct ph_entry *entry = phtable + phi * ehead.phentry_size;
if (entry->type != PT_LOADME)
continue;
void *pma = pd_user_allocate(pd, entry->vma, (entry->vms - 1) / 4096 + 1, entry->flags & PH_WRITABLE);
fmcpy(pma, d, h, entry->fa, entry->fs);
}
free_pages(phtable, phtable_pages);
struct task_state tstate;
tstate.page_directory = pd;
tstate.ret_addr = ehead.entry_vma;
new_task(tstate);
return true;
}