#!/bin/bash # test-boot-arm64.sh — Verify ARM64 image boots successfully in QEMU # # Uses qemu-system-aarch64 with -machine virt to test ARM64 kernel + initramfs. # Exit 0 = PASS, Exit 1 = FAIL # # Usage: ./test/qemu/test-boot-arm64.sh [kernel] [initramfs] set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" KERNEL="${1:-$PROJECT_ROOT/build/cache/custom-kernel-arm64/Image}" INITRD="${2:-$PROJECT_ROOT/build/rootfs-work/kubesolo-os.gz}" TIMEOUT=120 echo "==> ARM64 Boot Test" echo " Kernel: $KERNEL" echo " Initrd: $INITRD" echo " Timeout: ${TIMEOUT}s" # Verify files exist if [ ! -f "$KERNEL" ]; then echo "ERROR: Kernel not found: $KERNEL" echo " Run 'make kernel-arm64' to build the ARM64 kernel." exit 1 fi if [ ! -f "$INITRD" ]; then echo "ERROR: Initrd not found: $INITRD" echo " Run 'make initramfs' to build the initramfs." exit 1 fi # Verify qemu-system-aarch64 is available if ! command -v qemu-system-aarch64 >/dev/null 2>&1; then echo "ERROR: qemu-system-aarch64 not found." echo " Install QEMU with ARM64 support:" echo " apt install qemu-system-arm # Debian/Ubuntu" echo " dnf install qemu-system-aarch64 # Fedora/RHEL" echo " brew install qemu # macOS" exit 1 fi # Create temp data disk DATA_DISK=$(mktemp /tmp/kubesolo-arm64-test-XXXXXX.img) dd if=/dev/zero of="$DATA_DISK" bs=1M count=512 2>/dev/null mkfs.ext4 -q -L KSOLODATA "$DATA_DISK" 2>/dev/null SERIAL_LOG=$(mktemp /tmp/kubesolo-arm64-serial-XXXXXX.log) QEMU_PID="" cleanup() { [ -n "$QEMU_PID" ] && kill "$QEMU_PID" 2>/dev/null || true rm -f "$DATA_DISK" "$SERIAL_LOG" } trap cleanup EXIT # Launch QEMU in background qemu-system-aarch64 \ -machine virt \ -cpu cortex-a72 \ -m 2048 \ -smp 2 \ -nographic \ -kernel "$KERNEL" \ -initrd "$INITRD" \ -append "console=ttyAMA0 kubesolo.data=/dev/vda kubesolo.debug" \ -drive "file=$DATA_DISK,format=raw,if=virtio" \ -net nic,model=virtio \ -net user \ -serial "file:$SERIAL_LOG" & QEMU_PID=$! # Wait for boot success marker echo " Waiting for boot..." ELAPSED=0 SUCCESS=0 while [ "$ELAPSED" -lt "$TIMEOUT" ]; do # Check for stage 90 completion (same marker as x86_64 test) if grep -q "\[kubesolo-init\] \[OK\] Stage 90-kubesolo.sh complete" "$SERIAL_LOG" 2>/dev/null; then SUCCESS=1 break fi # Also check for generic KubeSolo running message if grep -q "KubeSolo is running" "$SERIAL_LOG" 2>/dev/null; then SUCCESS=1 break fi # Check if QEMU exited prematurely if ! kill -0 "$QEMU_PID" 2>/dev/null; then echo "" echo "==> FAIL: QEMU exited prematurely" echo " Last 20 lines of serial output:" tail -20 "$SERIAL_LOG" 2>/dev/null || echo " (no output)" exit 1 fi sleep 2 ELAPSED=$((ELAPSED + 2)) printf "\r Elapsed: %ds / %ds" "$ELAPSED" "$TIMEOUT" done echo "" # Kill QEMU kill "$QEMU_PID" 2>/dev/null || true wait "$QEMU_PID" 2>/dev/null || true QEMU_PID="" if [ "$SUCCESS" = "1" ]; then echo "==> ARM64 Boot Test PASSED (${ELAPSED}s)" exit 0 else echo "==> ARM64 Boot Test FAILED (timeout ${TIMEOUT}s)" echo "" echo "==> Last 30 lines of serial output:" tail -30 "$SERIAL_LOG" 2>/dev/null || echo " (no output)" exit 1 fi