qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [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).