From dc23d2f22cafeb6b97ba460789a834a6c586314d Mon Sep 17 00:00:00 2001 From: salmonik Date: Fri, 31 Jul 2026 19:53:53 +0200 Subject: ahci: SATA driver + FAT32 persistent disk mounted at /disk - ahci.rs: polling AHCI on PCI class 1/6/1, bus mastering + ABAR map, port 0 up, IDENTIFY + READ/WRITE DMA EXT through one 4KiB DMA buffer - fat.rs: BPB parse, whole-FAT RAM cache with write-back to both copies, LFN read/write, dirs, multi-cluster files, FSInfo free-count sync, space-padded dot entries ('..' = cluster 0 under root), fsck-clean - fs.rs: /disk mount node + 24-slot ephemeral node pool; ls/cat/hexdump/ echo/mkdir/touch/rm/edit all work on disk paths unchanged - QEMU: explicit bus assignment (disk=ide.0, ESP=ide.1); the implicit fat:rw:esp drive was stealing AHCI port 0 - Debugged against QEMU source: header DW0 is CFL in bits 4:0 / PRDTL in bits 31:16 (Linux libahci layout), FIS count at bytes 12-13, device at byte 7; QEMU rejects H2D FIS flags bits 6:4, so direction is the header W bit only - Verified: full shell round-trip on /disk, reboot persistence (poweroff then mdir/mtype and a fresh boot), fsck.fat clean --- CONTEXT.md | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) (limited to 'CONTEXT.md') diff --git a/CONTEXT.md b/CONTEXT.md index 8fa4025..24a4b1e 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -97,10 +97,18 @@ Single Rust crate (`x86_64-unknown-uefi` target). Module breakdown: - `paging.rs` — identity page-table helpers (map/unmap/query, large-page split) - `power.rs` — `ResetSystem`-based shutdown, hlt loop fallback - `rtc.rs` — CMOS/RTC clock (ports 0x70/0x71), BCD/12h normalization -- `pci.rs` — legacy PCI config space (0xCF8/0xCFC), full enumeration +- `pci.rs` — legacy PCI config space (0xCF8/0xCFC), full enumeration; `config_write` + - 64-bit BAR reader for the AHCI driver +- `ahci.rs` — SATA AHCI host driver (polling, DMA, no interrupts): scans PCI for + class 1/subclass 6/prog-if 1, maps ABAR, starts port 0 (FRE/ST/DMAE), runs + IDENTIFY + READ/WRITE DMA EXT through a 4 KiB DMA buffer +- `fat.rs` — FAT32: BPB parse, whole-FAT cache in RAM with write-back to both FAT + copies, cluster chains, directory scan with checksum-validated LFN + reassembly, LFN + 8.3 writing, FSInfo free-count maintenance, mkdir/rm/read/write - `fs.rs` — VFS: dirs, ramfs files, char devices (`/dev/mem`, `rtc`, `pci`, `version`, `meminfo`, `null`, `zero`, `console`, `serial`; `/tmp` ramfs; - `/etc/motd`) + `/etc/motd`); `/disk` mount node + 24-slot ephemeral node pool so shell + commands work on disk paths unchanged - `gop.rs` — framebuffer rasteriser (glyph blits, pixel shifts); the text surface itself lives in `vt` - `vt.rs` — terminal emulator: cell grid, cursor, ANSI CSI parser (H/J/K, @@ -159,6 +167,23 @@ Single Rust crate (`x86_64-unknown-uefi` target). Module breakdown: `tty` raw mode, stdout → `vt`, `std::fs` → VFS, SIGWINCH → fixed geometry. Verified in QEMU: edit/type/navigate/insert/save/exit, exact bytes via `cat`/`hexdump`, syntax colours via framebuffer dump. +✅ **AHCI + FAT32 (persistent disk)** — a SATA AHCI driver (polling DMA, + no interrupts) plus a FAT32 filesystem, mounted as `/disk`; every shell + command works on disk paths: `ls`/`cat`/`hexdump`/`echo >`/`>>`/ + `mkdir`/`touch`/`rm`/`edit`. Whole-FAT cache with write-back to both + FAT copies, checksum-validated LFN read/write, multi-cluster files, + space-padded `.`/`..` dot entries (`..` → cluster 0 under the root), + FSInfo free-count maintenance (fsck-clean after a session, verified + with `fsck.fat -n`). **Files survive reboot** — verified by + poweroff → `mdir`/`mtype` on the image and by a fresh boot seeing the + prior session's files. + + QEMU setup: `-drive id=disk,if=none,format=raw,file=disk.img` + + `-device ide-hd,drive=disk,bus=ide.0` puts the data disk on AHCI port + 0; the ESP gets `bus=ide.1`. (The implicit `-drive file=fat:rw:esp` + otherwise grabs port 0.) Make targets (`run`, `run-gui`, `debug`) + attach `$(DISK_IMG)` (default `/tmp/disk.img`). OVMF writes its + `NvVars` varstore file onto the first FAT volume — harmless. ## Known issues / perf notes @@ -181,8 +206,16 @@ Single Rust crate (`x86_64-unknown-uefi` target). Module breakdown: the whole framebuffer at all. - **Editor redraw** re-blits changed cells per keystroke (fine at 1280×800); the "optimize drawing someday" item. -- **ramfs only**: edited files live in memory, lost on reboot until disk - support (AHCI/FAT32) lands. +- **AHCI quirks learned (QEMU ground truth)**: the command header layout is + FIS length in DW0 bits 4:0 and PRDTL in bits 31:16 (not the classic + CFL-at-24 bit-fields); the H2D FIS sector count lives at bytes 12-13 with + the device register at byte 7 (byte 10 is LBA[47:40] — no separate + device byte); QEMU rejects H2D FISes with flags bits 6:4 set, so the + write direction is signalled purely by the header W bit (1<<6). + Real hardware follows the same FIS layout; the header layout matches + Linux libahci. +- **ramfs only for `/`**: the root filesystem is still the ramfs (lost on + reboot); persistent files live under `/disk` (AHCI/FAT32). ## Target audience -- cgit v1.2.3