:: commit 7002918c91e0bf8b7e4e8941b9ff58038e8760d6

Kacper Słomiński <kacper.slominski72@gmail.com> — 2021-06-30 18:16

parents: f84b33650e

multiboot1: add a.out kludge support

diff --git a/stage23/protos/multiboot1.c b/stage23/protos/multiboot1.c
index ff5d2886..095acc56 100644
--- a/stage23/protos/multiboot1.c
+++ b/stage23/protos/multiboot1.c
@@ -33,13 +33,14 @@ void multiboot1_load(char *config, char *cmdline) {
     uint8_t *kernel = freadall(kernel_file, MEMMAP_USABLE);
 
     struct multiboot1_header header = {0};
+    size_t header_offset = 0;
 
-    for (size_t i = 0; i < 8192; i += 4) {
+    for (header_offset = 0; header_offset < 8192; header_offset += 4) {
         uint32_t v;
-        memcpy(&v, kernel + i, 4);
+        memcpy(&v, kernel + header_offset, 4);
 
         if (v == MULTIBOOT1_HEADER_MAGIC) {
-            memcpy(&header, kernel + i, sizeof(header));
+            memcpy(&header, kernel + header_offset, sizeof(header));
             break;
         }
     }
@@ -50,28 +51,54 @@ void multiboot1_load(char *config, char *cmdline) {
     if (header.magic + header.flags + header.checksum)
         panic("multiboot1: Header checksum is invalid");
 
-    if (header.flags & (1 << 16))
-        panic("multiboot1: Aout kludge not supported");
+    uint32_t entry_point = 0;
 
-    int bits = elf_bits(kernel);
+    if (header.flags & (1 << 16)) {
+        if (header.load_addr > header.header_addr)
+            panic("multiboot1: Illegal load address");
 
-    uint32_t entry_point = 0;
+        size_t load_size = 0;
 
-    switch (bits) {
-        case 32:
-            if (elf32_load(kernel, &entry_point, MEMMAP_KERNEL_AND_MODULES))
-                panic("multiboot1: ELF32 load failure");
-            break;
-        case 64: {
-            uint64_t e;
-            if (elf64_load(kernel, &e, NULL, MEMMAP_KERNEL_AND_MODULES, false, true))
-                panic("multiboot1: ELF64 load failure");
-            entry_point = e;
+        if (header.load_end_addr)
+            load_size = header.load_end_addr - header.load_addr;
+        else
+            load_size = kernel_file->size;
 
-            break;
+        memmap_alloc_range(header.load_addr, load_size, MEMMAP_KERNEL_AND_MODULES, true, true, false, false);
+        memcpy((void *)(uintptr_t)header.load_addr, kernel + (header_offset
+                - (header.header_addr - header.load_addr)), load_size);
+
+        if (header.bss_end_addr) {
+            uintptr_t bss_addr = header.load_addr + load_size;
+            if (header.bss_end_addr < bss_addr)
+                panic("multiboot1: Illegal bss end address");
+
+            uint32_t bss_size = header.bss_end_addr - bss_addr;
+
+            memmap_alloc_range(bss_addr, bss_size, MEMMAP_KERNEL_AND_MODULES, true, true, false, false);
+            memset((void *)bss_addr, 0, bss_size);
+        }
+
+        entry_point = header.entry_addr;
+    } else {
+        int bits = elf_bits(kernel);
+
+        switch (bits) {
+            case 32:
+                if (elf32_load(kernel, &entry_point, MEMMAP_KERNEL_AND_MODULES))
+                    panic("multiboot1: ELF32 load failure");
+                break;
+            case 64: {
+                uint64_t e;
+                if (elf64_load(kernel, &e, NULL, MEMMAP_KERNEL_AND_MODULES, false, true))
+                    panic("multiboot1: ELF64 load failure");
+                entry_point = e;
+
+                break;
+            }
+            default:
+                panic("multiboot1: Invalid ELF file bitness");
         }
-        default:
-            panic("multiboot1: Invalid ELF file bitness");
     }
 
     uint32_t n_modules;
tab: 248 wrap: offon