Partially implemented ELF loading

This commit is contained in:
Thomas Oltmann 2025-07-07 16:18:46 +02:00
parent e8e139ddf3
commit 1c0b8a53d6
2 changed files with 83 additions and 12 deletions

10
lboot.S
View file

@ -102,8 +102,12 @@ init_com1: com1_write 1, 0x00 // clear interrupts
com1_write 3, 0x07 // 8 bit data + 1 parity bit com1_write 3, 0x07 // 8 bit data + 1 parity bit
ret ret
// enable_a20: Allow use of 'high' memory // enable_a20: Allow use of 'high' (>1Mb) memory
enable_a20: // TODO more thorough implementation enable_a20: // Of all the ways to toggle A20, we only try the Fast A20 Gate.
// This is known to cause problems on some ancient systems,
// but as our bootloader exclusively runs on 64-bit machines,
// we should not run into any of those systems.
// Modern machines apparently don't even have the A20 line anymore.
inb $0x92, %al inb $0x92, %al
or $2, %al or $2, %al
outb %al, $0x92 outb %al, $0x92
@ -129,7 +133,7 @@ _urunreal: pop %ds
ret ret
// get_map: Retrieve memory map using e820 BIOS function // get_map: Retrieve memory map using e820 BIOS function
get_map: mov %ds, %ax get_map: mov %ds, %ax
mov %ax, %es mov %ax, %es
mov $memmap, %di mov $memmap, %di
xor %ebx, %ebx xor %ebx, %ebx

View file

@ -1,3 +1,5 @@
// loader.c: boot mechanism agnostic, bootboot-compliant loader
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
@ -85,16 +87,20 @@ typedef struct {
#include "bootboot.h" #include "bootboot.h"
#include "fs.h" #include "fs.h"
#define KILO(x) ((intptr_t)(x) * 1024)
#define MEG(x) (KILO(x) * 1024)
#define PAGES(x) ((intptr_t)(x) * 0x1000)
#define ADDR_FRAMEBUFFER MEG(-64)
#define ADDR_MMIO MEG(-128)
#define ADDR_BOOTBOOT MEG(-2)
#define ADDR_ENVIRONMENT (MEG(-2) + PAGES(1))
#define ADDR_LOAD (MEG(-2) + PAGES(2))
// ELF64 // ELF64
#define EI_NIDENT 16
#define EI_MAG0 0x7F
#define EI_MAG1 'E'
#define EI_MAG2 'L'
#define EI_MAG3 'F'
typedef struct { typedef struct {
unsigned char e_ident[EI_NIDENT]; unsigned char e_ident[16];
uint16_t e_type; uint16_t e_type;
uint16_t e_machine; uint16_t e_machine;
uint32_t e_version; uint32_t e_version;
@ -121,8 +127,69 @@ typedef struct {
uint64_t p_align; uint64_t p_align;
} Elf64_Phdr; } Elf64_Phdr;
void static void
loader_main(void) panic(void)
{ {
for (;;) {} for (;;) {}
} }
static int
load_elf(file_t file, uintptr_t *entry)
{
if (file.size < sizeof (Elf64_Ehdr)) {
return -1;
}
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)file.ptr;
if (memcmp(ehdr->e_ident, "\177ELF\2\1\1", 7) != 0) {
return -1;
}
if (ehdr->e_type != 2) {
return -1;
}
if (ehdr->e_phentsize < sizeof (Elf64_Phdr)) {
return -1;
}
if (file.size < ehdr->e_phoff + ehdr->e_phentsize * ehdr->e_phnum) {
return -1;
}
for (uint16_t p = 0; p < ehdr->e_phnum; p++) {
Elf64_Phdr *phdr = (Elf64_Phdr *)(file.ptr + ehdr->e_phoff + ehdr->e_phentsize * p);
if (phdr->p_type == 1) { // PT_LOAD
if (file.size < phdr->p_offset + phdr->p_filesz) {
return -1;
}
memcpy((void *)ADDR_LOAD, file.ptr + phdr->p_offset, phdr->p_filesz);
if (phdr->p_filesz < phdr->p_memsz) {
memset((void *)(ADDR_LOAD + phdr->p_filesz), 0, phdr->p_memsz - phdr->p_filesz);
}
}
}
*entry = ehdr->e_entry;
return 0;
}
void
loader_main(void)
{
uint64_t entry = 0;
file_t elf = { 0, 0 };
if (load_elf(elf, &entry) < 0) {
panic();
}
uint64_t stack = 0;
__asm__ __volatile__ (
"mov\t%1, %rbp\n\t"
"mov\t%rbp, %rsp\n\t"
"call\t*%0"
: : "r"(entry), "r"(stack) : "memory");
panic();
}