docs: README, plan, guides and the site describe what is built now

README: rewritten around what runs (Linux software, Xorg, apk, Linux's drivers), the honest gaps, measured numbers.
plan/: 1.0.md is the finish line, where each clause of the acceptance test stands, and the register (one failing
clause: a root that survives a reboot); built plans (foundations, hybrid, alpine, xorg) and the decided-against one
(wayland) are gone, their content lives in architecture/; roadmap.md is only what is still open.
guides: building/layout/testing/adding-a-driver (Linux code may be used). history: four entries (ls -lR, TLB
shootdowns, MDIO 0x02460246, netlink MSG_TRUNC). Website: cards, stack, download page, docs index.
Code comments that pointed at deleted plan docs point at the architecture docs.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVRhxi9zpdW2uDUN4FVcao
This commit is contained in:
Nexoniarz 2026-10-26 08:08:05 +01:00
commit cb3d28e3d6
57 changed files with 685 additions and 2121 deletions

193
README.md
View file

@ -4,48 +4,50 @@
# SchOS
**A 64-bit operating system, written from the metal up.**
**A 64-bit operating system, written from the metal up — and it runs Linux's software.**
SMP kernel · copy-on-write filesystem · Linux syscall ABI · Alpine packages · X11 on real hardware
SMP kernel · copy-on-write filesystem · Linux syscall ABI · Alpine packages · Xorg · Linux's own drivers
</div>
---
SchOS began as [xv6](https://github.com/mit-pdos/xv6-public) and is now mostly
something else. The scheduler, the memory manager and the trap path have been
rewritten for x86-64 and for more than one processor; the filesystem has been
replaced outright; the syscall table speaks Linux numbering, so real Linux
software runs on it unmodified — statically or dynamically linked, straight
out of Alpine's package repositories.
SchOS is a hobby operating system built by one person. It began as
[xv6](https://github.com/mit-pdos/xv6-public) and almost nothing of that is left:
the scheduler, the memory manager, the trap path and every driver have been
rewritten for x86-64 and for more than one processor, and the filesystem is a
different one. The syscall table speaks Linux's numbering, so **real Linux
programs run on it unmodified** — statically or dynamically linked, straight out
of Alpine's package repositories — and a desktop (Xorg and Window Maker) and a
web browser (NetSurf) come up on the framebuffer.
It is a hobby system built by one person, and it is honest about that: what
works below has been *run*, not inferred, and the gaps are listed as plainly as
the features.
It is honest about being a hobby system: what is listed below has been *run*,
not inferred, and [the gaps](#not-there-yet) are listed as plainly as the
features. It boots from a USB stick on three different real machines.
## In numbers
<!-- stats:begin -->
| | |
|---|---|
| **First-party code** | 61,367 lines, plus 21,128 lines of comments (26%) in 272 files |
| **Kernel** (`kernel/`, `include/`) | 45,207 lines of code, 16,111 of comments |
| **Syscalls** | 208, of which 184 on Linux numbering |
| **First-party code** | 72,766 lines, plus 23,668 lines of comments (25%) in 307 files |
| **Kernel** (`kernel/`, `include/`) | 51,893 lines of code, 17,213 of comments |
| **Syscalls** | 215, of which 193 on Linux numbering |
| **Drivers** | 15 in the kernel |
| **First-party programs** | 29 in `cmd/` |
| **Alpine packages in the root** | 88, from 11 asked for in `ports/alpine/world` |
| **History** | 253 commits since 2026-08-09 (76 days) |
| **Alpine packages in the root** | 179, from 29 asked for in `ports/alpine/world` |
| **History** | 289 commits since 2026-08-09 (78 days) |
<details>
<summary>Lines by language</summary>
| Language | Code | Comments |
|---|--:|--:|
| C | 56,580 | 19,427 |
| C | 67,615 | 21,904 |
| Assembly | 1,750 | 336 |
| PowerShell | 1,362 | 638 |
| Python | 759 | 147 |
| Shell | 716 | 469 |
| Python | 943 | 150 |
| Shell | 896 | 529 |
| Perl | 129 | 45 |
| Linker script | 71 | 66 |
@ -55,78 +57,74 @@ the features.
<code>ports/</code> and generated tables are not counted.</sub>
<!-- stats:end -->
## The pieces
## What it is made of
| Layer | Name | What it is |
|---|---|---|
| System | **SchOS** | The distribution — kernel, userland, tooling |
| Kernel | **SchIFT** | Multi-core x86-64 kernel with a modular VFS |
| Kernel | **SchIFT** | Multi-core x86-64 kernel with a modular VFS and Linux's syscall ABI |
| Filesystem | **SchFS** | Transactional, copy-on-write, the root filesystem |
| Image format | **SCFF** | The SchOS Compressed File Format the live root ships in |
| API | **SchAPI** | System programming interface — the stable surface |
| Compositor | **SchCom** | Display compositor *(planned)* |
| Window manager | **SchWM** | *(planned)* |
| Desktop | **SchDE** | *(planned)* |
| Packages | **apk** | Alpine's package manager manages the root; SchOS itself is the package `schos-base` |
| Desktop | **Xorg + Window Maker** | Alpine's, on the framebuffer |
| Crash screen | **PSOGM / GMMOS** | The Purple Screen of Guru Meditation, and the micro OS that runs under it |
| API | **SchAPI** | The long-term native interface — *designed, not built* |
`uname -s` reports `SchIFT`, the way every Unix reports its kernel rather than
its distribution.
## What works
**Kernel** — Long mode, 4-level paging, preemptive multitasking. **SMP** up to
64 processors, enumerated from the ACPI MADT. ACPI through
[uACPI](https://github.com/uACPI/uACPI): interrupt routing from `_PRT`, the
power button, clean power-off and reset. Memory sized from the E820/UEFI map.
**Kernel** — Long mode, 4-level paging, preemptive multitasking, a fair-share
scheduler with `nice`. **SMP** up to 64 processors, enumerated from the ACPI
MADT. **Threads** (`clone`, `futex`, TLB shootdowns), **demand paging** for the
huge reservations browsers make, and dynamic linking. ACPI through
[uACPI](https://github.com/uACPI/uACPI): interrupt routing, the power button,
clean power-off and reset, batteries and AC through a laptop's embedded
controller, and deep idle states. Memory sized from the firmware's map, up to 256 GB.
**Filesystem** — **SchFS** is the root: a copy-on-write B-tree with a
uberblock ring, so a crash leaves either the old tree or the new one and there
is nothing to repair. The live image ships as **[SCFF](docs/architecture/scff.md)**:
the 358 MB root compresses to 102 MB with zstd and is unpacked a chunk at a
time, the first time something reads it. `/proc` has `/proc/<pid>/fd`,
`/proc/self` and the rest that `ps`, `top` and Xorg read.
**Filesystem** — **SchFS** is the root: a copy-on-write B-tree with an uberblock
ring, so a crash leaves either the old tree or the new one and there is nothing
to repair. The live image ships as **[SCFF](docs/architecture/scff.md)**: the
root compresses with zstd to about a third of its size and is unpacked a chunk at
a time, the first time something reads it. `/proc`, `/sys` and `/dev` are
synthesised, in Linux's layouts, because that is what the programs read.
**Processes** — fork, exec, wait, pipes, signals, sessions and job control,
`mmap` (anonymous and file-backed), POSIX shared memory, `memfd`, Unix domain
sockets with descriptor passing (`SCM_RIGHTS`), `poll`, `epoll`, `eventfd`,
`timerfd`, `signalfd`. **Dynamic linking**: `exec` loads `ld-musl`, so
binaries come from Alpine as they are.
**Linux software** — `fork`, `clone`, `exec`, pipes, signals, sessions and job
control, `mmap`, POSIX and `memfd` shared memory, Unix sockets with descriptor and
credential passing, `poll`, `epoll`, `eventfd`, `timerfd`, `signalfd`, `inotify`,
pseudo-terminals. The root is managed by Alpine's **apk**: `ports/alpine/world`
says what is installed, `world.lock` pins it, and `apk add` fetches more over HTTPS.
**Packages** — the root is managed by Alpine's **apk**. `ports/alpine/world`
says what is installed; the build resolves it once into `world.lock` and every
image after that is reproducible. SchOS itself is one more package in it.
**Desktop** — **Xorg with Window Maker**, `xterm`, the classic X clients, SDL games
and the NetSurf browser, on the framebuffer (`/dev/fb0`, Linux fbdev) with input
as Linux evdev. Twelve virtual terminals, switched with Ctrl+Alt+F1–F12, with X on
a terminal of its own. Sound through ALSA (over OSS and an AC'97 driver).
**Graphics** — **Xorg with Window Maker**, preinstalled, on the framebuffer
(`/dev/fb0`, Linux fbdev). Six virtual terminals, switched with
Ctrl+Alt+F1–F6 or Alt+F1–F6, with X on a terminal of its own; Ctrl+Alt+Backspace
ends the session. Input as Linux evdev on `/dev/input/event*`.
**Devices** — PCI with a bus-agnostic device model at `/proc/devices`.
**Drivers** — written from the specifications, and **Linux's own, unmodified,
through [LDLS](docs/architecture/ldls.md)**: a `.ko` runs in an ordinary process
and reaches the hardware through `/dev/pci`, so a crashed driver costs an interface,
not the machine. The laptop's Realtek NIC is driven that way.
| | |
|---|---|
| Storage | AHCI (SATA), NVMe, IDE, USB mass storage |
| Network | Intel e1000, Realtek r8169 and RTL8139 |
| Network | Intel e1000, Realtek RTL8139 and r8169 (the latter also as Linux's driver in a process) |
| USB | xHCI, hubs, HID keyboards and mice |
| Input | PS/2, I2C-HID laptop touchpads (DesignWare I2C, found through ACPI) |
| Input | PS/2, I2C-HID laptop touchpads and keyboards (DesignWare I2C, found through ACPI) |
| Display | UEFI GOP framebuffer, virtio-gpu, Bochs/stdvga |
| Audio | AC'97 |
**Networking** — ARP, IPv4, ICMP, UDP, TCP and DHCP on lwIP. DNS, `wget`
over **HTTPS**, `ping`, and an `httpd` serving a directory back.
**Networking** — ARP, IPv4, ICMP, UDP, TCP and DHCP on lwIP; DNS, `wget` and `curl`
over **HTTPS**, `ping`, `httpd`, netlink for `getifaddrs`.
**Userland** — musl, toybox, mksh and zsh, plus whatever Alpine has: `ls`,
`ps`, `top`, `awk`, `diff`, `xterm`, `fastfetch` behave the way you expect,
because they are the real programs.
**When it dies** — PSOGM, the Purple Screen of Guru Meditation: stop code, fault
address, call chain, and the log as QR codes. Under it runs **GMMOS**, a micro OS with
its own keyboard drivers, so a dead machine can still show its log, take a few
commands, and restart or power off.
**Text** — a TrueType rasteriser (`glyf` outlines, composite glyphs, cmap
format 4). JetBrains Mono for the terminal, Roboto for the desktop to come.
**When it dies** — PSOGM, the Purple Screen of Guru Meditation: stop code,
fault address, call chain, and a QR code containing a text copy of the whole
report.
**On real hardware** — booted on an AMD B550 desktop (Ryzen 5 4600G), an ASUS
TUF A15 laptop and an Ivy Bridge HP all-in-one, from a USB stick.
**On real hardware** — booted from a USB stick on an AMD B550 desktop (Ryzen 5
4600G), an ASUS TUF A15 laptop and an Ivy Bridge HP all-in-one.
## Quick start
@ -134,19 +132,19 @@ TUF A15 laptop and an Ivy Bridge HP all-in-one, from a USB stick.
make # kernel + UEFI loader + root filesystem
make qemu # build it and boot it
make iso # a bootable ISO for VMware or real hardware
./write.sh sdX # write that ISO to a USB stick (Linux; it checks what it is overwriting)
```
The ISO is a hybrid image: write it to a USB stick with
`dd if=schos.iso of=/dev/sdX bs=4M` (or Rufus/Etcher in DD mode) and boot it
on any UEFI machine.
The ISO is a hybrid image: it boots on any UEFI machine from a stick written with
`write.sh`, `dd if=schos.iso of=/dev/sdX bs=4M`, or Rufus/Etcher in DD mode. **It runs
from RAM and touches none of the machine's disks.** Log in on the console, and type
`startx` for the desktop.
Builds on **Linux, macOS, FreeBSD/OpenBSD/NetBSD and Windows** (Git Bash). The
toolchain is clang + lld everywhere — it is a cross-compiler by construction, so
one LLVM install targets the bare-metal kernel, the 16-bit boot code and musl
userland from any host. See **[docs/guides/building.md](docs/guides/building.md)** for
prerequisites per platform, and
**[docs/history/moving-to-linux.md](docs/history/moving-to-linux.md)** for moving a checkout
between machines.
userland from any host; `nix-shell` supplies all of it. See
**[docs/guides/building.md](docs/guides/building.md)** for prerequisites per platform.
## Testing
@ -160,28 +158,35 @@ tools/windows/bootcheck.ps1 -Tty -Ps # terminal behaviour, process enumeration
make schfs-check # SchFS B-tree, object and image suites
```
`bootcheck` is PowerShell because `pwsh` runs on every supported host.
The numbers at the top are measured, not typed: `python3 tools/python/stats.py`
rewrites them here and on the website.
`bootcheck` is PowerShell because `pwsh` runs on every supported host. Several
programs in `cmd/` (`socktest`, `memfdtest`, `xready`, …) exist to be run *on* the
system and report which of their own checks failed. See
**[docs/guides/testing.md](docs/guides/testing.md)** for what each proves. The numbers at
the top are measured, not typed: `python3 tools/python/stats.py` rewrites them here
and on the website.
## Layout
```
kernel/ arch/ core/ dev/ drivers/ fs/ net/ proc/ sys/
kernel/ arch/ core/ dev/ drivers/ fs/ net/ proc/ sys/ acpi/ gmmos/ scff/
fs/schfs/ the filesystem -- same source the host tools compile
ldls/ the Linux driver layer: the .ko loader, BTF reader, Linux symbols
include/ kernel and userland headers, by subsystem (arch/ core/ fs/ dev/ ...)
boot/ uefi/ (PE loader) common/ (shared loader UI)
lib/ cmd/ first-party userland runtime and programs
ports/ third-party software built from source
etc/ what the image starts with: schinit's job manifests, motd, ...
ports/ third-party software built from source; ports/alpine is the apk root
tools/ windows/ (.ps1) posix/ (.sh) python/ (.py) and .c/.pl
projects/ things that run ON SchOS (an installer, SchFS for Linux: both frozen)
docs/ architecture/ (what it is) plan/ (what's next)
guides/ (how to work on it) history/ (why it's like this)
Website/ (the site, and the docs reader)
```
**[docs/README.md](docs/README.md)** is the index. If you are reading the tree
for the first time, [docs/architecture/README.md](docs/architecture/README.md)
is the system layer by layer.
is the system layer by layer, and [docs/plan/1.0.md](docs/plan/1.0.md) says
where it stands against its finish line.
One rule worth knowing: **the kernel and the host tools compile the same SchFS
source**. `mkschfs` cannot disagree with the kernel about the on-disk format,
@ -193,19 +198,24 @@ Another: **syscalls are declared in exactly one place**,
## Not there yet
- **No threads.** `clone` makes processes, not threads (`CLONE_VM` is
refused), so multi-threaded programs run on one thread or not at all. Xorg
runs with `-dumbSched` for this reason.
- **No installer, and nothing persists.** The live image runs from RAM and
writes nothing to the machine's disks, so what you install or save is gone at
reboot. This is the one thing between the system and its 1.0 definition.
- **No GPU acceleration.** Xorg draws in software; the plan is Linux's `amdgpu`
through LDLS ([docs/plan/gpu.md](docs/plan/gpu.md)). There is no IOMMU either,
so a driver in a process is isolated against its bugs, not against malice.
- **No udev.** Xorg is told its input devices by a config file instead of
finding them; `/sys` and the device-event socket are what is missing.
finding them; `/sys` has no device tree and no uevent socket.
- **WebKit browsers do not start.** NetSurf does; Epiphany's web process dies at
start-up, and it has not been run to ground.
- **USB 2.0 controllers (EHCI)** have no driver. On older machines the ports
wired only to EHCI do nothing; xHCI ports work.
- **Touchpads run in mouse mode**: pointer, click and tap, but no two-finger
scroll yet.
- **No page cache**, so writable `MAP_SHARED` of a file is refused rather than
faked. SysV shared memory is missing too.
- **No installer.** SchOS runs live from the USB stick; nothing is written to
the machine's disks.
faked, and `mprotect` is accepted and ignored (nothing has NX).
- **No Wi-Fi, no HDA audio**, and the Realtek NIC on the laptop has reached the
point of finding its PHY; whether it carries traffic there is not confirmed.
- SchFS has no Linux driver yet; the plan is on-disk format version first, then
FUSE, then a kernel module.
- CFF/OpenType outlines and TrueType hinting are deliberately out of scope.
@ -215,14 +225,15 @@ Another: **syscalls are declared in exactly one place**,
**GPL-2.0-or-later**, copyright Nexoniarz. See [LICENSE](LICENSE).
The kernel derives from xv6, which is MIT — see [LICENSE.MIT](LICENSE.MIT).
Third-party code redistributed in a built image (musl, toybox, mksh, zsh, kilo,
the fonts) keeps its own licence; [NOTICE](NOTICE) carries the attributions.
See [docs/licensing.md](docs/licensing.md).
Third-party code redistributed in a built image (musl, toybox, mksh, zstd, the
fonts, and Alpine's packages, each under its own licence) keeps that licence;
[NOTICE](NOTICE) carries the attributions. See [docs/licensing.md](docs/licensing.md).
Drivers may be adapted from BSD sources and, since the move to the GPL, from
Linux — GPL-2.0-only code combines with GPL-2.0-or-later, and the result ships
under GPLv2. Best of all is still the public specification — xHCI, virtio,
AHCI, e1000 — which carries no licence on what you write from it.
under GPLv2; Linux's own drivers can also be run unmodified through LDLS. Best of
all is still the public specification — xHCI, virtio, AHCI, e1000 — which carries
no licence on what you write from it.
---