:: commit 945c43de0d6b79aab3607f97570d9e9adf4b10a9

Kacper Słomiński <kacper.slominski72@gmail.com> — 2024-12-24 16:07

parents: e721cecc25

lib: Move DTB_PATH handling logic into common code

diff --git a/common/entry.s3.c b/common/entry.s3.c
index 9788c3df..c080599b 100644
--- a/common/entry.s3.c
+++ b/common/entry.s3.c
@@ -177,7 +177,6 @@ noreturn void stage3_common(void) {
 #else
 #error riscv: only UEFI is supported
 #endif
-    init_riscv();
 #endif
 
     term_notready();
diff --git a/common/lib/misc.c b/common/lib/misc.c
index 366d1f84..a692e85d 100644
--- a/common/lib/misc.c
+++ b/common/lib/misc.c
@@ -6,6 +6,8 @@
 #include <lib/print.h>
 #include <lib/trace.h>
 #include <lib/real.h>
+#include <lib/config.h>
+#include <lib/uri.h>
 #include <fs/file.h>
 #include <mm/pmm.h>
 #include <libfdt/libfdt.h>
@@ -111,34 +113,62 @@ uint32_t hex2bin(uint8_t *str, uint32_t size) {
 
 #if defined (UEFI)
 
-void *get_device_tree_blob(size_t extra_size) {
+void *get_device_tree_blob(const char *config, size_t extra_size) {
     int ret;
 
-    EFI_GUID dtb_guid = EFI_DTB_TABLE_GUID;
-    for (size_t i = 0; i < gST->NumberOfTableEntries; i++) {
-        EFI_CONFIGURATION_TABLE *cur_table = &gST->ConfigurationTable[i];
-        if (memcmp(&cur_table->VendorGuid, &dtb_guid, sizeof(EFI_GUID)))
-            continue;
+    size_t size = 0;
+    void *dtb = NULL;
 
-        size_t s = fdt_totalsize(cur_table->VendorTable);
+    {
+        char *dtb_path = config_get_value(config, 0, "DTB_PATH");
+        if (dtb_path) {
+            struct file_handle *dtb_file;
+            if ((dtb_file = uri_open(dtb_path)) == NULL)
+                panic(true, "dtb: Failed to open device tree blob with path `%#`. Is the path correct?", dtb_path);
 
-        printv("efi: found dtb at %p, size %x\n", cur_table->VendorTable, s);
+            dtb = freadall(dtb_file, MEMMAP_BOOTLOADER_RECLAIMABLE);
+            size = dtb_file->size;
+            fclose(dtb_file);
+            printv("dtb: loaded dtb at %p from file `%#`\n", dtb, dtb_path);
+        }
+    }
+
+    if (!dtb) {
+        EFI_GUID dtb_guid = EFI_DTB_TABLE_GUID;
+        for (size_t i = 0; i < gST->NumberOfTableEntries; i++) {
+            EFI_CONFIGURATION_TABLE *cur_table = &gST->ConfigurationTable[i];
+            if (memcmp(&cur_table->VendorGuid, &dtb_guid, sizeof(EFI_GUID)))
+                continue;
+            dtb = cur_table->VendorTable;
+            printv("dtb: found dtb at %p via EFI\n", cur_table->VendorTable);
+            break;
+        }
+    }
+
+    if (extra_size == 0) {
+        return dtb;
+    }
+
+    if (dtb) {
+        size_t s = fdt_totalsize(dtb);
+
+        printv("efi: dtb has size %x\n", s);
 
         void *new_tab = ext_mem_alloc(s + extra_size);
 
-        ret = fdt_open_into(cur_table->VendorTable, new_tab, s + extra_size);
+        ret = fdt_open_into(dtb, new_tab, s + extra_size);
         if (ret < 0) {
             panic(true, "dtb: failed to resize new DTB");
         }
 
-        return new_tab;
-    }
+        if (size) {
+            pmm_free(dtb, size);
+        }
 
-    if (extra_size == 0) {
-        return NULL;
+        return new_tab;
     }
 
-    void *dtb = ext_mem_alloc(extra_size);
+    dtb = ext_mem_alloc(extra_size);
 
     ret = fdt_create_empty_tree(dtb, extra_size);
     if (ret < 0) {
diff --git a/common/lib/misc.h b/common/lib/misc.h
index 38810e32..8e27023c 100644
--- a/common/lib/misc.h
+++ b/common/lib/misc.h
@@ -27,7 +27,7 @@ extern UINT32 efi_desc_ver;
 extern bool efi_boot_services_exited;
 bool efi_exit_boot_services(void);
 
-void *get_device_tree_blob(size_t extra_size);
+void *get_device_tree_blob(const char *config, size_t extra_size);
 #endif
 
 extern struct volume *boot_volume;
diff --git a/common/protos/limine.c b/common/protos/limine.c
index 68c7b1d6..67d9476e 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -405,6 +405,10 @@ static void *_get_request(uint64_t id[4]) {
 #define FEAT_END } while (0);
 
 noreturn void limine_load(char *config, char *cmdline) {
+#if defined (__riscv)
+    init_riscv(config);
+#endif
+
 #if defined (__x86_64__) || defined (__i386__)
     uint32_t eax, ebx, ecx, edx;
 #endif
@@ -1015,7 +1019,7 @@ FEAT_START
         fclose(dtb_file);
     } else {
 #if defined (UEFI)
-        dtb = get_device_tree_blob(0);
+        dtb = get_device_tree_blob(config, 0);
 #else
         break;
 #endif
@@ -1415,7 +1419,7 @@ FEAT_START
 #elif defined (__aarch64__)
     uint64_t bsp_mpidr;
 
-    mp_info = init_smp(&cpu_count, &bsp_mpidr,
+    mp_info = init_smp(config, &cpu_count, &bsp_mpidr,
                         pagemap, LIMINE_MAIR(fb_attr), LIMINE_TCR(tsz, pa), LIMINE_SCTLR,
                         direct_map_offset);
 #elif defined (__riscv)
diff --git a/common/protos/linux_risc.c b/common/protos/linux_risc.c
index e510dba0..9f9f91f9 100644
--- a/common/protos/linux_risc.c
+++ b/common/protos/linux_risc.c
@@ -405,34 +405,7 @@ noreturn void linux_load(char *config, char *cmdline) {
     struct boot_param p;
     memset(&p, 0, sizeof(p));
     p.cmdline = cmdline;
-
-    char *dtb_path = config_get_value(config, 0, "DTB_PATH");
-    if (dtb_path) {
-        struct file_handle *dtb_file;
-        if ((dtb_file = uri_open(dtb_path)) == NULL)
-            panic(true, "linux: Failed to open device tree blob with path `%#`. Is the path correct?", dtb_path);
-
-
-        void *dtb = freadall(dtb_file, MEMMAP_BOOTLOADER_RECLAIMABLE);
-        fclose(dtb_file);
-
-        // TODO(qookie): This is a copy of the logic in get_device_tree_blob
-        size_t s = fdt_totalsize(dtb);
-
-        printv("linux: loaded dtb at %p, size %x\n", dtb, s);
-
-        void *new_dtb = ext_mem_alloc(s + 0x1000);
-
-        int ret = fdt_open_into(dtb, new_dtb, s + 0x1000);
-        if (ret < 0) {
-            panic(true, "linux: failed to resize new DTB");
-        }
-
-        p.dtb = new_dtb;
-    } else {
-        // Hopefully 4K should be enough (mainly depends on the length of cmdline)
-        p.dtb = get_device_tree_blob(0x1000);
-    }
+    p.dtb = get_device_tree_blob(config, 0x1000);
 
     struct file_handle *kernel_file;
 
diff --git a/common/sys/cpu.h b/common/sys/cpu.h
index 2c12bdc7..434c436c 100644
--- a/common/sys/cpu.h
+++ b/common/sys/cpu.h
@@ -336,7 +336,7 @@ static inline bool riscv_check_isa_extension(const char *ext, size_t *maj, size_
     return riscv_check_isa_extension_for(bsp_hartid, ext, maj, min);
 }
 
-void init_riscv(void);
+void init_riscv(const char *config);
 
 #elif defined (__loongarch64)
 
diff --git a/common/sys/cpu_riscv.c b/common/sys/cpu_riscv.c
index 052d1a78..4160a2da 100644
--- a/common/sys/cpu_riscv.c
+++ b/common/sys/cpu_riscv.c
@@ -224,8 +224,8 @@ static void init_riscv_fdt(const void *fdt) {
     }
 }
 
-void init_riscv(void) {
-    void *fdt = get_device_tree_blob(0);
+void init_riscv(const char *config) {
+    void *fdt = get_device_tree_blob(config, 0);
     if (fdt != NULL) {
         init_riscv_fdt(fdt);
     } else if (acpi_get_rsdp()) {
diff --git a/common/sys/smp.c b/common/sys/smp.c
index 150a818b..b5b5562d 100644
--- a/common/sys/smp.c
+++ b/common/sys/smp.c
@@ -514,14 +514,15 @@ static struct limine_mp_info *try_acpi_smp(size_t   *cpu_count,
     return ret;
 }
 
-static struct limine_mp_info *try_dtb_smp(size_t   *cpu_count,
+static struct limine_mp_info *try_dtb_smp(const char *config,
+                                           size_t   *cpu_count,
                                            uint64_t *_bsp_mpidr,
                                            pagemap_t pagemap,
                                            uint64_t  mair,
                                            uint64_t  tcr,
                                            uint64_t  sctlr,
                                            uint64_t  hhdm_offset) {
-    void *dtb = get_device_tree_blob(0);
+    void *dtb = get_device_tree_blob(config, 0);
 
     uint64_t bsp_mpidr;
     asm volatile ("mrs %0, mpidr_el1" : "=r"(bsp_mpidr));
@@ -695,7 +696,8 @@ static struct limine_mp_info *try_dtb_smp(size_t   *cpu_count,
 }
 
 
-struct limine_mp_info *init_smp(size_t   *cpu_count,
+struct limine_mp_info *init_smp(const char *config,
+                                 size_t   *cpu_count,
                                  uint64_t *bsp_mpidr,
                                  pagemap_t pagemap,
                                  uint64_t  mair,
@@ -710,9 +712,10 @@ struct limine_mp_info *init_smp(size_t   *cpu_count,
         return info;
 
     // No RSDP means no ACPI, try device trees in that case.
-    if (get_device_tree_blob(0) && (info = try_dtb_smp(
-                                        cpu_count, bsp_mpidr, pagemap,
-                                        mair, tcr, sctlr, hhdm_offset)))
+    if (get_device_tree_blob(config, 0)
+                    && (info = try_dtb_smp(
+                                config, cpu_count, bsp_mpidr, pagemap,
+                                mair, tcr, sctlr, hhdm_offset)))
         return info;
 
     printv("Failed to figure out how to start APs.");
diff --git a/common/sys/smp.h b/common/sys/smp.h
index fa05bb8c..de45f08c 100644
--- a/common/sys/smp.h
+++ b/common/sys/smp.h
@@ -21,7 +21,8 @@ struct limine_mp_info *init_smp(size_t   *cpu_count,
 
 #elif defined (__aarch64__)
 
-struct limine_mp_info *init_smp(size_t   *cpu_count,
+struct limine_mp_info *init_smp(const char *config,
+                                 size_t   *cpu_count,
                                  uint64_t *bsp_mpidr,
                                  pagemap_t pagemap,
                                  uint64_t  mair,
tab: 248 wrap: offon