tier2-gate.sh (3374B)
1 #!/bin/sh 2 # tier2-gate.sh — end-to-end Tier 2 acceptance: scheme1 driver spawns a 3 # chain stage as a subprocess (clone + execve + waitid), waits for it, 4 # returns its result file. One qemu boot, end-to-end. 5 # 6 # Usage: 7 # tier2-gate.sh <scheme1> <prelude.scm> <driver.scm> \ 8 # <child-bin> <output-dir> -- <input-files...> 9 # 10 # Stages: combines prelude.scm + driver.scm into combined.scm via host 11 # `cat`, packs an in.img cpio archive containing /init=scheme1, 12 # /combined.scm, /child-prog=<child-bin>, plus every input file at its 13 # basename, then boots qemu with bootargs "init combined.scm". driver.scm 14 # is expected to use prelude's (run "child-prog" ...) wrapper. 15 # 16 # After qemu exits, every file from the post-run SEEDFS dump (out.img) is 17 # extracted into <output-dir>/. The driver's exit status is reflected in 18 # this script's exit status (0 = scheme1 driver said success). 19 20 set -eu 21 22 if [ $# -lt 6 ]; then 23 echo "usage: $0 <scheme1> <prelude.scm> <driver.scm> <child-bin> <outdir> -- <inputs...>" >&2 24 exit 2 25 fi 26 27 SCHEME1=$1; PRELUDE=$2; DRIVER=$3; CHILD=$4; OUTDIR=$5 28 shift 5 29 [ "$1" = "--" ] || { echo "expected -- before input files" >&2; exit 2; } 30 shift 31 32 HERE=$(cd "$(dirname "$0")" && pwd) 33 SEED_DIR=$(cd "$HERE/.." && pwd) 34 KERNEL=$SEED_DIR/build/Image 35 EXTRACT=$HERE/extract-blk.sh 36 [ -f "$KERNEL" ] || { echo "missing $KERNEL — run 'make' in $SEED_DIR first" >&2; exit 1; } 37 38 mkdir -p "$OUTDIR" 39 STAGE=$(mktemp -d -t tier2-stage.XXXXXX) 40 trap 'rm -rf "$STAGE"' EXIT 41 42 cp "$SCHEME1" "$STAGE/init"; chmod +x "$STAGE/init" 43 cp "$CHILD" "$STAGE/child-prog"; chmod +x "$STAGE/child-prog" 44 cat "$PRELUDE" "$DRIVER" > "$STAGE/combined.scm" 45 NAMES="init 46 child-prog 47 combined.scm" 48 for inp in "$@"; do 49 base=$(basename "$inp") 50 cp "$inp" "$STAGE/$base" 51 NAMES="$NAMES 52 $base" 53 done 54 ( cd "$STAGE" && printf '%s\n' "$NAMES" | cpio -o -H newc 2>/dev/null > initramfs.cpio ) 55 sz=$(wc -c < "$STAGE/initramfs.cpio") 56 pad=$(( (512 - sz % 512) % 512 )) 57 if [ "$pad" -gt 0 ]; then 58 head -c "$pad" /dev/zero >> "$STAGE/initramfs.cpio" 59 fi 60 mv "$STAGE/initramfs.cpio" "$STAGE/in.img" 61 truncate -s 256M "$STAGE/out.img" 62 63 TRANSCRIPT=$STAGE/transcript.txt 64 echo "[gate] running scheme1 driver" >&2 65 qemu-system-aarch64 \ 66 -machine virt,gic-version=3,accel=hvf -cpu host -m 2048M \ 67 -nographic -no-reboot \ 68 -global virtio-mmio.force-legacy=false \ 69 -kernel "$KERNEL" \ 70 -drive file="$STAGE/in.img",if=none,format=raw,id=hd0,readonly=on \ 71 -device virtio-blk-device,drive=hd0 \ 72 -drive file="$STAGE/out.img",if=none,format=raw,id=hd1 \ 73 -device virtio-blk-device,drive=hd1 \ 74 -append "init combined.scm" \ 75 > "$TRANSCRIPT" 2>&1 & 76 QPID=$! 77 ( sleep 240; kill -9 $QPID 2>/dev/null ) </dev/null >/dev/null 2>&1 & 78 WATCHER=$! 79 wait $QPID 2>/dev/null || true 80 kill $WATCHER 2>/dev/null || true 81 82 if ! "$EXTRACT" "$OUTDIR" "$STAGE/out.img" >/dev/null 2>&1; then 83 echo "[gate] FAIL: extract-blk failed (kernel didn't reach exit?)" >&2 84 tail -40 "$TRANSCRIPT" >&2 85 exit 3 86 fi 87 88 # Capture the driver's exit code from the kernel's parting message. 89 EXIT_LINE=$(grep -E "user exit_group" "$TRANSCRIPT" | tail -1 || true) 90 case "$EXIT_LINE" in 91 *"exit_group(0)"*) 92 echo "[gate] PASS — driver exit 0; outputs in $OUTDIR" >&2 93 exit 0 ;; 94 *) 95 echo "[gate] FAIL — driver did not exit 0: $EXIT_LINE" >&2 96 exit 4 ;; 97 esac