<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rs-dos/scripts, branch qemu</title>
<subtitle>Simple, kernel-only, 64bit OS, early stage.
</subtitle>
<id>https://git.2137697.xyz/rs-dos/atom?h=qemu</id>
<link rel='self' href='https://git.2137697.xyz/rs-dos/atom?h=qemu'/>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/'/>
<updated>2026-11-01T15:33:09Z</updated>
<entry>
<title>scripts: add test-usb; fix duplicate -bios in the test harness</title>
<updated>2026-11-01T15:33:09Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-01T15:33:09Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=363e24bcd18a28948f63fa78ac8a4eaa8784fe59'/>
<id>urn:sha1:363e24bcd18a28948f63fa78ac8a4eaa8784fe59</id>
<content type='text'>
- test-usb boots an EHCI and an xHCI controller with a mouse + keyboard and
  asserts enumeration, report decoding, and input reaching the shell.  The
  EHCI case asserts one key end-to-end (QEMU's EHCI model delivers only the
  first report through root-port split transactions); the xHCI case asserts a
  whole typed command.
- lib.sh: qemu_args() already supplies -bios, so the fresh OVMF varstore copy
  was silently overridden by the system firmware.  Pass the copy last (QEMU
  honours the last -bios) so tests really boot clean NVRAM.
- DEBUG_NOTES: document why USB never worked on the OptiPlex (EHCI shipped
  with DEBUG_MATRIX enabled, no RMH/hub support, only the first controller,
  no boot protocol, unbounded DMA), the success/failure log to look for on
  hardware, and the QEMU coverage limits.
- Makefile: add test-usb and include it in `make test`.
</content>
</entry>
<entry>
<title>scripts: rebuild the dev loop around build.sh/run.sh</title>
<updated>2026-11-01T14:53:29Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-11-01T14:53:29Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=7958276c9f0d230053520ba20f2a00f5ecda18e4'/>
<id>urn:sha1:7958276c9f0d230053520ba20f2a00f5ecda18e4</id>
<content type='text'>
`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 -&gt; test-disk, test-gfx, test-mouse,
test-msg, test-fault all PASS.
</content>
</entry>
<entry>
<title>build: default profile is release (debug too slow for dev loop)</title>
<updated>2026-08-27T16:39:29Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-27T16:39:29Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=277218fe1ba1e3616bd147c9d9abecfc56b9957f'/>
<id>urn:sha1:277218fe1ba1e3616bd147c9d9abecfc56b9957f</id>
<content type='text'>
Makefile: PROFILE=release, CARGO_FLAGS=--release; make release target
kept as no-op (now default).  boot.sh: PROFILE=release default;
--debug flag opt-in.  mksystem.sh: PROFILE=release default.
test-disk/fault/gfx/mouse/msg: all use --release.
All scripts syntax-checked.
</content>
</entry>
<entry>
<title>scripts: migrate all QEMU/test scripts to single system image</title>
<updated>2026-08-27T16:35:59Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-27T16:35:59Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=acd0fe1bc38746f36fff24a7497041e5c5010977'/>
<id>urn:sha1:acd0fe1bc38746f36fff24a7497041e5c5010977</id>
<content type='text'>
boot.sh: replace esp/ + DISK_IMG with single SYSTEM_IMG on ide.0
(hooks into mksystem.sh --force for auto-staging).

boot-image.sh: delegate to mksystem.sh --chain (build-image.sh deleted).

build-image-release.sh: delegate to mksystem.sh --chain --gpt.

qemu.sh: flexible launcher uses SYSTEM_IMG; --chain flag for
full-chain build.

test-disk.sh: drop ESP_DIR (mksystem.sh stages everything).

test-fault.sh: boot system.img on ide.0 + CRASHLOG stick on ide.1;
replace deleted mkdisk.sh with inline mkfs.fat.

test-gfx.sh: system.img on ide.0, stage via mksystem.sh.

test-mouse.sh: system.img on ide.0, stage via mksystem.sh.

test-msg.sh: system.img on ide.0, stage via mksystem.sh.

Makefile: remove stale build-image.sh/mkdisk.sh references from help;
image target delegates to mksystem.sh --chain.

All scripts syntax-checked (bash -n). build-image.sh and mkdisk.sh
no longer referenced anywhere.
</content>
</entry>
<entry>
<title>input: total keyboard routing + per-terminal discipline (ADR 0006 ph1)</title>
<updated>2026-08-21T18:13:59Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-21T18:13:59Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=2f4cf666c0c7bd224932fa48973e7334360c1de3'/>
<id>urn:sha1:2f4cf666c0c7bd224932fa48973e7334360c1de3</id>
<content type='text'>
wm: FOCUSED is now a plain window id — window 0 (home terminal) is an
ordinary focusable window in the z-order.  The CONSOLE sentinel
(usize::MAX) and the focused()==0 special cases are gone; focus_console()
is an alias for focus(0).  Desktop clicks focus window 0.  The WM input
pump routes every key unconditionally: IRQ ring -&gt; pump -&gt; focused
window's owner; nothing polls the scancode rings directly any more.

tty: read_line() reads from the calling task's message queue (the old
global-ring read_line and the duplicate read_line_from_queue are merged);
raw mode (read_byte/try_read_byte) consumes the same queue;
interrupt_pressed drains the queue instead of the ring.

shell: task 0 owns home terminal window 0 and blocks on its queue like a
windowed shell; cat/hexdump stdin paths pass the home terminal handle.

sched: watchdog comments updated (shell parks on recv_blocking).

Verified in QEMU: F1 spawns terminals, F2 cycles focus home-&gt;term1-&gt;
term2, keystrokes land only in the focused window, ^C cancels a line,
edit runs raw over the queue and exits to a working prompt; test-disk
regression PASS.
</content>
</entry>
<entry>
<title>image: single dd-able system.img replaces vvfat+data-disk pair</title>
<updated>2026-08-21T17:13:52Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-21T17:13:52Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=298528581d1a29032a1224600297316384d4e4f7'/>
<id>urn:sha1:298528581d1a29032a1224600297316384d4e4f7</id>
<content type='text'>
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-&gt;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).
</content>
</entry>
<entry>
<title>v0.5.5: on-screen boot markers for disk/fs stage</title>
<updated>2026-08-02T13:34:45Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-02T13:34:45Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=c6827451bce4cd3774a9e066a4a1bf51bb83592e'/>
<id>urn:sha1:c6827451bce4cd3774a9e066a4a1bf51bb83592e</id>
<content type='text'>
Real hardware has no serial console, and the ahci/fat/fs boot
diagnostics were serial-only — a silent fs failure left the user with
no way to see where boot stopped.  Add boot_marker lines for the AHCI
disk count, FAT volume count, and the VFS tree + fs self-test result.
</content>
</entry>
<entry>
<title>v0.5.5: crash reports go to a dedicated CRASHLOG USB stick</title>
<updated>2026-08-02T13:21:34Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-02T13:21:34Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=c7d92071e1dd11c45999457b16554b4abaa73b28'/>
<id>urn:sha1:c7d92071e1dd11c45999457b16554b4abaa73b28</id>
<content type='text'>
The fault handler now writes crash.log to the volume labeled CRASHLOG
(label-selected via fat::crash_vol), falling back to slot 0.  On real
hardware the boot USB may be unwritable, so a second stick labeled
CRASHLOG survives the write; the shell auto-prints the previous crash
report from it at next boot (read_crash_log resolves /disk/&lt;uid&gt;/crash.log
through the FAT path, since Disk nodes hold no cached children).

- fat.rs: volume_label() + crash_vol() (no allocation)
- fs.rs: write_crash_log targets crash_vol(); read_crash_log prefers the
  CRASHLOG disk node; drop now-unused first_disk()
- mkdisk.sh: --label option
- test-fault.sh: boots with a dedicated CRASHLOG stick (mkfs -F 32 -n
  CRASHLOG), verifies crash.log lands there and NOT on the ESP
</content>
</entry>
<entry>
<title>v0.5.5: fix real-hardware boot crash — shadow back in heap as first allocation</title>
<updated>2026-08-02T00:16:40Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-02T00:16:40Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=d9fe082ef07b6e5c599585d6911dbad2bbe4c787'/>
<id>urn:sha1:d9fe082ef07b6e5c599585d6911dbad2bbe4c787</id>
<content type='text'>
User's machine: boot reached 'rsnix: boot done — shell' then panicked
'len is 0, index 0' at the first cell write — CELLS (the vt grid) was
valid at vt::init and empty at the first shell paint, i.e. something
stomped the heap between vt::init and the shell banner.  The only
change in that window vs the working v0.5.3 was the v0.5.4 move of the
1.9 MB display shadow from the heap to the fb-aware page allocator:
on this machine's memory layout the page-allocator shadow's fill loop
(480K words) clobbered the heap's vt vectors.

- Shadow is again the *first* heap allocation, in gop::init before
  vt::init builds its grids (the v0.5.3 layout that provably boots on
  the user's hardware) — nothing else in the heap can collide with it.
- init_heap now splits the free list at the GOP framebuffer hole
  instead of subtracting its size from one block that still *spanned*
  the hole — no heap allocation of any size can land on the display.
- Kept the panic-proof try_reserve + fb-overlap rejection + no-shadow
  warning band; dropped the late init_shadow() call in main.rs.
- Verified on QEMU: shadow @ 0x1980020 origin=heap, allocated before
  vt::init, fb clean at 0x80000000; all 5 suites PASS; 0 warnings.
</content>
</entry>
<entry>
<title>rsnix v0.5.2: fault diagnostics + real-hardware scroll-crash hardening</title>
<updated>2026-08-01T20:28:34Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-01T20:28:34Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=ab7d87bcde31c1681ea09c30534dde840a58d6fa'/>
<id>urn:sha1:ab7d87bcde31c1681ea09c30534dde840a58d6fa</id>
<content type='text'>
The real-hardware scroll crash (white bands + instant freeze, QEMU-clean)
was invisible because the only trace was a single serial line on machines
with no serial console.  This makes every crash self-identifying and
hardens the real-hardware failure surfaces:

- Every CPU exception vector 0-31 now has an IDT entry (macro-generated
  stubs; 8/14 keep their IST stacks).  A fault in the shell prints a
  white-on-red band to the framebuffer via gop::dump_lines (raw fb
  writes bypassing the vt, fully clamped) plus a parseable serial line:
  '!!! &lt;kind&gt; vec=N err=… rip=… cr2=… rsp=… rflags=… task=N "name"',
  then halts — instead of converging to a cryptic double fault.
  Background-task faults abort the task as before.
- Boot log now reports the authoritative post-SetMode geometry:
  'gop: fb base=… size=… pitch=… WxH bpp=… bgr=…', so the next real
  machine's report identifies whether pitch*height exceeds the mapping.
- Framebuffer writes (clear, push_rect, shift_up_n bulk push, cursor
  overlay) are clamped to the firmware's framebuffer_size: a pitch-
  padded mode degrades to a truncated view instead of faulting past
  the mapping.
- The GOP framebuffer region is excluded from the page allocator (and
  subtracted from the heap's conventional-region pick) even when the
  firmware lists it as ConventionalMemory — kernel allocations can
  never overwrite the display again.  The GOP protocol is located and
  peeked before the memory map is captured so the exclusion is known
  at heap-init time.
- Shell gains a hidden 'fault' command (deliberate unmapped write) and
  'make test-fault' verifies the dump: vec=14, cr2=0x400000000000,
  task=0, halt — no triple fault.  All other suites re-pass.
- CONTEXT.md: fault-dump format documented for real-hardware reports.
</content>
</entry>
</feed>
