# Foundry OS **Foundry OS** is a small operating system that runs on the **Rustbelt** kernel, the way Ubuntu runs on Linux. The kernel (in its own repo, `/workspace/rust-kernel`) drives the hardware; Foundry OS is everything else: the shell `rbsh`, the tools (`ls`, `cat`, `grep`...), the network and system programs, and the disk image they live on. This repo builds **one file**, `out/foundry.img`, a virtual hard disk with three parts (partitions): the system (drive `A:`, mounted at `/`), a data disk (`B:`) and a share for swapping files with other computers (`C:`). The kernel boots, mounts them, and runs our `/sbin/init`, which starts the shell. ## Quick start ```sh make # build out/foundry.img (the same as `make image`) make test # boot it headless in QEMU: init runs the self-test make run # boot it in a QEMU window and play make help # every target ``` The first `make test` also builds the pinned kernel (a few minutes). You need the packages the kernel needs plus `make` (all already on the box): `rustup` (nightly), `qemu-system-x86`, `dosfstools`, `mtools`, `fdisk`, `e2fsprogs`, `exfatprogs`, `btrfs-progs`, `musl-tools`, `gcc`. ## Make targets | Target | What it does | |---|---| | `make image` | builds the Rust programs, our C programs and ports, the kernel's test fixtures, assembles `out/staging-v2/`, and writes `out/foundry.img` (boot contract v2: ext2 root A:, FAT32 data B:, exFAT share C:; see [docs/boot-contract.md](docs/boot-contract.md)) | | `make image-v1` | the old one-partition FAT32 image, `out/foundry-v1.img` (contract v1) | | `make rust` | `cargo build --release` in `rust/` (rbsh, init, the tools) | | `make fixtures` | builds the kernel's ABI test programs from the pinned kernel source | | `make cprogs` | builds our C programs (`c/`: hello-musl, fprobe, orphan) as static-PIEs with `toolchain/foundry-cc` | | `make ports` | downloads (SHA256-checked, into `cache/`) and builds the ports (dash) the same way | | `make kernel` | builds the pinned Rustbelt kernel into `out/kernel-target` | | `make run` | boots the image in a QEMU window (`NOGRAPHIC=1` for serial only; `KEEP=1` keeps what you write to the disk) | | `make test` | headless boot: our `/sbin/init` runs the self-test (expected lines in `scripts/expect-v2.txt`), then the host fscks all three file systems and reads the share back; exit 0 = pass | | `make test-v1` | the contract-v1 test: the kernel runs the shell self-test on `out/foundry-v1.img` (~100 checks) | | `make test-reference` | the v1 test on the kernel's *own* disk image (the baseline) | | `make compare` | compares our v1 image with the kernel's, file by file | | `make unit` | host unit tests (`cargo test` on the build machine, no QEMU): rbsh's parser and drive letters. `make rbsh-test` is the old name. | | `make k1-check` | builds the kernel with `RUSTBELT_DISK0=out/foundry.img` and checks it uses our image | | `make musl` | downloads (into `cache/`) and builds musl into `out/sysroot`; `make cprogs`/`make ports` run it when needed | | `make clean` | `rm -rf out` (`make distclean` also empties `cache/`) | ## What is where ``` foundry/ ├── Makefile, config.mk the build; config.mk pins the kernel commit ├── rust/ the Rust programs (a Cargo workspace) │ ├── init/ /sbin/init: the first program; starts shells, reaps orphans │ ├── rbsh/ the shell, /bin/rbsh (drive letters A: B: C:) │ ├── coreutils-rs/ ls cat wc grep mkdir rm touch cp sleep │ ├── net/ ifconfig ping host fetch httpd │ ├── sys/ getty tile random sysinfo │ ├── rbrt/ the runtime every program includes (ulib.rs) + shared build.rs │ └── link.ld puts programs at address 0x80_0040_0000 ├── root/ the root file system, A: = / (etc/, the v2 self-test in scripts/) ├── rootfs/ the FAT32 data disk, B: = /mnt/disk0 (readme, notes; v1 self-test) ├── share/ the exFAT share, C: = /mnt/share (README.TXT) ├── toolchain/ foundry-cc (gcc + musl, static-PIE); musl/ pinned by SHA256, downloaded into cache/ ├── c/ our own C programs: hello-musl, fprobe (the libc self-check), orphan ├── ports/ other people's C programs, one directory each (dash: /bin/dash) ├── scripts/ mkimage(-v2), exfat.py, build-kernel, run-qemu, run-headless, check-v2-image... ├── docs/ how it all fits together (start with docs/glossary.md) ├── out/ everything built (git-ignored) └── cache/ downloads (git-ignored) ``` ## How it fits with the kernel The kernel repo and this repo meet in exactly one place: the **disk image**. [docs/boot-contract.md](docs/boot-contract.md) says what the image must contain. QEMU gets our image as its first virtio disk; the kernel (0.21.0+) mounts the ext2 root partition at `/`, the FAT32 partition at `/mnt/disk0` and the exFAT share at `/mnt/share`, and runs `/sbin/init` as process 1 (contract v2). `make test-v1` still checks the old layout (contract v1: one FAT32 partition at `/mnt/disk0`, the kernel runs `/mnt/disk0/bin/sh`). We build against **one exact kernel commit** (`KERNEL_REV` in `config.mk`, now `50476f4` = Rustbelt 0.21.0). The build exports that commit from the kernel repo's git store with `git archive` and compiles it in `out/`, so the kernel repo itself is never changed. To move to a newer kernel, follow [docs/bumping-the-kernel.md](docs/bumping-the-kernel.md). ## Where this came from The programs were in the kernel repo's `user/` folder. They were brought here with **`git subtree split`**, which keeps their full history: try `git log --follow rust/coreutils-rs/src/bin/ls.rs`. The kernel keeps its ABI test programs (`forktest`, `rawabi`...), and for now the image still carries them because the self-test runs them. See [docs/plan.md](docs/plan.md) for what comes next and [docs/proposal.md](docs/proposal.md) for the full background. New to these words? **[docs/glossary.md](docs/glossary.md)** explains sysroot, static-PIE, subtree, GPT, musl and the rest.