Rename Schunix to SchOS; the kernel becomes SchIFT

Removes the "-unix" element and with it any trademark exposure to The
Open Group.

The split follows the ecosystem layout: SchOS is the system, and the
kernel has its own name. Kernel-identity strings are the only places
that take SchIFT -- uname(2) sysname, /proc/version, and the two licence
sentences that say "kernel" outright. That is what every Unix does here:
`uname -s` on Linux reports the kernel, not the distribution. Everything
a user reads as the product -- panic screen, boot menu, error prefixes,
docs, LICENSE, NOTICE -- is SchOS.

schunix.img is schos.img, the logo assets and the musl TLS patch are
renamed, and __SCHUNIX__ is __SCHOS__ (the define and the patch that
consumes it moved together).

Two things the rename broke, both found by the bootcheck suite:

  - shmtest wrote "SCHUNIX-MMAP-OK" with a hardcoded length of 15 and
    compared it back by hand-counted offsets (m[3]=='U', m[14]=='K').
    The shorter marker left the write running two bytes past the literal
    and the compare reading past the data, failing a file-backed mmap
    that was working correctly. Now written and compared through one
    constant with sizeof.
  - bootcheck asserted a 31-byte file after appending to
    "hello-from-schunix"; the shorter string makes it 29.

Both are the same mistake: a string literal whose length is written out
somewhere else. Full suite green -- base, Tty, Ps, Sock, Fb, Usb, Evdev.
This commit is contained in:
Nexoniarz 2026-08-09 14:09:59 +02:00
commit e04ca28812
83 changed files with 520 additions and 601 deletions

View file

@ -77,7 +77,7 @@ Bringing in toybox (see "Coreutils" below) surfaced four more, all fixed:
all (`kernel/sys/linux_abi.c`) — every external command spawn from a
program that prefers `vfork()` over `fork()` failed outright. Mapped to
the existing `fork()` (a fully correct, if slightly slower, substitute).
- `sys_stat`/`fstat`/`fstatat` (`kernel/sys/sys_fs.c`) filled in Schunix's
- `sys_stat`/`fstat`/`fstatat` (`kernel/sys/sys_fs.c`) filled in SchOS's
own native `struct stat` layout regardless of the caller — musl/toybox
parse a fixed Linux ABI byte layout instead, so `st_mode` was garbage and
tools like `ls` couldn't tell files from directories, or executables from
@ -110,7 +110,7 @@ programs, pipes, and `ls`/`mkdir`/`grep` without issue.
## 2. Naming standardization
Schunix standardizes on exactly one name per role, regardless of the
SchOS standardizes on exactly one name per role, regardless of the
underlying implementation: the shell is always installed and exec'd as
`/bin/sh` (currently mksh, built from `ports/mksh/`), and PID 1 is always
`/bin/init`. `cmd/init/main.c`'s exec loop only ever tries `/bin/sh` — no
@ -161,7 +161,7 @@ Split into two stages, the standard way real bootloaders solve this:
compiled size, and errors out (like `tools/sign.pl` does for stage 1) if
it ever grows past that budget instead of silently corrupting the layout.
The kernel now starts at disk sector 17 instead of 1 (`schunix.img`'s `dd
The kernel now starts at disk sector 17 instead of 1 (`schos.img`'s `dd
... seek=17` in the root `Makefile`, and the equivalent `+(1+STAGE2_SECTORS)`
in `stage2main.c`'s `readseg()` — all three places that encode
`STAGE2_SECTORS` have to agree, or the kernel won't be found on disk at
@ -184,7 +184,7 @@ renderer in `stage2main.c` (not the kernel's `vga.c` — paging isn't set up
yet, so the LFB physical address from the VBE block is used as a plain
pointer) reusing the kernel's own font data (`include/font.h`) directly.
It fills the framebuffer with PSOGM's purple (matching
`kernel/core/console.c`'s panic screen) and draws "SCHUNIX" centered, then:
`kernel/core/console.c`'s panic screen) and draws "SCHOS" centered, then:
- **Real-time loading bar**: `readsect()` (in `stage2main.c`, not the
kernel) calls `progress_tick()` after every 512-byte disk read, updating
@ -210,7 +210,7 @@ It fills the framebuffer with PSOGM's purple (matching
`sys_reboot()`); a real bootloader can't jump into BIOS/UEFI setup
directly, so this is the closest honest equivalent — it gives the user
a fresh POST during which their firmware's own setup-menu key works.
- **Verbose boot**: picking "Boot Schunix (verbose)" writes a flag byte to
- **Verbose boot**: picking "Boot SchOS (verbose)" writes a flag byte to
`BOOT_VERBOSE_FLAG_ADDR` (`VBE_INFO_ADDR + 0x100`, i.e. just past the VBE
block) before jumping to the kernel. `kernel/core/main.c`'s `kmain()`
reads it into a global `boot_verbose` as its very first action and, if
@ -496,7 +496,7 @@ became an amber terminal. `include/theme.h` is now the one palette, and the
rule is: **normal states are calm and dark; only failure is loud.** PSOGM keeps
the purple entirely to itself, which is what makes it mean something.
The splash copy went from "Schunix Boot Manager / version 1.0 / Memory: 1023 MB
The splash copy went from "SchOS Boot Manager / version 1.0 / Memory: 1023 MB
/ Press F8 for boot menu..." to the product name, a rule in the accent colour,
and the one hint that is actionable — moved to the bottom, where a hint
belongs. No shipping OS names its bootloader on the splash.

View file

@ -1,4 +1,4 @@
# SchAPI, and Schunix as a system
# SchAPI, and SchOS as a system
Status: **direction agreed, not yet implemented.** Nothing in this document
changes what is being built this week; it changes what everything is being
@ -8,7 +8,7 @@ built *towards*. See §7 for what actually happens now.
## 1. The decision
Schunix stops being "a Unix-like kernel with a userland bolted on" and becomes
SchOS stops being "a Unix-like kernel with a userland bolted on" and becomes
a **system**: a kernel, a native API, and the services and applications that
sit on it, designed together.
@ -50,7 +50,7 @@ Linux made the opposite choice — the syscall ABI *is* the contract, "we do not
break userspace" — and consequently every syscall mistake ever made is still
there, with a `2` or a `64` suffixed to the name of its replacement.
So, for Schunix:
So, for SchOS:
```
┌──────────────────────────────────────────────┐
@ -58,7 +58,7 @@ So, for Schunix:
├──────────────────────────────────────────────┤
│ SchAPI │ POSIX / Linux personality│ ← THE STABLE BOUNDARY
├──────────────────┴───────────────────────────┤
│ libschunix — the only thing that may syscall│
│ libschos — the only thing that may syscall│
├──────────────────────────────────────────────┤
│ syscall table — PRIVATE, unstable, renumberable
├──────────────────────────────────────────────┤
@ -69,11 +69,11 @@ So, for Schunix:
Rules that follow, and they are not negotiable if the promise is to hold:
1. **A program that issues `syscall` directly is unsupported.** It may break at
any release. Only `libschunix` may.
2. `libschunix` exports versioned symbols. An entry point's behaviour never
any release. Only `libschos` may.
2. `libschos` exports versioned symbols. An entry point's behaviour never
changes; a changed behaviour is a new version of the symbol.
3. The kernel may renumber, merge, split or delete syscalls at will, provided
`libschunix` still presents the same surface.
`libschos` still presents the same surface.
This *reconciles* with the existing decision to adopt Linux syscall numbering
(`docs/roadmap.md`, and the reason musl/toybox/mksh work at all). Linux
@ -98,7 +98,7 @@ Every public interface carries exactly one tier:
| `provisional` | Until the next release | Freely |
| `internal` | None | Freely, without notice |
**Everything in Schunix today is `provisional`.** The freeze starts at 1.0 and
**Everything in SchOS today is `provisional`.** The freeze starts at 1.0 and
covers only what is marked `stable` at that moment. This is not a way of
dodging the commitment — it is the only way to make it, because a promise made
now would permanently enshrine, among other things, a `fcntl(F_SETFL)` that
@ -164,7 +164,7 @@ reasons that a single tree cannot give:
That table is the same lesson §1 of the roadmap already learned the hard way
with FreeBSD's `sys/dev/usb`: 100k lines welded to newbus, where porting the
USB stack means porting the device framework first. Networking is the same
shape. Read FreeBSD, lift NetBSD, write Schunix.
shape. Read FreeBSD, lift NetBSD, write SchOS.
### Licensing — read this before copying anything
@ -181,7 +181,7 @@ Ranked by value, not by size:
1. **`sys/net`, `sys/netinet` — the TCP/IP stack.** The largest single win
available. Phase 2 of the roadmap wants ARP/IPv4/ICMP/UDP/TCP, and this is a
mature, clean, readable, 2-clause-heavy implementation of exactly that.
2. **`sys/kern/subr_pool.c` — the pool/slab allocator.** Schunix has `kalloc`
2. **`sys/kern/subr_pool.c` — the pool/slab allocator.** SchOS has `kalloc`
and a page at a time. Every subsystem written since has invented its own
fixed-size table to work around that.
3. **`autoconf` — the driver framework** (`config(1)`, `cfdriver`/`cfattach`,
@ -203,7 +203,7 @@ relicensed-in-notice, and maintained forever under the §3 promise.
Not yet designed. What is decided about it:
- It is the native interface; POSIX is available beneath it but not the idiom.
- It is reached through `libschunix`, never by direct syscall.
- It is reached through `libschos`, never by direct syscall.
- It is designed *with* Schcom in mind, because a compositor and its clients
are the first real users and their needs (IPC, shared buffers, event streams,
object lifetimes) are what will shape it.
@ -234,6 +234,6 @@ What this document changes *today* is only this:
something to work with at 1.0.
3. When the network stack is written, NetBSD's is the starting point rather
than a blank file — with the licence check in §5 applied per file.
4. `libschunix` is created when there is a second personality to justify it.
4. `libschos` is created when there is a second personality to justify it.
Until then, the *rule* stands even though the library does not exist yet:
no new first-party program issues raw syscalls.

View file

@ -42,7 +42,7 @@ end to end.
## 2. What is deliberately not taken
- **No ZFS storage pools / RAID-Z / vdevs.** Multi-disk redundancy is a large
subsystem that solves a problem Schunix does not have yet.
subsystem that solves a problem SchOS does not have yet.
- **No btrfs-style rebalancing or online format conversion.** Enormous
complexity, and it is the historical source of btrfs's worst bugs.
- **No actual SQL.** No parser, no query planner, no relational engine. See §6 —
@ -242,7 +242,7 @@ Phases 1-3 are roughly 3,000-4,000 lines and are the bulk of the work. Phase 1
alone (B-tree + torture harness) is worth doing carefully and unhurriedly; every
later phase compounds on it.
This is the largest single piece of work in Schunix. It is also entirely
This is the largest single piece of work in SchOS. It is also entirely
ordinary filesystem engineering with excellent published references
(Giampaolo for BeFS; the btrfs design papers; the ZFS uberblock/checksum-in-
parent scheme) — there is no research risk here, only volume.
@ -254,7 +254,7 @@ populate this format. Building it against v1 means building it twice.
Three different things get called "the limit", and they are worth keeping apart:
what the **on-disk format** can express, what **this implementation** can
currently mount, and what the **rest of Schunix** can carry. The smallest one is
currently mount, and what the **rest of SchOS** can carry. The smallest one is
what you actually hit.
### The format
@ -292,7 +292,7 @@ raising `SCHFS_SPACE_PAGES` to 4096 makes it 512 GiB at 64 KiB of pointers per
mount. It is set where it is because the page-pointer vector lives inside
`struct schfs_vol`, which the kernel holds as static storage.
### The rest of Schunix
### The rest of SchOS
These are VFS and driver limits rather than SchFS ones:

View file

@ -75,9 +75,9 @@ need.
## 3. Linux drivers
**Decided 2026-08-08.** Linux drivers are not shipped with Schunix and never
**Decided 2026-08-08.** Linux drivers are not shipped with SchOS and never
will be. The user may install one on their own machine, through a device
manager or equivalent, and Schunix will load it.
manager or equivalent, and SchOS will load it.
The licensing reasoning matters and is worth stating exactly, because it is
easy to get wrong in both directions:

View file

@ -9,7 +9,7 @@ that can't be rebuilt (except upstream tarballs, which live in `dist/` and are
deliberately kept out of `clean`).
```
schunix/
schos/
├─ boot/ Stage 1 MBR + stage 2 loader (splash, F8 menu, kernel load)
├─ kernel/ The kernel, by subsystem: arch/ core/ dev/ fs/ proc/ sys/
├─ include/ Headers shared by kernel, userland, and tools/mkfs
@ -19,7 +19,7 @@ schunix/
│ cmd/<name>/main.c → sysroot/bin/<name>
├─ ports/ Third-party software — one directory per port.
│ Contains ONLY a Makefile and optional patches/.
├─ projects/ Things that run ON Schunix rather than things that ARE it:
├─ projects/ Things that run ON SchOS rather than things that ARE it:
│ the compositor, window manager, desktop, and installer.
│ Not part of the kernel build. See projects/README.md.
├─ tools/ Host-side helpers, SOURCE ONLY: mkfs.c, the SchFS test

View file

@ -1,13 +1,13 @@
# Licensing
The one page to check before copying anyone else's code into Schunix.
The one page to check before copying anyone else's code into SchOS.
Referenced from `LICENSE`, `LICENSE.MIT` and `NOTICE`, all three of which
pointed here long before this file existed.
---
## 1. Schunix is Apache-2.0
## 1. SchOS is Apache-2.0
Copyright Nexoniarz. See `LICENSE`.
@ -19,7 +19,7 @@ outside contributions, that silence is the expensive kind.
What that grant means in practice: Apache-2.0 §2 gives everyone a perpetual,
worldwide, irrevocable licence to reproduce, modify, sublicense and distribute
Schunix. Any additional restriction stated elsewhere — in a README, a website,
SchOS. Any additional restriction stated elsewhere — in a README, a website,
or a policy — does not narrow it. The licence text is what holds up.
If restricted distribution is ever genuinely wanted, that is a licence change
@ -57,7 +57,7 @@ licences at once.
GPL-3.0 fixed this in the other direction (Apache-2.0 is compatible *into*
GPLv3), but that does not help: the result would have to ship under GPLv3, and
Schunix does not.
SchOS does not.
**Practical consequence:** BSD drivers can be adopted. Linux drivers cannot,
ever, no matter how convenient. This is why the USB stack was written from the
@ -113,7 +113,7 @@ sys/netinet6 51 files, 5 " " "
```
Encouraging at first glance — the 25 in `sys/netinet` are almost all SCTP,
DCCP and multicast routing, none of which Schunix needs. `ip_input.c`,
DCCP and multicast routing, none of which SchOS needs. `ip_input.c`,
`ip_output.c`, `udp_usrreq.c`, `if_arp.c`, `ip_icmp.c`, `if.c` and `route.c`
are all UC 3-clause, i.e. fine.
@ -161,7 +161,7 @@ tables and FreeBSD's locking. Taking it means porting FreeBSD's kernel
infrastructure first and finding the TCP somewhere underneath, which is the same
conclusion `docs/roadmap.md` §1 already reached about `sys/dev/usb`.
lwIP was written for the case Schunix is in: a small operating system with a raw
lwIP was written for the case SchOS is in: a small operating system with a raw
Ethernet driver and no infrastructure to speak of. Its port layer is a handful
of files, it has no dependency on the host kernel's allocator or locking, and it
brings ARP, IPv4, ICMP, UDP, TCP, DHCP and DNS.
@ -175,7 +175,7 @@ Chosen 2026-08-09, both licences checked at source rather than assumed:
| Roboto | desktop, window manager, compositor | **Apache-2.0** |
| JetBrains Mono | terminal, TTY | **SIL OFL 1.1** |
Roboto is the same licence as Schunix, so it is the easy case: a NOTICE entry
Roboto is the same licence as SchOS, so it is the easy case: a NOTICE entry
and nothing else.
OFL is permissive and bundling is precisely what it is for, with two conditions
@ -195,7 +195,7 @@ worth knowing before anyone subsets or converts a font:
## 4. Things that are deliberately not shipped
Some code is fine to *build and run locally* and impossible to *distribute*
with Schunix. Keeping the distinction sharp is what stops it eroding:
with SchOS. Keeping the distinction sharp is what stops it eroding:
- **`Refrence/`** — a FreeBSD checkout (`Refrence/freebsd-src`), kept as
reference material and a parts bin. Never built, never in an image. The

View file

@ -7,7 +7,7 @@ plus an installer and a `.sip` package format.
This file records two things that are easy to lose: the *order* the work has
to happen in, and the decisions that constrain it.
**Superseded in direction, not in order.** Schunix is now aimed at being a
**Superseded in direction, not in order.** SchOS is now aimed at being a
*system* rather than a Unix-like kernel with a userland attached: a NeXTSTEP/
macOS-shaped layering, with POSIX kept complete but demoted from identity to
personality, and a native API (**SchAPI**) above it. See
@ -189,7 +189,7 @@ width text is not a font change, it is a text-rendering layer.
as-is if wanted; writing one is also reasonable and more interesting
- [ ] **The typefaces, decided 2026-08-09.** Both verified, not assumed:
**Roboto** for the desktop, window manager and compositor --
**Apache-2.0**, the same licence as Schunix, so it needs nothing beyond a
**Apache-2.0**, the same licence as SchOS, so it needs nothing beyond a
NOTICE entry.
**JetBrains Mono** for the terminal and TTY -- **SIL OFL 1.1**, and
notably with *no* Reserved Font Name declared, so it may be modified and
@ -205,7 +205,7 @@ width text is not a font change, it is a text-rendering layer.
**Font licensing: public domain or very permissive only.** No SIL OFL if it
can be avoided, no "free for personal use", no CC-BY-SA. The constraint is
the same one that governs drivers (§1): a font file is redistributed inside
every Schunix image, so its licence attaches to the image.
every SchOS image, so its licence attaches to the image.
Safe choices, in rough order of usefulness:
@ -237,7 +237,7 @@ key-down/key-up with modifiers and no line discipline at all — an evdev-style
### Phase 6 — Installer and `.sip`
`.sip` (Schunix Installation Package), the stated model being WIM in Windows
`.sip` (SchOS Installation Package), the stated model being WIM in Windows
PE: a *file-based* image rather than a block image, so one file can hold a
whole filesystem, be applied to a partition of any size, and hold several
images that share their common files.
@ -301,7 +301,7 @@ sysvinit is not the config format, it is *demand launching*: launchd holds the
listening socket or watches the path, and starts the job when something actually
arrives. That inverts the dependency graph — jobs stop needing to declare what
must start before them, because the thing they depend on answers on first use.
Schunix already has the two pieces that makes possible: `AF_UNIX` sockets
SchOS already has the two pieces that makes possible: `AF_UNIX` sockets
(`kernel/net/unix.c`) and a real `/proc`. What is missing is a supervisor that
can hold a socket on a job's behalf and hand it over on exec, plus a job
description format. Prerequisite for this being worth anything: `ps` and `top`
@ -360,7 +360,7 @@ palette and a layout, none of which care how the pixels were found. What does
not survive is every assumption in `stage2main.c` about where things live in low
memory (see `docs/layout.md`).
### SchFS beyond Schunix
### SchFS beyond SchOS
Three ideas parked 2026-08-08, in the order they should happen.
@ -447,7 +447,7 @@ Three details worth keeping:
- The ceiling is **3 GB**, because `kvmalloc()` maps 0–4 GB as four 1 GB pages
and marks the top one uncached for PCI BARs.
- Below `PHYSTOP_MIN` it prints why and stops, rather than triple faulting in
silence. At 24 MB: `e820: only 23 MB usable; Schunix needs at least 24 MB`.
silence. At 24 MB: `e820: only 23 MB usable; SchOS needs at least 24 MB`.
The original text is kept below because the reasoning still applies to the SMP
half of §3b, which is the same shape of bug: a constant nobody revisited.