Initial commit: Schunix as it stands before the SchOS rename

An x86-64 operating system built from xv6, now largely rewritten: SMP,
a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF
rasteriser, and a Linux-numbered syscall ABI.

No history before this point -- the tree was never under version control.
This commit exists so the rename that follows has something to undo to.
This commit is contained in:
Nexoniarz 2026-08-09 13:47:01 +02:00
commit d0f7acf9eb
275 changed files with 51417 additions and 0 deletions

57
projects/README.md Normal file
View file

@ -0,0 +1,57 @@
# projects/
Things that run **on** Schunix rather than things that **are** Schunix.
Everything above this directory — `kernel/`, `boot/`, `lib/`, `cmd/`,
`include/` — is the operating system: it boots, it owns the hardware, and it
is one program that either works or does not. Everything in here is an
ordinary program that talks to it through syscalls, exactly as `toybox` does.
The split exists because the alternative gets bad quickly. A compositor,
a window manager and a desktop are each larger than the kernel will be for a
long time. Grown inside the OS tree they would blur into it: a compositor
would start reaching into kernel headers because they are right there, the
build would grow a dependency from the kernel to a GUI, and "does Schunix
boot" would stop having a clear answer. Keeping them separate forces the
boundary to be a real interface — syscalls and protocols — rather than a
shared header nobody meant to share.
Concretely, code in here:
- links against the sysroot's libc, never against kernel headers
- talks to the kernel only through syscalls and `/dev`
- can be built, run and debugged without rebuilding the kernel
- may be split into its own repository later without untangling anything
## What lives here
| Directory | What it is |
|------------|-----------------------------------------------------------------|
| `schcom/` | Schunix Compositor. Owns the display, composites clients, routes input. |
| `schwm/` | Schunix Window Manager. Window placement, decoration, focus, on top of Schcom. |
| `schde/` | Schunix Desktop Environment. Panel, launcher, settings, file manager. |
| `schinst/` | The installer, the installation environment, and `.sip` tooling. |
| `schfs-linux/` | SchFS as a filesystem for Linux. FUSE first, a kernel module later. |
**`schfs-linux/` is written to stand on its own.** It does not mention Schunix
anywhere, and that is deliberate rather than an oversight: it is intended to be
the first piece released, and it has to make sense to somebody who has never
heard of the OS it came from — a filesystem is judged as a filesystem. The
connection can be made later, once there is a finished system to connect it to.
Practically, that means anything added there needs its own licence header, its
own README framing, and no cross-references into this tree. It shares the
*format* with `kernel/fs/schfs/`, not the prose.
They stack: SchDE needs SchWM needs Schcom needs the kernel. Nothing points
the other way, and nothing here is a dependency of the kernel build.
## Status
All four are scoped and none is started. What each is waiting on is written
in its own README, and the ordering is in `docs/roadmap.md`.
The short version: Schcom cannot start until the kernel has **unix domain
sockets** (for the client protocol and for passing buffer handles) and **raw
input events** (a `/dev/input` that bypasses the tty line discipline).
Shared memory and framebuffer mmap are already done.

42
projects/schcom/README.md Normal file
View file

@ -0,0 +1,42 @@
# Schcom — the Schunix Compositor
Owns the display. Every pixel that reaches the screen goes through it.
Clients do not draw to the framebuffer; they draw into their own buffers and
hand them over. Schcom decides what is on top of what, composites the result,
and presents it. It also owns input: it reads the raw event devices and sends
each event to whichever client should have it.
That is the whole job. Window *placement* is not part of it — that is SchWM's,
and Schcom exposes a protocol for it rather than implementing policy itself.
## Status
Not started. Scoped only.
## What it needs from the kernel first
| Need | State |
|---|---|
| Shared memory (`shmget`/`shmat`/`shmdt`) | done |
| `mmap` of `/dev/fb0` | done |
| Framebuffer geometry via the fbdev ioctls | done |
| **Unix domain sockets**, with `SCM_RIGHTS` | **missing** — `socket()` is a `NO_LINUX` stub |
| **Raw input events** — key down/up with modifiers | **missing** — input only arrives cooked, through the tty line discipline |
| Mode setting and double buffering | **missing** — needs the virtio-gpu driver |
The two marked missing are hard blockers, not inconveniences. A client and
the compositor have to pass a buffer handle between them, and a pipe cannot
carry one. And a compositor that reads the tty gets line-buffered text
delivered to a single foreground process, which is not input in any sense it
can use.
## Design notes, so far
- **Buffers are shared memory, not pipes.** A pipe means copying every frame;
at 800×600×32 that is 1.9 MB per frame per client. shm exists for this.
- **One protocol, versioned from the start.** SchWM and SchDE are separate
programs, so the protocol is a real compatibility surface from day one, not
after the fact.
- **Policy belongs to SchWM.** If Schcom starts deciding where windows go, the
split has already failed.

27
projects/schde/README.md Normal file
View file

@ -0,0 +1,27 @@
# SchDE — the Schunix Desktop Environment
The parts you actually look at: a panel, a launcher, settings, a file
manager, a terminal.
SchDE is a set of ordinary Schcom clients plus whatever shared widget code
they end up needing. Nothing in it is privileged and nothing in it is
special — if SchDE can do something that a third-party program could not, the
line has been drawn in the wrong place.
## Status
Not started. Last of the three, and deliberately so: there is no point
designing a panel before there is a compositor to put it on.
## What it will need that does not exist yet
- **Text rendering.** Everything here is text, and the console's fixed 8×16
CP437 grid is not usable for it. See phase 4 of `docs/roadmap.md` — a real
glyph cache and rasteriser, and layout as a library in `lib/` so the
terminal and the file manager are not each solving it.
- **A widget toolkit**, however small. Even a panel needs buttons, labels and
hit testing.
- **A terminal emulator.** Note the direction: the *kernel* console parses
ANSI today because it draws directly to the framebuffer. A GUI terminal is
a client that parses ANSI itself and renders it with proportional-capable
text. The two do not share code.

View file

@ -0,0 +1,178 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship made available under
the License, as indicated by a copyright notice that is included in
or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean, as submitted to the Licensor for inclusion
in the Work by the copyright owner or by an individual or Legal Entity
authorized to submit on behalf of the copyright owner. For the purposes
of this definition, "contribution" means any work of authorship,
including the original version of the Work and any modifications or
additions to that Work or Derivative Works of the Work.
"Contributor" shall mean Licensor and any Legal Entity on behalf of
whom a Contribution has been received by the Licensor and included
within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by the combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a cross-claim
or counterclaim in a lawsuit) alleging that the Work or any
Contribution embodied within the Work constitutes patent or
contributory patent infringement, then any patent licenses granted to
You under this License for that Work shall terminate as of the date
such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, You must include a readable copy of the
attribution notices contained within such NOTICE file, in
at least one of the following places: within a NOTICE text
file distributed as part of the Derivative Works; within
the Source form or documentation, if provided along with the
Derivative Works; or, within a display generated by the
Derivative Works, if and wherever such third-party notices
normally appear. The contents of the NOTICE file are for
informational purposes only and do not modify the License.
You may add Your own attribution notices within Derivative
Works that You distribute, alongside or in addition to the
NOTICE text from the Work, provided that such additional
attribution notices cannot be construed as modifying the License.
You may add Your own license statement for Your modifications and
may provide additional grant of rights to use, copy, modify, and
distribute those modifications as a separate work, subject to the
terms and conditions of this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any conditions of TITLE,
NONINFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
You are solely responsible for determining the appropriateness of
using or reproducing the Work and assume any risks associated with
Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or exemplary damages of any character arising as a
result of this License or out of the use or inability to use the
Work (even if such Contributor has been advised of the possibility
of such damages).
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may offer such
obligations only on Your behalf and on Your sole responsibility,
not on behalf of any other Contributor, and only if You agree to
indemnify, defend, and hold each Contributor harmless for any
liability incurred by, or claims asserted against, such Contributor
by reason of your accepting any warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright 2026 Nexoniarz
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copyright 2026 Nexoniarz

View file

@ -0,0 +1,72 @@
# SchFS
A copy-on-write filesystem, built from the ground up.
SchFS is a modern-shaped filesystem in the tradition of BeFS, ZFS and btrfs: a
copy-on-write B-tree, 64-bit object identifiers, checksummed metadata, and an
extent-based layout. It is written from first principles rather than derived
from an existing implementation.
**Status: early.** The on-disk format works and is exercised by a test suite,
but it is not stable and there is no compatibility promise yet. Do not put
anything you care about on it.
---
## What it is
| | |
|---|---|
| **Copy-on-write B-tree** | Metadata is never overwritten in place. An update writes new blocks and swings a pointer, so a torn write leaves the previous consistent state rather than a half-updated tree. |
| **Objects, not paths** | Everything is a 64-bit object id. Directories are a mapping from name to id, which keeps naming a separate concern from storage. |
| **Checksummed metadata** | CRC32c on every inode and on the superblock, verified on read. Corruption is detected where it happens rather than inferred later from strange behaviour. |
| **Derived free space** | The free map is computed from the allocation tree rather than stored alongside it. There is no second structure to disagree with the first. |
| **Extents** | Contiguous ranges rather than per-block pointers, so a large file costs a small number of records. |
## What it is not, yet
Being honest about this up front, because a filesystem's missing features are
the part that matters:
- **No snapshots.** The B-tree is copy-on-write, which is most of the machinery,
but nothing takes or names a snapshot yet.
- **No journal replay** beyond what copy-on-write gives for free.
- **No extended attributes**, no sparse-file support, no online repair.
- **No format versioning policy.** This is the first thing being fixed — see
the roadmap below — because everything else is harder to change without it.
---
## Roadmap
**1. An on-disk format version, and an upgrade path.** Not optional, and it gets
harder every day it is postponed: the moment an image exists that somebody cares
about, changing the layout means being able to read the old one. The superblock
already carries a version field and a checksum; what is missing is the policy —
a documented meaning for a version bump, a refusal to mount something newer than
the driver understands rather than misreading it, and an explicit upgrade step.
**2. FUSE.** The first Linux implementation is a FUSE filesystem, not a kernel
module. Three reasons, in order of weight: it can be tested with `fsx` and
`xfstests`, which are far harsher than any suite written alongside the code; it
carries no licence entanglement, since libfuse is LGPL and used across a process
boundary; and it can reuse the existing image-building and checking code rather
than reimplementing the format a second time and having the two disagree.
**3. A kernel module.** Only after the format is pinned and FUSE passes
`xfstests`. Writing a kernel filesystem against a format that is still moving is
how you end up maintaining two of them.
---
## Licence
Apache-2.0. See [LICENSE](LICENSE).
Apache-2.0 rather than MIT or BSD for one reason that matters at this level: it
contains an express patent grant and a patent-retaliation clause. MIT and BSD
are silent on patents, which means a contributor can hand you code and later
assert a patent over it.
Note that a Linux **kernel module** is a different licensing question from FUSE,
and one reason the FUSE implementation comes first.

View file

@ -0,0 +1,60 @@
# schinst — the installer, the installation environment, and `.sip`
Getting Schunix from an ISO onto a disk.
Three separate things live here:
1. **The installation environment.** A Schunix that boots from the ISO into a
known state with the installer running instead of a login shell. The ISO
already boots to userspace without a hard disk (`make iso`), so this is a
different init and a different root, not a different kernel.
2. **`.sip` tooling.** `mksip` to capture a tree into a package, and the apply
path that unpacks one onto a filesystem.
3. **The installer itself.** Partition, make a filesystem, apply the `.sip`,
install the bootloader, reboot.
## Status
Not started. `.sip` needs its format written down before any code exists.
## `.sip` — Schunix Installation Package
The stated model is WIM, the image format Windows PE installs from, and the
thing worth copying from WIM is that it is **file-based, not block-based**.
A block image (`.img`, `.iso`) is a byte-for-byte copy of a partition. It can
only be applied to a partition of the same size or larger, it carries the
free space and the fragmentation of the machine it came from, and two images
that share 90% of their files share nothing on disk.
A file-based image stores files and metadata. It can be applied to any
filesystem of any size, it carries no free space at all, and identical files
across images are stored once.
Sketched structure — one header, one index, one blob store:
```
header magic, version, blob count, index offset, uncompressed size
index per file: path, mode, uid/gid, mtime, size, content hash
(directories and symlinks are index entries with no blob)
blob store content-addressed, one entry per distinct hash, compressed
```
Deduplication falls out of content addressing rather than being a feature:
two identical files hash the same and there is only one blob. **Most of this
already exists.** `tools/mkschfs.c` and `tools/mkfs.c` both do exactly this
dedup, with an `(st_dev, st_ino)` fast path so a hard link is not hashed
twice, and SchFS's B-tree is already content addressed. `mksip` should share
that code rather than reimplement it — that was the reason the dedup was
factored the way it was.
Open questions, all of which want deciding before code:
- Compression. Something with a small decompressor is worth more here than
something with a good ratio, because the decompressor has to run in the
installation environment.
- Whether multiple images per `.sip` (WIM's real trick — install, recovery
and boot images sharing one blob store) is worth the complexity now.
- Whether the kernel can mount a `.sip` read-only directly. It is close to a
filesystem already, and if it can, the installation environment's root can
simply *be* the `.sip`.

27
projects/schwm/README.md Normal file
View file

@ -0,0 +1,27 @@
# SchWM — the Schunix Window Manager
Policy. Where windows go, which one has focus, what happens when you drag a
title bar, how alt-tab behaves, what a window looks like at its edges.
SchWM is a *client* of Schcom, not part of it. It talks the same protocol
every other client does, plus a privileged extension that lets it position
and stack surfaces it does not own. That extension is the entire difference
between a window manager and an ordinary application.
## Status
Not started. Blocked on Schcom, which is blocked on the kernel — see
`../schcom/README.md`.
## Why it is separate from the compositor
Merging them is the common shortcut and it is the one that hurts later.
Compositing is mechanical and must never stall: it runs every frame and a
mistake there is a frozen screen. Window management is policy, full of
special cases and personal taste, and it changes constantly. Putting them in
one process means every experiment with focus behaviour risks the thing that
puts pixels on the screen.
Keeping them apart also means SchWM can be restarted, replaced, or simply not
run. A Schcom with no window manager should still show a full-screen client —
that is a useful state to be able to reach when something is wrong.