[Concept,2/6] test: Add QEMU helper for EFI application boards

Message ID 20260220213235.2112347-3-sjg@u-boot.org
State New
Headers
Series test: Add QEMU-based CI for EFI application boards |

Commit Message

Simon Glass Feb. 20, 2026, 9:32 p.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

EFI application boards (efi-x86_app32, efi-x86_app64, efi-arm_app64,
efi-riscv_app64) build U-Boot as an EFI application that runs under
UEFI firmware. They cannot boot directly like normal QEMU boards, so
the test framework needs two changes:

Add qemu.efi_app, a helper script sourced by console.qemu that stages
the EFI binary, a startup.nsh script and a writable copy of the UEFI
firmware variables, then adds the appropriate pflash and FAT drive
arguments. It supports both standard pflash drives and the
blockdev-style pflash needed by the RISC-V virt machine.

In conftest.py, skip ensure_spawned() for tests marked with
@pytest.mark.localqemu. These tests launch their own QEMU instance,
so the framework must not attempt to boot the board itself, which
would fail for EFI boards and abort the entire test session.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
---

 test/hooks/bin/qemu.efi_app | 45 +++++++++++++++++++++++++++++++++++++
 test/py/conftest.py         |  4 ++++
 2 files changed, 49 insertions(+)
 create mode 100644 test/hooks/bin/qemu.efi_app
  

Patch

diff --git a/test/hooks/bin/qemu.efi_app b/test/hooks/bin/qemu.efi_app
new file mode 100644
index 00000000000..c0c40108f79
--- /dev/null
+++ b/test/hooks/bin/qemu.efi_app
@@ -0,0 +1,45 @@ 
+# SPDX-License-Identifier: MIT
+# Copyright 2026 Canonical Ltd.
+# Written by Simon Glass <simon.glass@canonical.com>
+#
+# Helper script sourced by console.qemu for EFI-application boards.
+#
+# Sets up a staging directory with:
+#   - u-boot-app.efi copied from the build directory
+#   - startup.nsh that launches the EFI app
+#   - a writable copy of the UEFI firmware variables file
+#
+# Required variables (set by the board conf.*):
+#   efi_app_binary  - name of the EFI app (default: u-boot-app.efi)
+#   efi_fw_code     - path to UEFI firmware code (pflash, read-only)
+#   efi_fw_vars     - path to UEFI firmware vars (pflash template)
+#
+# Optional:
+#   efi_use_blockdev - set to "y" for machines that need blockdev-style
+#                      pflash (e.g. RISC-V virt)
+#   efi_virtio_blk   - set to "y" to use virtio-blk for the FAT drive
+
+efi_app_binary="${efi_app_binary:-u-boot-app.efi}"
+
+efi_stage="${U_BOOT_BUILD_DIR}/efi_stage"
+rm -rf "${efi_stage}"
+mkdir -p "${efi_stage}"
+
+cp "${U_BOOT_BUILD_DIR}/${efi_app_binary}" "${efi_stage}/"
+printf 'fs0:%s\n' "${efi_app_binary}" > "${efi_stage}/startup.nsh"
+cp "${efi_fw_vars}" "${efi_stage}/vars.fd"
+
+if [ "${efi_use_blockdev}" = "y" ]; then
+	ARGS+=" -blockdev node-name=pflash0,driver=file,read-only=on,filename=${efi_fw_code}"
+	ARGS+=" -blockdev node-name=pflash1,driver=file,filename=${efi_stage}/vars.fd"
+else
+	ARGS+=" -drive if=pflash,format=raw,file=${efi_fw_code},readonly=on"
+	ARGS+=" -drive if=pflash,format=raw,file=${efi_stage}/vars.fd"
+fi
+
+if [ "${efi_virtio_blk}" = "y" ]; then
+	ARGS+=" -device virtio-blk-device,drive=efi_fat"
+	ARGS+=" -drive id=efi_fat,file=fat:rw:${efi_stage},format=raw"
+else
+	ARGS+=" -drive file=fat:rw:${efi_stage},format=raw"
+fi
diff --git a/test/py/conftest.py b/test/py/conftest.py
index b7a03669751..f4c5e390a93 100644
--- a/test/py/conftest.py
+++ b/test/py/conftest.py
@@ -530,6 +530,10 @@  def ubman(request):
     Returns:
         The fixture value.
     """
+    # Tests marked @pytest.mark.localqemu run QEMU locally, so they
+    # don't need a target-board connection; return the fixture directly.
+    if request.node.get_closest_marker('localqemu'):
+        return ubman_fix
     if not ubconfig.connection_ok:
         pytest.skip('Cannot get target connection')
         return None