[PATCH 0/3] qemu: allow auto-booting through firmware device

Hi,
when running QEMU and specifying both a firmware binary (--bios) and a kernel (-kernel) on the command line, QEMU will run the firmware, but will also record information about the provided kernel in the QEMU firmware device. U-Boot's "qfw" command can load the kernel to a provided address then. However using a kernel (and initrd) provided this way requires typing some rather generic commands.
This series automates this, so that the default boot sequence tries to launch a kernel this way first. If that fails, we gracefully continue with the existing boot locations.
This simplifies automated booting, with external firmware: $ qemu-system-aarch64 -machine virt,virtualization=on,gic-version=2 -cpu cortex-a57 -nographic -display none -d unimp --bios u-boot.bin -kernel Image -initrd initrd.gz -append "earlycon"
The first two patches clean up some qfw issues, so that the automatic booting becomes smoother, while the third patch adds the new commands to QEMU's distro_boot script.
Please have a look!
Cheers, Andre
Andre Przywara (3): qfw: store loaded file size in environment variable qfw: return failure when no kernel could be loaded qemu: Try to automatically boot from the QEMU firmware device (qfw)
cmd/qfw.c | 6 ++++-- include/configs/qemu-arm.h | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-)

At the moment the QEMU firmware command just prints the size of the loaded binaries on the console. To go with all the other load methods, and many boot scripts' expectations, also store the size of the file loaded last in the environment variable "filesize". We first put the kernel size in there, but overwrite this with the initrd size, should we have one, because this is probably the more prominent user of $filesize (in the booti or bootz command).
Signed-off-by: Andre Przywara andre.przywara@arm.com --- cmd/qfw.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/cmd/qfw.c b/cmd/qfw.c index ccbc967ca9f..c61001b771d 100644 --- a/cmd/qfw.c +++ b/cmd/qfw.c @@ -40,6 +40,7 @@ static int qemu_fwcfg_cmd_setup_kernel(void *load_addr, void *initrd_addr) qfw_read_entry(qfw_dev, FW_CFG_KERNEL_DATA, le32_to_cpu(kernel_size), data_addr); data_addr += le32_to_cpu(kernel_size); + env_set_hex("filesize", le32_to_cpu(kernel_size));
data_addr = initrd_addr; qfw_read_entry(qfw_dev, FW_CFG_INITRD_SIZE, 4, &initrd_size); @@ -49,6 +50,7 @@ static int qemu_fwcfg_cmd_setup_kernel(void *load_addr, void *initrd_addr) qfw_read_entry(qfw_dev, FW_CFG_INITRD_DATA, le32_to_cpu(initrd_size), data_addr); data_addr += le32_to_cpu(initrd_size); + env_set_hex("filesize", le32_to_cpu(initrd_size)); }
qfw_read_entry(qfw_dev, FW_CFG_CMDLINE_SIZE, 4, &cmdline_size);

On Mon, Oct 10, 2022 at 06:01:20PM +0100, Andre Przywara wrote:
At the moment the QEMU firmware command just prints the size of the loaded binaries on the console. To go with all the other load methods, and many boot scripts' expectations, also store the size of the file loaded last in the environment variable "filesize". We first put the kernel size in there, but overwrite this with the initrd size, should we have one, because this is probably the more prominent user of $filesize (in the booti or bootz command).
Signed-off-by: Andre Przywara andre.przywara@arm.com
Applied to u-boot/master, thanks!

When we try to load a kernel via the QEMU firmware device, we currently "return -1;" if no kernel was specified on the QEMU command line. This leads to the usage output, which is confusing (since nothing on the command line was really wrong), but also somewhat hides the actual error message.
Return CMD_RET_FAILURE (1), as it's a proper error, and make the message more clear that this is not only a "warning".
This helps to call this command in boot scripts, and to gracefully continue if this doesn't work.
Signed-off-by: Andre Przywara andre.przywara@arm.com --- cmd/qfw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cmd/qfw.c b/cmd/qfw.c index c61001b771d..95ddc4b79ec 100644 --- a/cmd/qfw.c +++ b/cmd/qfw.c @@ -26,8 +26,8 @@ static int qemu_fwcfg_cmd_setup_kernel(void *load_addr, void *initrd_addr) qfw_read_entry(qfw_dev, FW_CFG_KERNEL_SIZE, 4, &kernel_size);
if (kernel_size == 0) { - printf("warning: no kernel available\n"); - return -1; + printf("fatal: no kernel available\n"); + return CMD_RET_FAILURE; }
data_addr = load_addr;

On Mon, Oct 10, 2022 at 06:01:21PM +0100, Andre Przywara wrote:
When we try to load a kernel via the QEMU firmware device, we currently "return -1;" if no kernel was specified on the QEMU command line. This leads to the usage output, which is confusing (since nothing on the command line was really wrong), but also somewhat hides the actual error message.
Return CMD_RET_FAILURE (1), as it's a proper error, and make the message more clear that this is not only a "warning".
This helps to call this command in boot scripts, and to gracefully continue if this doesn't work.
Signed-off-by: Andre Przywara andre.przywara@arm.com
Applied to u-boot/master, thanks!

At the moment the QEMU boot sequence tries various (storage) devices when trying to find a payload to boot. To simplify starting a specific kernel and initrd, there is also the qfw command, which can use the files specified on the QEMU command line, via the -kernel and -initrd options. Add this command to the list of boot options to try. Since users specifying those options on the command line probably explicitly want to run them, let's place the new command first. Without those options, the qfw command will just gracefully fail, and we continue with the existing order.
This allows auto-booting of specific kernels in QEMU, for instance in CI systems.
Signed-off-by: Andre Przywara andre.przywara@arm.com --- include/configs/qemu-arm.h | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/include/configs/qemu-arm.h b/include/configs/qemu-arm.h index dd2faebbbb2..535762ecb24 100644 --- a/include/configs/qemu-arm.h +++ b/include/configs/qemu-arm.h @@ -21,6 +21,17 @@ EFI_GUID(0x058b7d83, 0x50d5, 0x4c47, 0xa1, 0x95, \ 0x60, 0xd8, 0x6a, 0xd3, 0x41, 0xc4)
+/* Try files from QEMU's -kernel/-initrd, through the QEMU firmware device. */ +#define BOOTENV_DEV_QFW(devtypeu, devtypel, instance) \ + "bootcmd_qfw= " \ + "if qfw load $kernel_addr_r $ramdisk_addr_r; then " \ + " booti $kernel_addr_r $ramdisk_addr_r:$filesize $fdtcontroladdr; " \ + " if test $? -eq 1; then " \ + " bootz $kernel_addr_r $ramdisk_addr_r:$filesize $fdtcontroladdr; " \ + " fi ; " \ + "fi\0" +#define BOOTENV_DEV_NAME_QFW(devtypeu, devtypel, instance) "qfw " + /* For timer, QEMU emulates an ARMv7/ARMv8 architected timer */
/* Environment options */ @@ -56,6 +67,7 @@ #endif
#define BOOT_TARGET_DEVICES(func) \ + func(QFW, qfw, na) \ BOOT_TARGET_USB(func) \ BOOT_TARGET_SCSI(func) \ BOOT_TARGET_VIRTIO(func) \

On Mon, Oct 10, 2022 at 06:01:22PM +0100, Andre Przywara wrote:
At the moment the QEMU boot sequence tries various (storage) devices when trying to find a payload to boot. To simplify starting a specific kernel and initrd, there is also the qfw command, which can use the files specified on the QEMU command line, via the -kernel and -initrd options. Add this command to the list of boot options to try. Since users specifying those options on the command line probably explicitly want to run them, let's place the new command first. Without those options, the qfw command will just gracefully fail, and we continue with the existing order.
This allows auto-booting of specific kernels in QEMU, for instance in CI systems.
Signed-off-by: Andre Przywara andre.przywara@arm.com
Applied to u-boot/master, thanks!
participants (2)
-
Andre Przywara
-
Tom Rini