<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rs-dos/rsnix/src/fat.rs, 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-08-17T17:56:24Z</updated>
<entry>
<title>Terminal-app design (ADR 0005) + disk-write controller</title>
<updated>2026-08-17T17:56:24Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-17T17:56:24Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=126d5b2e55dca93e024f5654fed6fae37a012369'/>
<id>urn:sha1:126d5b2e55dca93e024f5654fed6fae37a012369</id>
<content type='text'>
- ADR 0005: persistent home terminal (full-screen, chrome-less,
  bottom-pinned), F1 terminal windows, per-instance vt/tty/shell,
  queue-based input for all terminals, and the disk controller
- Glossary: add the Terminal term; update Task/App for the new model
- Add a re-entrant disk lock (DiskGuard over the preemption-depth
  counter) and wrap all fs/fat mutating operations per-call
</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>fix pi-lens warnings: unwraps, shell SC2046, dup code (fmtbuf/scripts/hexdump/cat/ahci/pci)</title>
<updated>2026-08-01T16:25:55Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-01T16:25:55Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=1ea2f68e6a9af135e6cb3274fdf28d4ddc5812d5'/>
<id>urn:sha1:1ea2f68e6a9af135e6cb3274fdf28d4ddc5812d5</id>
<content type='text'>
- memory.rs: self-test Layout::from_size_align no longer panics — the
  test fails cleanly on an invalid layout
- fat.rs: v() no longer unwraps the active-volume slot — invariant
  violation logs + halts instead of panicking mid-disk-io
- strbuf: shared FmtBuf replaces the duplicated PanicBuf/FmtBuf
  (main.rs + sched.rs)
- test-disk.sh: SC2046 — conditional --fresh arg no longer relies on
  word splitting
- scripts: boot.sh/boot-image.sh share lib-boot-args.sh (dup args loop)
- shell: cat/hexdump stdin pairs unified with Option&lt;&amp;str&gt; marker;
  hexdump format_row folded into format_partial
- ahci: read/write_sectors unified behind dma_sectors
- pci: config_read/write share config_addr
</content>
</entry>
<entry>
<title>rsnix: formatting</title>
<updated>2026-08-01T13:08:29Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-01T13:08:29Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=c04fc970e5d9b0c82ae2923af88ad870a74608af'/>
<id>urn:sha1:c04fc970e5d9b0c82ae2923af88ad870a74608af</id>
<content type='text'>
</content>
</entry>
<entry>
<title>rsnix: runtime device detection — rescan for hotplugged/removed disks</title>
<updated>2026-08-01T13:00:47Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-01T13:00:47Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=d562e9df2bc5e69bba7298a9439e2adca5c18faf'/>
<id>urn:sha1:d562e9df2bc5e69bba7298a9439e2adca5c18faf</id>
<content type='text'>
Phase 1: make the boot discovery pipeline re-runnable and diff it
against live hardware state.

- ahci: store ABAR/NP/port bitmap; poll_dirty() (cheap PxSSTS.DET check
  per port) and rescan() which starts newly-present ports and tombstones
  the slots of removed ones.  Slots never shift, so disk indices stay
  valid.  select() now rejects tombstoned slots.
- fat: Volume gets a mounted flag; rescan() unmounts volumes whose disk
  left and mounts every disk without a mounted volume (re-trying failed
  boot mounts).  UID dedup ignores tombstones so a re-plugged disk keeps
  its /disk/&lt;UID&gt; name.
- fs: init's mount loop factored into rescan_disks(), which lazily
  creates /disk, ensures a mount node per mounted volume and tombstones
  nodes of unmounted ones.
- shell: 'rescan' command + automatic deep rescan before each prompt
  when ahci::poll_dirty() sees a port-presence change.

Rescan events flow through serial_println so they land in klog too.
Removal (PxSSTS) is a real-hardware path: QEMU q35 rejects disk hotplug
on the ich9-ahci IDE buses, and PCIe device_del is a guest-cooperative
protocol this kernel does not implement.
</content>
</entry>
<entry>
<title>Bump workspace to edition 2024</title>
<updated>2026-08-01T01:47:51Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-01T01:47:51Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=7c5603b2fed27be86982665a8b10dcd8f1c5a483'/>
<id>urn:sha1:7c5603b2fed27be86982665a8b10dcd8f1c5a483</id>
<content type='text'>
- edition = "2024" in the workspace manifest and rsdosedit
- extern blocks must be unsafe: interrupts.rs ISR stubs -&gt; unsafe extern "C"
- #[no_mangle] -&gt; #[unsafe(no_mangle)] (efi_main, isr_dispatch)
- One missed static-mut read in free_list_insert wrapped in an explicit
  unsafe block (edition 2024 removed the implicit unsafe context inside
  unsafe fns)
- rustfmt reflows for 2024: nested if-lets become let-chains, imports
  re-sorted, rsdosedit help-screen box rows wrapped

No codegen-affecting changes. Validated: cargo check/clippy/fmt clean
(host + uefi target), make test-disk PASS, editor round-trip PASS.
</content>
</entry>
<entry>
<title>Clean up warnings, fix FAT32 multi-cluster dirs, prep for edition 2024</title>
<updated>2026-08-01T01:44:57Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-01T01:44:57Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=63d01e9d8eb6f3ccb6a96b7c577834276cf51add'/>
<id>urn:sha1:63d01e9d8eb6f3ccb6a96b7c577834276cf51add</id>
<content type='text'>
Warning cleanup (cargo check + clippy now 0 across the workspace):
- Migrate all 21 static_mut_refs sites to &amp;raw mut accessors (fat, gop,
  ps2, vt, ahci, interrupts, memory) so edition 2024 won't deny them
- panic = "abort" profiles: bare cargo check/build now works without
  nightly/-Zbuild-std
- Wire TICKS in the timer ISR (it was never incremented, so the vt scroll
  batching trigger was dead code)
- Clippy: efi_main becomes unsafe extern "efiapi" with a # Safety doc,
  KeyBuf::new uses inline-const array repeat (no interior-mutable const),
  editor main loop is a while-let, PIT control byte regrouped
- [workspace.lints.clippy] allows result_unit_err + needless_range_loop
  (deliberate kernel style); large_enum_variant allowed on LineInput
- Drop now-stale static_mut_refs allow from the rsdos bin

FAT32 correctness fixes (both pre-existing, exposed by the SFN fix):
- Unique 8.3 short names: to_8_3() never disambiguated collisions, so
  files sharing a long-name prefix got identical SFNs and fsck reported
  duplicate directory entries.  Add dir_short_names() + unique_short_name()
  (~N tails, Windows-style) and force LFN when the SFN changes.
- Multi-cluster directories: scan_dir/dir_short_names stopped at the first
  0x00 slot, hiding every entry written into a chained cluster (writes
  failed with 'cannot write', duplicate SFNs accumulated); add_dir_entry
  now packs the cluster (0xE5 deleted-markers) before extending so other
  FAT readers (mtools, Windows) see the continuation too.

Other: delete dead fields (Disk.fis, Volume.fat_count), drop timer_irq/
keyboard_irq/rendered, refresh_and_exit is a documented unsafe fn, CONTEXT
.md corrected (stable toolchain, IRQ input, 4-crate layout), .gitignore
excludes .pi-subagents artifacts.

Validated: cargo check/clippy/fmt clean, make test-disk PASS on fresh and
reused images (incl. two directory-chain extensions and ~10 SFN tails),
editor round-trip smoke test PASS.
</content>
</entry>
<entry>
<title>rustfmt: reflow fat.rs/fs.rs formatting</title>
<updated>2026-08-01T00:50:34Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-01T00:50:34Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=c00c74f3f96f36440733e5007b465452d39212a2'/>
<id>urn:sha1:c00c74f3f96f36440733e5007b465452d39212a2</id>
<content type='text'>
</content>
</entry>
<entry>
<title>fat: mount every FAT32 volume under /disk/&lt;UID&gt;/, fix multi-entry LFN</title>
<updated>2026-08-01T00:19:07Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-01T00:19:07Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=92ed4f6668efccf6af73f45654405d333e6a318c'/>
<id>urn:sha1:92ed4f6668efccf6af73f45654405d333e6a318c</id>
<content type='text'>
- fat.rs: VOL: Option&lt;Volume&gt; → VOLS: Vec&lt;Volume&gt;; try_mount() returns
  a Volume per disk and init() mounts every valid FAT32 volume found.
  Volume UID = sanitized uppercase label + 8-hex volume serial
  (e.g. RSDOS-5BD1E55F): unique per format, stable across reboots,
  human-recognizable, machine-parseable (^[A-Z0-9_]+-[0-9A-F]{8}$);
  cloned volumes get a -N suffix.  Public ops take a vol index and
  select it (select_vol also picks the backing AHCI disk), matching
  the ahci::select pattern
- fs.rs: /disk is now a plain directory whose children are one Disk
  node per mounted volume, named by UID; DiskInfo carries vol
- LFN fix: entries are stored last-first on disk — both the writer
  (head-entry first) and reader (append in disk order) were reversed
  and cancelled out for ≤13-char names; multi-entry names (&gt;13 chars)
  read back mangled (e.g. 'from-kernel.txt' as 'xt').  Writer now
  places seq=1 closest to the SFN and seq=N|0x40 first; reader places
  chunks by sequence number and trims at the first NUL.  Verified with
  a 25-char filename round trip: kernel ls/cat correct, mtools shows
  the full LFN, fsck clean on both volumes
- test-disk.sh: test file renamed to disk-test-.txt (&gt;13 chars,
  exercises multi-entry LFN); UID discovered from the boot log; QEMU
  stdio redirected to a log file + EXIT trap so an orphaned QEMU can
  never hang a piped caller (it previously did, 400s)
</content>
</entry>
<entry>
<title>ahci: scan all ports; fat: mount first valid FAT32 disk</title>
<updated>2026-07-31T19:29:49Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-07-31T19:29:49Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=3997ec4d2d7d6f69b08d0c04ce8de0df03c52a45'/>
<id>urn:sha1:3997ec4d2d7d6f69b08d0c04ce8de0df03c52a45</id>
<content type='text'>
The kernel previously started only AHCI port 0, so any launch where the
firmware/QEMU put something else on port 0 (e.g. the ESP from an implicit
-drive file=fat:rw:esp) left the real disk unnoticed: 'unsupported sector
size 0' and no mount.

- ahci.rs: enumerate CAP.NP/PI ports, start every port that links up
  (empty ports settle at DET=0 and are skipped quickly), keep up to 8
  disks, and expose disk_count()/select() for the filesystem
- fat.rs: try each disk in port order and mount the first valid FAT32
  volume; non-FAT disks are logged and skipped
- scripts/boot.sh: attach the data disk on ide.0 and the ESP on ide.1
  (DISK_IMG env var, default /tmp/disk.img), matching the Makefile
- Verified with the disk on port 0 (Makefile style), port 5 (old-style
  command line), and with the ESP on port 0; fsck.fat stays clean
</content>
</entry>
</feed>
