diff options
| author | user <user@clank> | 2026-09-24 14:15:46 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-09-24 14:15:46 +0200 |
| commit | 50a56b48f22cd31868403f1fde10cf8367344e2e (patch) | |
| tree | 57c606182378dde67ce63d115ea07f98cc96b709 /include/gbos.inc | |
| parent | usr: xxd - hex dump a file or stdin (diff) | |
| download | gbos-50a56b48f22cd31868403f1fde10cf8367344e2e.tar.gz gbos-50a56b48f22cd31868403f1fde10cf8367344e2e.tar.xz gbos-50a56b48f22cd31868403f1fde10cf8367344e2e.zip | |
fs: mount the builtins at /bin
The commands only existed in the kernel's program table, so the only way to
find out what the machine could do was to already know (or read the source).
They are now a directory in the tree:
/# ls / /# xxd -l 16 /bin/uname
bin 0000: cd 6b 43 06 00 0e 00 f7 .kC.....
readme 0008: 18 fe 47 0e 03 f7 c9 21 ..G....!
/# ls -l /bin | head -2
- 1 16384 worker
/bin is synthetic, not disk: dir_find resolves "bin" in the root to BIN_INO
and names inside it through the NameTable, so `ls /bin` lists exactly what the
shell can run - one table, one truth, no second list to keep in sync. The root
listing carries "bin" as a synthetic first entry so it is discoverable by
walking the tree.
A program image is inode BIN_FILE|progid: it stats as a 16 KiB file (a program
IS its ROM bank) and reads through rom_getb, which maps that bank, takes the
byte, and maps the CALLER'S text bank back before returning - the caller is
itself executing from $4000, so leaving the wrong bank mapped would return
into another program's code. Verified byte-for-byte against the host's view of
the blob. The tree is read-only: create/remove/write inside /bin all fail.
xxd grows -l (stop after N bytes), because a program image is 2048 dump lines
- more than a pipe's temp file can hold, let alone the screen.
Two traps worth remembering, both found the hard way here: `and BIN_FILE`
destroys A, so the inode must be reloaded before inode_ptr (missing it once
made ls -l stat inode 0 and call every file an empty non-directory); and ls
now copies its directory argument to the stack first, because stat()'s request
block is a static living at $A000 - on top of the command line it was reading.
Diffstat (limited to 'include/gbos.inc')
| -rw-r--r-- | include/gbos.inc | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/include/gbos.inc b/include/gbos.inc index 1af3fc8..32418b6 100644 --- a/include/gbos.inc +++ b/include/gbos.inc @@ -235,6 +235,13 @@ DEF BLK_DATA0 EQU 4 ; first data block DEF FS_VERSION EQU 3 ; bumped: dirs now carry "."/".." entries DEF NINODES EQU 32 DEF ROOT_INO EQU 1 +; /bin is synthetic: a directory made of the kernel's program table rather +; than of disk blocks, so the builtins can be found (ls /bin), stat'd and read +; (xxd /bin/echo) like files. Both values are outside the real inode range +; (1..NINODES), so anything holding an inode number can tell them apart. +DEF BIN_INO EQU $F0 ; the /bin directory itself +DEF BIN_FILE EQU $80 ; BIN_FILE|progid = one program image +DEF BIN_SIZE EQU $4000 ; a program is exactly its 16 KiB ROM bank DEF NDIRECT EQU 12 ; direct block pointers per inode -> files <= 3 KiB ; (4..15: the whole tail of the 16-byte inode. It ; was 8, and bytes 12-15 were unused - but nothing |
