[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-riscv] [PATCH for-4.1 2/2] target/riscv: Add support for -bios "fi
From: |
Jonathan Behrens |
Subject: |
[Qemu-riscv] [PATCH for-4.1 2/2] target/riscv: Add support for -bios "firmware_filename" flag |
Date: |
Fri, 17 May 2019 18:23:42 -0400 |
QEMU does not have any default firmware for RISC-V. However, it isn't possible
to run a normal kernel binary without firmware. Thus it has previously been
necessary to compile the two together into a single binary to pass with the
-kernel flag. This patch allows passing separate firmware and kernel binaries by
passing both the -bios and -kernel flags.
This is based on a previously proposed patch by Michael Clark:
https://patchwork.kernel.org/patch/10419975/
Signed-off-by: Jonathan Behrens <address@hidden>
---
hw/riscv/virt.c | 66 ++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 55 insertions(+), 11 deletions(-)
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 87cc08016b..d7b1792b58 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -62,6 +62,40 @@ static const struct MemmapEntry {
[VIRT_PCIE_ECAM] = { 0x30000000, 0x10000000 },
};
+
+static target_ulong load_firmware_and_kernel(const char *firmware_filename,
+ const char *kernel_filename,
+ uint64_t mem_size,
+ uint64_t* kernel_start,
+ uint64_t* kernel_end)
+{
+ uint64_t firmware_entry, firmware_end;
+ int size;
+
+ if (load_elf(firmware_filename, NULL, NULL, NULL,
+ &firmware_entry, NULL, &firmware_end,
+ 0, EM_RISCV, 1, 0) < 0) {
+ error_report("could not load firmware '%s'", firmware_filename);
+ exit(1);
+ }
+
+ /* align kernel load address to the megapage after the firmware */
+#if defined(TARGET_RISCV32)
+ *kernel_start = (firmware_end + 0x3fffff) & ~0x3fffff;
+#else
+ *kernel_start = (firmware_end + 0x1fffff) & ~0x1fffff;
+#endif
+
+ size = load_image_targphys(kernel_filename, *kernel_start,
+ mem_size - *kernel_start);
+ if (size == -1) {
+ error_report("could not load kernel '%s'", kernel_filename);
+ exit(1);
+ }
+ *kernel_end = *kernel_start + size;
+ return firmware_entry;
+}
+
static target_ulong load_kernel(const char *kernel_filename)
{
uint64_t kernel_entry;
@@ -423,19 +457,29 @@ static void riscv_virt_board_init(MachineState *machine)
mask_rom);
uint64_t entry = memmap[VIRT_DRAM].base;
- if (machine->kernel_filename) {
+ if (machine->firmware && machine->kernel_filename) {
+ uint64_t kernel_start, kernel_end;
+ entry = load_firmware_and_kernel(machine->firmware,
+ machine->kernel_filename,
+ machine->ram_size, &kernel_start,
+ &kernel_end);
+
+ qemu_fdt_setprop_cells(fdt, "/chosen", "riscv,kernel-end",
+ kernel_end >> 32, kernel_end);
+ qemu_fdt_setprop_cells(fdt, "/chosen", "riscv,kernel-start",
+ kernel_start >> 32, kernel_start);
+ } else if (machine->kernel_filename) {
entry = load_kernel(machine->kernel_filename);
+ }
- if (machine->initrd_filename) {
- uint64_t start;
- uint64_t end = load_initrd(machine->initrd_filename,
- memmap[VIRT_DRAM].base,
machine->ram_size,
- &start);
- qemu_fdt_setprop_cell(fdt, "/chosen",
- "linux,initrd-start", start);
- qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
- end);
- }
+ if (machine->kernel_filename && machine->initrd_filename) {
+ uint64_t start;
+ uint64_t end = load_initrd(machine->initrd_filename,
+ memmap[VIRT_DRAM].base, machine->ram_size,
+ &start);
+
+ qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", start);
+ qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", end);
}
/* reset vector */
--
2.20.1