seed-accept.sh (5935B)
1 #!/bin/sh 2 ## seed-accept.sh — Tier-2 acceptance for boot0/1/2 on seed-kernel. 3 ## 4 ## Loads the boot2-built scheme1 as /init in the seed kernel, runs a 5 ## .scm driver that: 6 ## 1. Logs "hello" to stdout (sys_write fd=1 → UART). 7 ## 2. Spawns child-prog (=catm from boot2) via clone+execve to 8 ## concatenate two files A + B → C in the in-memory tmpfs. 9 ## 3. waitids the child, reads C back, prints it to stdout. 10 ## 4. exit_group(0). 11 ## 12 ## End-to-end exercise of every Tier-1 syscall (read/write/openat/close/ 13 ## brk/exit_group) plus the three Tier-2 ones (clone/execve/waitid). 14 ## 15 ## Verifies the transcript contains the expected log lines and that 16 ## sys_exit_or_resume_parent saw the child exit cleanly. 17 ## 18 ## Usage: scripts/seed-accept.sh 19 20 set -eu 21 22 ARCH=aarch64 23 ROOT=$(cd "$(dirname "$0")/.." && pwd) 24 cd "$ROOT" 25 26 KERNEL=build/$ARCH/boot6/Image 27 EXTRACT=seed-kernel/scripts/extract-blk.sh 28 SCHEME1=build/$ARCH/boot2/scheme1 29 CATM=build/$ARCH/boot2/catm 30 PRELUDE=scheme1/prelude.scm 31 32 [ -f "$KERNEL" ] || { echo "missing $KERNEL — run ./scripts/boot.sh $ARCH (default DRIVER=podman) first" >&2; exit 1; } 33 [ -x "$SCHEME1" ] || { echo "missing $SCHEME1 — run boot2 first" >&2; exit 1; } 34 [ -x "$CATM" ] || { echo "missing $CATM — run boot2 first" >&2; exit 1; } 35 36 OUTDIR=$ROOT/build/$ARCH/seed-accept 37 rm -rf "$OUTDIR"; mkdir -p "$OUTDIR" 38 39 STAGE=$(mktemp -d -t seed-accept.XXXXXX) 40 trap 'rm -rf "$STAGE"' EXIT 41 42 # ─── driver.scm — the in-VM acceptance program ──────────────────────── 43 cat > "$STAGE/driver.scm" <<'SCM' 44 ;; driver.scm — Tier-2 acceptance for seed-kernel. 45 (write-string stdout "scheme1: hello from acceptance driver\n") 46 (write-string stdout "scheme1: spawning child-prog (catm) C <- A + B\n") 47 48 (let ((r (run "child-prog" "C" "A" "B"))) 49 (if (car r) 50 (begin 51 (write-string stdout "scheme1: child returned\n")) 52 (begin 53 (write-string stdout "scheme1: spawn FAILED\n") 54 (exit 1)))) 55 56 (let ((rp (open-input "C"))) 57 (if (car rp) 58 (let* ((p (cdr rp)) 59 (rb (read-all p))) 60 (if (car rb) 61 (begin 62 (write-string stdout "scheme1: read C: [") 63 (write-bytes stdout (cdr rb)) 64 (write-string stdout "]\n")) 65 (write-string stdout "scheme1: read C FAILED\n")) 66 (close p)) 67 (write-string stdout "scheme1: open C FAILED\n"))) 68 69 (write-string stdout "scheme1: ALL-OK\n") 70 (exit 0) 71 SCM 72 73 # ─── Combine prelude + driver via host catm — this matches the chain's 74 # own boot-run-scheme1.sh wrapper, so the .scm shape is identical 75 # to what scheme1 expects everywhere. ────────────────────────────── 76 cat "$PRELUDE" "$STAGE/driver.scm" > "$STAGE/combined.scm" 77 78 # ─── Two demo input files. catm reads them from the in-VM tmpfs. ────── 79 printf 'Hello, ' > "$STAGE/A" 80 printf 'seed-kernel!\n' > "$STAGE/B" 81 82 # ─── Stage the cpio: /init=scheme1, /child-prog=catm, plus inputs. ──── 83 mkdir -p "$STAGE/cpio" 84 cp "$SCHEME1" "$STAGE/cpio/init"; chmod +x "$STAGE/cpio/init" 85 cp "$CATM" "$STAGE/cpio/child-prog"; chmod +x "$STAGE/cpio/child-prog" 86 cp "$STAGE/combined.scm" "$STAGE/cpio/combined.scm" 87 cp "$STAGE/A" "$STAGE/cpio/A" 88 cp "$STAGE/B" "$STAGE/cpio/B" 89 90 NAMES='init 91 child-prog 92 combined.scm 93 A 94 B' 95 96 ( cd "$STAGE/cpio" && printf '%s\n' "$NAMES" | cpio -o -H newc 2>/dev/null ) > "$STAGE/initramfs.cpio" 97 sz=$(wc -c < "$STAGE/initramfs.cpio") 98 pad=$(( (512 - sz % 512) % 512 )) 99 if [ "$pad" -gt 0 ]; then 100 head -c "$pad" /dev/zero >> "$STAGE/initramfs.cpio" 101 fi 102 mv "$STAGE/initramfs.cpio" "$STAGE/in.img" 103 truncate -s 256M "$STAGE/out.img" 104 105 TRANSCRIPT=$OUTDIR/transcript.txt 106 echo "[seed-accept] booting scheme1 + driver.scm on seed-kernel" 107 qemu-system-aarch64 \ 108 -machine virt,gic-version=3,accel=hvf -cpu host -m 2048M \ 109 -nographic -no-reboot \ 110 -global virtio-mmio.force-legacy=false \ 111 -kernel "$KERNEL" \ 112 -drive file="$STAGE/in.img",if=none,format=raw,id=hd0,readonly=on \ 113 -device virtio-blk-device,drive=hd0 \ 114 -drive file="$STAGE/out.img",if=none,format=raw,id=hd1 \ 115 -device virtio-blk-device,drive=hd1 \ 116 -append "init combined.scm" \ 117 > "$TRANSCRIPT" 2>&1 & 118 QPID=$! 119 ( sleep 240; kill -9 $QPID 2>/dev/null ) </dev/null >/dev/null 2>&1 & 120 WATCHER=$! 121 wait $QPID 2>/dev/null || true 122 kill $WATCHER 2>/dev/null || true 123 124 # Extract files (we want C from the tmpfs). 125 if ! "$EXTRACT" "$OUTDIR" "$STAGE/out.img" >/dev/null 2>&1; then 126 echo "[seed-accept] FAIL: extract-blk failed (kernel didn't reach exit?)" >&2 127 tail -60 "$TRANSCRIPT" >&2 128 exit 3 129 fi 130 131 # ─── Verify ─────────────────────────────────────────────────────────── 132 fail=0 133 for needle in \ 134 'scheme1: hello from acceptance driver' \ 135 'scheme1: spawning child-prog' \ 136 'scheme1: child returned' \ 137 'scheme1: read C: \[Hello, seed-kernel!' \ 138 'scheme1: ALL-OK' \ 139 'exit_group(0)' 140 do 141 if ! grep -q "$needle" "$TRANSCRIPT"; then 142 echo "[seed-accept] MISSING in transcript: $needle" >&2 143 fail=1 144 fi 145 done 146 147 if [ ! -f "$OUTDIR/C" ]; then 148 echo "[seed-accept] MISSING extracted file: $OUTDIR/C" >&2 149 fail=1 150 elif ! diff -q "$OUTDIR/C" - <<EOF >/dev/null 151 Hello, seed-kernel! 152 EOF 153 then 154 echo "[seed-accept] C differs from expected:" >&2 155 od -c "$OUTDIR/C" | head -3 >&2 156 fail=1 157 fi 158 159 if [ $fail -ne 0 ]; then 160 echo "[seed-accept] FAIL — see $TRANSCRIPT" >&2 161 exit 4 162 fi 163 164 echo "" 165 echo "=== driver log (excerpt from transcript) ===" 166 grep '^scheme1:' "$TRANSCRIPT" || true 167 echo "===========================================" 168 echo "" 169 echo "[seed-accept] PASS — scheme1 + .scm + child-prog cycle complete" 170 echo "[seed-accept] artifacts in $OUTDIR/"