aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
authoruser <user@clank>2026-07-16 12:20:57 +0200
committeruser <user@clank>2026-07-16 12:20:57 +0200
commit4f2d40ca35e0e39886dc881d06256fc25ba27a77 (patch)
tree368474d3d24a2480b45c0efd8ffe0b7ee018b879 /README.md
parentfs rewrite stage 1: persistent block device (bounce buffer, cart SRAM) (diff)
downloadgbos-4f2d40ca35e0e39886dc881d06256fc25ba27a77.tar.gz
gbos-4f2d40ca35e0e39886dc881d06256fc25ba27a77.tar.xz
gbos-4f2d40ca35e0e39886dc881d06256fc25ba27a77.zip
fs rewrite stage 2: inodes + root directory (block-based, persistent)
- fs.asm: a real block filesystem on the persistent block device - superblock, block/inode bitmaps, a 32-entry inode table (type, size, 8 direct block pointers -> files up to 2 KiB), and a root directory of 16-byte entries. Metadata cached in WRAMX; one-block data cache streams file/dir blocks. - same syscall interface (open/getb/putb/list/remove) -> tools unchanged; ls now enumerates until flist() runs out (16 files, was hardcoded 8). - old 8-slot WRAM FS removed; cart RAM partitioned: process banks 0-7, disk 8-11. - two register-clobber bugs fixed: alloc_block/alloc_inode returned the bitmap-block number (write_bitmap clobbers C); db_use loaded the wrong block on a transition (db_flush->write_block clobbers C) -> multi-block files broke. - verified: 10+ files, multi-block (300-byte) files, delete, and persistence across reboots. Debug 'blk' disk tool retained (fill/peek). - README: document the block filesystem.
Diffstat (limited to 'README.md')
-rw-r--r--README.md56
1 files changed, 26 insertions, 30 deletions
diff --git a/README.md b/README.md
index 7479e52..74f3608 100644
--- a/README.md
+++ b/README.md
@@ -294,42 +294,38 @@ $ ps
## Filesystem
-> **Being rewritten** into a persistent block-based FS. Stage 1 landed: a block
-> device (`src/blk.asm`) over battery-backed cart RAM (banks 8–11, 256-byte
-> blocks) read/written through a WRAM bounce buffer — so only two routines touch
-> cart-RAM banking, and (crucially) they never touch the stack while the disk
-> bank is mapped over the process's `$A000` window. Data survives power-off via
-> the emulator's `.sav`. The 8-slot WRAM filesystem below still backs the tools
-> until stages 2–3 (inodes + directories) replace it.
+A small **block-based, persistent filesystem** on battery-backed cart RAM
+(`src/blk.asm` + `src/fs.asm`). Layout on the 32 KiB "disk" (256-byte blocks):
+```
+block 0 superblock (magic + version)
+block 1 bitmaps (free blocks + free inodes)
+blocks 2-3 inode table (32 inodes x 16 B: type, size, 8 direct block ptrs)
+blocks 4.. data blocks
+```
-A tiny **RAM filesystem** lives in **WRAMX (`$D000-$DFFF`, 4 KiB)** — always
-mapped in DMG mode and simultaneously accessible with a process's `$A000` data
-bank, so the kernel copies between file and process memory with no bounce
-buffer. 8 fixed slots of 512 bytes: `name[8]` + `len[2]` + `data[502]`. Seeded
-with a `readme` at boot.
-
-Syscalls: `open` (4), `close` (5), `getb` (12), `putb` (13, byte in `E`),
-`list` (14), `remove` (15). Libc: `open`/`close`/`fgetc`/`fputc`/`flist`/
-`fremove` (`c/libc.s`).
+- **Inodes + a root directory.** A directory is a file of 16-byte entries
+ (inode# + name). Files are up to **2 KiB** (8 direct blocks); up to **16**
+ entries in the root, **32** inodes.
+- **Bounce buffer.** Only `read_block`/`write_block` touch cart-RAM banking;
+ everything else works on WRAM buffers. The bitmap + inode table are cached in
+ WRAMX; data/dir blocks stream through a one-block cache.
+- **Persistent.** Formats on first boot (magic/version check), then survives
+ power-off via the emulator's `.sav`.
+- Same syscalls as before (`open`/`getb`/`putb`/`list`/`remove`) so the tools
+ (`cat`/`ls`/`save`/`rm`/`wc`/`head`) are unchanged.
```
$ save notes
-gbos has a filesystem now
+gbos has a real filesystem now
$ cat notes
-gbos has a filesystem now
-$ wc notes
-1 5 26
+gbos has a real filesystem now
$ ls
-readme
notes
-$ rm notes
+$ wc notes # survives a reboot
+1 5 31
```
-> **ABI note:** the syscall trap indexes its jump table with `A`, so syscall
-> args go in `B`/`DE`/`E` (never `A`) and results come back in `A`. That's why
-> `putb` takes its byte in `E`.
-
## Roadmap
- [x] `fork`: copy parent's 8 KiB RAM bank → free bank, child returns 0
@@ -348,10 +344,10 @@ $ rm notes
- [x] per-process stdin/stdout routing (`KGetc`/`KPutc`, `setin`/`setout`)
- [ ] more tools (`rev`, `grep`, `tail`), true concurrent pipes
- [~] persistent filesystem rewrite (block-based, cart SRAM), directories:
- - [x] **stage 1**: block device (`blk.asm`) — read_block/write_block via a WRAM
- bounce buffer, format-on-first-boot, **persists across reboots** (`.sav`)
- - [ ] stage 2: inodes + flat root dir (variable-size files); port cat/ls/save
- - [ ] stage 3: directories, path resolution, per-process cwd, `cd`/`mkdir`
+ - [x] **stage 1**: block device (`blk.asm`) via a WRAM bounce buffer
+ - [x] **stage 2**: inodes + root directory; variable-size files (<=2 KiB),
+ bitmap allocators; 16 files / 32 inodes; persists across reboots
+ - [ ] stage 3: nested directories, path resolution, per-process cwd, `cd`/`mkdir`
- [ ] Preemptive scheduling: real context save in `TimerISR` → `hSwitchTo`
- [ ] Use the `$D000-$DFFF` u-area (SVBK) for per-process kernel state / kstack
- [ ] `brk`/heap allocator inside the task bank (heap up, stack down, collision = ENOMEM)