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:
parent
2556a955b3
commit
cb3d28e3d6
57 changed files with 685 additions and 2121 deletions
193
README.md
193
README.md
|
|
@ -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.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue