Partially implemented ELF loading
This commit is contained in:
parent
e8e139ddf3
commit
1c0b8a53d6
2 changed files with 83 additions and 12 deletions
8
lboot.S
8
lboot.S
|
|
@ -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
|
||||||
|
|
|
||||||
85
loader.c
85
loader.c
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue