:: commit e0fefcf21c440f3675b0278e37e904a6ca3fb6df

mintsuki <mintsuki@protonmail.com> — 2021-11-10 11:25

parents: 907ddcd388

bootboot: Remove uselessness and compliance fixes (see #124)

diff --git a/CONFIG.md b/CONFIG.md
index 883a0d43..7d890aed 100644
--- a/CONFIG.md
+++ b/CONFIG.md
@@ -100,12 +100,7 @@ Some keys take *URIs* as values; these are described in the next section.
   modules.
   * `RESOLUTION` - The resolution to be used. This setting takes the form of `<width>x<height>x<bpp>`. If the resolution is not available, Limine will pick another one automatically. Omitting `<bpp>` will default to 32.
 * Bootboot protocol:
-  * `KERNEL_PATH` - The URI path of the kernel.
-  * `INITRD_PATH` - The URI path to the ramdisk/initrd.
-  * `BOOTBOOT_ENV` - A configuration key to be passed into the kernel.
-
-  Note that one can define this last variable multiple times to specify multiple
-  environemnt keys.
+  * `INITRD_PATH` - The URI path to the ramdisk/initrd or kernel.
   * `RESOLUTION` - The resolution to be used. This setting takes the form of `<width>x<height>x<bpp>`. If the resolution is not available, Limine will pick another one automatically. Omitting `<bpp>` will default to 32.
 * stivale and stivale2 protocols:
   * `KERNEL_PATH` - The URI path of the kernel.
@@ -118,7 +113,7 @@ Some keys take *URIs* as values; these are described in the next section.
   to the 1st module string entry that appear, and so on.
 
   **Note**: If `MODULE_STRING` is not specified for an entry, the `MODULE_STRING` will default to the `MODULE_PATH`.
-  
+
   * `RESOLUTION` - The resolution to be used should the kernel request a graphical framebuffer. This setting takes the form of `<width>x<height>x<bpp>` and *overrides* any resolution requested by the kernel, or automatic resolution requests. If the resolution is not available, Limine will pick another one automatically. Omitting `<bpp>` will default to 32.
   * `KASLR` - For relocatable kernels, if set to `no`, disable kernel address space layout randomisation. KASLR is enabled by default.
   * `TEXTMODE` - If set to `yes`, prefer text mode if the kernel has no video mode requirements. (Only for stivale2)
diff --git a/stage23/protos/bootboot.c b/stage23/protos/bootboot.c
index b732ad9a..87153337 100644
--- a/stage23/protos/bootboot.c
+++ b/stage23/protos/bootboot.c
@@ -46,38 +46,27 @@ void bootboot_load(char *config) {
     uint64_t env_vaddr = BOOTBOOT_ENV;
     uint64_t init_stack_size = (uint64_t)-1;
 
-    /// Config ///
-    char *kernel_path = config_get_value(config, 0, "KERNEL_PATH");
-
     char *initrd = config_get_value(config, 0, "INITRD_PATH");
     if (initrd == NULL) {
-        initrd = kernel_path;
-        kernel_path = NULL;
-    }
-
-    if (kernel_path == NULL && initrd == NULL) {
-        panic("bootboot: no KERNEL_PATH or INITRD_PATH specified!");
+        panic("bootboot: no INITRD_PATH specified!");
     }
 
     /// Initrd loading ///
     struct initrd_file bootboot_initrd_file;
     uint64_t initrd_start = 0, initrd_size = 0;
-    if (initrd) {
-        struct file_handle *initrd_file;
-        if ((initrd_file = uri_open(initrd)) == NULL) {
-            panic("bootboot: Failed to open initrd with path `%s`. Is the path correct?", initrd);
-        }
 
-        uint8_t *initrd_data = freadall(initrd_file, MEMMAP_KERNEL_AND_MODULES);
-        initrd_size = initrd_file->size;
-        initrd_start = (uint64_t)(size_t)initrd_data;
-        fclose(initrd_file);
-        bootboot_initrd_file.size = initrd_size;
-        bootboot_initrd_file.data = initrd_data;
-    } else {
-        panic("bootboot: logic error: no initrd, even though one MUST be present");
+    struct file_handle *initrd_file;
+    if ((initrd_file = uri_open(initrd)) == NULL) {
+        panic("bootboot: Failed to open initrd with path `%s`. Is the path correct?", initrd);
     }
 
+    uint8_t *initrd_data = freadall(initrd_file, MEMMAP_KERNEL_AND_MODULES);
+    initrd_size = initrd_file->size;
+    initrd_start = (uint64_t)(size_t)initrd_data;
+    fclose(initrd_file);
+    bootboot_initrd_file.size = initrd_size;
+    bootboot_initrd_file.data = initrd_data;
+
     /// Load bootboot config ///
     uint8_t *env = ext_mem_alloc_type_aligned(4096, MEMMAP_BOOTLOADER_RECLAIMABLE, 4096);
     uint64_t envoff = 0;
@@ -113,25 +102,23 @@ void bootboot_load(char *config) {
 
     /// Kernel loading code ///
     uint8_t *kernel;
-    if (kernel_path) {
-        print("bootboot: Loading kernel `%s`...\n", kernel_path);
-        struct file_handle *kernel_file;
-        if ((kernel_file = uri_open(kernel_path)) == NULL)
-            panic("bootboot: Failed to open kernel with path `%s`. Is the path correct?", kernel_path);
 
-        kernel = freadall(kernel_file, MEMMAP_KERNEL_AND_MODULES);
-
-        fclose(kernel_file);
-    } else {
+    if (known_initrd_format(bootboot_initrd_file)) {
         const char *corefile = config_get_value((char *)env, 0, "kernel");
-        if (!corefile) {
+        if (corefile == NULL) {
             corefile = "sys/core";
         }
         struct initrd_file file = initrd_open_auto(bootboot_initrd_file, corefile);
+        if (!file.size) {
+            panic("bootboot: cannot find the kernel!");
+        }
         kernel = file.data;
+    } else {
+        struct initrd_file file = bruteforce_kernel(bootboot_initrd_file);
         if (!file.size) {
             panic("bootboot: cannot find the kernel!");
         }
+        kernel = file.data;
     }
 
     /// Memory mappings ///
@@ -208,24 +195,7 @@ void bootboot_load(char *config) {
     map_page(pmap, struct_vaddr, (uintptr_t)bootboot, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false);
 
     /// Environment ///
-    {
-        map_page(pmap, env_vaddr, (uintptr_t)env, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false);
-        uint32_t index = 0, offset = 0;
-        char *cfgent = NULL;
-        do {
-            cfgent = config_get_value(config, index++, "BOOTBOOT_ENV");
-            if (cfgent) {
-                uint32_t off = strlen(cfgent);
-                if (offset + off + 1 > 4095) {
-                    panic("Too much config options! we only have 4k of env vars!");
-                }
-                memcpy(&env[offset], cfgent, off);
-                offset += off;
-                env[offset++] = '\n';
-            }
-        } while (cfgent);
-        cfgent[offset] = 0;
-    }
+    map_page(pmap, env_vaddr, (uintptr_t)env, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false);
 
     /// Identity mapping ///
     for (uint64_t i = 0; i < 0x400000000; i += 0x200000) {
diff --git a/stage23/protos/bootboot/initrd.c b/stage23/protos/bootboot/initrd.c
index e92f1ac7..387c7de0 100644
--- a/stage23/protos/bootboot/initrd.c
+++ b/stage23/protos/bootboot/initrd.c
@@ -1,53 +1,56 @@
 #include <stdint.h>
 #include <stddef.h>
+#include <stdbool.h>
 #include <protos/bootboot/initrd.h>
 #include <lib/print.h>
 #include <lib/libc.h>
 #include <lib/blib.h>
 
+struct initrd_file bruteforce_kernel(struct initrd_file file) {
+    for (size_t i = 0; i < file.size; i++) {
+        if (memcmp(file.data + i, "\177ELF", 4) == 0) {
+            printv("bootboot: using bruteforced kernel at initrd offset %X\n", file.data + i);
+            return (struct initrd_file){
+                .size = file.size - i,
+                .data = file.data + i
+            };
+        }
+    }
+    return (struct initrd_file){0};
+}
+
+bool known_initrd_format(struct initrd_file file) {
+    if (file.size >= 5 && file.data[4] == 0xbf) {
+        return true;
+    }
+
+    if (file.size >= 5 && memcmp("07070", file.data, 5) == 0) {
+        return true;
+    }
+
+    if (file.size >= 262 && memcmp("ustar", file.data + 257, 5) == 0) {
+        return true;
+    }
+
+    return false;
+}
+
 INITRD_HANDLER(jamesm);
 INITRD_HANDLER(ustar);
 INITRD_HANDLER(cpio);
 
 INITRD_HANDLER(auto) {
     if (file.size >= 5 && file.data[4] == 0xbf) {
-        struct initrd_file jamesm_attempt = initrd_open_jamesm(file, path);
-        if (jamesm_attempt.data) {
-            printv("bootboot: jamesm matched when reading file `%s`\n", path);
-            return jamesm_attempt;
-        }
-        panic("bootboot: cannot read file `%s`: no such file or directory", path);
+        return initrd_open_jamesm(file, path);
     }
 
     if (file.size >= 5 && memcmp("07070", file.data, 5) == 0) {
-        struct initrd_file cpio_attempt = initrd_open_cpio(file, path);
-        if (cpio_attempt.data) {
-            printv("bootboot: cpio matched when reading file `%s`\n", path);
-            return cpio_attempt;
-        }
-        panic("bootboot: cannot read file `%s`: no such file or directory", path);
+        return initrd_open_cpio(file, path);
     }
 
     if (file.size >= 262 && memcmp("ustar", file.data + 257, 5) == 0) {
-        struct initrd_file ustar_attempt = initrd_open_ustar(file, path);
-        if (ustar_attempt.data) {
-            printv("bootboot: ustar matched when reading file `%s`\n", path);
-            return ustar_attempt;
-        }
-        panic("bootboot: cannot read file `%s`: no such file or directory", path);
-    }
-
-    if (strcmp("sys/core", path) == 0) {
-        for (size_t i = 0; i < file.size; i += 4) {
-            if (memcmp(file.data + i, "\177ELF", 4) == 0) {
-                printv("bootboot: using ELF as initrd to open sys/core\n");
-                return (struct initrd_file){
-                    .size = file.size - i,
-                    .data = file.data + i
-                };
-            }
-        }
+        return initrd_open_ustar(file, path);
     }
 
-    panic("bootboot: cannot read file `%s`: cannot detect initrd type (only ustar, cpio and jamesm is supported).", path);
+    return (struct initrd_file){0};
 }
diff --git a/stage23/protos/bootboot/initrd.h b/stage23/protos/bootboot/initrd.h
index 752faff4..1c3d7f1d 100644
--- a/stage23/protos/bootboot/initrd.h
+++ b/stage23/protos/bootboot/initrd.h
@@ -2,12 +2,16 @@
 #define __PROTOS__BOOTBOOT__INITRD_H__
 
 #include <stdint.h>
+#include <stdbool.h>
 
 struct initrd_file {
     uint64_t size;
     uint8_t *data;
 };
 
+struct initrd_file bruteforce_kernel(struct initrd_file file);
+bool known_initrd_format(struct initrd_file file);
+
 #define INITRD_HANDLER(name) struct initrd_file initrd_open_##name(struct initrd_file file, const char *path)
 
 INITRD_HANDLER(auto);
tab: 248 wrap: offon