#!/bin/sh
# Boot the installed ukiboot EFI binary in QEMU from GPT and DOS
# partitioned disks and check it chainloads the active slot, before
# and after switching slots with ukibootctl.
set -eu

srcdir=$(pwd)

# sfdisk and mkfs.vfat live in sbin, which is not in PATH for users.
export PATH="$PATH:/usr/sbin:/sbin"

case "$(uname -m)" in
    x86_64)
        efi_arch=x64
        qemu_machine=q35
        qemu_cpu=qemu64
        export OVMF=/usr/share/ovmf/OVMF.fd
        ;;
    aarch64)
        efi_arch=aa64
        qemu_machine=virt
        qemu_cpu=cortex-a57
        export OVMF=/usr/share/qemu-efi-aarch64/QEMU_EFI.fd
        ;;
    *)
        echo "Unsupported architecture $(uname -m)" >&2
        exit 1
        ;;
esac

# Skip if QEMU cannot start in this environment, e.g. /dev/kvm exists
# but is not accessible. Use the same accelerator choice as efitest.sh.
if [ -c /dev/kvm ]; then
    qemu_accel=kvm
    qemu_cpu=host
else
    qemu_accel=tcg
fi
if ! echo quit | timeout 60 "qemu-system-$(uname -m)" \
        -accel "$qemu_accel" -M "$qemu_machine" -cpu "$qemu_cpu" \
        -nodefaults -display none -monitor stdio -S >/dev/null; then
    echo "QEMU ($qemu_accel) cannot start in this environment, skipping" >&2
    exit 77
fi

cd "$AUTOPKGTEST_TMP"

# efitest.sh expects to run from a meson build directory.
mkdir efi test
cp "/usr/libexec/ukiboot/efi/ukiboot${efi_arch}.efi" efi/

# Build the dummy slot payloads the same way as test/meson.build.
for slot in a b; do
    clang \
        -target "$(uname -m)-unknown-windows" \
        -I/usr/include/efi \
        -fno-stack-protector \
        -ffreestanding \
        -fshort-wchar \
        -mno-red-zone \
        -g \
        -fuse-ld=lld \
        -Wl,-nodefaultlib \
        -Wl,-entry:efi_main \
        -Wl,-subsystem:efi_application \
        -o "test/SLOT$(echo "$slot" | tr a-z A-Z).EFI" \
        "$srcdir/test/slot$slot.c"
done

# Guard against QEMU hanging if the expected slot never boots.
UKIBOOTCTL_PATH=/usr/bin/ukibootctl \
    timeout 1200 bash "$srcdir/test/efitest.sh"
