summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarvin Borner2021-07-07 14:14:37 +0200
committerMarvin Borner2021-07-07 14:14:37 +0200
commit6355c3e08c9f4d3db122252abce5837c364d5b81 (patch)
tree8fffa4b79f6b5a2936766becb43282afbf0d675b
parent736d2b820d968915516d1662b84f9995d53895a3 (diff)
ELF execution of mb1 implementation
-rw-r--r--src/loader/cfg.c8
-rw-r--r--src/loader/elf.c57
-rw-r--r--src/loader/impl/all.c18
-rw-r--r--src/loader/impl/mb1.c12
-rw-r--r--src/loader/inc/cfg.h1
-rw-r--r--src/loader/inc/elf.h163
-rw-r--r--src/loader/inc/impl/all.h1
-rw-r--r--src/loader/inc/impl/mb1.h1
-rw-r--r--src/loader/sel.c36
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, &section_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);
}