:: commit 6578b55c9f1e09cb73f8c70865fa4c26377e9755

mintsuki <mintsuki@protonmail.com> — 2020-03-30 20:27

parents: babc5269eb

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
tab: 248 wrap: offon