SchOS
A 64-bit operating system written from scratch — its own kernel, its own
filesystem, its own bootloader. It boots on UEFI, drives real hardware,
and runs unmodified musl and toybox on top.
Origin
It started as a teaching kernel and stopped being one
SchOS began as xv6, MIT's teaching operating system: 32-bit, single core, one filesystem, a few dozen syscalls. Almost none of that survives. What follows is what replaced it.
64-bit, and more than one core
Four-level paging, a real SMP bring-up, per-CPU state and a trap path that survives both. This is the part that invalidates most of what a 32-bit uniprocessor kernel assumes.
Its own filesystem
xv6's log-structured filesystem was replaced by SchFS: a copy-on-write B-tree with an uberblock ring, extents and checksummed metadata. A crash leaves either the old tree or the new one.
A Linux-shaped ABI
The syscall table adopted Linux numbering, which is what makes an
unmodified musl and an unmodified toybox run. The table is one
.inc file, and it is the seam the whole system is built around.
Hardware, not emulation
A UEFI loader, xHCI and USB storage, an e1000 with a real TCP/IP stack, virtio-gpu and VBE framebuffers, and a device model where a driver never names its consumer.
Drivers that are not in the kernel
A process can be handed a PCI device — its registers, its memory, its interrupts — and drive it. The GPU driver already runs that way. Nobody writes a driver for every device that exists; the answer is to stop requiring that they live inside.
Architecture
Three seams hold the whole thing together
Above the syscall table, software is ordinary and portable. Below the device
model, a driver never names its consumer and a consumer never names a driver.
And at /dev/pci, a driver stops needing to be in the kernel at
all. Everything else is arrangement.
cmd/vgpud — a driver that is an ordinary process.inc file — the ABI seamSCM_RIGHTS, signals, mmap, poll, procfsboot/uefi
uname -s reports SchIFT — the kernel — the way every Unix
reports its kernel rather than its distribution.
What it has
Built and running, and honest about the rest
Every card marked runs is in the tree and works today. The tags are not aspirational; the things that are not finished say so.
SchFS
Copy-on-write B-tree, a 128-slot uberblock ring, extents with refcounts and reflink, CRC32c on metadata, and free space derived from the tree rather than stored beside it — so there is no second structure to disagree with the first. There is nothing to repair after a crash.
SMP x86-64 kernel
Four-level paging, multiple cores, preemptive scheduling, a calibrated LAPIC timer, real signal delivery and job control. 205 syscalls on Linux numbering.
Networking
An e1000 driver under lwIP, with sockets for AF_INET, AF_UNIX and
AF_NETLINK. DHCP brings the interface up at boot; ping
reaches the outside world.
UEFI boot
A PE/COFF loader built with clang and lld-link that sets up its own page tables and hands the kernel a framebuffer. No BIOS path, no chainloading.
USB
xHCI, hubs, HID and mass storage — a keyboard and a USB disk that the kernel can mount, through the same device model as everything else.
Virtual terminals
Six of them, each with its own cell grid, scrollback and foreground
job — switched with AltGr+F1…F6, which is the
one chord a Linux host does not take for itself. The console draws to
whichever framebuffer is present, from the kernel's first line.
schinit
PID 1 does almost nothing: it forks a supervisor, spawns jobs on its behalf, and reaps. The supervisor holds the manifests and the respawn policy, and if it dies PID 1 replaces it and hands back the children it was already watching. PID 1 can re-exec itself without dropping them.
A real userland
musl and toybox, both unmodified, plus mksh as /bin/sh.
fastfetch builds from upstream source with an empty
patches/ directory — when it could not detect something, the
answer was to give the kernel what it was looking for.
Drivers outside the kernel
/dev/pci hands a process a device: its registers by
mmap, physically contiguous memory it can point the device
at, and interrupts as something to read(). The virtio-gpu
driver already lives out there. How that works →
Schcom
The compositor that will own the display. v0 runs, and descriptor passing — the one thing a Wayland client cannot do without — now exists. What a buffer still needs is a shareable memory object.
SchAPI
The native programming interface — specified, not built, and deliberately so. It should be designed from the compositor's experience rather than before it.
Hybrid
A driver can leave the kernel
Nobody writes a driver for every device that exists — not a project this size, and not any project. So the interesting question is not how to write more of them, but what a driver actually needs from a kernel, and whether it can have that from outside.
Its registers
mmap on /dev/pci, where the offset is the
physical address of a BAR. The kernel refuses any offset that is not
inside a BAR of a device this process was given, which is what stops it
being /dev/mem with extra steps.
Memory the device can reach
Physically contiguous, and the process is told the physical address — which is the whole reason it cannot do this for itself. The arena is reserved at boot, before the general allocator gets anything.
To be told when to look
Interrupts arrive by read(), so they compose with
poll. The kernel masks the line and leaves it masked until
the driver writes back — because a PCI interrupt is level-triggered, and
nobody but the driver knows how to clear it at the device.
A descriptor to arrive
sendmsg with SCM_RIGHTS. Handing a process the
device it is allowed to touch and handing a compositor a buffer turned
out to be the same act, which is why one primitive answered both.
$ vgpud vgpud: virtio-gpu at 00:03.0, currently held by virtio-gpu virtio-gpu: released to userspace; screen is the VBE framebuffer vgpud: claimed vgpud: display is 1280x800 vgpud: scanout is ours, framebuffer at physical 0x3eceb000 vgpud: drew a test pattern from userspace
No syscall in that transcript knows it is talking about a GPU. The kernel handed over a PCI device; the process decided what it was. That is the property that makes the interface general — and the reason SchOS's own drivers are being moved out through it first, rather than shaping it around something foreign and hoping it fits.
Numbers
The size of it
kernel/ and include/When it stops
PSOGM
When the kernel panics it does not scroll a stack trace past you. It draws a full-screen report — what failed, where, and the state that mattered — and encodes the whole thing as a QR code so it can leave the machine without being retyped.
This purple is #4B1D9A, and the theme reserves it for exactly
this. Normal states are calm and dark; only failure is loud. It is the one
colour in the system that means something, which is why it appears once on
this page and nowhere else.
Reading
Where to look
The documentation is written to outlive the work. Anything finished is
described in architecture/; anything intended lives in
plan/; and the bugs worth remembering are kept in
history/, in full, including the wrong turns.
Try it
One ISO, one stick, nothing written to your disks
It runs from RAM and leaves the machine as it found it. Or skip the
stick entirely — make qemu is the same system in a window.