foundry
Foundry OS: the operating system built on the Rustbelt kernel
| author | Grok Bot <grokbot@localhost> | 2026-10-31 20:44:39 -0700 |
|---|---|---|
| commit | 4d3d43fe69a25b308b6b99bc13227921acc04571 | |
| parent | df4191d29409284655df0dba5dc439e76f30e9e0 | |
| tree | browse files at this commit | |
docs: M4 done; sbase results table, K14 (light kernel gaps from sbase), /usr/lib/sbase
| M | docs/glossary.md | +4 -0 |
| M | docs/kernel-requests.md | +26 -0 |
| M | docs/plan.md | +3 -2 |
| M | docs/porting.md | +1 -1 |
| M | docs/syscall-gaps.md | +21 -0 |
5 files changed, 55 insertions, 3 deletions
@@ -31,3 +31,7 @@ | **fixture** | A test program that checks the *kernel* (fork, signals, raw syscalls). The kernel repo owns them; they are not part of Foundry OS. | | **git subtree split** | A git command that takes one folder of a repo (here the kernel's `user/`) and makes a new history containing only that folder, with all its old commits. We merged that history in here, so `git log --follow` still shows how each file grew. | | **drive letters** | `A:`, `B:`... are **rbsh** syntax only (DOS style): `A:` = `/`, `B:` = `/mnt/disk0` (our disk), `C:`-`E:` = the other disks. The kernel knows nothing about them. |+| **sbase** | suckless's collection of small Unix tools (`sort`, `sed`, `find`...), one short C file each. Foundry OS ships it in `/usr/lib/sbase` (M4), off the default `PATH`; call a tool by its full path. Its sister project **ubase** has the Linux-only tools (`df`, `id`, `mount`). |+| **xfail** | "expected failure": a test for something we *know* doesn't work yet (e.g. a missing syscall). It is reported, not counted as a failure, and if it ever starts working the test says **XPASS** so we update the list. |+| **FIFO** (named pipe) | A pipe with a name in the file system, made by `mkfifo`: one program writes into it, another reads. Needs the `mknod` syscall. |+| **chroot** | "Change root": run a program so that it sees a chosen directory as `/`. Used for build sandboxes. |
@@ -196,6 +196,32 @@ without it; **nice** = can wait. | (k) | `/proc/<pid>/status` `Uid:`/`Gid:` lines (for `ps`, `id` checks in tests) | nice | | (l) | Signals: a non-root process may only `kill` processes with the same real/effective uid | nice (needed before untrusted users) | +## K14: small gaps found by sbase (light; all nice-to-have)++M4 ran 86 checks of suckless sbase 0.1 (`root/scripts/sbase-test.sh`,+part of `make test`) on Rustbelt 0.21.1. 79 pass: sorting, sed, find,+xargs, dd, `ls -l`, `chmod`, links, `touch`, `cp -p`, checksums, `kill`,+`nice`, `date`... Only these need the kernel. None blocks anything today;+the test runs each one as an expected failure ("xfail") and turns red when+it starts working, so we notice.++| | Gap | Evidence (Rustbelt 0.21.1, 6bb2b25) | Who notices |+|---|---|---|---|+| (a) | `mknod`/`mknodat` (133/259) missing, so no named pipes (FIFOs) | probe: `mknod(S_IFIFO)` on /tmp and `mkfifo` on ext2 both `-1 errno 38 (ENOSYS)` (Linux: 0); `sbase/mkfifo fifo` → "Function not implemented"; no `mknod` in `syscall.rs`'s dispatch | `mkfifo`, shell scripts that use FIFOs, busybox `mkfifo` |+| (b) | `chroot` (161) missing | probe: `chroot("/")` = `-1 errno 38` (Linux as root: 0); `sbase/chroot / true` fails | `chroot`; later, build sandboxes |+| (c) | `getdents64` never returns `.` and `..`; a directory's `st_size` is its entry count (ext2 /etc: `st_size` 6, `st_blocks` 1; Linux: 1024 or 4096) | probe: `readdir(/etc)` gives 6 entries, none of them `.`/`..` (Linux: 2 of them); `fs/mod.rs:114` "All children of this directory (without "." and "..")"; `ls -a` shows no dot entries | `ls -a`, `find`-style tools that expect them; `du` on directories counts a bit low |+| (d) | FAT32/exFAT keep no file times: `stat` shows 0 (1970) and `utimensat` is accepted and forgotten | `touch -t 200001020304` on `/mnt/disk0` exits 0 but `ls -l` still shows `Jan 01 1970`; `fs/mod.rs` `set_times` default "FAT and exFAT have time fields, but our drivers don't write them yet" | `ls -l`, `make`, `cp -p` to B:/C:, files copied to a PC |++Not kernel issues (ours, or just sbase): `df` and `id` are not in sbase 0.1+(busybox at M5 has them; `statfs` already exists); `logname` fails because+nothing sets `LOGNAME` yet (M6's `login` will); sbase has no `sed -i`,+`head -c`, `od -c` or fractional `sleep`. An SIGINT sent to a background+`sleep` is ignored, which looked like a bug but is right: dash sets SIGINT+to "ignore" for background jobs and that survives `exec` (probe: a+`SIG_IGN` child's `nanosleep(3s)` returns 0 after 3.00 s, a handler's+returns EINTR with `rem` 2.70 s, `SIG_DFL` is killed by signal 2, same as+Linux).+ ## What Foundry OS still takes from the kernel repo | What | How | Goes away when |
@@ -8,7 +8,7 @@ | 2 | What stays in the kernel | The ABI test programs stay as kernel fixtures: `hello evil spin demo child overflow forktest cowtest mmaptest sigtest threads echoserver ptytest nbtest fputest pathtest libctest coretest unixtest rawabi` and the musl ones `vdsotest piehello piethreads dynhello remaptest`. The shell, the tools and the net/sys programs moved here. | | 3 | Which shell | The Rust shell stays the interactive login shell, renamed **rbsh**, keeping its DOS commands (`run`/`start`, `dir`/`type`/`cls`...) and drive letters. **dash** (later busybox `ash`) becomes `/bin/sh` for POSIX scripts once the root is ext2. Under contract v1 rbsh is still installed as `/bin/sh`, because that is the path the kernel runs. | | 4 | Root file system | An **ext2 root**, so `A:` = `/` is the OS disk. The FAT32 disk stays as a **data disk** (`B:`). Plus an **exFAT share** (`C:`, `/mnt/share`) for files that go to Windows/macOS. Built in M3 (contract v2). |-| 5 | Name clashes | The Rust tools stay the default. busybox/sbase applets go under **`/usr/lib/busybox`**, off the default `PATH` (call them by full path, or add the directory to `PATH` yourself). |+| 5 | Name clashes | The Rust tools stay the default. sbase tools go under **`/usr/lib/sbase`** (M4) and busybox applets under **`/usr/lib/busybox`** (M5), both off the default `PATH` (call them by full path, or add the directory to `PATH` yourself). | | 6 | Tarballs | **Not in git.** A git-ignored download cache (`cache/`), each file pinned by SHA256 (`toolchain/musl/musl.sha256` + `fetch.sh`; `ports/<name>/<name>.sha256`). | | 7 | Which kernel | A **pinned commit**: `KERNEL_REV` in `config.mk` (now `50476f4`, Rustbelt 0.21.0; before that `5291332`, 0.20.0), bumped deliberately: see [bumping-the-kernel.md](bumping-the-kernel.md). | | 8 | Box packages | Small build packages are OK (`make`, `bzip2`, `musl-tools`, `autoconf`). |@@ -32,6 +32,7 @@ Inside the ext2 root: /bin rbsh, dash (also /bin/sh), the Rust tools (ls cat grep ...), our C programs /etc passwd group hosts resolv.conf motd (root/etc/) /scripts the self-test init runs headless+/usr/lib/sbase sbase's 97 small tools, off the default PATH (M4) /usr/lib/busybox busybox + applet symlinks, off the default PATH (M5) ``` @@ -44,7 +45,7 @@ Inside the ext2 root: | **M2** | musl hello + probes in `/bin`, built static-PIE with `toolchain/foundry-cc` | **done**: `hello-musl` and `fprobe` (40 checks incl. timerfd) in `/bin`, checked by `make test` | | M2b | dash built from ports/ as `/bin/dash`, with script checks in `make test` | **done** | | **M3** | dash as `/bin/sh`, ext2 root (contract v2), Rust `/sbin/init`, exFAT share | **done** on Rustbelt 0.21.0: `make test` (v2) passes, plus host fsck of all three file systems; `make test-v1` still passes |-| M4 | sbase tools | needs testing per tool (docs/syscall-gaps.md) |+| M4 | sbase tools in `/usr/lib/sbase` | **done** on Rustbelt 0.21.1: 97 tools built static-PIE; `make test` runs 86 checks (79 pass, 5 known kernel gaps as xfail, K14; `df`/`id` aren't in sbase). Table in docs/syscall-gaps.md | | M5 | busybox in `/usr/lib/busybox` | `bzip2` for the tarball | | M6 | User management: passwords, `login`, users and groups, real file owners and modes ([below](#m6-user-management-approved-not-started)) | approved; needs kernel K13 | | M7 | A bootable Raspberry Pi 3 build ([below](#m7-raspberry-pi-3-bootable-build-placeholder)) | placeholder; Edward's arm64/Raspberry Pi port is in progress on the kernel side |
@@ -80,7 +80,7 @@ ports/<name>/<name>.sha256 "SHA256 <tarball>" ports/<name>/<name>.url where to download it ports/<name>/patches/ 0001-*.patch ... ports/<name>/build.sh unpack from cache/, patch, CC=toolchain/foundry-cc ./configure --host=x86_64-linux-musl,- make, install into out/staging-v2/root (busybox/sbase: under /usr/lib/busybox)+ make, install into out/staging-v2/root (sbase: /usr/lib/sbase, busybox: /usr/lib/busybox) ``` Then boot it (`make test` / `make run`), try it, and note any missing
@@ -16,3 +16,24 @@ static-PIE and `mremap`. | no `/etc/passwd` | `getpwuid(0)` fails, `ls -l` owner names | Foundry OS job: `rootfs/etc/` (ships with contract v2) | | `mremap` 25 | big `realloc`s copied | fixed in 0.19.0 (to re-check) | | `ttyname()`, fd-message merging, `/proc/self/cwd` (K11) | `tty` | fixed in b0a701d (to re-check) |+| `mknod`/`mknodat` 133/259 (ENOSYS): no FIFOs | sbase `mkfifo`, `mknod NAME p` | open (K14 a) |+| `chroot` 161 (ENOSYS) | sbase `chroot` | open (K14 b) |+| `getdents64` has no `.`/`..`; directory `st_size` = entry count | `ls -a`, `du` of directories | open (K14 c) |+| FAT32/exFAT: no file times (`stat` shows 1970, `utimensat` ignored) | `touch`/`ls -l`/`cp -p` on B: and C: | open (K14 d) |+| `df`, `id` not in sbase 0.1 | M4 test list | not a kernel gap: busybox (M5) has them |+| `LOGNAME` unset, so `logname` fails | sbase `logname` | Foundry OS job: `login` (M6) |+| root image files owned by the build user (uid 1000) | `ls -l` showed `tyler tyler` | fixed in M4: scripts/mkimage-v2.sh sets 0:0 |++## sbase 0.1 on Rustbelt 0.21.1 (M4)++`make test` runs `root/scripts/sbase-test.sh` (86 checks; every tool from+`/usr/lib/sbase/` by full path). Results:++| Area | Tools checked | Result |+|---|---|---|+| text | `sort` (`-n -u -r -t -k`), `uniq -c -d`, `head -n`, `tail -n`/`+N`/`-f`, `cut -d -f -c`, `tr` (`-d -s`), `sed` (`s///g`, `d`, `-n /re/p`, `y`), `grep` (`-c -v`), `wc`, `od -t c`, `printf`, `expr`, `seq` (`-s -w`), `basename`, `dirname`, `paste`, `comm`, `rev`, `fold`, `nl`, `cat` | all pass |+| checksums | `cksum`, `sha256sum` (and `-c`), `md5sum`, `sha1sum` | all pass |+| files | `ls -l`/`-ld`/`-i`, `chmod` (octal, symbolic), `ln` and `ln -s`, `readlink -f`, `touch` (new, `-t`, `-d`), `cp -p`/`-R`, `mv`, `rm -r`, `rmdir`, `mkdir -p`, `dd` (`bs count skip`), `du -k`, `find` (`-name -type -newer`), `xargs` (`-n`), `tee` (`-a`), `test`, `tar c/t/x`, `cmp`, `split`, `mktemp` (`-d`) | all pass on A: (ext2) |+| system | `env -i`/`-u`, `date` (`-u -d`, `+FORMAT`), `yes \| head`, `sleep`, `kill` (TERM, -9, `-l`), `nice`, `renice`, `uname`, `whoami`, `hostname`, `true`/`false`, `getconf PAGESIZE` | all pass |+| known gaps (xfail) | `mkfifo`, `mknod p`, `chroot`, `ls -a` dot entries, `touch` on FAT | kernel, K14 (a)-(d) |+| absent | `df`, `id` | not in sbase 0.1 (ubase tools); busybox at M5 |