#!/usr/bin/env bash # # scripts/run.sh — build, stage and boot the system image in QEMU. # # Usage: # ./scripts/run.sh build + stage + boot (window + serial) # ./scripts/run.sh --headless serial console only, no window # ./scripts/run.sh --debug GDB stub on :1234, CPU starts paused # (attach: gdb -x scripts/debug-kernel.py) # ./scripts/run.sh --monitor HMP monitor socket for sendkeys.py / # test-focus.py (default path below) # ./scripts/run.sh --fresh re-create the system image first # (wipes runtime data on the image) # ./scripts/run.sh --mem 512M guest memory (default 256M) # ./scripts/run.sh --smp 2 guest CPUs (default 1) # ./scripts/run.sh --bios FILE OVMF firmware (default: system path) # ./scripts/run.sh --image FILE system image (default: /tmp/system.img) # ./scripts/run.sh --grab confine the pointer: GTK runs as an X11 # (XWayland) client and grabs on hover # ./scripts/run.sh --no-grab Wayland-native window, no pointer grab # # Mouse: Wayland forbids global pointer grabs, so a Wayland-native window # cannot confine the cursor (QEMU's grab silently does nothing). # In a Wayland session with XWayland, run.sh defaults to --grab; # Ctrl+Alt+G toggles the grab in either mode. # # Environment (same names the other scripts honour): TARGET, PROFILE, # SYSTEM_IMG, OVMF, QEMU, MEM, SMP. # # Two-command flow: ./scripts/build.sh && ./scripts/run.sh # One-command flow: ./scripts/run.sh (builds what is missing) # # Monitor socket: /tmp/rsdos-monitor.sock # set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" usage() { awk 'NR > 1 && /^#/ { sub(/^# ?/, ""); print; next } NR > 1 { exit }' "$0" } HEADLESS=0 DEBUG=0 FRESH=0 MON=0 MON_SOCK="/tmp/rsdos-monitor.sock" GRAB="" # "" = auto: grab when a Wayland session has XWayland while [ $# -gt 0 ]; do case "$1" in --headless | -H) HEADLESS=1 ;; # GDB stub + keep whatever profile the env asked for (release is the # default; PROFILE=debug ./scripts/run.sh --debug adds line symbols). --debug | -d) DEBUG=1 ;; --fresh) FRESH=1 ;; --monitor) MON=1 ;; --mem) shift; MEM="$1" ;; --smp) shift; SMP="$1" ;; --bios) shift; OVMF="$1" ;; --image | -i) shift; SYSTEM_IMG="$1" ;; --grab) GRAB=1 ;; --no-grab) GRAB=0 ;; --help | -h) usage exit 0 ;; *) echo "run.sh: unknown argument: $1" >&2 usage >&2 exit 1 ;; esac shift done # shellcheck source=lib.sh source "$SCRIPT_DIR/lib.sh" # reads MEM/SMP/OVMF/SYSTEM_IMG from the env # build.sh is a separate process: it re-derives OUT_DIR/KERNEL from these, # so whatever we resolved above (including a --mem/--bios override) wins # there too. export TARGET PROFILE QEMU MEM SMP OVMF SYSTEM_IMG # ---- mouse grab (Wayland) -------------------------------------------------- # Wayland forbids global pointer grabs, so a Wayland-native GTK window cannot # confine the cursor — QEMU's grab silently does nothing there. XWayland can, # so a Wayland session that has XWayland (DISPLAY set) defaults to GTK-on-X11 # plus grab-on-hover. Ctrl+Alt+G toggles the grab; --no-grab keeps the # Wayland-native window. if [ -z "$GRAB" ]; then if [ "${XDG_SESSION_TYPE:-}" = "wayland" ] && [ -n "${DISPLAY:-}" ]; then GRAB=1 else GRAB=0 fi fi [ "$HEADLESS" -eq 1 ] && GRAB=0 # no window, nothing to grab if [ "$GRAB" -eq 1 ]; then if [ -n "${DISPLAY:-}" ]; then export GDK_BACKEND=x11 else echo "run.sh: --grab needs XWayland (DISPLAY is unset); not grabbing" >&2 GRAB=0 fi fi # ---- build + stage -------------------------------------------------------- "$SCRIPT_DIR/build.sh" if [ "$FRESH" -eq 1 ]; then stage_image --force else stage_image fi # ---- boot ----------------------------------------------------------------- mapfile -t QARGS < <(qemu_args) if [ "$HEADLESS" -eq 1 ]; then QARGS+=(-display none) else QARGS+=(-vga std) if [ "$GRAB" -eq 1 ]; then QARGS+=(-display gtk,grab-on-hover=on) fi fi [ "$MON" -eq 1 ] && QARGS+=(-monitor "unix:$MON_SOCK,server,nowait") [ "$DEBUG" -eq 1 ] && QARGS+=(-s -S) QARGS+=(-serial stdio) echo "" echo "=== boot ===" echo " image: $SYSTEM_IMG" echo " ovmf: $OVMF" echo " mem: $MEM smp: $SMP" echo " mode: $([ "$HEADLESS" -eq 1 ] && echo headless || echo window) gdb: $([ "$DEBUG" -eq 1 ] && echo ':1234 (paused)' || echo off)" if [ "$HEADLESS" -eq 0 ]; then echo " mouse: $([ "$GRAB" -eq 1 ] && echo 'grab on hover (XWayland; Ctrl+Alt+G toggles)' || echo 'not grabbed (Wayland cannot confine the pointer)')" fi [ "$MON" -eq 1 ] && echo " monitor: unix:$MON_SOCK" echo "" exec "$QEMU" "${QARGS[@]}"