A 64-bit operating system written from the metal up: SMP kernel, copy-on-write filesystem, Linux syscall ABI, Alpine packages, X11 on real hardware.
  • C 90.2%
  • Makefile 3.2%
  • PowerShell 2.3%
  • Shell 1.7%
  • Python 1.3%
  • Other 1.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Nexoniarz 8d836c66b2 PCI and USB devices in the /sys/devices tree, with uevents and USB hot-plug
PCI devices live at /sys/devices/pci0000:00/<addr> and USB devices under the
xHCI controller that carries their bus, below that bus's root hub usbN;
/sys/bus/pci/devices and /sys/bus/usb/devices are symlinks into it, and every
device has its subsystem and driver links, which is how udev learns SUBSYSTEM
and DRIVER. Writing to a device's uevent now announces it with MODALIAS,
PCI_ID, PRODUCT and the rest, so udevadm trigger covers them, and the USB core
sends add when a device is attached and remove as it goes. The root hub is
announced when the controller comes up, before anything is plugged in.

Checked under QEMU: lspci and udevadm info through the links, udevadm monitor
showing the kernel and udev add event for device_add usb-kbd/usb-mouse and
the remove event for device_del, and a triggered add for usb1 and 1-5.

Known limits: the bus-to-controller mapping is a convention (bus N is the Nth
xHCI in PCI order); PCI bridges are not parents; USB interfaces and
/dev/bus/usb nodes are absent; busybox's lsusb reads /dev/bus/usb and prints
nothing.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVRhxi9zpdW2uDUN4FVcao
2026-10-26 15:51:28 +01:00
.claude/memory include: one folder per subsystem, and includes that name it 2026-10-23 15:05:12 +02:00
boot Boot manager: Niveus window, keys and wells, Instrument Sans, pointer, other systems, working power entries 2026-10-26 15:31:39 +01:00
cmd Users and permissions: accounts, login, enforced file permissions, setuid, su, passwd, doas 2026-10-26 13:16:07 +01:00
config config/drivers.conf: which drivers are compiled in 2026-10-26 08:59:55 +01:00
docs PCI and USB devices in the /sys/devices tree, with uevents and USB hot-plug 2026-10-26 15:51:28 +01:00
etc Users and permissions: accounts, login, enforced file permissions, setuid, su, passwd, doas 2026-10-26 13:16:07 +01:00
include PCI and USB devices in the /sys/devices tree, with uevents and USB hot-plug 2026-10-26 15:51:28 +01:00
kernel PCI and USB devices in the /sys/devices tree, with uevents and USB hot-plug 2026-10-26 15:51:28 +01:00
ldls Cheaper cursor, a fortify panic that names its function; Finch's gap 2026-10-25 18:31:40 +01:00
lib include: one folder per subsystem, and includes that name it 2026-10-23 15:05:12 +02:00
ports Users and permissions: accounts, login, enforced file permissions, setuid, su, passwd, doas 2026-10-26 13:16:07 +01:00
projects Schcom is gone; the desktop path is Xorg now, Wayland groundwork next 2026-10-26 09:35:54 +01:00
srv userland: 268 applets, an editor, names that resolve, and a web server 2026-09-14 19:24:55 +02:00
tools Boot manager: Niveus window, keys and wells, Instrument Sans, pointer, other systems, working power entries 2026-10-26 15:31:39 +01:00
.gdbinit build: a gdb target, because the tree had no source-level debugger 2026-09-13 15:05:46 +02:00
.gitattributes README: the logo, what works now, and measured numbers 2026-10-24 22:02:44 +02:00
.gitignore Schcom is gone; the desktop path is Xorg now, Wayland groundwork next 2026-10-26 09:35:54 +01:00
LICENSE licence: SchOS is GPL-2.0-or-later, no longer Apache-2.0 2026-10-22 08:48:45 +02:00
LICENSE.MIT Rename Schunix to SchOS; the kernel becomes SchIFT 2026-08-09 14:09:59 +02:00
Makefile Boot manager: Niveus window, keys and wells, Instrument Sans, pointer, other systems, working power entries 2026-10-26 15:31:39 +01:00
NOTICE docs: 1.0 is reached; Schcom stays; Linux's r8169 set ships 2026-10-26 08:23:20 +01:00
README.md eudev starts at boot; Xorg finds its input devices through it 2026-10-26 11:44:21 +01:00
run.ps1 boot/uefi: the system information panel, and the offset that faked a version 2026-08-11 10:52:43 +02:00
shell.nix NetSurf: what GTK's images and libcurl's resolver needed 2026-10-25 04:10:26 +01:00
write.sh Faster ISO builds (69 s to 9 s) and a faster write.sh check 2026-10-25 19:28:03 +01:00

Shift, the SchOS mark

SchOS

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 · Xorg · Linux's own drivers


SchOS is a hobby operating system built by one person. It began as xv6 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 honest about being a hobby system: what is listed below has been run, not inferred, and the gaps are listed as plainly as the features. It boots from a USB stick on three different real machines.

In numbers

First-party code 72,766 lines, plus 23,670 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 179, from 29 asked for in ports/alpine/world
History 292 commits since 2026-08-09 (78 days)
Lines by language
Language Code Comments
C 67,615 21,904
Assembly 1,750 336
PowerShell 1,362 638
Python 943 150
Shell 896 531
Perl 129 45
Linker script 71 66

Measured by tools/python/stats.py; first-party code only, so ports/ and generated tables are not counted.

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 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
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, 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: 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 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: 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.

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.

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

Drivers — written from the specifications, and Linux's own, unmodified, through LDLS: 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 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 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 and curl over HTTPS, ping, httpd, netlink for getifaddrs.

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.

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

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: 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; nix-shell supplies all of it. See docs/guides/building.md for prerequisites per platform.

Testing

Booting to a prompt proves nothing: a filesystem can mount and still fail the first real command, and that has happened here. So the test harness drives the serial console and asserts on what comes back.

tools/windows/bootcheck.ps1            # boot, run real commands, check the answers
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. 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 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/ 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
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 is the index. If you are reading the tree for the first time, docs/architecture/README.md is the system layer by layer, and 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, because there is only one implementation — found and fixed on the host, where a test takes a second instead of a boot.

Another: syscalls are declared in exactly one place, kernel/sys/table.inc. Everything else is generated from it.

Not there yet

  • 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). There is no IOMMU either, so a driver in a process is isolated against its bugs, not against malice.
  • udev sees the kernel's own devices only. eudev runs and Xorg finds its input devices through it; PCI and USB devices are not yet in the /sys/devices tree.
  • 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, 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.

Licensing

GPL-2.0-or-later, copyright Nexoniarz. See LICENSE.

The kernel derives from xv6, which is MIT — see LICENSE.MIT. 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 carries the attributions. See 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. Linux's own drivers run unmodified through LDLS, and the ISO ships the Realtek r8169 set and its firmware; their licences and source are in NOTICE. Best of all is still the public specification — xHCI, virtio, AHCI, e1000 — which carries no licence on what you write from it.


Built with stubbornness and a serial console.