<feed xmlns='http://www.w3.org/2005/Atom'>
<title>gbos.git/src/fs.asm, branch master</title>
<subtitle>gbos - a tiny Unix-flavored OS for the Game Boy Color (kernel, shell, coreutils in C, RAM filesystem)</subtitle>
<id>https://git.sl0p.foo/gbos.git/atom/src/fs.asm?h=master</id>
<link rel='self' href='https://git.sl0p.foo/gbos.git/atom/src/fs.asm?h=master'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/'/>
<updated>2026-07-17T22:46:26Z</updated>
<entry>
<title>kernel: dmesg-style boot spew before init spawns</title>
<updated>2026-07-17T22:46:26Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-07-17T22:46:26Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/commit/?id=3fd3454212dc1d4dc396e393812833ec2e15e41a'/>
<id>urn:sha1:3fd3454212dc1d4dc396e393812833ec2e15e41a</id>
<content type='text'>
Print everything the kernel knows implicitly at boot, Linux-flavored, on
the LCD console and mirrored over the link (gbhub logs each GB's boot):

  gbos sm83 microkernel
  console: CGB (boot a=$11)          &lt;- boot ROM's A/B, saved at entry
  cart: mbc5, 1M rom, 128K sram      &lt;- our own cart header ($0147-49)
  mem: 32K wram 16K vram 127B hram   &lt;- CGB constants
  proc: 8 slots, 31 programs         &lt;- link-time table sizes
  net: slip on link port, 4 sockets
  fs: gbfs v3 mounted, 120/128 blk free  &lt;- bitmap popcount; 'formatted'
  tty: 40x18 console, SELECT = osk      on first boot
  init: spawning pid 1

New src/dmesg.asm with kernel print helpers (kputc/kputs/kputhex/kputdec)
that bypass KPutc (no process context at boot). term_init now runs before
net/fs init so the spew is visible as subsystems come up.
</content>
</entry>
<entry>
<title>kernel+sh: real anonymous pipes (concurrent, streaming, SIGPIPE)</title>
<updated>2026-07-16T23:04:16Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-07-16T23:04:16Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/commit/?id=73295e7acc1e5ec3ee8814fd4ccc45f7cee63392'/>
<id>urn:sha1:73295e7acc1e5ec3ee8814fd4ccc45f7cee63392</id>
<content type='text'>
Replace the shell's temp-file pipe hack with proper in-kernel FIFOs.

Kernel (src/pipe.asm, new):
- A small pool of bounded ring buffers (PIPE_MAX=2, 64 B each) with
  writers/readers refcounts. Pipe fds are $F0+idx*2 (read) / +1 (write);
  $FF stays "console".
- SYS_PIPE allocates one (writers=readers=1) and returns the read fd
  (write = read+1). getb/putb/close dispatch pipe fds here; sys_exit drops
  the refcounts held as PROC_STDIN/PROC_STDOUT.
- Blocking with SchedYield, which is the flow control: read blocks while
  empty with a writer (EOF once writers hit 0), write blocks while full
  with a reader, and if the last reader is gone the writer is killed
  (SIGPIPE -&gt; exit 141). Cooperative-scheduler friendly.

Shell (c/sh.c):
- run_pipeline(): split on '|', make a pipe between adjacent stages, and
  fork ALL stages concurrently (no wait between), wiring stdin/stdout;
  then wait for all. Per-stage &gt;/&lt; still honored; orphaned pipe ends are
  closed on a lookup miss so EOF/EPIPE propagate.
- Drop the __pipe temp file and its 2 KB / serialized limits.

libc: pipe(). New c/ptest.c exercises the FIFO (write, read back, EOF).

Now works (old version couldn't): multi-stage a|b|c; streaming beyond 2 KB
(count 120 | wc = 3372 bytes through a 64 B buffer); early-exit SIGPIPE
(count 200 | true kills count instead of hanging/overflowing a file).
</content>
</entry>
<entry>
<title>fs: reject open()/read() on a directory (EISDIR)</title>
<updated>2026-07-16T11:07:28Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-07-16T11:07:28Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/commit/?id=fc6f690727aac2b5c9bd368f9b13188fb0ba36a7'/>
<id>urn:sha1:fc6f690727aac2b5c9bd368f9b13188fb0ba36a7</id>
<content type='text'>
open() now checks the target's inode type: opening a directory as a file
returns $FE (EISDIR) instead of a valid fd, so 'cat docs' no longer streams the
raw directory block as bytes. cat reports 'is a directory'; wc/head/save treat
any invalid fd (&gt;3) as an open failure. (ls is unaffected - it uses the
structural opendir/list path, not open/getb.)
</content>
</entry>
<entry>
<title>fs rewrite stage 3: nested directories, paths, cwd (cd/mkdir/ls)</title>
<updated>2026-07-16T10:49:19Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-07-16T10:49:19Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/commit/?id=5fefd233769a56caefdb2ffecaa9fb8b9ec6db86'/>
<id>urn:sha1:5fefd233769a56caefdb2ffecaa9fb8b9ec6db86</id>
<content type='text'>
- directories generalized: dir_find/dir_add/dir_remove take any dir inode;
  every dir carries '.'/'..'. Path resolution (resolve / resolve_parent) walks
  absolute or cwd-relative paths; open/mkdir/chdir/remove/opendir take paths.
- per-process cwd: PROC_CWD in the PCB (root by default, inherited on fork);
  sys_chdir sets it, sys_opendir points ls at any directory.
- shell: 'cd' builtin + cwd-aware prompt; 'mkdir'/'ls &lt;dir&gt;' tools; 'exit'/'quit'
  and EOF call poweroff() (clean shutdown via the $ED opcode -&gt; reliable save).
- three HL/buffer-clobber bugs fixed along the way: resolve didn't preserve the
  path cursor across dir_find; cur_cwd clobbered HL; resolve_parent set the final
  name before resolve() overwrote wFsNameBuf (now copied after).
- verified: nested mkdir/cd/save, multi-level paths (cat docs/sub/b), and the
  whole tree persists across a reboot.
- README: document directories + the poweroff opcode.
</content>
</entry>
<entry>
<title>fs rewrite stage 2: inodes + root directory (block-based, persistent)</title>
<updated>2026-07-16T10:20:57Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-07-16T10:20:57Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/commit/?id=4f2d40ca35e0e39886dc881d06256fc25ba27a77'/>
<id>urn:sha1:4f2d40ca35e0e39886dc881d06256fc25ba27a77</id>
<content type='text'>
- 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 -&gt; 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) -&gt; 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-&gt;write_block clobbers C) -&gt; 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.
</content>
</entry>
<entry>
<title>filesystem: a RAM FS (WRAMX) + ls/cat/save/rm; wc/head read files</title>
<updated>2026-07-16T05:53:19Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-07-16T05:53:19Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/commit/?id=7b5c532625a864a3fbaf76f44df6aa99b0d6861e'/>
<id>urn:sha1:7b5c532625a864a3fbaf76f44df6aa99b0d6861e</id>
<content type='text'>
- fs.asm: 8-slot RAM filesystem in WRAMX ($D000-$DFFF), name[8]+len[2]+data[502];
  syscalls open/close/getb/putb/list/remove, seeded with a 'readme' at boot.
- libc: open/close/fgetc/fputc/flist/fremove wrappers + O_READ/O_WRITE/NOFD.
- tools: ls, save (stdin-&gt;file, one line), rm; cat/wc/head now take a file arg.
- fix: syscall dispatch clobbers A, so putb takes its byte in E (was reading the
  handler's low address byte, 0xDC); ls NUL-terminates 8-char names.
- verified: save/cat/ls/rm cycle; wc readme -&gt; '2 7 38'; head -n 1 readme.
- README: document the filesystem + the A-clobber ABI note.
</content>
</entry>
</feed>
