diff options
| author | salmonik <salmonik@tuta.io> | 2026-11-01 15:53:29 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-11-01 15:53:29 +0100 |
| commit | 7958276c9f0d230053520ba20f2a00f5ecda18e4 (patch) | |
| tree | 596f5f71ad597ed951bae98de818cb37f171a18d /CONTEXT.md | |
| parent | fs: /bin alias for the system volume (diff) | |
| download | rs-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 '')
| -rw-r--r-- | CONTEXT.md | 51 |
1 files changed, 40 insertions, 11 deletions
| @@ -135,7 +135,10 @@ The single dd-able FAT filesystem image the build produces: bootloader, | |||
| 135 | kernel, /bin, /etc and seed content on one volume. Imaging it onto a disk | 135 | kernel, /bin, /etc and seed content on one volume. Imaging it onto a disk |
| 136 | yields a complete installed system. Binaries live on the system image | 136 | yields a complete installed system. Binaries live on the system image |
| 137 | under /bin/cli and /bin/gui; the shell finds them by scanning mounted | 137 | under /bin/cli and /bin/gui; the shell finds them by scanning mounted |
| 138 | volumes — no volume is privileged. | 138 | volumes — no volume is privileged. For user-facing paths, /bin is a |
| 139 | transparent VFS alias: `ls /bin/cli` resolves to the first mounted | ||
| 140 | volume whose root has \bin, so nobody needs /disk/<UID>/bin/... (ADR | ||
| 141 | 0006). | ||
| 139 | 142 | ||
| 140 | ## Loader | 143 | ## Loader |
| 141 | 144 | ||
| @@ -194,7 +197,18 @@ reaped) without taking the kernel down. | |||
| 194 | 197 | ||
| 195 | Standalone project — no integration with the RNG initramfs build system. | 198 | Standalone project — no integration with the RNG initramfs build system. |
| 196 | Testing via QEMU with OVMF. The kernel PE binary is placed on a FAT | 199 | Testing via QEMU with OVMF. The kernel PE binary is placed on a FAT |
| 197 | image as `\bzImage` (matching rsbl's expected path). | 200 | image as `\bzImage` (matching rsbl's expected path) and also as |
| 201 | `\EFI\BOOT\BOOTX64.EFI` (what the firmware boots directly). | ||
| 202 | |||
| 203 | Two commands, compile + boot: | ||
| 204 | |||
| 205 | ```sh | ||
| 206 | ./scripts/build.sh # cargo build --workspace --target x86_64-unknown-uefi --release | ||
| 207 | ./scripts/run.sh # stage /tmp/system.img if stale, then boot QEMU | ||
| 208 | ``` | ||
| 209 | |||
| 210 | (`./scripts/run.sh` alone does both; `--headless`, `--debug`, `--monitor`, | ||
| 211 | `--fresh` as per its `--help`. `make` / `make run` are thin aliases.) | ||
| 198 | 212 | ||
| 199 | ## Versioning | 213 | ## Versioning |
| 200 | 214 | ||
| @@ -397,20 +411,35 @@ Workspace of four crates, all built for the `x86_64-unknown-uefi` target: | |||
| 397 | 411 | ||
| 398 | The whole disk workflow is scripted (no manual mkfs/mcopy): | 412 | The whole disk workflow is scripted (no manual mkfs/mcopy): |
| 399 | 413 | ||
| 400 | - `make disk` / `./scripts/mkdisk.sh` — create the FAT32 image with | 414 | - `./scripts/build.sh` — the single cargo invocation: kernel + |
| 401 | `mkfs.fat -C` (the flag that actually creates the file; plain | 415 | every `/bin` binary (`bins/*.efi`), release profile by default |
| 402 | `mkfs.fat` needs an existing file), label `RSDOS`, seed from | 416 | - `./scripts/mksystem.sh` / `make system` — assemble the dd-able |
| 403 | `seed/` via mtools; `--fresh` re-formats, `--size 128M` sizes it | 417 | FAT32 image (`mkfs.fat -C`, label `RSDOS`, seed from `seed/` via |
| 418 | mtools, stage `/bin/cli` + `/bin/gui`); rebuilt only when a | ||
| 419 | kernel/binary/seed file is newer than it, `--force` wipes runtime | ||
| 420 | data, `--gpt` wraps it for USB sticks | ||
| 421 | - `./scripts/run.sh` / `make run` — build + stage + boot QEMU | ||
| 422 | (`--headless`, `--debug` GDB stub, `--monitor` HMP socket, | ||
| 423 | `--fresh`, `--mem/--smp/--bios/--image`); the two-command flow is | ||
| 424 | `./scripts/build.sh && ./scripts/run.sh` | ||
| 404 | - `make inspect` — `mdir -i` listing of the image (mtools) | 425 | - `make inspect` — `mdir -i` listing of the image (mtools) |
| 405 | - `make test-disk` / `./scripts/test-disk.sh` — full automated round | 426 | - `make test` — all automated round trips; each boots QEMU headless, |
| 406 | trip: build → deploy → ensure image → boot QEMU headless → drive | 427 | drives the shell via `sendkeys.py` through the monitor and asserts |
| 428 | on the serial log | ||
| 429 | - `./scripts/tests/test-disk.sh` / `make test-disk` — full automated | ||
| 430 | round trip: build → stage → boot QEMU headless → drive | ||
| 407 | the shell via `sendkey` through the monitor (`ls /disk`, `mkdir`, | 431 | the shell via `sendkey` through the monitor (`ls /disk`, `mkdir`, |
| 408 | `echo WRITING`, `cat`, `poweroff`) → fsck-clean check → `mtype` verifies | 432 | `echo WRITING`, `cat`, `poweroff`) → fsck-clean check → `mtype` verifies |
| 409 | the written file survived poweroff | 433 | the written file survived poweroff |
| 410 | - `./scripts/sendkeys.py` — types lines into the guest via the QEMU | 434 | - `./scripts/tests/sendkeys.py` — types lines into the guest via the QEMU |
| 411 | monitor (`--sock`, US layout, named keys for punctuation; bare | 435 | monitor (`--sock`, US layout, named keys for punctuation; bare |
| 412 | `-`/`.`/`/` are not valid sendkey names) | 436 | `-`/`.`/`/` are not valid sendkey names) |
| 413 | 437 | ||
| 438 | Shared config and helpers (image path, OVMF, QEMU flags, `build_all`, | ||
| 439 | `stage_image`, `test_boot`, `wait_log`, `fail`) live in | ||
| 440 | `scripts/lib.sh` — every script sources it; there is exactly one | ||
| 441 | `cargo build` and one QEMU invocation shape in the tree. | ||
| 442 | |||
| 414 | ✅ **`klog` kernel log ring** — a RAM ring of the last 128 serial log | 443 | ✅ **`klog` kernel log ring** — a RAM ring of the last 128 serial log |
| 415 | lines (128 chars each, ~16 KB), fed by `serial_println!` (one choke | 444 | lines (128 chars each, ~16 KB), fed by `serial_println!` (one choke |
| 416 | point — every boot/low-level message captured for free). Sequence | 445 | point — every boot/low-level message captured for free). Sequence |
| @@ -806,7 +835,7 @@ Resolved this session: | |||
| 806 | see intermediate steps of the filtering. | 835 | see intermediate steps of the filtering. |
| 807 | - **`> >> < <<` are gone.** Keywords are the *only* redirection syntax; | 836 | - **`> >> < <<` are gone.** Keywords are the *only* redirection syntax; |
| 808 | `>` is now ordinary text (`echo a > b` prints `a > b`). Collateral: | 837 | `>` is now ordinary text (`echo a > b` prints `a > b`). Collateral: |
| 809 | `scripts/test-disk.sh` and the `help` text must be rewritten to the | 838 | `scripts/tests/test-disk.sh` and the `help` text must be rewritten to the |
| 810 | keyword syntax; the milestone bullets above describing `echo >`/`>>` | 839 | keyword syntax; the milestone bullets above describing `echo >`/`>>` |
| 811 | record the old behavior (superseded by these notes). | 840 | record the old behavior (superseded by these notes). |
| 812 | - **Quoting (C): `"..."` groups + literalizes; `\x` escapes one char.** | 841 | - **Quoting (C): `"..."` groups + literalizes; `\x` escapes one char.** |
| @@ -888,7 +917,7 @@ Everything above is now implemented in `shell/src/lib.rs`: | |||
| 888 | - **^D** — EOF everywhere, at the prompt it is a no-op (fresh | 917 | - **^D** — EOF everywhere, at the prompt it is a no-op (fresh |
| 889 | prompt); ^C keeps line-cancel / stream-abort; `poweroff`/`exit` | 918 | prompt); ^C keeps line-cancel / stream-abort; `poweroff`/`exit` |
| 890 | are the only shutdown verbs. | 919 | are the only shutdown verbs. |
| 891 | - **Collateral** — `help` text rewritten; `scripts/test-disk.sh` and | 920 | - **Collateral** — `help` text rewritten; `scripts/tests/test-disk.sh` and |
| 892 | the `sendkeys.py` docstring updated to keyword syntax. | 921 | the `sendkeys.py` docstring updated to keyword syntax. |
| 893 | 922 | ||
| 894 | Bugs found by QEMU verification and fixed: | 923 | Bugs found by QEMU verification and fixed: |
