diff options
author | Michael Clark <michaeljclark@mac.com> | 2018-05-21 13:29:31 +1200 |
---|---|---|
committer | Michael Clark <michaeljclark@mac.com> | 2018-05-22 21:41:18 +1200 |
commit | 474ee5a81880dcf60789e7c2a3054b3afb34c3ca (patch) | |
tree | 343a134219be59ee0347343a5ea415707d711ab3 /machine/fdt.c | |
parent | 9ffedde3d747a9b6f559041cc69478df6d647135 (diff) | |
download | riscv-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.c | 57 |
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 { |