diff options
author | Marvin Borner | 2021-07-07 14:14:37 +0200 |
---|---|---|
committer | Marvin Borner | 2021-07-07 14:14:37 +0200 |
commit | 6355c3e08c9f4d3db122252abce5837c364d5b81 (patch) | |
tree | 8fffa4b79f6b5a2936766becb43282afbf0d675b | |
parent | 736d2b820d968915516d1662b84f9995d53895a3 (diff) |
ELF execution of mb1 implementation
-rw-r--r-- | src/loader/cfg.c | 8 | ||||
-rw-r--r-- | src/loader/elf.c | 57 | ||||
-rw-r--r-- | src/loader/impl/all.c | 18 | ||||
-rw-r--r-- | src/loader/impl/mb1.c | 12 | ||||
-rw-r--r-- | src/loader/inc/cfg.h | 1 | ||||
-rw-r--r-- | src/loader/inc/elf.h | 163 | ||||
-rw-r--r-- | src/loader/inc/impl/all.h | 1 | ||||
-rw-r--r-- | src/loader/inc/impl/mb1.h | 1 | ||||
-rw-r--r-- | src/loader/sel.c | 36 |
9 files changed, 293 insertions, 4 deletions
diff --git a/src/loader/cfg.c b/src/loader/cfg.c index 9f2e06a..2c6cce3 100644 --- a/src/loader/cfg.c +++ b/src/loader/cfg.c @@ -191,12 +191,18 @@ static void cfg_print(void) log("[CFG] Entry: %s at %s\n", cfg.entry[i].name, cfg.entry[i].path); } +// Execute entry implementation +void cfg_exec(struct cfg_entry *entry) +{ + impl_exec(entry->dev, &entry->path[cfg_path_disk(entry->path) + 1]); +} + void cfg_read(void) { dev_foreach(DEV_DISK, &cfg_find); if (!file[0]) panic("No config found\n"); cfg_parse(); - cfg_print(); cfg_verify(); + cfg_print(); } diff --git a/src/loader/elf.c b/src/loader/elf.c new file mode 100644 index 0000000..3f5aea3 --- /dev/null +++ b/src/loader/elf.c @@ -0,0 +1,57 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +#include <elf.h> +#include <pnc.h> + +u32 elf_load(struct dev *dev, const char *path) +{ + assert(dev->type == DEV_DISK); + + struct elf_header header = { 0 }; + s32 rd = dev->p.disk.fs.read(path, &header, 0, sizeof(header), dev); + if (rd < 0) + panic("File couldn't be found\n"); + if (rd != sizeof(header)) + panic("File too small\n"); + + // Valid? + u8 *magic = header.ident; + u8 valid_magic = magic[ELF_IDENT_MAG0] == ELF_MAG0 && magic[ELF_IDENT_MAG1] == ELF_MAG1 && + magic[ELF_IDENT_MAG2] == ELF_MAG2 && magic[ELF_IDENT_MAG3] == ELF_MAG3 && + magic[ELF_IDENT_CLASS] == ELF_IDENT_CLASS_32 && + magic[ELF_IDENT_DATA] == ELF_IDENT_DATA_LSB; + if (!valid_magic || (header.type != ELF_ETYPE_REL && header.type != ELF_ETYPE_EXEC) || + header.version != 1 || header.machine != ELF_MACHINE_386) + panic("File is not valid ELF\n"); + + // Loop through programs + for (u32 i = 0; i < header.phnum; i++) { + struct elf_program program = { 0 }; + + if (dev->p.disk.fs.read(path, &program, header.phoff + header.phentsize * i, + sizeof(program), dev) != sizeof(program)) + panic("Couldn't read program\n"); + + if (program.type == ELF_PROGRAM_TYPE_INTERP) + panic("Program interpreters aren't supported\n"); + + if (program.vaddr == 0 || program.type != ELF_PROGRAM_TYPE_LOAD) + continue; + + if ((u32)dev->p.disk.fs.read(path, (void *)program.vaddr, program.offset, + program.filesz, dev) != program.filesz) + panic("Couldn't load program\n"); + } + + // Find section string table + struct elf_section section_strings = { 0 }; + if (dev->p.disk.fs.read(path, §ion_strings, + header.shoff + header.shentsize * header.shstrndx, + sizeof(section_strings), dev) != sizeof(section_strings)) + panic("Couldn't find string section\n"); + + if (section_strings.type != ELF_SECTION_TYPE_STRTAB) + panic("Invalid string section\n"); + + return header.entry; +} diff --git a/src/loader/impl/all.c b/src/loader/impl/all.c index 1f19b1e..a5c93b1 100644 --- a/src/loader/impl/all.c +++ b/src/loader/impl/all.c @@ -2,6 +2,7 @@ #include <impl/all.h> #include <impl/mb1.h> +#include <pnc.h> u8 impl_detect(struct dev *dev, const char *path) { @@ -10,3 +11,20 @@ u8 impl_detect(struct dev *dev, const char *path) return 0; } + +void impl_exec(struct dev *dev, const char *path) +{ + assert(dev->type == DEV_DISK); + + switch (dev->p.disk.impl.type) { + case IMPL_MB1: + mb1_exec(dev, path); + break; + case IMPL_MB2: + case IMPL_NONE: + default: + panic("Invalid implementation\n"); + } + + panic("Couldn't execute implementation\n"); +} diff --git a/src/loader/impl/mb1.c b/src/loader/impl/mb1.c index cb75976..765433e 100644 --- a/src/loader/impl/mb1.c +++ b/src/loader/impl/mb1.c @@ -1,6 +1,7 @@ // MIT License, Copyright (c) 2021 Marvin Borner // Everything according to spec +#include <elf.h> #include <impl/mb1.h> #include <pnc.h> @@ -58,3 +59,14 @@ u8 mb1_detect(struct dev *dev, const char *path) return 1; } + +// Execute mb1 type kernel +void mb1_exec(struct dev *dev, const char *path) +{ + u32 entry = elf_load(dev, path); + void (*kernel)(void *); + *(void **)(&kernel) = (void *)entry; + + // TODO: Push mb1 stuff + kernel(dev); +} diff --git a/src/loader/inc/cfg.h b/src/loader/inc/cfg.h index 27b3ca3..156d561 100644 --- a/src/loader/inc/cfg.h +++ b/src/loader/inc/cfg.h @@ -28,6 +28,7 @@ struct cfg { }; void cfg_foreach(u8 (*cb)(struct cfg_entry *)); +void cfg_exec(struct cfg_entry *entry); void cfg_read(void); #endif diff --git a/src/loader/inc/elf.h b/src/loader/inc/elf.h new file mode 100644 index 0000000..4b19f2f --- /dev/null +++ b/src/loader/inc/elf.h @@ -0,0 +1,163 @@ +// MIT License, Copyright (c) 2021 Marvin Borner +// According to spec + +#ifndef ELF_H +#define ELF_H + +#include <def.h> +#include <dev.h> + +#define ELF_MAG0 0x7F +#define ELF_MAG1 'E' +#define ELF_MAG2 'L' +#define ELF_MAG3 'F' + +#define ELF_IDENT_COUNT 16 +#define ELF_IDENT_MAG0 0 +#define ELF_IDENT_MAG1 1 +#define ELF_IDENT_MAG2 2 +#define ELF_IDENT_MAG3 3 + +#define ELF_IDENT_CLASS 4 +#define ELF_IDENT_CLASS_NONE 0 +#define ELF_IDENT_CLASS_32 1 +#define ELF_IDENT_CLASS_64 2 + +#define ELF_IDENT_DATA 5 +#define ELF_IDENT_DATA_NONE 0 +#define ELF_IDENT_DATA_LSB 1 +#define ELF_IDENT_DATA_MSB 2 + +#define ELF_IDENT_VERSION 6 +#define ELF_IDENT_OSABI 7 +#define ELF_IDENT_ABIVERSION 8 +#define ELF_IDENT_PAD 9 + +#define ELF_ETYPE_NONE 0 +#define ELF_ETYPE_REL 1 +#define ELF_ETYPE_EXEC 2 +#define ELF_ETYPE_DYN 3 +#define ELF_ETYPE_CORE 4 +#define ELF_ETYPE_NUM 5 + +#define ELF_MACHINE_NONE 0 +#define ELF_MACHINE_SPARC 2 +#define ELF_MACHINE_386 3 +#define ELF_MACHINE_SPARC32PLUS 18 +#define ELF_MACHINE_SPARCV9 43 +#define ELF_MACHINE_AMD64 62 + +#define ELF_PROGRAM_TYPE_NULL 0 +#define ELF_PROGRAM_TYPE_LOAD 1 +#define ELF_PROGRAM_TYPE_DYNAMIC 2 +#define ELF_PROGRAM_TYPE_INTERP 3 +#define ELF_PROGRAM_TYPE_NOTE 4 +#define ELF_PROGRAM_TYPE_SHLIB 5 +#define ELF_PROGRAM_TYPE_PHDR 6 +#define ELF_PROGRAM_TYPE_TLS 7 + +#define ELF_PROGRAM_FLAG_X 0x1 +#define ELF_PROGRAM_FLAG_W 0x2 +#define ELF_PROGRAM_FLAG_R 0x4 + +#define ELF_SECTION_TYPE_NULL 0 +#define ELF_SECTION_TYPE_PROGBITS 1 +#define ELF_SECTION_TYPE_SYMTAB 2 +#define ELF_SECTION_TYPE_STRTAB 3 +#define ELF_SECTION_TYPE_RELA 4 +#define ELF_SECTION_TYPE_HASH 5 +#define ELF_SECTION_TYPE_DYNAMIC 6 +#define ELF_SECTION_TYPE_NOTE 7 +#define ELF_SECTION_TYPE_NOBITS 8 +#define ELF_SECTION_TYPE_REL 9 +#define ELF_SECTION_TYPE_SHLIB 10 +#define ELF_SECTION_TYPE_DYNSYM 11 +#define ELF_SECTION_TYPE_COUNT 12 + +#define ELF_SECTION_FLAG_WRITE 0x1 +#define ELF_SECTION_FLAG_ALLOC 0x2 +#define ELF_SECTION_FLAG_EXEC 0x3 +#define ELF_SECTION_FLAG_MERGE 0x10 +#define ELF_SECTION_FLAG_STRINGS 0x20 +#define ELF_SECTION_FLAG_INFO_LINK 0x40 +#define ELF_SECTION_FLAG_LINK_ORDER 0x80 +#define ELF_SECTION_FLAG_OS_SPECIAL 0x100 +#define ELF_SECTION_FLAG_GROUP 0x200 +#define ELF_SECTION_FLAG_TLS 0x400 +#define ELF_SECTION_FLAG_COMPRESSED 0x800 + +#define ELF_BSS ".bss" +#define ELF_DATA ".data" +#define ELF_DEBUG ".debug" +#define ELF_DYNAMIC ".dynamic" +#define ELF_DYNSTR ".dynstr" +#define ELF_DYNSYM ".dynsym" +#define ELF_FINI ".fini" +#define ELF_GOT ".got" +#define ELF_HASH ".hash" +#define ELF_INIT ".init" +#define ELF_REL_DATA ".rel.data" +#define ELF_REL_FINI ".rel.fini" +#define ELF_REL_INIT ".rel.init" +#define ELF_REL_DYN ".rel.dyn" +#define ELF_REL_RODATA ".rel.rodata" +#define ELF_REL_TEXT ".rel.text" +#define ELF_RODATA ".rodata" +#define ELF_SHSTRTAB ".shstrtab" +#define ELF_STRTAB ".strtab" +#define ELF_SYMTAB ".symtab" +#define ELF_TEXT ".text" + +struct elf_header { + u8 ident[ELF_IDENT_COUNT]; + u16 type; + u16 machine; + u32 version; + u32 entry; + u32 phoff; + u32 shoff; + u32 flags; + u16 ehsize; + u16 phentsize; + u16 phnum; + u16 shentsize; + u16 shnum; + u16 shstrndx; +} PACKED; + +struct elf_program { + u32 type; + u32 offset; + u32 vaddr; + u32 paddr; + u32 filesz; + u32 memsz; + u32 flags; + u32 align; +} PACKED; + +struct elf_section { + u32 name; + u32 type; + u32 flags; + u32 addr; + u32 offset; + u32 size; + u32 link; + u32 info; + u32 addralign; + u32 entsize; +} PACKED; + +struct elf_symbol { + u32 name; + u32 value; + u32 size; + u8 info; + u8 other; + u16 shndx; +} PACKED; + +u32 elf_load(struct dev *dev, const char *path); + +#endif diff --git a/src/loader/inc/impl/all.h b/src/loader/inc/impl/all.h index 1568322..f38fe42 100644 --- a/src/loader/inc/impl/all.h +++ b/src/loader/inc/impl/all.h @@ -21,5 +21,6 @@ struct impl { #include <dev.h> u8 impl_detect(struct dev *dev, const char *path); +void impl_exec(struct dev *dev, const char *path); #endif diff --git a/src/loader/inc/impl/mb1.h b/src/loader/inc/impl/mb1.h index fcaf048..d737cb2 100644 --- a/src/loader/inc/impl/mb1.h +++ b/src/loader/inc/impl/mb1.h @@ -7,5 +7,6 @@ #include <dev.h> u8 mb1_detect(struct dev *dev, const char *path); +void mb1_exec(struct dev *dev, const char *path); #endif diff --git a/src/loader/sel.c b/src/loader/sel.c index c4303a4..acdc783 100644 --- a/src/loader/sel.c +++ b/src/loader/sel.c @@ -4,17 +4,47 @@ #include <cfg.h> #include <def.h> #include <log.h> +#include <pnc.h> #include <sel.h> -static u8 sel_entry(struct cfg_entry *entry) +struct { + struct cfg_entry *cfg; +} sel_entries[16] = { 0 }; + +static u8 sel_entry_add(struct cfg_entry *entry) { - vga_log("> '%s' (%s)\n", entry->name, entry->path); + static u8 index = 0; + assert(index + 1 < (u8)sizeof(sel_entries)); + + sel_entries[index].cfg = entry; + + index++; return 0; } +// TODO: Keyboard listener +static void sel_entry_select(u8 entry) +{ + cfg_exec(sel_entries[entry].cfg); +} + +static void sel_entries_draw(void) +{ + for (u8 i = 0; i < COUNT(sel_entries); i++) { + if (!sel_entries[i].cfg) + break; + + vga_log("> '%s' (%s)\n", sel_entries[i].cfg->name, sel_entries[i].cfg->path); + } +} + void sel_draw(void) { vga_clear(); - cfg_foreach(&sel_entry); + cfg_foreach(&sel_entry_add); + sel_entries_draw(); + + // Just for testing + sel_entry_select(0); } |