Add module support to stivale
diff --git a/src/lib/config.c b/src/lib/config.c
index 03afc117..c48e0247 100644
--- a/src/lib/config.c
+++ b/src/lib/config.c
@@ -17,7 +17,7 @@ int init_config(int drive, int part) {
return -1;
}
- if (f.dir_entry.size >= 4096) {
+ if (f.dir_entry.size >= MAX_CONFIG_SIZE) {
print("Config file is too big!\n");
for (;;);
}
@@ -30,7 +30,7 @@ int init_config(int drive, int part) {
return 0;
}
-char *config_get_value(char *buf, size_t limit, const char *key) {
+char *config_get_value(char *buf, size_t index, size_t limit, const char *key) {
if (!limit || !buf || !key)
return NULL;
@@ -40,6 +40,8 @@ char *config_get_value(char *buf, size_t limit, const char *key) {
if (!strncmp(&config_addr[i], key, key_len) && config_addr[i + key_len] == '=') {
if (i && config_addr[i - 1] != SEPARATOR)
continue;
+ if (index--)
+ continue;
i += key_len + 1;
size_t j;
for (j = 0; config_addr[i + j] != SEPARATOR && config_addr[i + j]; j++) {
diff --git a/src/lib/config.h b/src/lib/config.h
index a6b68579..a403fade 100644
--- a/src/lib/config.h
+++ b/src/lib/config.h
@@ -4,6 +4,6 @@
#include <stddef.h>
int init_config(int drive, int part);
-char *config_get_value(char *buf, size_t limit, const char *key);
+char *config_get_value(char *buf, size_t index, size_t limit, const char *key);
#endif
diff --git a/src/lib/elf.c b/src/lib/elf.c
index 939c71c3..063c0ddf 100644
--- a/src/lib/elf.c
+++ b/src/lib/elf.c
@@ -103,13 +103,13 @@ int elf_load_section(struct echfs_file_handle *fd, void *buffer, const char *nam
#define FIXED_HIGHER_HALF_OFFSET ((uint64_t)0xffffffff80000000)
-int elf_load(struct echfs_file_handle *fd, uint64_t *entry_point) {
+int elf_load(struct echfs_file_handle *fd, uint64_t *entry_point, uint64_t *top) {
struct elf_hdr hdr;
echfs_read(fd, &hdr, 0, sizeof(struct elf_hdr));
if (strncmp((char *)hdr.ident, "\177ELF", 4)) {
print("Not a valid ELF file.\n");
- return 1;
+ return -1;
}
if (hdr.ident[EI_DATA] != BITS_LE) {
@@ -122,6 +122,8 @@ int elf_load(struct echfs_file_handle *fd, uint64_t *entry_point) {
return -1;
}
+ *top = 0;
+
for (uint16_t i = 0; i < hdr.ph_num; i++) {
struct elf_phdr phdr;
echfs_read(fd, &phdr, hdr.phoff + i * sizeof(struct elf_phdr),
@@ -133,6 +135,10 @@ int elf_load(struct echfs_file_handle *fd, uint64_t *entry_point) {
if (phdr.p_vaddr & (1ull << 63))
phdr.p_vaddr -= FIXED_HIGHER_HALF_OFFSET;
+ uint64_t this_top = phdr.p_vaddr + phdr.p_memsz;
+ if (this_top > *top)
+ *top = this_top;
+
echfs_read(fd, (void *)(uint32_t)phdr.p_vaddr,
phdr.p_offset, phdr.p_filesz);
diff --git a/src/lib/elf.h b/src/lib/elf.h
index 447db2ed..f8433b0c 100644
--- a/src/lib/elf.h
+++ b/src/lib/elf.h
@@ -4,7 +4,7 @@
#include <stdint.h>
#include <fs/echfs.h>
-int elf_load(struct echfs_file_handle *fd, uint64_t *entry_point);
+int elf_load(struct echfs_file_handle *fd, uint64_t *entry_point, uint64_t *top);
int elf_load_section(struct echfs_file_handle *fd, void *buffer, const char *name, size_t limit);
#endif
diff --git a/src/main.c b/src/main.c
index 825f815d..f1f1ef5a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -60,22 +60,22 @@ void main(int boot_drive) {
if (config_loaded) {
char buf[32];
- if (!config_get_value(buf, 32, "KERNEL_DRIVE")) {
+ if (!config_get_value(buf, 0, 32, "KERNEL_DRIVE")) {
print("KERNEL_DRIVE not specified, using boot drive (%x)", boot_drive);
drive = boot_drive;
} else {
drive = (int)strtoui(buf);
}
- if (!config_get_value(buf, 64, "TIMEOUT")) {
+ if (!config_get_value(buf, 0, 64, "TIMEOUT")) {
timeout = 5;
} else {
timeout = (int)strtoui(buf);
}
- config_get_value(buf, 32, "KERNEL_PARTITION");
+ config_get_value(buf, 0, 32, "KERNEL_PARTITION");
part = (int)strtoui(buf);
- config_get_value(path, 128, "KERNEL_PATH");
- config_get_value(cmdline, 128, "KERNEL_CMDLINE");
- config_get_value(proto, 64, "KERNEL_PROTO");
+ config_get_value(path, 0, 128, "KERNEL_PATH");
+ config_get_value(cmdline, 0, 128, "KERNEL_CMDLINE");
+ config_get_value(proto, 0, 64, "KERNEL_PROTO");
} else {
print(" !! NO CONFIG FILE FOUND ON BOOT DRIVE !!");
for (;;);
diff --git a/src/protos/stivale.c b/src/protos/stivale.c
index 3c8dd7e1..7cd91c65 100644
--- a/src/protos/stivale.c
+++ b/src/protos/stivale.c
@@ -5,7 +5,9 @@
#include <lib/blib.h>
#include <lib/acpi.h>
#include <lib/e820.h>
+#include <lib/config.h>
#include <drivers/vbe.h>
+#include <fs/echfs.h>
struct stivale_header {
uint64_t stack;
@@ -19,6 +21,7 @@ struct stivale_module {
uint64_t begin;
uint64_t end;
char string[128];
+ uint64_t next;
} __attribute__((packed));
struct stivale_struct {
@@ -32,7 +35,7 @@ struct stivale_struct {
uint16_t framebuffer_bpp;
uint64_t rsdp;
uint64_t module_count;
- struct stivale_module modules[];
+ uint64_t modules;
} __attribute__((packed));
struct stivale_struct stivale_struct = {0};
@@ -59,11 +62,58 @@ void stivale_load(struct echfs_file_handle *fd) {
print("stivale: Requested stack at %X\n", stivale_hdr.stack);
print("stivale: Video mode: %u\n", stivale_hdr.video_mode);
- elf_load(fd, &entry_point);
+ uint64_t top_used_addr;
+ elf_load(fd, &entry_point, &top_used_addr);
+
+ print("stivale: Top used address in ELF: %X\n", top_used_addr);
stivale_struct.memory_map_entries = (uint64_t)init_e820();
stivale_struct.memory_map_addr = (uint64_t)(size_t)e820_map;
+ stivale_struct.module_count = 0;
+ uint64_t *prev_mod_ptr = &stivale_struct.modules;
+ for (int i = 0; ; i++) {
+ char module_file[64];
+ if (!config_get_value(module_file, i, 64, "MODULE_PATH"))
+ break;
+
+ stivale_struct.module_count++;
+
+ struct stivale_module *m = balloc(sizeof(struct stivale_module));
+
+ config_get_value(m->string, i, 128, "MODULE_STRING");
+
+ int part; {
+ char buf[32];
+ config_get_value(buf, i, 32, "MODULE_PARTITION");
+ part = (int)strtoui(buf);
+ }
+
+ struct echfs_file_handle f;
+ echfs_open(&f, fd->disk, part, module_file);
+
+ void *module_addr = (void *)(((uint32_t)top_used_addr & 0xfff) ?
+ ((uint32_t)top_used_addr & ~((uint32_t)0xfff)) + 0x1000 :
+ (uint32_t)top_used_addr);
+
+ echfs_read(&f, module_addr, 0, f.dir_entry.size);
+
+ m->begin = (uint64_t)(size_t)module_addr;
+ m->end = m->begin + f.dir_entry.size;
+ m->next = 0;
+
+ top_used_addr = (uint64_t)(size_t)m->end;
+
+ *prev_mod_ptr = (uint64_t)(size_t)m;
+ prev_mod_ptr = &m->next;
+
+ print("stivale: Requested module %u:\n", i);
+ print(" Path: %s\n", module_file);
+ print(" String: %s\n", m->string);
+ print(" Begin: %X\n", m->begin);
+ print(" End: %X\n", m->end);
+ }
+
stivale_struct.rsdp = (uint64_t)(size_t)get_rsdp();
print("stivale: RSDP at %X\n", stivale_struct.rsdp);
diff --git a/test/qloader2.cfg b/test/qloader2.cfg
index c8083102..5d2854fc 100644
--- a/test/qloader2.cfg
+++ b/test/qloader2.cfg
@@ -1,5 +1,14 @@
+TIMEOUT=0
+
KERNEL_PARTITION=0
KERNEL_PATH=test.elf
KERNEL_PROTO=stivale
KERNEL_CMDLINE=none
-TIMEOUT=0
+
+MODULE_PARTITION=0
+MODULE_PATH=qloader2.cfg
+MODULE_STRING=something here
+
+MODULE_PARTITION=0
+MODULE_PATH=qloader2.cfg
+MODULE_STRING=second module
diff --git a/test/test.asm b/test/test.asm
index 5b65394e..bce612b6 100644
--- a/test/test.asm
+++ b/test/test.asm
@@ -5,10 +5,10 @@ section .stivalehdr
stivale_header:
dq stack.top ; rsp
- dw 1 ; video mode
- dw 800 ; fb_width
- dw 600 ; fb_height
- dw 16 ; fb_bpp
+ dw 0 ; video mode
+ dw 0 ; fb_width
+ dw 0 ; fb_height
+ dw 0 ; fb_bpp
section .bss
@@ -25,7 +25,7 @@ _start:
mov rax, 'h e l l '
mov rbx, 'o w o '
mov rcx, 'r l d '
- mov rdx, [rdi+24]
+ mov rdx, 0xb8000
mov [rdx], rax
mov [rdx+8], rbx
mov [rdx+16], rcx
