RustForge

foundry

Foundry OS: the operating system built on the Rustbelt kernel

foundry / README.md
4540 bytes · raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# 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. The
kernel boots and runs the shell from it.

## Quick start

```sh
make            # build out/foundry.img (the same as `make image`)
make test       # boot it headless in QEMU and run the shell 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, the kernel's test fixtures, assembles `out/staging/`, and writes `out/foundry.img` |
| `make rust` | `cargo build --release` in `rust/` |
| `make fixtures` | builds the kernel's ABI test programs from the pinned kernel source |
| `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) |
| `make test` | headless boot, self-test, ~90 expected-output checks; exit 0 = pass |
| `make test-reference` | the same test on the kernel's *own* disk image (the baseline) |
| `make compare` | compares our image with the kernel's, file by file |
| `make musl` | downloads (into `cache/`) and builds musl into `out/sysroot` (for M2) |
| `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)
│   ├── rbsh/             the shell (installed as /bin/sh for now)
│   ├── 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
├── rootfs/               files copied onto the disk as they are (readme, notes, the self-test)
│   └── etc/              passwd, hosts... for the later ext2 root (not in the image yet)
├── toolchain/musl/       musl C library: pinned by SHA256, downloaded into cache/
├── c/                    our own C programs (M2)
├── ports/                other people's C programs, one directory each (dash first)
├── scripts/              mkimage, build-kernel, run-qemu, run-headless, compare-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 mounts it at
`/mnt/disk0` (the shell calls it drive `B:`) and runs `/mnt/disk0/bin/sh`.

We build against **one exact kernel commit** (`KERNEL_REV` in `config.mk`,
now `a55b41d` = Rustbelt 0.19.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, change
`KERNEL_REV`, run `make test`, and commit.

## 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.