[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-riscv] [PATCH v2 3/4] RISC-V: Honor entry point in loaded ELF firm
From: |
Stefan O'Rear |
Subject: |
[Qemu-riscv] [PATCH v2 3/4] RISC-V: Honor entry point in loaded ELF firmware |
Date: |
Sun, 16 Dec 2018 18:12:26 -0500 |
The virt board is changed to use the firmware address from the
loaded firmware or combined firmware+kernel. This is normally
equal to the DRAM base address of 0x8000_0000, however now it
is possible to boot firmware at different load addresses because
the reset code jumps to the actual firmware entry address.
Signed-off-by: Michael Clark <address@hidden>
Signed-off-by: Stefan O'Rear <address@hidden>
---
hw/riscv/boot.c | 9 ++++++---
hw/riscv/virt.c | 17 ++++++++++++++---
include/hw/riscv/boot.h | 2 +-
3 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 54e3139..e51e7f9 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -87,15 +87,18 @@ static void riscv_load_initrd(const char *filename,
uint64_t mem_size,
}
}
-void riscv_load_firmware_kernel_initrd(MachineState *machine, void *fdt)
+hwaddr riscv_load_firmware_kernel_initrd(MachineState *machine, void *fdt)
{
- if (machine->kernel_filename) {
- uint64_t firmware_entry = load_kernel(machine->kernel_filename);
+ hwaddr firmware_entry = 0;
+ if (machine->kernel_filename) {
+ firmware_entry = load_kernel(machine->kernel_filename);
if (machine->initrd_filename) {
/* load separate initrd */
riscv_load_initrd(machine->initrd_filename, machine->ram_size,
firmware_entry, fdt);
}
}
+
+ return firmware_entry;
}
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 4c2e894..38979f7 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -235,6 +235,7 @@ static void riscv_virt_board_init(MachineState *machine)
size_t plic_hart_config_len;
int i;
void *fdt;
+ hwaddr firmware_entry;
/* Initialize SOC */
object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc),
@@ -261,7 +262,17 @@ static void riscv_virt_board_init(MachineState *machine)
memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
mask_rom);
- riscv_load_firmware_kernel_initrd(machine, fdt);
+ /*
+ * combined firmware and kernel: -kernel bbl_vmlimux
+ * separate firmware and kernel: -bios bbl -kernel vmlinux
+ * firmware, kernel and ramdisk: -bios bbl -kernel vmlinux -initrd
initramfs
+ */
+ firmware_entry = riscv_load_firmware_kernel_initrd(machine, fdt);
+
+ if (firmware_entry == 0) {
+ firmware_entry = memmap[VIRT_DRAM].base;
+ }
+
/* reset vector */
uint32_t reset_vec[8] = {
0x00000297, /* 1: auipc t0, %pcrel_hi(dtb) */
@@ -274,8 +285,8 @@ static void riscv_virt_board_init(MachineState *machine)
#endif
0x00028067, /* jr t0 */
0x00000000,
- memmap[VIRT_DRAM].base, /* start: .dword memmap[VIRT_DRAM].base */
- 0x00000000,
+ firmware_entry, /* .word firmware_entry */
+ firmware_entry >> 32,
/* dtb: */
};
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index 92948f3..3af21fc 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -19,6 +19,6 @@
#ifndef HW_RISCV_BOOT_H
#define HW_RISCV_BOOT_H
-void riscv_load_firmware_kernel_initrd(MachineState *machine, void *fdt);
+hwaddr riscv_load_firmware_kernel_initrd(MachineState *machine, void *fdt);
#endif
--
2.8.0