From c3b280fb67f2efac9124f4cbd8731e9ae5632043 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 20 Nov 2022 01:28:19 +0000 Subject: [PATCH] test-various: Add tests for {i686,aarch64}-unknown-uefi This extends the existing test for x86_64-unknown-uefi to test the other two UEFI targets as well. --- .../host-x86_64/test-various/Dockerfile | 13 +++- .../test-various/uefi_qemu_test/run.py | 78 +++++++++++++++---- 2 files changed, 74 insertions(+), 17 deletions(-) diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile index 0bddffa3436f4..7c09e3a582fd6 100644 --- a/src/ci/docker/host-x86_64/test-various/Dockerfile +++ b/src/ci/docker/host-x86_64/test-various/Dockerfile @@ -19,11 +19,18 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins wget \ patch \ ovmf \ + qemu-efi-aarch64 \ + qemu-system-arm \ qemu-system-x86 RUN curl -sL https://nodejs.org/dist/v15.14.0/node-v15.14.0-linux-x64.tar.xz | \ tar -xJ +# Install 32-bit OVMF files for the i686-unknown-uefi test. This package +# is not available in ubuntu 20.04, so download a 22.04 package. +RUN curl -sL --output ovmf-ia32.deb http://mirrors.kernel.org/ubuntu/pool/universe/e/edk2/ovmf-ia32_2022.02-3_all.deb +RUN dpkg -i ovmf-ia32.deb && rm ovmf-ia32.deb + WORKDIR /build/ COPY scripts/musl-patch-configure.diff /build/ COPY scripts/musl-toolchain.sh /build/ @@ -68,7 +75,11 @@ ENV MUSL_TARGETS=x86_64-unknown-linux-musl \ ENV MUSL_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $MUSL_TARGETS COPY host-x86_64/test-various/uefi_qemu_test /uefi_qemu_test -ENV UEFI_TARGETS=x86_64-unknown-uefi \ +ENV UEFI_TARGETS=aarch64-unknown-uefi,i686-unknown-uefi,x86_64-unknown-uefi \ + CC_aarch64_unknown_uefi=clang-11 \ + CXX_aarch64_unknown_uefi=clang++-11 \ + CC_i686_unknown_uefi=clang-11 \ + CXX_i686_unknown_uefi=clang++-11 \ CC_x86_64_unknown_uefi=clang-11 \ CXX_x86_64_unknown_uefi=clang++-11 ENV UEFI_SCRIPT python3 /checkout/x.py --stage 2 build --host='' --target $UEFI_TARGETS && \ diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py index 46793ce3afa15..ffae7b0d4ac27 100644 --- a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py +++ b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py @@ -8,8 +8,11 @@ from pathlib import Path +TARGET_AARCH64 = 'aarch64-unknown-uefi' +TARGET_I686 = 'i686-unknown-uefi' +TARGET_X86_64 = 'x86_64-unknown-uefi' -def run(*cmd, capture=False, check=True, env=None): +def run(*cmd, capture=False, check=True, env=None, timeout=None): """Print and run a command, optionally capturing the output.""" cmd = [str(p) for p in cmd] print(' '.join(cmd)) @@ -17,10 +20,39 @@ def run(*cmd, capture=False, check=True, env=None): capture_output=capture, check=check, env=env, - text=True) - + text=True, + timeout=timeout) + +def build_and_run(tmp_dir, target): + if target == TARGET_AARCH64: + boot_file_name = 'bootaa64.efi' + ovmf_dir = Path('/usr/share/AAVMF') + ovmf_code = 'AAVMF_CODE.fd' + ovmf_vars = 'AAVMF_VARS.fd' + qemu = 'qemu-system-aarch64' + machine = 'virt' + cpu = 'cortex-a72' + elif target == TARGET_I686: + boot_file_name = 'bootia32.efi' + ovmf_dir = Path('/usr/share/OVMF') + ovmf_code = 'OVMF32_CODE_4M.secboot.fd' + ovmf_vars = 'OVMF32_VARS_4M.fd' + # The i686 target intentionally uses 64-bit qemu; the important + # difference is that the OVMF code provides a 32-bit environment. + qemu = 'qemu-system-x86_64' + machine = 'q35' + cpu = 'qemu64' + elif target == TARGET_X86_64: + boot_file_name = 'bootx64.efi' + ovmf_dir = Path('/usr/share/OVMF') + ovmf_code = 'OVMF_CODE.fd' + ovmf_vars = 'OVMF_VARS.fd' + qemu = 'qemu-system-x86_64' + machine = 'q35' + cpu = 'qemu64' + else: + raise KeyError('invalid target') -def build_and_run(tmp_dir): host_artifacts = Path('/checkout/obj/build/x86_64-unknown-linux-gnu') stage0 = host_artifacts / 'stage0/bin' stage2 = host_artifacts / 'stage2/bin' @@ -33,7 +65,6 @@ def build_and_run(tmp_dir): shutil.copytree('/uefi_qemu_test', test_crate) # Build the UEFI executable. - target = 'x86_64-unknown-uefi' run('cargo', 'build', '--manifest-path', @@ -49,14 +80,24 @@ def build_and_run(tmp_dir): # Copy the executable into the ESP. src_exe_path = test_crate / 'target' / target / 'debug/uefi_qemu_test.efi' - shutil.copy(src_exe_path, boot / 'bootx64.efi') + shutil.copy(src_exe_path, boot / boot_file_name) + print(src_exe_path, boot / boot_file_name) + + # Select the appropriate EDK2 build. + ovmf_code = ovmf_dir / ovmf_code + ovmf_vars = ovmf_dir / ovmf_vars + + # Make a writable copy of the vars file. aarch64 doesn't boot + # correctly with read-only vars. + ovmf_rw_vars = Path(tmp_dir) / 'vars.fd' + shutil.copy(ovmf_vars, ovmf_rw_vars) # Run the executable in QEMU and capture the output. - qemu = 'qemu-system-x86_64' - ovmf_dir = Path('/usr/share/OVMF') - ovmf_code = ovmf_dir / 'OVMF_CODE.fd' - ovmf_vars = ovmf_dir / 'OVMF_VARS.fd' output = run(qemu, + '-machine', + machine, + '-cpu', + cpu, '-display', 'none', '-serial', @@ -64,7 +105,7 @@ def build_and_run(tmp_dir): '-drive', f'if=pflash,format=raw,readonly=on,file={ovmf_code}', '-drive', - f'if=pflash,format=raw,readonly=on,file={ovmf_vars}', + f'if=pflash,format=raw,readonly=off,file={ovmf_rw_vars}', '-drive', f'format=raw,file=fat:rw:{esp}', capture=True, @@ -73,7 +114,9 @@ def build_and_run(tmp_dir): # shutdown under some circumstances. That has been # fixed in newer versions of QEMU, but for now just # don't check the exit status. - check=False).stdout + check=False, + # Set a timeout to kill the VM in case something goes wrong. + timeout=60).stdout if 'Hello World!' in output: print('VM produced expected output') @@ -86,10 +129,13 @@ def build_and_run(tmp_dir): def main(): - # Create a temporary directory so that we have a writeable - # workspace. - with tempfile.TemporaryDirectory() as tmp_dir: - build_and_run(tmp_dir) + targets = [TARGET_AARCH64, TARGET_I686, TARGET_X86_64] + + for target in targets: + # Create a temporary directory so that we have a writeable + # workspace. + with tempfile.TemporaryDirectory() as tmp_dir: + build_and_run(tmp_dir, target) if __name__ == "__main__":