qemu-riscv
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]