Partially implemented ELF loading
This commit is contained in:
parent
e8e139ddf3
commit
1c0b8a53d6
2 changed files with 83 additions and 12 deletions
10
lboot.S
10
lboot.S
|
|
@ -102,8 +102,12 @@ init_com1: com1_write 1, 0x00 // clear interrupts
|
|||
com1_write 3, 0x07 // 8 bit data + 1 parity bit
|
||||
ret
|
||||
|
||||
// enable_a20: Allow use of 'high' memory
|
||||
enable_a20: // TODO more thorough implementation
|
||||
// enable_a20: Allow use of 'high' (>1Mb) memory
|
||||
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
|
||||
or $2, %al
|
||||
outb %al, $0x92
|
||||
|
|
@ -129,7 +133,7 @@ _urunreal: pop %ds
|
|||
ret
|
||||
|
||||
// get_map: Retrieve memory map using e820 BIOS function
|
||||
get_map: mov %ds, %ax
|
||||
get_map: mov %ds, %ax
|
||||
mov %ax, %es
|
||||
mov $memmap, %di
|
||||
xor %ebx, %ebx
|
||||
|
|
|
|||
85
loader.c
85
loader.c
|
|
@ -1,3 +1,5 @@
|
|||
// loader.c: boot mechanism agnostic, bootboot-compliant loader
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
|
@ -85,16 +87,20 @@ typedef struct {
|
|||
#include "bootboot.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
|
||||
|
||||
#define EI_NIDENT 16
|
||||
#define EI_MAG0 0x7F
|
||||
#define EI_MAG1 'E'
|
||||
#define EI_MAG2 'L'
|
||||
#define EI_MAG3 'F'
|
||||
|
||||
typedef struct {
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
unsigned char e_ident[16];
|
||||
uint16_t e_type;
|
||||
uint16_t e_machine;
|
||||
uint32_t e_version;
|
||||
|
|
@ -121,8 +127,69 @@ typedef struct {
|
|||
uint64_t p_align;
|
||||
} Elf64_Phdr;
|
||||
|
||||
void
|
||||
loader_main(void)
|
||||
static void
|
||||
panic(void)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue