From e3fe3f3f45d135ff6e3c097106610b1e41b04c6f Mon Sep 17 00:00:00 2001 From: Daniel Samson <12231216+daniel-samson@users.noreply.github.com> Date: Mon, 13 Jul 2026 05:05:08 +0100 Subject: [PATCH] Boot zig-out directly in the qemu test harness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The FHS-shaped zig-out IS the boot volume (docs/efi.md), and `zig build run-x86-64` already presents it to the guest with fat:rw:zig-out. The test harness instead assembled a separate ESP by copying the boot-critical files out of zig-out into zig-out/qemu-test/esp — but every (dest, src) pair was identical, so the copy was pure redundancy. Drop make_esp and point QEMU straight at zig-out, matching run-x86-64 and the docs. Removes the now-dead efi_app/kernel/extra arch-config entries. --- test/qemu_test.py | 39 +++++++++------------------------------ 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/test/qemu_test.py b/test/qemu_test.py index bd30af4..53d87b3 100644 --- a/test/qemu_test.py +++ b/test/qemu_test.py @@ -55,20 +55,16 @@ ARCHES = { "/opt/homebrew/share/qemu/edk2-i386-vars.fd", # macOS Homebrew (Apple Silicon) "/usr/local/share/qemu/edk2-i386-vars.fd", # macOS Homebrew (Intel) ], - # zig-out is a FHS-shaped image and the boot volume; the harness copies the - # boot-critical files from their FHS paths into a fresh ESP with the same - # layout. (dest in ESP, source path under zig-out) — identical here. - "efi_app": ("EFI/BOOT/BOOTX64.efi", "EFI/BOOT/BOOTX64.efi"), - "kernel": ("system/kernel", "system/kernel"), - # The init user program and the initial-ramdisk (VFS server + drivers). - "extra": [("system/services/init", "system/services/init"), - ("boot/initial-ramdisk.img", "boot/initial-ramdisk.img")], + # zig-out is itself the FHS-shaped boot volume (docs/efi.md): the build + # installs BOOTX64.efi, the kernel, init, and the initial-ramdisk at their + # boot paths. The harness presents zig-out to the guest directly — exactly + # as `zig build run-x86-64` does — so there is no separate ESP to assemble. # Built as a function so we can splice in per-run paths. - "qemu_args": lambda a, esp, vars_fd, serial: [ + "qemu_args": lambda a, boot_volume, vars_fd, serial: [ "-machine", "q35", "-m", "128M", "-drive", f"if=pflash,format=raw,readonly=on,file={a['ovmf_code']}", "-drive", f"if=pflash,format=raw,file={vars_fd}", - "-drive", f"format=raw,file=fat:rw:{esp}", + "-drive", f"format=raw,file=fat:rw:{boot_volume}", "-net", "none", "-vga", "none", "-device", "VGA,edid=on,xres=1280,yres=720", "-display", "none", @@ -404,24 +400,6 @@ def build(arch, case): return None -def make_esp(arch): - """Assemble a fresh EFI System Partition from the freshly built binaries.""" - esp = os.path.join(WORK, "esp") - if os.path.exists(esp): - shutil.rmtree(esp) - efi_dest, efi_src = arch["efi_app"] - kern_dest, kern_src = arch["kernel"] - fhs = os.path.join(REPO, "zig-out") # zig-out is the FHS image - os.makedirs(os.path.join(esp, os.path.dirname(efi_dest)), exist_ok=True) - os.makedirs(os.path.join(esp, os.path.dirname(kern_dest)), exist_ok=True) - shutil.copy(os.path.join(fhs, efi_src), os.path.join(esp, efi_dest)) - shutil.copy(os.path.join(fhs, kern_src), os.path.join(esp, kern_dest)) - for dest, src in arch.get("extra", []): - os.makedirs(os.path.join(esp, os.path.dirname(dest)), exist_ok=True) - shutil.copy(os.path.join(fhs, src), os.path.join(esp, dest)) - return esp - - def resolve_firmware(arch): """Collapse the ovmf_code/ovmf_vars candidate lists to the first path that exists on this machine. Mutates `arch` in place; idempotent (a resolved @@ -445,7 +423,8 @@ def run_case(arch, case): if err: return False, "build failed:\n" + err - esp = make_esp(arch) + # zig-out is the FHS boot volume; hand it to the guest as-is (see qemu_args). + boot_volume = os.path.join(REPO, "zig-out") vars_fd = os.path.join(WORK, "vars.fd") shutil.copy(arch["ovmf_vars"], vars_fd) serial = os.path.join(WORK, "serial.log") @@ -455,7 +434,7 @@ def run_case(arch, case): expect = re.compile(case["expect"]) fail = re.compile(case["fail"]) if case.get("fail") else None - cmd = [arch["qemu"]] + arch["qemu_args"](arch, esp, vars_fd, serial) + cmd = [arch["qemu"]] + arch["qemu_args"](arch, boot_volume, vars_fd, serial) if case.get("smp"): # some cases need more than one core (e.g. parallelism) cmd += ["-smp", str(case["smp"])] if case.get("qemu_extra"): # extra qemu args, e.g. -device intel-iommu for the IOMMU case