:: commit 84e540ee4846a1077716a4a3a6495b0e9163ac01

mintsuki <mintsuki@protonmail.com> — 2021-07-05 08:20

parents: d62c4f67d5

stivale2: Implement kernel loading by anchor for non-ELF kernels

diff --git a/stage23/protos/stivale2.c b/stage23/protos/stivale2.c
index 84ae4744..51cb3ddf 100644
--- a/stage23/protos/stivale2.c
+++ b/stage23/protos/stivale2.c
@@ -70,24 +70,36 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table
     if (!uri_open(kernel_file, kernel_path))
         panic("stivale2: Failed to open kernel with path `%s`. Is the path correct?", kernel_path);
 
+    char *kaslr_s = config_get_value(config, 0, "KASLR");
+    bool kaslr = true;
+    if (kaslr_s != NULL && strcmp(kaslr_s, "no") == 0)
+        kaslr = false;
+
     struct stivale2_header stivale2_hdr;
 
-    uint8_t *kernel = freadall(kernel_file, STIVALE2_MMAP_BOOTLOADER_RECLAIMABLE);
+    bool level5pg = false;
+    uint64_t slide = 0;
+    uint64_t entry_point = 0;
 
+    uint8_t *kernel = freadall(kernel_file, STIVALE2_MMAP_BOOTLOADER_RECLAIMABLE);
     int bits = elf_bits(kernel);
+    bool loaded_by_anchor = false;
 
-    int ret;
+    if (bits == -1) {
+        struct stivale_anchor *anchor;
+        if (!stivale_load_by_anchor(&anchor, "STIVALE2  ANCHOR", kernel, kernel_file->size)) {
+            panic("stivale2: Not a valid ELF or anchored file.");
+        }
 
-    bool level5pg = false;
+        bits = anchor->bits;
 
-    char *kaslr_s = config_get_value(config, 0, "KASLR");
-    bool kaslr = true;
-    if (kaslr_s != NULL && strcmp(kaslr_s, "no") == 0)
-        kaslr = false;
+        memcpy(&stivale2_hdr, (void *)(uintptr_t)anchor->phys_stivalehdr,
+               sizeof(struct stivale2_header));
 
-    uint64_t slide = 0;
-    uint64_t entry_point = 0;
+        loaded_by_anchor = true;
+    }
 
+    int ret = 0;
     switch (bits) {
         case 64: {
             // Check if 64 bit CPU
@@ -101,26 +113,33 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table
                 level5pg = true;
             }
 
-            if (elf64_load(kernel, &entry_point, NULL, &slide, STIVALE2_MMAP_KERNEL_AND_MODULES, kaslr, false))
-                panic("stivale2: ELF64 load failure");
+            if (!loaded_by_anchor) {
+                if (elf64_load(kernel, &entry_point, NULL, &slide,
+                               STIVALE2_MMAP_KERNEL_AND_MODULES, kaslr, false))
+                    panic("stivale2: ELF64 load failure");
 
-            ret = elf64_load_section(kernel, &stivale2_hdr, ".stivale2hdr", sizeof(struct stivale2_header), slide);
+                ret = elf64_load_section(kernel, &stivale2_hdr, ".stivale2hdr",
+                                         sizeof(struct stivale2_header), slide);
+            }
 
             break;
         }
         case 32: {
-            if (elf32_load(kernel, (uint32_t *)&entry_point, NULL, 10))
-                panic("stivale2: ELF32 load failure");
+            if (!loaded_by_anchor) {
+                if (elf32_load(kernel, (uint32_t *)&entry_point, NULL, 10))
+                    panic("stivale2: ELF32 load failure");
 
-            ret = elf32_load_section(kernel, &stivale2_hdr, ".stivale2hdr", sizeof(struct stivale2_header));
+                ret = elf32_load_section(kernel, &stivale2_hdr, ".stivale2hdr",
+                                         sizeof(struct stivale2_header));
+            }
 
             break;
         }
         default:
-            panic("stivale2: Not 32 nor 64 bit x86 ELF file.");
+            panic("stivale2: Not 32 nor 64-bit kernel. What is this?");
     }
 
-    printv("stivale2: %u-bit ELF file detected\n", bits);
+    printv("stivale2: %u-bit kernel detected\n", bits);
 
     switch (ret) {
         case 1:
tab: 248 wrap: offon