aboutsummaryrefslogtreecommitdiff
path: root/machine/fdt.c
diff options
context:
space:
mode:
authorMichael Clark <michaeljclark@mac.com>2018-05-21 13:29:31 +1200
committerMichael Clark <michaeljclark@mac.com>2018-05-22 21:41:18 +1200
commit474ee5a81880dcf60789e7c2a3054b3afb34c3ca (patch)
tree343a134219be59ee0347343a5ea415707d711ab3 /machine/fdt.c
parent9ffedde3d747a9b6f559041cc69478df6d647135 (diff)
downloadriscv-pk-474ee5a81880dcf60789e7c2a3054b3afb34c3ca.zip
riscv-pk-474ee5a81880dcf60789e7c2a3054b3afb34c3ca.tar.gz
riscv-pk-474ee5a81880dcf60789e7c2a3054b3afb34c3ca.tar.bz2
RISC-V: Support separate firmware and kernel payload
Support for separate firmware and kernel payload is added by updating BBL to read optional preloaded kernel address attributes from device-tree using a similar mechanism to that used to pass init ramdisk addresses to linux kernel. chosen { riscv,kernel-start = <0x00000000 0x80200000>; riscv,kernel-end = <0x00000000 0x80590634>; }; These attributes are added by QEMU and read by BBL when combining -bios <firmware-image> and -kernel <kernel-image> options. e.g. $ qemu-system-riscv64 -machine virt -bios bbl -kernel vmlinux With this change, bbl can be compiled without --with-payload and the dummy payload alignment is altered to make the memory footprint of the firmware-only bbl smaller. The dummy payload message is updated to indicate the alternative load method. This load method could also be supported by a first stage boot loader that reads seperate firmware and kernel from SPI flash. The main advantage of this new mechanism is that it eases kernel development by avoiding the riscv-pk packaging step after kernel builds, makes building per repository artefacts for CI simpler, and mimics bootloaders on other platforms that can load a kernel image file directly. Ultimately BBL should use an SPI driver to load the kernel image however this mechanism supports use cases such such as QEMU's -bios, -kernel and -initrd options following examples from other platforms that pass kernel entry to firmware via device-tree. Cc: Palmer Dabbelt <palmer@sifive.com> Cc: Alistair Francis <Alistair.Francis@wdc.com> Signed-off-by: Michael Clark <mjc@sifive.com>
Diffstat (limited to 'machine/fdt.c')
-rw-r--r--machine/fdt.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/machine/fdt.c b/machine/fdt.c
index 061b19e..27f5462 100644
--- a/machine/fdt.c
+++ b/machine/fdt.c
@@ -548,6 +548,63 @@ void filter_compat(uintptr_t fdt, const char *compat)
fdt_scan(fdt, &cb);
}
+//////////////////////////////////////////// CHOSEN SCAN ////////////////////////////////////////
+
+struct chosen_scan {
+ const struct fdt_scan_node *chosen;
+ void* kernel_start;
+ void* kernel_end;
+};
+
+static void chosen_open(const struct fdt_scan_node *node, void *extra)
+{
+ struct chosen_scan *scan = (struct chosen_scan *)extra;
+ if (!strcmp(node->name, "chosen")) {
+ scan->chosen = node;
+ }
+}
+
+static int chosen_close(const struct fdt_scan_node *node, void *extra)
+{
+ struct chosen_scan *scan = (struct chosen_scan *)extra;
+ if (scan->chosen && scan->chosen == node) {
+ scan->chosen = NULL;
+ }
+ return 0;
+}
+
+static void chosen_prop(const struct fdt_scan_prop *prop, void *extra)
+{
+ struct chosen_scan *scan = (struct chosen_scan *)extra;
+ uint64_t val;
+ if (!scan->chosen) return;
+ if (!strcmp(prop->name, "riscv,kernel-start")) {
+ fdt_get_address(prop->node->parent, prop->value, &val);
+ scan->kernel_start = (void*)val;
+ } else if (!strcmp(prop->name, "riscv,kernel-end")) {
+ fdt_get_address(prop->node->parent, prop->value, &val);
+ scan->kernel_end = (void*)val;
+ }
+}
+
+void query_chosen(uintptr_t fdt)
+{
+ struct fdt_cb cb;
+ struct chosen_scan chosen;
+
+ memset(&cb, 0, sizeof(cb));
+ cb.open = chosen_open;
+ cb.close = chosen_close;
+ cb.prop = chosen_prop;
+
+ memset(&chosen, 0, sizeof(chosen));
+ cb.extra = &chosen;
+
+ fdt_scan(fdt, &cb);
+ kernel_start = chosen.kernel_start;
+ kernel_end = chosen.kernel_end;
+}
+
//////////////////////////////////////////// HART FILTER ////////////////////////////////////////
struct hart_filter {