summaryrefslogtreecommitdiffstats
path: root/scripts/mksystem.sh
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-11-01 15:53:29 +0100
committersalmonik <salmonik@tuta.io>2026-11-01 15:53:29 +0100
commit7958276c9f0d230053520ba20f2a00f5ecda18e4 (patch)
tree596f5f71ad597ed951bae98de818cb37f171a18d /scripts/mksystem.sh
parentfs: /bin alias for the system volume (diff)
downloadrs-dos-7958276c9f0d230053520ba20f2a00f5ecda18e4.tar.gz
rs-dos-7958276c9f0d230053520ba20f2a00f5ecda18e4.zip
scripts: rebuild the dev loop around build.sh/run.sh
`make` did not parse at all (missing separator at line 139), so every make target was dead. The folder also carried three overlapping launchers (boot.sh, qemu.sh, boot-image.sh) plus a fourth partial one in the Makefile, `cargo build --package rsdos` copy-pasted eight times, the QEMU invocation copy-pasted per script, and the test helpers (fail/wait_log/wait_qemu_exit/qemu_hmp) duplicated in five tests. New layout: - scripts/lib.sh: single config (image, OVMF, mem/smp), the one cargo invocation (build_all), the one QEMU shape (qemu_args), and the test harness (test_boot, wait_log, wait_qemu_exit, qemu_hmp, sendkeys) - scripts/build.sh: kernel + every bins/* in one pass - scripts/mksystem.sh: freshness-aware image build that now stages every bins/*.efi into /bin/cli|gui (they were never copied before) - scripts/run.sh: build + stage + boot in one command; --headless, --debug (GDB stub), --monitor (HMP socket), --fresh, --mem/--smp/ --bios/--image; on Wayland it auto-selects XWayland plus grab-on-hover so the mouse can be captured (Ctrl+Alt+G toggles) - scripts/tests/: the five automated tests on the shared harness - deleted: boot.sh, qemu.sh, boot-image.sh, lib-boot-args.sh, build-image-release.sh, build-bootloader.sh (rsboot chain dropped) The Makefile is now a thin wrapper: make run, make test, make system, make inspect, make help. Two-command flow: ./scripts/build.sh then ./scripts/run.sh (run.sh alone also works). Stale test assumptions fixed so the suite is green again: test-gfx waited for "gfx: check" while the shell prints "gfx check: PASS"; test-mouse/test-msg hardcoded msgrecv = task 3 (wm-input took slot 3 — ids are parsed from the log now); the queue-full probe targeted task 0, whose exec pump drains its own queue as completion codes (moved to the cursor task, which never recvs). Verified in QEMU: make test -> test-disk, test-gfx, test-mouse, test-msg, test-fault all PASS.
Diffstat (limited to 'scripts/mksystem.sh')
-rwxr-xr-xscripts/mksystem.sh144
1 files changed, 75 insertions, 69 deletions
diff --git a/scripts/mksystem.sh b/scripts/mksystem.sh
index 044c86c..053fb3b 100755
--- a/scripts/mksystem.sh
+++ b/scripts/mksystem.sh
@@ -2,44 +2,49 @@
2# 2#
3# scripts/mksystem.sh — assemble the single dd-able rs-dos system image 3# scripts/mksystem.sh — assemble the single dd-able rs-dos system image
4# 4#
5# Replaces the old two-source setup (vvfat `esp/` directory for boot + 5# One FAT32 image holds EVERYTHING (boot medium and data medium are the
6# separate /tmp/disk.img for data). One FAT32 image holds EVERYTHING: 6# same disk, mounted by the kernel at /disk/<UID>/):
7# 7#
8# \bzImage kernel (rsbl requires this exact path) 8# \EFI\BOOT\BOOTX64.EFI the kernel — the firmware boots it directly
9# \initramfs.cpio.gz empty initramfs (rsbl requires it) 9# \bzImage kernel copy (rsbl's expected path, real hw)
10# \EFI\BOOT\BOOTX64.EFI boot entry: the kernel (default) or rsboot 10# \initramfs.cpio.gz empty initramfs (rsbl requires the path)
11# \bin\cli\*.efi terminal binaries (invoked by the shell)
12# \bin\gui\*.efi windowed binaries (launched with no shell)
11# \etc\motd.txt seed config 13# \etc\motd.txt seed config
12# \bin\cli\ \bin\gui\ binary tree (empty until Phase 2/4 migrate tools)
13# \*.txt seed files (seed/) 14# \*.txt seed files (seed/)
14# 15#
15# The firmware boots from this image and the kernel mounts the same 16# Freshness: an existing image is only rebuilt when a kernel/binary/seed
16# volume at /disk/<UID>/ — boot medium and data medium are one disk. 17# file is newer than it, so files written at runtime survive across
18# boots. --force always re-creates (wipes runtime data).
17# 19#
18# Usage: 20# Usage:
19# ./scripts/mksystem.sh [options] [output.img] # default /tmp/system.img 21# ./scripts/mksystem.sh [options] [output.img] default: $SYSTEM_IMG
20# 22#
21# Options: 23# Options:
22# --force rebuild even if the image exists (Makefile stamps handle 24# --force rebuild even if the image is up to date
23# normal freshness; without --force an existing image is kept,
24# so user files survive across reboots)
25# --size NM image size in MB (default 64) 25# --size NM image size in MB (default 64)
26# --chain \EFI\BOOT\BOOTX64.EFI = rsboot bootloader (full chain:
27# firmware → rsboot → rsnix). Default is the kernel itself
28# (direct: firmware → rsnix), matching the old dev loop.
29# --gpt wrap the FAT volume in a GPT partition table (for dd-ing
30# to real USB sticks whose firmware refuses superfloppies)
31# --label NAME FAT volume label (default RSDOS) 26# --label NAME FAT volume label (default RSDOS)
27# --gpt wrap the FAT volume in a GPT partition table (for
28# dd-ing to real USB sticks whose firmware refuses
29# superfloppies)
30# --help show this help
31#
32# Needs: dosfstools (mkfs.fat), mtools (mcopy/mmd), cargo (kernel+bins
33# built via scripts/build.sh when missing).
32# 34#
33set -euo pipefail 35set -euo pipefail
34 36
35SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" 37SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
36PROJECT_DIR="$(dirname "$SCRIPT_DIR")" 38# Absolute self path: lib.sh cd's to the project root, so a relative $0
37cd "$PROJECT_DIR" 39# would no longer resolve by the time --help prints the header.
40SELF="$SCRIPT_DIR/$(basename "$0")"
41
42# shellcheck source=lib.sh
43source "$SCRIPT_DIR/lib.sh"
38 44
39IMG="/tmp/system.img" 45IMG="$SYSTEM_IMG"
40SIZE_MB=64 46SIZE_MB=64
41FORCE=0 47FORCE=0
42CHAIN=0
43GPT=0 48GPT=0
44LABEL="RSDOS" 49LABEL="RSDOS"
45 50
@@ -52,18 +57,15 @@ while [ $# -gt 0 ]; do
52 shift 57 shift
53 SIZE_MB="$1" 58 SIZE_MB="$1"
54 ;; 59 ;;
55 --chain)
56 CHAIN=1
57 ;;
58 --gpt)
59 GPT=1
60 ;;
61 --label) 60 --label)
62 shift 61 shift
63 LABEL="$1" 62 LABEL="$1"
64 ;; 63 ;;
64 --gpt)
65 GPT=1
66 ;;
65 --help | -h) 67 --help | -h)
66 head -30 "$0" | grep "^#" | sed 's/^# \?//' 68 awk 'NR > 1 && /^#/ { sub(/^# ?/, ""); print; next } NR > 1 { exit }' "$SELF"
67 exit 0 69 exit 0
68 ;; 70 ;;
69 -*) 71 -*)
@@ -77,15 +79,9 @@ while [ $# -gt 0 ]; do
77 shift 79 shift
78done 80done
79 81
80TARGET=x86_64-unknown-uefi 82SEED_DIR="$PROJECT_DIR/seed"
81PROFILE=release
82OUT_DIR="target/$TARGET/$PROFILE"
83KERNEL="$OUT_DIR/rsdos.efi"
84BZIMAGE="esp/bzImage"
85INITRD="esp/initramfs.cpio.gz"
86BOOTLOADER="build/bootloader/BOOTX64.EFI"
87 83
88# ---- checks ---- 84# ---- checks ---------------------------------------------------------------
89for cmd in mkfs.fat mcopy mmd; do 85for cmd in mkfs.fat mcopy mmd; do
90 if ! command -v "$cmd" >/dev/null 2>&1; then 86 if ! command -v "$cmd" >/dev/null 2>&1; then
91 echo "mksystem: $cmd not found (install dosfstools + mtools)" >&2 87 echo "mksystem: $cmd not found (install dosfstools + mtools)" >&2
@@ -101,29 +97,26 @@ if [ "$GPT" -eq 1 ]; then
101 done 97 done
102fi 98fi
103 99
104if [ -f "$IMG" ] && [ "$FORCE" -eq 0 ]; then 100# ---- build (only when artifacts are missing; build.sh is the only cargo
105 echo "mksystem: $IMG already exists (use --force to re-create)" 101# invocation, so an already-compiled tree costs nothing) --------------------
106 exit 0 102if [ ! -f "$KERNEL" ] || ! ls "$OUT_DIR"/*.efi >/dev/null 2>&1; then
103 "$SCRIPT_DIR/build.sh"
107fi 104fi
108 105
109# ---- build kernel ---- 106# ---- freshness stamp ------------------------------------------------------
110if [ ! -f "$KERNEL" ]; then 107newest=""
111 echo "mksystem: building kernel..." 108for f in "$OUT_DIR"/*.efi "$SEED_DIR"/*; do
112 cargo build --release --package rsdos --target "$TARGET" 109 [ -f "$f" ] || continue
113fi 110 if [ -z "$newest" ] || [ "$f" -nt "$newest" ]; then
114 111 newest="$f"
115# ---- build bootloader (chain mode only) ---- 112 fi
116if [ "$CHAIN" -eq 1 ] && [ ! -f "$BOOTLOADER" ]; then 113done
117 echo "mksystem: building bootloader..." 114if [ "$FORCE" -eq 0 ] && [ -f "$IMG" ] && { [ -z "$newest" ] || [ ! "$newest" -nt "$IMG" ]; }; then
118 "$SCRIPT_DIR/build-bootloader.sh" 115 echo "mksystem: up to date: $IMG (use --force to re-create)"
116 exit 0
119fi 117fi
120 118
121# ---- deploy kernel artifacts to esp/ (shared with the old layout) ---- 119# ---- create the FAT volume ------------------------------------------------
122mkdir -p esp/EFI/BOOT
123cp "$KERNEL" "$BZIMAGE"
124[ -f "$INITRD" ] || printf '' | gzip >"$INITRD"
125
126# ---- create the FAT volume ----
127rm -f "$IMG" 120rm -f "$IMG"
128SIZE_BLOCKS=$((SIZE_MB * 1024)) # mkfs.fat counts 1024-byte blocks 121SIZE_BLOCKS=$((SIZE_MB * 1024)) # mkfs.fat counts 1024-byte blocks
129echo "mksystem: creating $IMG (${SIZE_MB}M FAT32, label $LABEL)" 122echo "mksystem: creating $IMG (${SIZE_MB}M FAT32, label $LABEL)"
@@ -131,34 +124,47 @@ mkfs.fat -C -F 32 -n "$LABEL" "$IMG" "$SIZE_BLOCKS" >/dev/null
131 124
132echo "mksystem: staging system tree" 125echo "mksystem: staging system tree"
133mmd -i "$IMG" ::/EFI ::/EFI/BOOT ::/etc ::/bin ::/bin/cli ::/bin/gui 126mmd -i "$IMG" ::/EFI ::/EFI/BOOT ::/etc ::/bin ::/bin/cli ::/bin/gui
134mcopy -i "$IMG" "$BZIMAGE" ::/bzImage 127
128# The firmware entry point and rsbl's kernel path are the same file.
129mcopy -i "$IMG" "$KERNEL" ::/EFI/BOOT/BOOTX64.EFI
130mcopy -i "$IMG" "$KERNEL" ::/bzImage
131INITRD="$(mktemp -t rsdos-initrd.XXXXXX)"
132trap 'rm -f "$INITRD"' EXIT
133printf '' | gzip >"$INITRD"
135mcopy -i "$IMG" "$INITRD" ::/initramfs.cpio.gz 134mcopy -i "$IMG" "$INITRD" ::/initramfs.cpio.gz
136if [ "$CHAIN" -eq 1 ]; then 135echo " \\EFI\\BOOT\\BOOTX64.EFI \\bzImage \\initramfs.cpio.gz"
137 mcopy -i "$IMG" "$BOOTLOADER" ::/EFI/BOOT/BOOTX64.EFI 136
138 echo " \\EFI\\BOOT\\BOOTX64.EFI <- rsboot (full chain)" 137# External binaries: everything under bins/ was compiled into $OUT_DIR.
139else 138# Launch surface decides the directory (ADR 0006): GUI_BINS -> /bin/gui,
140 mcopy -i "$IMG" "$KERNEL" ::/EFI/BOOT/BOOTX64.EFI 139# everything else -> /bin/cli.
141 echo " \\EFI\\BOOT\\BOOTX64.EFI <- kernel (direct)" 140for src in "$OUT_DIR"/*.efi; do
142fi 141 [ -f "$src" ] || continue
143echo " \\bzImage \\initramfs.cpio.gz \\bin{\\cli,\\gui} \\etc" 142 name="$(basename "$src" .efi)"
143 [ "$name" = "rsdos" ] && continue # the kernel is not a /bin binary
144 case " $GUI_BINS " in
145 *" $name "*) kind="gui" ;;
146 *) kind="cli" ;;
147 esac
148 mcopy -i "$IMG" "$src" "::/bin/$kind/$name.efi"
149 printf ' \\bin\\%s\\%s.efi\n' "$kind" "$name"
150done
144 151
145# Seed files: motd lives in \etc, everything else at the volume root. 152# Seed files: motd lives in \etc, everything else at the volume root.
146SEED_DIR="$PROJECT_DIR/seed"
147if [ -d "$SEED_DIR" ]; then 153if [ -d "$SEED_DIR" ]; then
148 for f in "$SEED_DIR"/*; do 154 for f in "$SEED_DIR"/*; do
149 [ -f "$f" ] || continue 155 [ -f "$f" ] || continue
150 name="$(basename "$f")" 156 name="$(basename "$f")"
151 if [ "$name" = "motd.txt" ]; then 157 if [ "$name" = "motd.txt" ]; then
152 mcopy -i "$IMG" "$f" ::/etc/"$name" 158 mcopy -i "$IMG" "$f" ::/etc/"$name"
153 echo " \\etc\\$name" 159 printf ' \\etc\\%s\n' "$name"
154 else 160 else
155 mcopy -i "$IMG" "$f" ::/"$name" 161 mcopy -i "$IMG" "$f" ::/"$name"
156 echo " \\$name" 162 printf ' \\%s\n' "$name"
157 fi 163 fi
158 done 164 done
159fi 165fi
160 166
161# ---- optional GPT wrapper (real-hardware dd target) ---- 167# ---- optional GPT wrapper (real-hardware dd target) -----------------------
162if [ "$GPT" -eq 1 ]; then 168if [ "$GPT" -eq 1 ]; then
163 GPT_START=2048 # 1 MiB offset (standard alignment) 169 GPT_START=2048 # 1 MiB offset (standard alignment)
164 GPT_IMG="$(mktemp)" 170 GPT_IMG="$(mktemp)"
@@ -179,6 +185,6 @@ fi
179echo "" 185echo ""
180echo "=== Done: $IMG ===" 186echo "=== Done: $IMG ==="
181ls -lh "$IMG" 187ls -lh "$IMG"
182echo "Boot with: make run (or: make boot-image)" 188echo "Boot with: ./scripts/run.sh (or: make run)"
183[ "$GPT" -eq 0 ] && echo "USB dd tip: add --gpt for firmwares that refuse superfloppies" 189[ "$GPT" -eq 0 ] && echo "USB dd tip: add --gpt for firmwares that refuse superfloppies"
184exit 0 190exit 0