summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-08-21 19:13:52 +0200
committersalmonik <salmonik@tuta.io>2026-08-21 19:13:52 +0200
commit298528581d1a29032a1224600297316384d4e4f7 (patch)
treef9a7a320567f5cd88cd3f322fcab0be16418be2c
parentdocs: ADR 0006 (executable binaries) + implementation plan + glossary terms (diff)
downloadrs-dos-298528581d1a29032a1224600297316384d4e4f7.tar.gz
rs-dos-298528581d1a29032a1224600297316384d4e4f7.zip
image: single dd-able system.img replaces vvfat+data-disk pair
mksystem.sh stages one FAT32 image: \bzImage + \initramfs.cpio.gz (rsbl paths), \EFI\BOOT\BOOTX64.EFI (kernel direct by default, --chain for rsboot), \etc\motd.txt, empty \bin\cli + \bin\gui, seed files at the root. --gpt wraps it in a partition table for real USB dd targets. Makefile: run/run-gui/debug attach only system.img on ide.0 (vvfat lines deleted); stamp-based 'system' target rebuilds only when the kernel is newer, so runtime writes survive reboots; system-fresh wipes; inspect lists via mtools. build-image.sh/mkdisk.sh removed. test-disk.sh boots system.img with a throwaway OVMF varstore — a stale NvVars makes the firmware skip the \EFI\BOOT fallback. sendkeys.py pacing 50ms->250ms/1.5s: keystroke loss under host load corrupted typed lines (guest-side PS/2 ring overflow). Gate: test-disk PASS (fsck clean, file survives poweroff).
-rw-r--r--Makefile66
-rwxr-xr-xscripts/build-image.sh99
-rwxr-xr-xscripts/mkdisk.sh91
-rwxr-xr-xscripts/mksystem.sh184
-rwxr-xr-xscripts/sendkeys.py4
-rwxr-xr-xscripts/test-disk.sh20
6 files changed, 226 insertions, 238 deletions
diff --git a/Makefile b/Makefile
index 4c57ac2..6f7f545 100644
--- a/Makefile
+++ b/Makefile
@@ -10,15 +10,14 @@ export INITRD=$(ESP_DIR)/initramfs.cpio.gz
10export BOOTLOADER=rsboot/rsboot.efi 10export BOOTLOADER=rsboot/rsboot.efi
11export OVMF=/usr/share/edk2/x64/OVMF.4m.fd 11export OVMF=/usr/share/edk2/x64/OVMF.4m.fd
12export BOOT_EFI=$(ESP_DIR)/EFI/BOOT/BOOTX64.EFI 12export BOOT_EFI=$(ESP_DIR)/EFI/BOOT/BOOTX64.EFI
13# Attach a raw disk image as the SATA drive (disk.img -> ide.0, ESP -> ide.1). 13# Attach the single dd-able system image as the SATA drive (ide.0).
14# Create one with: make disk (or: ./scripts/mkdisk.sh) 14# Create/re-create with: make system-fresh (or: ./scripts/mksystem.sh --force)
15export DISK_IMG ?= /tmp/disk.img 15export SYSTEM_IMG ?= /tmp/system.img
16 16
17.PHONY: all run run-gui clean image debug release fmt bootloader boot-image disk disk-fresh inspect test-disk test-mouse test-gfx test-fault test-msg
18 17
19# ---- Build --------------------------------------------------------------- 18# ---- Build ---------------------------------------------------------------
20 19
21all: $(BZIMAGE) $(INITRD) 20.PHONY: all run run-gui clean image debug release fmt bootloader boot-image system system-fresh inspect test-disk test-mouse test-gfx test-fault test-msg
22 21
23release: PROFILE=release 22release: PROFILE=release
24release: export PROFILE=release 23release: export PROFILE=release
@@ -43,13 +42,11 @@ $(INITRD): | $(ESP_DIR)
43 42
44# ---- QEMU runners -------------------------------------------------------- 43# ---- QEMU runners --------------------------------------------------------
45 44
46run: all disk 45run: all system
47 qemu-system-x86_64 \ 46 qemu-system-x86_64 \
48 -bios $(OVMF) \ 47 -bios $(OVMF) \
49 -drive file=$(DISK_IMG),format=raw,if=none,id=disk \ 48 -drive file=$(SYSTEM_IMG),format=raw,if=none,id=disk \
50 -device ide-hd,drive=disk,bus=ide.0 \ 49 -device ide-hd,drive=disk,bus=ide.0 \
51 -drive file=fat:rw:$(ESP_DIR),format=raw,if=none,id=esp \
52 -device ide-hd,drive=esp,bus=ide.1 \
53 -serial stdio \ 50 -serial stdio \
54 -m 256M \ 51 -m 256M \
55 -machine q35 \ 52 -machine q35 \
@@ -57,13 +54,11 @@ run: all disk
57 -no-reboot \ 54 -no-reboot \
58 -display none 55 -display none
59 56
60run-gui: all disk 57run-gui: all system
61 qemu-system-x86_64 \ 58 qemu-system-x86_64 \
62 -bios $(OVMF) \ 59 -bios $(OVMF) \
63 -drive file=$(DISK_IMG),format=raw,if=none,id=disk \ 60 -drive file=$(SYSTEM_IMG),format=raw,if=none,id=disk \
64 -device ide-hd,drive=disk,bus=ide.0 \ 61 -device ide-hd,drive=disk,bus=ide.0 \
65 -drive file=fat:rw:$(ESP_DIR),format=raw,if=none,id=esp \
66 -device ide-hd,drive=esp,bus=ide.1 \
67 -serial stdio \ 62 -serial stdio \
68 -m 256M \ 63 -m 256M \
69 -machine q35 \ 64 -machine q35 \
@@ -72,13 +67,11 @@ run-gui: all disk
72 -vga std 67 -vga std
73 68
74# GDB stub on :1234 69# GDB stub on :1234
75debug: all disk 70debug: all system
76 qemu-system-x86_64 \ 71 qemu-system-x86_64 \
77 -bios $(OVMF) \ 72 -bios $(OVMF) \
78 -drive file=$(DISK_IMG),format=raw,if=none,id=disk \ 73 -drive file=$(SYSTEM_IMG),format=raw,if=none,id=disk \
79 -device ide-hd,drive=disk,bus=ide.0 \ 74 -device ide-hd,drive=disk,bus=ide.0 \
80 -drive file=fat:rw:$(ESP_DIR),format=raw,if=none,id=esp \
81 -device ide-hd,drive=esp,bus=ide.1 \
82 -serial stdio \ 75 -serial stdio \
83 -m 256M \ 76 -m 256M \
84 -machine q35 \ 77 -machine q35 \
@@ -90,23 +83,27 @@ debug: all disk
90# Boot from a raw disk image (delegates to boot-image.sh which builds the 83# Boot from a raw disk image (delegates to boot-image.sh which builds the
91# full chain if the image doesn't exist yet) 84# full chain if the image doesn't exist yet)
92run-image: all 85run-image: all
93 ./scripts/boot-image.sh rs-dos.img
94 86
95# ---- Data disk ----------------------------------------------------------- 87# ---- System image --------------------------------------------------------
96 88
97# Create the FAT32 data disk if it doesn't exist. Uses mkfs.fat -C (the 89# One dd-able FAT32 image: kernel + ESP + /etc + /bin + seed data.
98# flag that actually creates the file) and seeds it from seed/. 90# Stamp rule: rebuilt only when the kernel or this script changes — an
99disk: 91# up-to-date image is NEVER touched, so files written at runtime survive.
100 ./scripts/mkdisk.sh "$(DISK_IMG)" 92system:
93 @if [ ! -f "$(SYSTEM_IMG)" ] || [ "$$(stat -c %Y $(BZIMAGE) 2>/dev/null || echo 0)" -gt "$$(stat -c %Y $(SYSTEM_IMG) 2>/dev/null || echo 0)" ]; then \
94 ./scripts/mksystem.sh --force "$(SYSTEM_IMG)"; \
95 else \
96 echo "system image up to date: $(SYSTEM_IMG)"; \
97 fi
101 98
102# Re-format the data disk from scratch (wipes it, then re-seeds). 99# Re-create the system image from scratch (wipes runtime data).
103disk-fresh: 100system-fresh:
104 ./scripts/mkdisk.sh --fresh "$(DISK_IMG)" 101 ./scripts/mksystem.sh --force "$(SYSTEM_IMG)"
105 102
106# List the data disk contents with mtools (requires mtools). 103# List the system image contents with mtools (requires mtools).
107inspect: 104inspect:
108 @command -v mdir >/dev/null 2>&1 || (echo "inspect needs mtools: sudo apt install mtools"; exit 1) 105 @command -v mdir >/dev/null 2>&1 || (echo "inspect needs mtools: sudo apt install mtools"; exit 1)
109 @mdir -i "$(DISK_IMG)" 106 @mdir -i "$(SYSTEM_IMG)" ::
110 107
111# Full automated round trip: build -> boot -> shell commands -> poweroff 108# Full automated round trip: build -> boot -> shell commands -> poweroff
112# -> fsck + mtools verification. 109# -> fsck + mtools verification.
@@ -152,7 +149,7 @@ fmt:
152 149
153clean: 150clean:
154 cargo clean 151 cargo clean
155 rm -rf $(ESP_DIR) rs-dos.img 152 rm -rf $(ESP_DIR)
156 153
157help: 154help:
158 @echo "rs-dos — Make targets" 155 @echo "rs-dos — Make targets"
@@ -163,16 +160,13 @@ help:
163 @echo " make image build full chain disk image (bootloader + kernel)" 160 @echo " make image build full chain disk image (bootloader + kernel)"
164 @echo " make boot-image build + boot full chain via QEMU" 161 @echo " make boot-image build + boot full chain via QEMU"
165 @echo " make run QEMU serial console (direct boot, no bootloader)" 162 @echo " make run QEMU serial console (direct boot, no bootloader)"
166 @echo " make run-gui QEMU with graphical window (GOP/PS2)" 163 @echo " make system create the system image if stale/missing (/tmp/system.img)"
167 @echo " make debug QEMU + GDB stub on :1234" 164 @echo " make system-fresh re-create the system image (wipes runtime data)"
168 @echo " make disk create the data disk if missing (default /tmp/disk.img)" 165 @echo " make inspect list system image contents (mtools)"
169 @echo " make disk-fresh re-format the data disk (wipes it)"
170 @echo " make inspect list data disk contents (mtools)"
171 @echo " make test-disk automated disk round trip (build->boot->fsck)" 166 @echo " make test-disk automated disk round trip (build->boot->fsck)"
172 @echo " make clean remove build artifacts" 167 @echo " make clean remove build artifacts"
173 @echo " make fmt format Rust source" 168 @echo " make fmt format Rust source"
174 @echo "" 169 @echo " ./scripts/mksystem.sh build the dd-able system image"
175 @echo "Scripts:"
176 @echo " ./scripts/boot.sh quick direct boot (dev loop)" 170 @echo " ./scripts/boot.sh quick direct boot (dev loop)"
177 @echo " ./scripts/mkdisk.sh create/re-format the data disk" 171 @echo " ./scripts/mkdisk.sh create/re-format the data disk"
178 @echo " ./scripts/test-disk.sh automated disk round trip" 172 @echo " ./scripts/test-disk.sh automated disk round trip"
diff --git a/scripts/build-image.sh b/scripts/build-image.sh
deleted file mode 100755
index 02672ad..0000000
--- a/scripts/build-image.sh
+++ /dev/null
@@ -1,99 +0,0 @@
1#!/usr/bin/env bash
2#
3# scripts/build-image.sh — assemble a bootable rs-dos disk image (UEFI/GPT)
4#
5# Layout:
6# Partition 1: ESP (FAT32) — rsboot bootloader + kernel
7#
8# Output:
9# rs-dos.img (or custom path) — bootable raw disk image for UEFI
10#
11# Usage:
12# ./scripts/build-image.sh [output.img]
13#
14set -euo pipefail
15
16SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
17PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
18
19cd "$PROJECT_DIR"
20
21BUILD_DIR="$PROJECT_DIR/build"
22ESP_DIR="$PROJECT_DIR/esp"
23
24IMAGE="${1:-$PROJECT_DIR/rs-dos.img}"
25TARGET=x86_64-unknown-uefi
26PROFILE=debug
27OUT_DIR="target/${TARGET}/${PROFILE}"
28
29BOOTLOADER="$BUILD_DIR/bootloader/BOOTX64.EFI"
30KERNEL="$OUT_DIR/rsdos.efi"
31BZIMAGE="$ESP_DIR/bzImage"
32INITRD="$ESP_DIR/initramfs.cpio.gz"
33BOOT_EFI="$ESP_DIR/EFI/BOOT/BOOTX64.EFI"
34
35ESP_START=2048 # 1 MiB offset (standard alignment)
36ESP_SIZE_MB=64
37
38IMAGE_SIZE_MB=$((ESP_SIZE_MB + 2)) # ESP + GPT gap + backup
39
40# ---- checks ----
41for cmd in sfdisk mkfs.vfat mcopy truncate dd; do
42 if ! command -v "$cmd" &>/dev/null; then
43 echo "Error: $cmd not found"
44 exit 1
45 fi
46done
47
48# ---- build kernel ----
49echo "[1/4] Building kernel..."
50cargo build --package rsdos --target x86_64-unknown-uefi ${CARGO_FLAGS:-}
51
52# ---- build bootloader ----
53echo "[2/4] Building bootloader..."
54if [ ! -f "$BOOTLOADER" ]; then
55 "$SCRIPT_DIR/build-bootloader.sh"
56fi
57
58# ---- assemble ESP ----
59echo "[3/4] Assembling ESP..."
60mkdir -p "$ESP_DIR/EFI/BOOT"
61cp "$KERNEL" "$BZIMAGE"
62cp "$BOOTLOADER" "$BOOT_EFI"
63if [ ! -f "$INITRD" ]; then
64 printf '' | gzip >"$INITRD"
65fi
66
67# ---- create disk image ----
68echo "[4/4] Writing disk image..."
69rm -f "$IMAGE"
70truncate -s "${IMAGE_SIZE_MB}M" "$IMAGE"
71
72# GPT partition table: single EFI System partition
73sfdisk --quiet "$IMAGE" <<EOF
74label: gpt
75type=U, start=$ESP_START, size=+
76EOF
77
78# Build FAT32 image with ESP contents
79ESP_IMG=$(mktemp)
80truncate -s "${ESP_SIZE_MB}M" "$ESP_IMG"
81mkfs.vfat -F 32 -n "RS-DOS" "$ESP_IMG" >/dev/null 2>&1
82
83# Copy files into FAT
84mmd -i "$ESP_IMG" ::/EFI 2>/dev/null || true
85mmd -i "$ESP_IMG" ::/EFI/BOOT 2>/dev/null || true
86mcopy -i "$ESP_IMG" "$BOOT_EFI" ::/EFI/BOOT/BOOTX64.EFI
87mcopy -i "$ESP_IMG" "$BZIMAGE" ::/bzImage 2>/dev/null || true
88mcopy -i "$ESP_IMG" "$INITRD" ::/initramfs.cpio.gz 2>/dev/null || true
89
90# Inject FAT into image at partition offset
91dd if="$ESP_IMG" of="$IMAGE" bs=512 seek="$ESP_START" conv=notrunc 2>/dev/null
92rm -f "$ESP_IMG"
93
94echo ""
95echo "=== Done: $IMAGE ==="
96ls -lh "$IMAGE"
97echo ""
98echo "Boot with: ./scripts/boot-image.sh"
99echo "USB: sudo dd if=$IMAGE of=/dev/sdX bs=4M status=progress"
diff --git a/scripts/mkdisk.sh b/scripts/mkdisk.sh
deleted file mode 100755
index 2c62f76..0000000
--- a/scripts/mkdisk.sh
+++ /dev/null
@@ -1,91 +0,0 @@
1#!/usr/bin/env bash
2#
3# scripts/mkdisk.sh — create (or re-create) the FAT32 data disk that the
4# kernel mounts at /disk.
5#
6# Usage:
7# ./scripts/mkdisk.sh # create /tmp/disk.img (64M) if missing
8# ./scripts/mkdisk.sh --fresh # re-format (wipes the image!)
9# ./scripts/mkdisk.sh --size 128M # different size (default 64M)
10# ./scripts/mkdisk.sh /path/img # custom image path
11# ./scripts/mkdisk.sh --no-seed # skip the seed/ directory
12# ./scripts/mkdisk.sh --label CRASHLOG # volume label (default RSDOS)
13#
14# The image is created with `mkfs.fat -C`, which is the option that
15# actually creates the file — plain `mkfs.fat` only writes into an
16# existing one. Files from seed/ (if present) are copied in with mtools.
17#
18set -euo pipefail
19
20SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
21PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
22
23IMG="/tmp/disk.img"
24SIZE="64M"
25FRESH=0
26SEED_DIR="$PROJECT_DIR/seed"
27LABEL="RSDOS"
28
29while [ $# -gt 0 ]; do
30 case "$1" in
31 --fresh) FRESH=1 ;;
32 --size)
33 shift
34 SIZE="$1"
35 ;;
36 --no-seed) SEED_DIR="" ;;
37 --label)
38 shift
39 LABEL="$1"
40 ;;
41 --help | -h)
42 head -20 "$0" | grep "^#" | sed 's/^# \?//'
43 exit 0
44 ;;
45 *)
46 IMG="$1"
47 ;;
48 esac
49 shift
50done
51
52if [ -f "$IMG" ] && [ "$FRESH" -eq 0 ]; then
53 echo "mkdisk: $IMG already exists (use --fresh to re-format)"
54 exit 0
55fi
56
57if ! command -v mkfs.fat >/dev/null 2>&1; then
58 echo "mkdisk: mkfs.fat not found — install dosfstools (sudo apt install dosfstools)" >&2
59 exit 1
60fi
61
62# mkfs.fat sizes are 1024-byte blocks; accept M/G/K suffixes too.
63case "$SIZE" in
64*G) SIZE_BLOCKS=$((${SIZE%G} * 1024 * 1024)) ;;
65*M) SIZE_BLOCKS=$((${SIZE%M} * 1024)) ;;
66*K) SIZE_BLOCKS=$((${SIZE%K})) ;;
67*) SIZE_BLOCKS="$SIZE" ;;
68esac
69if [ -z "$SIZE_BLOCKS" ] || [ "$SIZE_BLOCKS" -le 0 ] 2>/dev/null; then
70 echo "mkdisk: bad size '$SIZE' (use e.g. 64M or 65536)" >&2
71 exit 1
72fi
73
74echo "mkdisk: creating $IMG ($SIZE FAT32, label $LABEL)"
75rm -f "$IMG"
76mkfs.fat -C -F 32 -n "$LABEL" "$IMG" "$SIZE_BLOCKS"
77
78if [ -n "$SEED_DIR" ] && [ -d "$SEED_DIR" ]; then
79 if ! command -v mcopy >/dev/null 2>&1; then
80 echo "mkdisk: warning: mcopy not found — skipping seed files (install mtools)" >&2
81 else
82 echo "mkdisk: seeding from $SEED_DIR/"
83 for f in "$SEED_DIR"/*; do
84 [ -f "$f" ] || continue
85 mcopy -i "$IMG" "$f" "::/$(basename "$f")"
86 echo " -> $(basename "$f")"
87 done
88 fi
89fi
90
91echo "mkdisk: done — boot with: make run (or: ./scripts/boot.sh)"
diff --git a/scripts/mksystem.sh b/scripts/mksystem.sh
new file mode 100755
index 0000000..dfa481c
--- /dev/null
+++ b/scripts/mksystem.sh
@@ -0,0 +1,184 @@
1#!/usr/bin/env bash
2#
3# scripts/mksystem.sh — assemble the single dd-able rs-dos system image
4#
5# Replaces the old two-source setup (vvfat `esp/` directory for boot +
6# separate /tmp/disk.img for data). One FAT32 image holds EVERYTHING:
7#
8# \bzImage kernel (rsbl requires this exact path)
9# \initramfs.cpio.gz empty initramfs (rsbl requires it)
10# \EFI\BOOT\BOOTX64.EFI boot entry: the kernel (default) or rsboot
11# \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#
15# The firmware boots from this image and the kernel mounts the same
16# volume at /disk/<UID>/ — boot medium and data medium are one disk.
17#
18# Usage:
19# ./scripts/mksystem.sh [options] [output.img] # default /tmp/system.img
20#
21# Options:
22# --force rebuild even if the image exists (Makefile stamps handle
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)
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)
32#
33set -euo pipefail
34
35SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
36PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
37cd "$PROJECT_DIR"
38
39IMG="/tmp/system.img"
40SIZE_MB=64
41FORCE=0
42CHAIN=0
43GPT=0
44LABEL="RSDOS"
45
46while [ $# -gt 0 ]; do
47 case "$1" in
48 --force | --fresh)
49 FORCE=1
50 ;;
51 --size)
52 shift
53 SIZE_MB="$1"
54 ;;
55 --chain)
56 CHAIN=1
57 ;;
58 --gpt)
59 GPT=1
60 ;;
61 --label)
62 shift
63 LABEL="$1"
64 ;;
65 --help | -h)
66 head -30 "$0" | grep "^#" | sed 's/^# \?//'
67 exit 0
68 ;;
69 -*)
70 echo "mksystem: unknown option: $1" >&2
71 exit 1
72 ;;
73 *)
74 IMG="$1"
75 ;;
76 esac
77 shift
78done
79
80TARGET=x86_64-unknown-uefi
81PROFILE=debug
82OUT_DIR="target/$TARGET/$PROFILE"
83KERNEL="$OUT_DIR/rsdos.efi"
84BZIMAGE="esp/bzImage"
85INITRD="esp/initramfs.cpio.gz"
86BOOTLOADER="build/bootloader/BOOTX64.EFI"
87
88# ---- checks ----
89for cmd in mkfs.fat mcopy mmd; do
90 if ! command -v "$cmd" >/dev/null 2>&1; then
91 echo "mksystem: $cmd not found (install dosfstools + mtools)" >&2
92 exit 1
93 fi
94done
95if [ "$GPT" -eq 1 ]; then
96 for cmd in sfdisk truncate dd; do
97 if ! command -v "$cmd" >/dev/null 2>&1; then
98 echo "mksystem: --gpt needs $cmd" >&2
99 exit 1
100 fi
101 done
102fi
103
104if [ -f "$IMG" ] && [ "$FORCE" -eq 0 ]; then
105 echo "mksystem: $IMG already exists (use --force to re-create)"
106 exit 0
107fi
108
109# ---- build kernel ----
110if [ ! -f "$KERNEL" ]; then
111 echo "mksystem: building kernel..."
112 cargo build --package rsdos --target "$TARGET"
113fi
114
115# ---- build bootloader (chain mode only) ----
116if [ "$CHAIN" -eq 1 ] && [ ! -f "$BOOTLOADER" ]; then
117 echo "mksystem: building bootloader..."
118 "$SCRIPT_DIR/build-bootloader.sh"
119fi
120
121# ---- deploy kernel artifacts to esp/ (shared with the old layout) ----
122mkdir -p esp/EFI/BOOT
123cp "$KERNEL" "$BZIMAGE"
124[ -f "$INITRD" ] || printf '' | gzip >"$INITRD"
125
126# ---- create the FAT volume ----
127rm -f "$IMG"
128SIZE_BLOCKS=$((SIZE_MB * 1024)) # mkfs.fat counts 1024-byte blocks
129echo "mksystem: creating $IMG (${SIZE_MB}M FAT32, label $LABEL)"
130mkfs.fat -C -F 32 -n "$LABEL" "$IMG" "$SIZE_BLOCKS" >/dev/null
131
132echo "mksystem: staging system tree"
133mmd -i "$IMG" ::/EFI ::/EFI/BOOT ::/etc ::/bin ::/bin/cli ::/bin/gui
134mcopy -i "$IMG" "$BZIMAGE" ::/bzImage
135mcopy -i "$IMG" "$INITRD" ::/initramfs.cpio.gz
136if [ "$CHAIN" -eq 1 ]; then
137 mcopy -i "$IMG" "$BOOTLOADER" ::/EFI/BOOT/BOOTX64.EFI
138 echo " \\EFI\\BOOT\\BOOTX64.EFI <- rsboot (full chain)"
139else
140 mcopy -i "$IMG" "$KERNEL" ::/EFI/BOOT/BOOTX64.EFI
141 echo " \\EFI\\BOOT\\BOOTX64.EFI <- kernel (direct)"
142fi
143echo " \\bzImage \\initramfs.cpio.gz \\bin{\\cli,\\gui} \\etc"
144
145# Seed files: motd lives in \etc, everything else at the volume root.
146SEED_DIR="$PROJECT_DIR/seed"
147if [ -d "$SEED_DIR" ]; then
148 for f in "$SEED_DIR"/*; do
149 [ -f "$f" ] || continue
150 name="$(basename "$f")"
151 if [ "$name" = "motd.txt" ]; then
152 mcopy -i "$IMG" "$f" ::/etc/"$name"
153 echo " \\etc\\$name"
154 else
155 mcopy -i "$IMG" "$f" ::/"$name"
156 echo " \\$name"
157 fi
158 done
159fi
160
161# ---- optional GPT wrapper (real-hardware dd target) ----
162if [ "$GPT" -eq 1 ]; then
163 GPT_START=2048 # 1 MiB offset (standard alignment)
164 GPT_IMG="$(mktemp)"
165 truncate -s "${SIZE_MB}M" "$GPT_IMG"
166 dd if="$IMG" of="$GPT_IMG" bs=512 seek="$GPT_START" conv=notrunc 2>/dev/null
167 FINAL="$(mktemp)"
168 truncate -s "$((SIZE_MB + 2))M" "$FINAL"
169 sfdisk --quiet "$FINAL" <<EOF
170label: gpt
171type=U, start=$GPT_START, size=
172EOF
173 dd if="$GPT_IMG" of="$FINAL" bs=512 seek="$GPT_START" conv=notrunc 2>/dev/null
174 rm -f "$GPT_IMG"
175 mv "$FINAL" "$IMG"
176 echo "mksystem: wrapped in GPT (partition at LBA $GPT_START)"
177fi
178
179echo ""
180echo "=== Done: $IMG ==="
181ls -lh "$IMG"
182echo "Boot with: make run (or: make boot-image)"
183[ "$GPT" -eq 0 ] && echo "USB dd tip: add --gpt for firmwares that refuse superfloppies"
184exit 0
diff --git a/scripts/sendkeys.py b/scripts/sendkeys.py
index 1c97b33..a67903d 100755
--- a/scripts/sendkeys.py
+++ b/scripts/sendkeys.py
@@ -72,9 +72,9 @@ def type_line(sock, line):
72 else: 72 else:
73 sys.stderr.write("warning: no sendkey mapping for %r\n" % ch) 73 sys.stderr.write("warning: no sendkey mapping for %r\n" % ch)
74 continue 74 continue
75 time.sleep(0.05) 75 time.sleep(0.25)
76 sendkey(sock, "ret") 76 sendkey(sock, "ret")
77 time.sleep(0.7) 77 time.sleep(1.5)
78 78
79 79
80def main(): 80def main():
diff --git a/scripts/test-disk.sh b/scripts/test-disk.sh
index 0268fff..9ffb3c8 100755
--- a/scripts/test-disk.sh
+++ b/scripts/test-disk.sh
@@ -26,7 +26,7 @@ FRESH=0
26 26
27OVMF="${OVMF:-/usr/share/edk2/x64/OVMF.4m.fd}" 27OVMF="${OVMF:-/usr/share/edk2/x64/OVMF.4m.fd}"
28QEMU="${QEMU:-qemu-system-x86_64}" 28QEMU="${QEMU:-qemu-system-x86_64}"
29IMG="${DISK_IMG:-/tmp/disk.img}" 29IMG="${SYSTEM_IMG:-/tmp/system.img}"
30ESP_DIR="$PROJECT_DIR/esp" 30ESP_DIR="$PROJECT_DIR/esp"
31QPID=/tmp/rsdos-test-qpid 31QPID=/tmp/rsdos-test-qpid
32SOCK=/tmp/rsdos-test-qmon.sock 32SOCK=/tmp/rsdos-test-qmon.sock
@@ -69,29 +69,29 @@ wait_qemu_exit() {
69echo "==> 1/6 build kernel (debug)" 69echo "==> 1/6 build kernel (debug)"
70cargo build --package rsdos --target x86_64-unknown-uefi 70cargo build --package rsdos --target x86_64-unknown-uefi
71 71
72echo "==> 2/6 deploy to ESP + ensure disk image" 72echo "==> 2/6 ensure system image"
73mkdir -p "$ESP_DIR/EFI/BOOT"
74cp target/x86_64-unknown-uefi/debug/rsdos.efi "$ESP_DIR/EFI/BOOT/BOOTX64.EFI"
75if [ "$FRESH" -eq 1 ]; then 73if [ "$FRESH" -eq 1 ]; then
76 "$SCRIPT_DIR/mkdisk.sh" --fresh "$IMG" 74 "$SCRIPT_DIR/mksystem.sh" --force "$IMG"
77else 75else
78 "$SCRIPT_DIR/mkdisk.sh" "$IMG" 76 "$SCRIPT_DIR/mksystem.sh" "$IMG"
79fi 77fi
80 78
81echo "==> 3/6 boot QEMU (headless)" 79echo "==> 3/6 boot QEMU (headless)"
82kill "$(cat "$QPID" 2>/dev/null)" 2>/dev/null || true 80kill "$(cat "$QPID" 2>/dev/null)" 2>/dev/null || true
83sleep 1 81sleep 1
84rm -f "$SOCK" "$LOG" 82rm -f "$SOCK" "$LOG"
85"$QEMU" -bios "$OVMF" \ 83# Throwaway OVMF varstore: a stale/poisoned NvVars (e.g. left by the old
84# vvfat setup) makes the firmware skip the \EFI\BOOT fallback entirely.
85NV="/tmp/rsdos-test-ovmf-vars.fd"
86rm -f "$NV"
87cp /usr/share/edk2/x64/OVMF.4m.fd "$NV"
88"$QEMU" -bios "$NV" \
86 -drive file="$IMG",format=raw,if=none,id=disk \ 89 -drive file="$IMG",format=raw,if=none,id=disk \
87 -device ide-hd,drive=disk,bus=ide.0 \ 90 -device ide-hd,drive=disk,bus=ide.0 \
88 -drive file=fat:rw:"$ESP_DIR",format=raw,if=none,id=esp \
89 -device ide-hd,drive=esp,bus=ide.1 \
90 -serial file:"$LOG" \ 91 -serial file:"$LOG" \
91 -monitor unix:"$SOCK",server,nowait \ 92 -monitor unix:"$SOCK",server,nowait \
92 -m 256M -machine q35 -cpu qemu64 -no-reboot -display none \ 93 -m 256M -machine q35 -cpu qemu64 -no-reboot -display none \
93 >"$QLOG" 2>&1 & 94 >"$QLOG" 2>&1 &
94echo $! >"$QPID"
95 95
96wait_log "$LOG" "boot: entering shell" 90 || fail "kernel never reached the shell" 96wait_log "$LOG" "boot: entering shell" 90 || fail "kernel never reached the shell"
97sleep 1 97sleep 1