* [PATCH V5 0/3] hw/riscv: virt: Enable booting S-mode firmware from pflash
@ 2022-10-04 9:23 Sunil V L
2022-10-04 9:23 ` [PATCH V5 1/3] hw/arm, loongarch: Move load_image_to_fw_cfg() to common location Sunil V L
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Sunil V L @ 2022-10-04 9:23 UTC (permalink / raw)
To: Peter Maydell, Xiaojuan Yang, Song Gao,
Philippe Mathieu-Daudé, Gerd Hoffmann, Palmer Dabbelt,
Alistair Francis, Bin Meng
Cc: qemu-arm, qemu-devel, qemu-riscv, Sunil V L
This series adds the support to boot S-mode FW like EDK2 from the flash. The
S-mode firmware should be kept in pflash unit 1.
When -kernel (and -initrd) option is also provided along with the flash,
the kernel (and initrd) will be loaded into fw_cfg table and opensbi will
branch to the flash address which will be the entry point of the S-mode
firmware. The S-mode FW then loads and launches the kernel.
When only -pflash option is provided in the command line, the kernel
will be located and loaded in the usual way by the S-mode firmware.
These patches are available in below branch.
https://github.com/vlsunil/qemu/tree/pflash_v2
The first two patches in this series are refactor patches.
These changes are tested with a WIP EDK2 port for virt machine. Below
are the instructions to build and test this feature.
1) Get EDK2 sources from below branches.
https://github.com/vlsunil/edk2/tree/virt_refactor_smode_v1
https://github.com/vlsunil/edk2-platforms/tree/virt_refactor_smode_v1
2) Build EDK2 for RISC-V
export WORKSPACE=`pwd`
export GCC5_RISCV64_PREFIX=riscv64-linux-gnu-
export PACKAGES_PATH=$WORKSPACE/edk2:$WORKSPACE/edk2-platforms
export EDK_TOOLS_PATH=$WORKSPACE/edk2/BaseTools
source edk2/edksetup.sh
make -C edk2/BaseTools clean
make -C edk2/BaseTools
make -C edk2/BaseTools/Source/C
source edk2/edksetup.sh BaseTools
build -a RISCV64 -p Platform/Qemu/RiscVVirt/RiscVVirt.dsc -t GCC5
3)Make the EDK2 image size to match with what qemu flash expects
truncate -s 32M Build/RiscVVirt/DEBUG_GCC5/FV/RISCV_VIRT.fd
4) Run
a) Boot to EFI shell (no -kernel / -initrd option)
qemu-system-riscv64 -nographic -drive file=Build/RiscVVirt/DEBUG_GCC5/FV/RISCV_VIRT.fd,if=pflash,format=raw,unit=1 -machine virt -M 2G
b) With -kernel, -initrd and -pflash
qemu-system-riscv64 -nographic -drive file=Build/RiscVVirt/DEBUG_GCC5/FV/RISCV_VIRT.fd,if=pflash,format=raw,unit=1 -machine virt -M 2G -kernel arch/riscv/boot/Image.gz -initrd rootfs.cpio
Changes since V4:
1) Rebased on riscv-to-apply.next branch
2) Added RB tags
3) Gerd's feedback on removing the truncate requirement will be addressed as separate
patch in future.
Changes since V3:
1) White space and comment edits
2) Added RB tag
Changes since V2:
1) Moved the doc comment to .h file
Changes since V1:
1) Modified code to support the use case when both -kernel and -pflash are configured.
2) Refactor patches added to help (1) above.
3) Cover letter added with test instructions.
Sunil V L (3):
hw/arm,loongarch: Move load_image_to_fw_cfg() to common location
hw/riscv: virt: Move create_fw_cfg() prior to loading kernel
hw/riscv: virt: Enable booting S-mode firmware from pflash
hw/arm/boot.c | 49 ---------------------------------------
hw/loongarch/virt.c | 33 --------------------------
hw/nvram/fw_cfg.c | 32 +++++++++++++++++++++++++
hw/riscv/boot.c | 29 +++++++++++++++++++++++
hw/riscv/virt.c | 32 ++++++++++++++++++-------
include/hw/nvram/fw_cfg.h | 21 +++++++++++++++++
include/hw/riscv/boot.h | 1 +
7 files changed, 107 insertions(+), 90 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH V5 1/3] hw/arm, loongarch: Move load_image_to_fw_cfg() to common location
2022-10-04 9:23 [PATCH V5 0/3] hw/riscv: virt: Enable booting S-mode firmware from pflash Sunil V L
@ 2022-10-04 9:23 ` Sunil V L
2022-10-04 9:23 ` [PATCH V5 2/3] hw/riscv: virt: Move create_fw_cfg() prior to loading kernel Sunil V L
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Sunil V L @ 2022-10-04 9:23 UTC (permalink / raw)
To: Peter Maydell, Xiaojuan Yang, Song Gao,
Philippe Mathieu-Daudé, Gerd Hoffmann, Palmer Dabbelt,
Alistair Francis, Bin Meng
Cc: qemu-arm, qemu-devel, qemu-riscv, Sunil V L, Andrew Jones
load_image_to_fw_cfg() is duplicated by both arm and loongarch. The same
function will be required by riscv too. So, it's time to refactor and
move this function to a common path.
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Song Gao <gaosong@loongson.cn>
---
hw/arm/boot.c | 49 ---------------------------------------
hw/loongarch/virt.c | 33 --------------------------
hw/nvram/fw_cfg.c | 32 +++++++++++++++++++++++++
include/hw/nvram/fw_cfg.h | 21 +++++++++++++++++
4 files changed, 53 insertions(+), 82 deletions(-)
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index ada2717f76..704f368d9c 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -818,55 +818,6 @@ static void do_cpu_reset(void *opaque)
}
}
-/**
- * load_image_to_fw_cfg() - Load an image file into an fw_cfg entry identified
- * by key.
- * @fw_cfg: The firmware config instance to store the data in.
- * @size_key: The firmware config key to store the size of the loaded
- * data under, with fw_cfg_add_i32().
- * @data_key: The firmware config key to store the loaded data under,
- * with fw_cfg_add_bytes().
- * @image_name: The name of the image file to load. If it is NULL, the
- * function returns without doing anything.
- * @try_decompress: Whether the image should be decompressed (gunzipped) before
- * adding it to fw_cfg. If decompression fails, the image is
- * loaded as-is.
- *
- * In case of failure, the function prints an error message to stderr and the
- * process exits with status 1.
- */
-static void load_image_to_fw_cfg(FWCfgState *fw_cfg, uint16_t size_key,
- uint16_t data_key, const char *image_name,
- bool try_decompress)
-{
- size_t size = -1;
- uint8_t *data;
-
- if (image_name == NULL) {
- return;
- }
-
- if (try_decompress) {
- size = load_image_gzipped_buffer(image_name,
- LOAD_IMAGE_MAX_GUNZIP_BYTES, &data);
- }
-
- if (size == (size_t)-1) {
- gchar *contents;
- gsize length;
-
- if (!g_file_get_contents(image_name, &contents, &length, NULL)) {
- error_report("failed to load \"%s\"", image_name);
- exit(1);
- }
- size = length;
- data = (uint8_t *)contents;
- }
-
- fw_cfg_add_i32(fw_cfg, size_key, size);
- fw_cfg_add_bytes(fw_cfg, data_key, data, size);
-}
-
static int do_arm_linux_init(Object *obj, void *opaque)
{
if (object_dynamic_cast(obj, TYPE_ARM_LINUX_BOOT_IF)) {
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 29df99727d..4b595a9ea4 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -598,39 +598,6 @@ static void reset_load_elf(void *opaque)
}
}
-/* Load an image file into an fw_cfg entry identified by key. */
-static void load_image_to_fw_cfg(FWCfgState *fw_cfg, uint16_t size_key,
- uint16_t data_key, const char *image_name,
- bool try_decompress)
-{
- size_t size = -1;
- uint8_t *data;
-
- if (image_name == NULL) {
- return;
- }
-
- if (try_decompress) {
- size = load_image_gzipped_buffer(image_name,
- LOAD_IMAGE_MAX_GUNZIP_BYTES, &data);
- }
-
- if (size == (size_t)-1) {
- gchar *contents;
- gsize length;
-
- if (!g_file_get_contents(image_name, &contents, &length, NULL)) {
- error_report("failed to load \"%s\"", image_name);
- exit(1);
- }
- size = length;
- data = (uint8_t *)contents;
- }
-
- fw_cfg_add_i32(fw_cfg, size_key, size);
- fw_cfg_add_bytes(fw_cfg, data_key, data, size);
-}
-
static void fw_cfg_add_kernel_info(FWCfgState *fw_cfg)
{
/*
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index d605f3f45a..371a45dfe2 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -41,6 +41,7 @@
#include "qapi/error.h"
#include "hw/acpi/aml-build.h"
#include "hw/pci/pci_bus.h"
+#include "hw/loader.h"
#define FW_CFG_FILE_SLOTS_DFLT 0x20
@@ -1221,6 +1222,37 @@ FWCfgState *fw_cfg_find(void)
return FW_CFG(object_resolve_path_type("", TYPE_FW_CFG, NULL));
}
+void load_image_to_fw_cfg(FWCfgState *fw_cfg, uint16_t size_key,
+ uint16_t data_key, const char *image_name,
+ bool try_decompress)
+{
+ size_t size = -1;
+ uint8_t *data;
+
+ if (image_name == NULL) {
+ return;
+ }
+
+ if (try_decompress) {
+ size = load_image_gzipped_buffer(image_name,
+ LOAD_IMAGE_MAX_GUNZIP_BYTES, &data);
+ }
+
+ if (size == (size_t)-1) {
+ gchar *contents;
+ gsize length;
+
+ if (!g_file_get_contents(image_name, &contents, &length, NULL)) {
+ error_report("failed to load \"%s\"", image_name);
+ exit(1);
+ }
+ size = length;
+ data = (uint8_t *)contents;
+ }
+
+ fw_cfg_add_i32(fw_cfg, size_key, size);
+ fw_cfg_add_bytes(fw_cfg, data_key, data, size);
+}
static void fw_cfg_class_init(ObjectClass *klass, void *data)
{
diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
index 0e7a8bc7af..c1f81a5f13 100644
--- a/include/hw/nvram/fw_cfg.h
+++ b/include/hw/nvram/fw_cfg.h
@@ -342,4 +342,25 @@ bool fw_cfg_dma_enabled(void *opaque);
*/
const char *fw_cfg_arch_key_name(uint16_t key);
+/**
+ * load_image_to_fw_cfg() - Load an image file into an fw_cfg entry identified
+ * by key.
+ * @fw_cfg: The firmware config instance to store the data in.
+ * @size_key: The firmware config key to store the size of the loaded
+ * data under, with fw_cfg_add_i32().
+ * @data_key: The firmware config key to store the loaded data under,
+ * with fw_cfg_add_bytes().
+ * @image_name: The name of the image file to load. If it is NULL, the
+ * function returns without doing anything.
+ * @try_decompress: Whether the image should be decompressed (gunzipped) before
+ * adding it to fw_cfg. If decompression fails, the image is
+ * loaded as-is.
+ *
+ * In case of failure, the function prints an error message to stderr and the
+ * process exits with status 1.
+ */
+void load_image_to_fw_cfg(FWCfgState *fw_cfg, uint16_t size_key,
+ uint16_t data_key, const char *image_name,
+ bool try_decompress);
+
#endif
--
2.25.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH V5 2/3] hw/riscv: virt: Move create_fw_cfg() prior to loading kernel
2022-10-04 9:23 [PATCH V5 0/3] hw/riscv: virt: Enable booting S-mode firmware from pflash Sunil V L
2022-10-04 9:23 ` [PATCH V5 1/3] hw/arm, loongarch: Move load_image_to_fw_cfg() to common location Sunil V L
@ 2022-10-04 9:23 ` Sunil V L
2022-10-04 9:23 ` [PATCH V5 3/3] hw/riscv: virt: Enable booting S-mode firmware from pflash Sunil V L
2022-10-11 22:39 ` [PATCH V5 0/3] " Alistair Francis
3 siblings, 0 replies; 7+ messages in thread
From: Sunil V L @ 2022-10-04 9:23 UTC (permalink / raw)
To: Peter Maydell, Xiaojuan Yang, Song Gao,
Philippe Mathieu-Daudé, Gerd Hoffmann, Palmer Dabbelt,
Alistair Francis, Bin Meng
Cc: qemu-arm, qemu-devel, qemu-riscv, Sunil V L, Andrew Jones
To enable both -kernel and -pflash options, the fw_cfg needs to be
created prior to loading the kernel.
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
---
hw/riscv/virt.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index befa9d2c26..de2efccebf 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1267,6 +1267,13 @@ static void virt_machine_done(Notifier *notifier, void *data)
RISCV64_BIOS_BIN, start_addr, NULL);
}
+ /*
+ * Init fw_cfg. Must be done before riscv_load_fdt, otherwise the device
+ * tree cannot be altered and we get FDT_ERR_NOSPACE.
+ */
+ s->fw_cfg = create_fw_cfg(machine);
+ rom_set_fw(s->fw_cfg);
+
if (machine->kernel_filename) {
kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0],
firmware_end_addr);
@@ -1300,13 +1307,6 @@ static void virt_machine_done(Notifier *notifier, void *data)
start_addr = virt_memmap[VIRT_FLASH].base;
}
- /*
- * Init fw_cfg. Must be done before riscv_load_fdt, otherwise the device
- * tree cannot be altered and we get FDT_ERR_NOSPACE.
- */
- s->fw_cfg = create_fw_cfg(machine);
- rom_set_fw(s->fw_cfg);
-
/* Compute the fdt load address in dram */
fdt_load_addr = riscv_load_fdt(memmap[VIRT_DRAM].base,
machine->ram_size, machine->fdt);
--
2.25.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH V5 3/3] hw/riscv: virt: Enable booting S-mode firmware from pflash
2022-10-04 9:23 [PATCH V5 0/3] hw/riscv: virt: Enable booting S-mode firmware from pflash Sunil V L
2022-10-04 9:23 ` [PATCH V5 1/3] hw/arm, loongarch: Move load_image_to_fw_cfg() to common location Sunil V L
2022-10-04 9:23 ` [PATCH V5 2/3] hw/riscv: virt: Move create_fw_cfg() prior to loading kernel Sunil V L
@ 2022-10-04 9:23 ` Sunil V L
2022-10-10 1:24 ` Alistair Francis
2022-10-11 21:56 ` Bernhard Beschow
2022-10-11 22:39 ` [PATCH V5 0/3] " Alistair Francis
3 siblings, 2 replies; 7+ messages in thread
From: Sunil V L @ 2022-10-04 9:23 UTC (permalink / raw)
To: Peter Maydell, Xiaojuan Yang, Song Gao,
Philippe Mathieu-Daudé, Gerd Hoffmann, Palmer Dabbelt,
Alistair Francis, Bin Meng
Cc: qemu-arm, qemu-devel, qemu-riscv, Sunil V L, Andrew Jones
To boot S-mode firmware payload like EDK2 from persistent
flash storage, qemu needs to pass the flash address as the
next_addr in fw_dynamic_info to the opensbi.
When both -kernel and -pflash options are provided in command line,
the kernel (and initrd if -initrd) will be copied to fw_cfg table.
The S-mode FW will load the kernel/initrd from fw_cfg table.
If only pflash is given but not -kernel, then it is the job of
of the S-mode firmware to locate and load the kernel.
In either case, update the kernel_entry with the flash address
so that the opensbi can jump to the entry point of the S-mode
firmware.
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
hw/riscv/boot.c | 29 +++++++++++++++++++++++++++++
hw/riscv/virt.c | 18 +++++++++++++++++-
include/hw/riscv/boot.h | 1 +
3 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 1ae7596873..fa8ad27da2 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -338,3 +338,32 @@ void riscv_setup_direct_kernel(hwaddr kernel_addr, hwaddr fdt_addr)
riscv_cpu->env.fdt_addr = fdt_addr;
}
}
+
+void riscv_setup_firmware_boot(MachineState *machine)
+{
+ if (machine->kernel_filename) {
+ FWCfgState *fw_cfg;
+ fw_cfg = fw_cfg_find();
+
+ assert(fw_cfg);
+ /*
+ * Expose the kernel, the command line, and the initrd in fw_cfg.
+ * We don't process them here at all, it's all left to the
+ * firmware.
+ */
+ load_image_to_fw_cfg(fw_cfg,
+ FW_CFG_KERNEL_SIZE, FW_CFG_KERNEL_DATA,
+ machine->kernel_filename,
+ true);
+ load_image_to_fw_cfg(fw_cfg,
+ FW_CFG_INITRD_SIZE, FW_CFG_INITRD_DATA,
+ machine->initrd_filename, false);
+
+ if (machine->kernel_cmdline) {
+ fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
+ strlen(machine->kernel_cmdline) + 1);
+ fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
+ machine->kernel_cmdline);
+ }
+ }
+}
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index de2efccebf..a5bc7353b4 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1274,7 +1274,23 @@ static void virt_machine_done(Notifier *notifier, void *data)
s->fw_cfg = create_fw_cfg(machine);
rom_set_fw(s->fw_cfg);
- if (machine->kernel_filename) {
+ if (drive_get(IF_PFLASH, 0, 1)) {
+ /*
+ * S-mode FW like EDK2 will be kept in second plash (unit 1).
+ * When both kernel, initrd and pflash options are provided in the
+ * command line, the kernel and initrd will be copied to the fw_cfg
+ * table and opensbi will jump to the flash address which is the
+ * entry point of S-mode FW. It is the job of the S-mode FW to load
+ * the kernel and initrd using fw_cfg table.
+ *
+ * If only pflash is given but not -kernel, then it is the job of
+ * of the S-mode firmware to locate and load the kernel.
+ * In either case, the next_addr for opensbi will be the flash address.
+ */
+ riscv_setup_firmware_boot(machine);
+ kernel_entry = virt_memmap[VIRT_FLASH].base +
+ virt_memmap[VIRT_FLASH].size / 2;
+ } else if (machine->kernel_filename) {
kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0],
firmware_end_addr);
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index a36f7618f5..93e5f8760d 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -57,5 +57,6 @@ void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
uint32_t reset_vec_size,
uint64_t kernel_entry);
void riscv_setup_direct_kernel(hwaddr kernel_addr, hwaddr fdt_addr);
+void riscv_setup_firmware_boot(MachineState *machine);
#endif /* RISCV_BOOT_H */
--
2.25.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH V5 3/3] hw/riscv: virt: Enable booting S-mode firmware from pflash
2022-10-04 9:23 ` [PATCH V5 3/3] hw/riscv: virt: Enable booting S-mode firmware from pflash Sunil V L
@ 2022-10-10 1:24 ` Alistair Francis
2022-10-11 21:56 ` Bernhard Beschow
1 sibling, 0 replies; 7+ messages in thread
From: Alistair Francis @ 2022-10-10 1:24 UTC (permalink / raw)
To: Sunil V L
Cc: Peter Maydell, Xiaojuan Yang, Song Gao,
Philippe Mathieu-Daudé, Gerd Hoffmann, Palmer Dabbelt,
Alistair Francis, Bin Meng, qemu-arm, qemu-devel, qemu-riscv,
Andrew Jones
On Tue, Oct 4, 2022 at 7:28 PM Sunil V L <sunilvl@ventanamicro.com> wrote:
>
> To boot S-mode firmware payload like EDK2 from persistent
> flash storage, qemu needs to pass the flash address as the
> next_addr in fw_dynamic_info to the opensbi.
>
> When both -kernel and -pflash options are provided in command line,
> the kernel (and initrd if -initrd) will be copied to fw_cfg table.
> The S-mode FW will load the kernel/initrd from fw_cfg table.
>
> If only pflash is given but not -kernel, then it is the job of
> of the S-mode firmware to locate and load the kernel.
>
> In either case, update the kernel_entry with the flash address
> so that the opensbi can jump to the entry point of the S-mode
> firmware.
>
> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Alistair
> ---
> hw/riscv/boot.c | 29 +++++++++++++++++++++++++++++
> hw/riscv/virt.c | 18 +++++++++++++++++-
> include/hw/riscv/boot.h | 1 +
> 3 files changed, 47 insertions(+), 1 deletion(-)
>
> diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
> index 1ae7596873..fa8ad27da2 100644
> --- a/hw/riscv/boot.c
> +++ b/hw/riscv/boot.c
> @@ -338,3 +338,32 @@ void riscv_setup_direct_kernel(hwaddr kernel_addr, hwaddr fdt_addr)
> riscv_cpu->env.fdt_addr = fdt_addr;
> }
> }
> +
> +void riscv_setup_firmware_boot(MachineState *machine)
> +{
> + if (machine->kernel_filename) {
> + FWCfgState *fw_cfg;
> + fw_cfg = fw_cfg_find();
> +
> + assert(fw_cfg);
> + /*
> + * Expose the kernel, the command line, and the initrd in fw_cfg.
> + * We don't process them here at all, it's all left to the
> + * firmware.
> + */
> + load_image_to_fw_cfg(fw_cfg,
> + FW_CFG_KERNEL_SIZE, FW_CFG_KERNEL_DATA,
> + machine->kernel_filename,
> + true);
> + load_image_to_fw_cfg(fw_cfg,
> + FW_CFG_INITRD_SIZE, FW_CFG_INITRD_DATA,
> + machine->initrd_filename, false);
> +
> + if (machine->kernel_cmdline) {
> + fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
> + strlen(machine->kernel_cmdline) + 1);
> + fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
> + machine->kernel_cmdline);
> + }
> + }
> +}
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index de2efccebf..a5bc7353b4 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -1274,7 +1274,23 @@ static void virt_machine_done(Notifier *notifier, void *data)
> s->fw_cfg = create_fw_cfg(machine);
> rom_set_fw(s->fw_cfg);
>
> - if (machine->kernel_filename) {
> + if (drive_get(IF_PFLASH, 0, 1)) {
> + /*
> + * S-mode FW like EDK2 will be kept in second plash (unit 1).
> + * When both kernel, initrd and pflash options are provided in the
> + * command line, the kernel and initrd will be copied to the fw_cfg
> + * table and opensbi will jump to the flash address which is the
> + * entry point of S-mode FW. It is the job of the S-mode FW to load
> + * the kernel and initrd using fw_cfg table.
> + *
> + * If only pflash is given but not -kernel, then it is the job of
> + * of the S-mode firmware to locate and load the kernel.
> + * In either case, the next_addr for opensbi will be the flash address.
> + */
> + riscv_setup_firmware_boot(machine);
> + kernel_entry = virt_memmap[VIRT_FLASH].base +
> + virt_memmap[VIRT_FLASH].size / 2;
> + } else if (machine->kernel_filename) {
> kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0],
> firmware_end_addr);
>
> diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
> index a36f7618f5..93e5f8760d 100644
> --- a/include/hw/riscv/boot.h
> +++ b/include/hw/riscv/boot.h
> @@ -57,5 +57,6 @@ void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
> uint32_t reset_vec_size,
> uint64_t kernel_entry);
> void riscv_setup_direct_kernel(hwaddr kernel_addr, hwaddr fdt_addr);
> +void riscv_setup_firmware_boot(MachineState *machine);
>
> #endif /* RISCV_BOOT_H */
> --
> 2.25.1
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH V5 3/3] hw/riscv: virt: Enable booting S-mode firmware from pflash
2022-10-04 9:23 ` [PATCH V5 3/3] hw/riscv: virt: Enable booting S-mode firmware from pflash Sunil V L
2022-10-10 1:24 ` Alistair Francis
@ 2022-10-11 21:56 ` Bernhard Beschow
1 sibling, 0 replies; 7+ messages in thread
From: Bernhard Beschow @ 2022-10-11 21:56 UTC (permalink / raw)
To: qemu-devel, Sunil V L, Peter Maydell, Xiaojuan Yang, Song Gao,
Philippe Mathieu-Daudé, Gerd Hoffmann, Palmer Dabbelt,
Alistair Francis, Bin Meng
Cc: qemu-arm, qemu-riscv, Andrew Jones
Am 4. Oktober 2022 09:23:51 UTC schrieb Sunil V L <sunilvl@ventanamicro.com>:
>To boot S-mode firmware payload like EDK2 from persistent
>flash storage, qemu needs to pass the flash address as the
>next_addr in fw_dynamic_info to the opensbi.
>
>When both -kernel and -pflash options are provided in command line,
>the kernel (and initrd if -initrd) will be copied to fw_cfg table.
>The S-mode FW will load the kernel/initrd from fw_cfg table.
>
>If only pflash is given but not -kernel, then it is the job of
>of the S-mode firmware to locate and load the kernel.
>
>In either case, update the kernel_entry with the flash address
>so that the opensbi can jump to the entry point of the S-mode
>firmware.
>
>Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
>Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
>---
> hw/riscv/boot.c | 29 +++++++++++++++++++++++++++++
> hw/riscv/virt.c | 18 +++++++++++++++++-
> include/hw/riscv/boot.h | 1 +
> 3 files changed, 47 insertions(+), 1 deletion(-)
>
>diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
>index 1ae7596873..fa8ad27da2 100644
>--- a/hw/riscv/boot.c
>+++ b/hw/riscv/boot.c
>@@ -338,3 +338,32 @@ void riscv_setup_direct_kernel(hwaddr kernel_addr, hwaddr fdt_addr)
> riscv_cpu->env.fdt_addr = fdt_addr;
> }
> }
>+
>+void riscv_setup_firmware_boot(MachineState *machine)
>+{
>+ if (machine->kernel_filename) {
>+ FWCfgState *fw_cfg;
>+ fw_cfg = fw_cfg_find();
>+
>+ assert(fw_cfg);
>+ /*
>+ * Expose the kernel, the command line, and the initrd in fw_cfg.
>+ * We don't process them here at all, it's all left to the
>+ * firmware.
>+ */
>+ load_image_to_fw_cfg(fw_cfg,
>+ FW_CFG_KERNEL_SIZE, FW_CFG_KERNEL_DATA,
>+ machine->kernel_filename,
>+ true);
>+ load_image_to_fw_cfg(fw_cfg,
>+ FW_CFG_INITRD_SIZE, FW_CFG_INITRD_DATA,
>+ machine->initrd_filename, false);
>+
>+ if (machine->kernel_cmdline) {
>+ fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
>+ strlen(machine->kernel_cmdline) + 1);
>+ fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
>+ machine->kernel_cmdline);
>+ }
>+ }
>+}
>diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
>index de2efccebf..a5bc7353b4 100644
>--- a/hw/riscv/virt.c
>+++ b/hw/riscv/virt.c
>@@ -1274,7 +1274,23 @@ static void virt_machine_done(Notifier *notifier, void *data)
> s->fw_cfg = create_fw_cfg(machine);
> rom_set_fw(s->fw_cfg);
>
>- if (machine->kernel_filename) {
>+ if (drive_get(IF_PFLASH, 0, 1)) {
>+ /*
>+ * S-mode FW like EDK2 will be kept in second plash (unit 1).
Nitpicking: s/plash/pflash/ ?
Best regards,
Bernhard
>+ * When both kernel, initrd and pflash options are provided in the
>+ * command line, the kernel and initrd will be copied to the fw_cfg
>+ * table and opensbi will jump to the flash address which is the
>+ * entry point of S-mode FW. It is the job of the S-mode FW to load
>+ * the kernel and initrd using fw_cfg table.
>+ *
>+ * If only pflash is given but not -kernel, then it is the job of
>+ * of the S-mode firmware to locate and load the kernel.
>+ * In either case, the next_addr for opensbi will be the flash address.
>+ */
>+ riscv_setup_firmware_boot(machine);
>+ kernel_entry = virt_memmap[VIRT_FLASH].base +
>+ virt_memmap[VIRT_FLASH].size / 2;
>+ } else if (machine->kernel_filename) {
> kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0],
> firmware_end_addr);
>
>diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
>index a36f7618f5..93e5f8760d 100644
>--- a/include/hw/riscv/boot.h
>+++ b/include/hw/riscv/boot.h
>@@ -57,5 +57,6 @@ void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
> uint32_t reset_vec_size,
> uint64_t kernel_entry);
> void riscv_setup_direct_kernel(hwaddr kernel_addr, hwaddr fdt_addr);
>+void riscv_setup_firmware_boot(MachineState *machine);
>
> #endif /* RISCV_BOOT_H */
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH V5 0/3] hw/riscv: virt: Enable booting S-mode firmware from pflash
2022-10-04 9:23 [PATCH V5 0/3] hw/riscv: virt: Enable booting S-mode firmware from pflash Sunil V L
` (2 preceding siblings ...)
2022-10-04 9:23 ` [PATCH V5 3/3] hw/riscv: virt: Enable booting S-mode firmware from pflash Sunil V L
@ 2022-10-11 22:39 ` Alistair Francis
3 siblings, 0 replies; 7+ messages in thread
From: Alistair Francis @ 2022-10-11 22:39 UTC (permalink / raw)
To: Sunil V L
Cc: Peter Maydell, Xiaojuan Yang, Song Gao,
Philippe Mathieu-Daudé, Gerd Hoffmann, Palmer Dabbelt,
Alistair Francis, Bin Meng, qemu-arm, qemu-devel, qemu-riscv
On Tue, Oct 4, 2022 at 7:25 PM Sunil V L <sunilvl@ventanamicro.com> wrote:
>
> This series adds the support to boot S-mode FW like EDK2 from the flash. The
> S-mode firmware should be kept in pflash unit 1.
>
> When -kernel (and -initrd) option is also provided along with the flash,
> the kernel (and initrd) will be loaded into fw_cfg table and opensbi will
> branch to the flash address which will be the entry point of the S-mode
> firmware. The S-mode FW then loads and launches the kernel.
>
> When only -pflash option is provided in the command line, the kernel
> will be located and loaded in the usual way by the S-mode firmware.
>
> These patches are available in below branch.
> https://github.com/vlsunil/qemu/tree/pflash_v2
>
> The first two patches in this series are refactor patches.
>
> These changes are tested with a WIP EDK2 port for virt machine. Below
> are the instructions to build and test this feature.
>
> 1) Get EDK2 sources from below branches.
> https://github.com/vlsunil/edk2/tree/virt_refactor_smode_v1
> https://github.com/vlsunil/edk2-platforms/tree/virt_refactor_smode_v1
>
> 2) Build EDK2 for RISC-V
> export WORKSPACE=`pwd`
> export GCC5_RISCV64_PREFIX=riscv64-linux-gnu-
> export PACKAGES_PATH=$WORKSPACE/edk2:$WORKSPACE/edk2-platforms
> export EDK_TOOLS_PATH=$WORKSPACE/edk2/BaseTools
> source edk2/edksetup.sh
> make -C edk2/BaseTools clean
> make -C edk2/BaseTools
> make -C edk2/BaseTools/Source/C
> source edk2/edksetup.sh BaseTools
> build -a RISCV64 -p Platform/Qemu/RiscVVirt/RiscVVirt.dsc -t GCC5
>
> 3)Make the EDK2 image size to match with what qemu flash expects
> truncate -s 32M Build/RiscVVirt/DEBUG_GCC5/FV/RISCV_VIRT.fd
>
> 4) Run
> a) Boot to EFI shell (no -kernel / -initrd option)
> qemu-system-riscv64 -nographic -drive file=Build/RiscVVirt/DEBUG_GCC5/FV/RISCV_VIRT.fd,if=pflash,format=raw,unit=1 -machine virt -M 2G
>
> b) With -kernel, -initrd and -pflash
> qemu-system-riscv64 -nographic -drive file=Build/RiscVVirt/DEBUG_GCC5/FV/RISCV_VIRT.fd,if=pflash,format=raw,unit=1 -machine virt -M 2G -kernel arch/riscv/boot/Image.gz -initrd rootfs.cpio
>
>
> Changes since V4:
> 1) Rebased on riscv-to-apply.next branch
> 2) Added RB tags
> 3) Gerd's feedback on removing the truncate requirement will be addressed as separate
> patch in future.
>
> Changes since V3:
> 1) White space and comment edits
> 2) Added RB tag
>
> Changes since V2:
> 1) Moved the doc comment to .h file
>
> Changes since V1:
> 1) Modified code to support the use case when both -kernel and -pflash are configured.
> 2) Refactor patches added to help (1) above.
> 3) Cover letter added with test instructions.
>
> Sunil V L (3):
> hw/arm,loongarch: Move load_image_to_fw_cfg() to common location
> hw/riscv: virt: Move create_fw_cfg() prior to loading kernel
> hw/riscv: virt: Enable booting S-mode firmware from pflash
Thanks!
Applied to riscv-to-apply.next
Alistair
>
> hw/arm/boot.c | 49 ---------------------------------------
> hw/loongarch/virt.c | 33 --------------------------
> hw/nvram/fw_cfg.c | 32 +++++++++++++++++++++++++
> hw/riscv/boot.c | 29 +++++++++++++++++++++++
> hw/riscv/virt.c | 32 ++++++++++++++++++-------
> include/hw/nvram/fw_cfg.h | 21 +++++++++++++++++
> include/hw/riscv/boot.h | 1 +
> 7 files changed, 107 insertions(+), 90 deletions(-)
>
> --
> 2.25.1
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2022-10-11 22:41 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-10-04 9:23 [PATCH V5 0/3] hw/riscv: virt: Enable booting S-mode firmware from pflash Sunil V L
2022-10-04 9:23 ` [PATCH V5 1/3] hw/arm, loongarch: Move load_image_to_fw_cfg() to common location Sunil V L
2022-10-04 9:23 ` [PATCH V5 2/3] hw/riscv: virt: Move create_fw_cfg() prior to loading kernel Sunil V L
2022-10-04 9:23 ` [PATCH V5 3/3] hw/riscv: virt: Enable booting S-mode firmware from pflash Sunil V L
2022-10-10 1:24 ` Alistair Francis
2022-10-11 21:56 ` Bernhard Beschow
2022-10-11 22:39 ` [PATCH V5 0/3] " Alistair Francis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).