Files
LithosAnanke/demo/make-snapshot.sh
Claude 3bd81097e1 chore(license): an SPDX header on every source file that had none (LicenseRef-Starship-1.0) [skip ci]
The header scan (Captain Bob, 2026-11-10): 788 source files -- 351 with the
SL-1.0 header, 12 with the old name (docs/working/experiments, kept by
ruling), 31 under someone else's licence (tools/kconfig, Linux's, GPL-2.0:
kept), and 394 with none. Ruled: the SPDX form; capsules (.4th, .f18) and
proofs (.thy) left for a ruling of their own (mkcapsule's 64x16 block format,
content-addressed capsules).

253 files now begin
    SPDX-License-Identifier: LicenseRef-Starship-1.0
    Copyright (c) 2023-2026 Robert A. James
as a /* */ block (C, headers, assembly, linker scripts) or # lines (scripts,
Makefiles, Kconfig; below a shebang or a coding line); tools/mkcapsule.c,
which had the copyright line, gets the SPDX line only.

Not touched: docs/working/ (archive and old campaign material, as the
ruling kept the experiments); v4/system/post_cases.c (generated by
v4/tools/mkpost.py, "do not edit" -- the generator has the header).

Comments only: the kernel builds on amd64, aarch64, riscv64; make -C v4
test-32: 39 programs, 0 failures; every changed script parses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 04:12:49 +00:00

59 lines
2.9 KiB
Bash
Executable File

#!/bin/bash
# SPDX-License-Identifier: LicenseRef-Starship-1.0
# Copyright (c) 2023-2026 Robert A. James
# make-snapshot.sh -- boot the demo machine once, to its prompt, and save it: every session
# resumes from here, at the prompt in seconds instead of after boot and POST (issue #113).
#
# demo/make-snapshot.sh <image.iso> <state-dir> [identity.img]
#
# <state-dir> gets the image, the identity drive if any, the firmware's variables as the boot
# left them (vars.fd) and the machine's state (state). One QEMU, in the foreground.
set -euo pipefail
here=$(cd "$(dirname "$0")" && pwd)
. "$here/qemu-args.sh"
iso=${1:?usage: demo/make-snapshot.sh <image.iso> <state-dir> [identity.img]}
dir=$(realpath -m "${2:?usage: demo/make-snapshot.sh <image.iso> <state-dir> [identity.img]}")
ident=${3:-}
prompt=${DEMO_PROMPT:-ok> } # what the console prints when it is ready
boot_limit=${DEMO_BOOT_LIMIT:-600} # seconds a boot may take, POST included
rm -rf "$dir"; mkdir -p "$dir"
cp "$iso" "$dir/StarshipOS.iso"
[ -z "$ident" ] || cp "$ident" "$dir/identity.img"
cp /usr/share/OVMF/OVMF_VARS_4M.fd "$dir/vars.fd"
demo_qemu_args "$dir" "$dir/vars.fd"
log=$dir/boot.log qmp=$dir/qmp.sock
qemu-system-x86_64 "${QEMU_ARGS[@]}" -serial "file:$log" -qmp "unix:$qmp,server=on,wait=off" &
pid=$!
trap 'kill $pid 2>/dev/null || true' EXIT
qmp() { # one QMP command, after the greeting and capabilities; prints QEMU's replies
python3 - "$qmp" "$1" <<'PY'
import json, socket, sys, time
s = socket.socket(socket.AF_UNIX); s.connect(sys.argv[1]); f = s.makefile("rw")
f.readline(); f.write(json.dumps({"execute": "qmp_capabilities"}) + "\n"); f.flush(); f.readline()
f.write(sys.argv[2] + "\n"); f.flush(); print(f.readline().strip())
PY
}
echo "demo: booting $iso to '$prompt' (at most ${boot_limit}s)"
t0=$(date +%s)
until [ -S "$qmp" ] && grep -aqF -- "$prompt" "$log" 2>/dev/null; do
kill -0 $pid 2>/dev/null || { echo "demo: QEMU exited during the boot" >&2; tail -5 "$log" >&2; exit 1; }
[ $(( $(date +%s) - t0 )) -lt "$boot_limit" ] || { echo "demo: no prompt in ${boot_limit}s" >&2; tail -5 "$log" >&2; exit 1; }
sleep 1
done
echo "demo: at the prompt after $(( $(date +%s) - t0 ))s; saving"
sleep 2 # let the console finish the line
# Saved running, not stopped first: QEMU saves the run state too, and a machine saved stopped
# resumes stopped -- every session would be a frozen screen. Migration stops it at the end itself.
qmp "{\"execute\":\"migrate\",\"arguments\":{\"uri\":\"file:$dir/state\"}}" >/dev/null
until qmp '{"execute":"query-migrate"}' | grep -q '"status": "completed"'; do
qmp '{"execute":"query-migrate"}' | grep -q '"status": "failed"' && { echo "demo: saving failed" >&2; exit 1; }
sleep 1
done
qmp '{"execute":"quit"}' >/dev/null || true
wait $pid 2>/dev/null || true
trap - EXIT
rm -f "$qmp"
echo "demo: saved $(du -h "$dir/state" | cut -f1) to $dir/state"