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,
