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

@ -1,4 +1,4 @@
# Headless boot check: run Schunix under QEMU, type commands at the shell, and
# Headless boot check: run SchOS under QEMU, type commands at the shell, and
# assert on what actually comes back.
#
# Booting to a prompt proves nothing on its own -- a filesystem can mount and
@ -22,7 +22,7 @@
param(
[switch]$Fb,
# Boot schunix.iso from an emulated optical drive with NO hard disk
# Boot schos.iso from an emulated optical drive with NO hard disk
# attached, which is the only way to prove the ISO is self-contained.
# Needs `make iso` first.
[switch]$Iso,
@ -54,7 +54,7 @@ param(
$ErrorActionPreference = 'Stop'
$root = Split-Path $PSScriptRoot -Parent
$hda = Join-Path $root 'schunix.img'
$hda = Join-Path $root 'schos.img'
# The root filesystem. SchFS is the only root there is, so this is not a
# choice -- a kernel handed anything else on device 1 panics in forkret().
$hdb = Join-Path $root 'build\schfs.img'
@ -67,7 +67,7 @@ Remove-Item -Force $log -ErrorAction SilentlyContinue
# on its own, and every one of these has broken at some point while the boot
# still looked perfectly healthy.
$commands = @(
'echo hello-from-schunix > /tmp/bc.txt'
'echo hello-from-schos > /tmp/bc.txt'
'cat /tmp/bc.txt'
'echo second-line >> /tmp/bc.txt'
'wc -c /tmp/bc.txt'
@ -161,7 +161,7 @@ $commands += 'echo MARKER-DONE'
# The ISO run attaches no hard disk at all. That is the whole point: a kernel
# that still quietly needs one would boot happily here otherwise, and only
# fail on someone else's machine.
$isoPath = Join-Path $root 'schunix.iso'
$isoPath = Join-Path $root 'schos.iso'
if ($Iso -and -not (Test-Path $isoPath)) { throw "no $isoPath -- run 'make iso' first" }
$drives = if ($Iso) {
@ -222,7 +222,7 @@ $psi.Arguments = ($drives + $usbDevices + $monitor + @(
$psi.RedirectStandardInput = $true
$psi.UseShellExecute = $false
$what = if ($Iso) { 'schunix.iso, no hard disk' } else { "hdb = $(Split-Path $hdb -Leaf)" }
$what = if ($Iso) { 'schos.iso, no hard disk' } else { "hdb = $(Split-Path $hdb -Leaf)" }
Write-Host "==> booting ($what)" -ForegroundColor Cyan
$p = [System.Diagnostics.Process]::Start($psi)
@ -372,12 +372,16 @@ function Expect($pattern, $what) {
}
Expect 'MARKER-DONE' 'shell stayed alive through every command'
Expect 'hello-from-schunix' 'a file written on the root filesystem reads back'
Expect 'hello-from-schos' 'a file written on the root filesystem reads back'
Expect 'second-line' 'appending to that file works'
# 19 bytes of "hello-from-schunix\n" plus 12 of "second-line\n". The exact
# 17 bytes of "hello-from-schos\n" plus 12 of "second-line\n". The exact
# number is the point: an append that silently truncated still produced a file,
# and only the byte count said which one.
Expect '(?m)^\s*31\s' 'append extended the file rather than replacing it'
#
# It follows the string above, so changing that changes this -- the SchOS
# rename shortened "hello-from-schunix" by two characters and this check went
# red on a filesystem that was working perfectly.
Expect '(?m)^\s*29\s' 'append extended the file rather than replacing it'
Expect '(?m)^copy\.txt' 'a copied file appears in a new directory'
Expect '(?ms)copy\.txt.*rmdir' 'rmdir removed the directory without an error'
@ -393,7 +397,7 @@ Expect 'vga: display controller' 'the display driver found its aperture'
Expect 'schfs: mounted' 'the kernel mounted SchFS as the root filesystem'
Expect 'init: ready' 'init came up on a SchFS root'
Expect 'label:\s*schunix' '/proc/schfs reports the volume label'
Expect 'label:\s*schos' '/proc/schfs reports the volume label'
Expect 'root_objectid:\s*16' '/proc/schfs reports the root object id'
Expect 'dir\s+bin' 'the root directory really contains bin/'
# / is the mounted volume, so mounting that same device again must be
@ -415,7 +419,7 @@ if ($gens.Count -ge 2 -and
}
if ($Fb) {
Expect 'id\s+schunixfb' 'FBIOGET_FSCREENINFO identifies the device'
Expect 'id\s+schosfb' 'FBIOGET_FSCREENINFO identifies the device'
# 800x600 is what boot/stage2.S asks VBE for. Asserting the numbers rather
# than just "the ioctl returned" is the point: the old code path returned
# success with an untouched buffer, i.e. a 0x0 screen.

View file

@ -1,4 +1,4 @@
# Boot Schunix, crash it on purpose, and capture the crash screen as an image.
# Boot SchOS, crash it on purpose, and capture the crash screen as an image.
#
# The crash screen is the one part of the system you cannot look at by using
# the system, so it is the one part that quietly rots. This drives it through
@ -21,7 +21,7 @@ param(
$ErrorActionPreference = 'Stop'
$root = Split-Path $PSScriptRoot -Parent
$hda = Join-Path $root 'schunix.img'
$hda = Join-Path $root 'schos.img'
$hdb = if ($SchFS) { Join-Path $root 'build\schfs.img' } else { Join-Path $root 'build\fs.img' }
$log = Join-Path $root 'build\crashshot.log'
$ppm = Join-Path $root $Out
@ -96,7 +96,7 @@ if (Test-Path $log) {
$text = Get-Content $log -Raw
Write-Host "==> serial transcript" -ForegroundColor Cyan
# Only the crash report, not the whole boot.
$idx = $text.IndexOf('Schunix stopped')
$idx = $text.IndexOf('SchOS stopped')
if ($idx -ge 0) { Write-Host $text.Substring($idx) } else { Write-Host $text }
}

View file

@ -1,4 +1,4 @@
# Boot Schunix, run the display self-test, and capture the result as an image.
# Boot SchOS, run the display self-test, and capture the result as an image.
#
# The display class cannot be checked without a display: the assertion is "did
# the right pixels reach the screen", and the only instrument for that is a
@ -26,7 +26,7 @@ param(
$ErrorActionPreference = 'Stop'
$root = Split-Path $PSScriptRoot -Parent
$hda = Join-Path $root 'schunix.img'
$hda = Join-Path $root 'schos.img'
$hdb = if ($SchFS) { Join-Path $root 'build\schfs.img' } else { Join-Path $root 'build\fs.img' }
$log = Join-Path $root 'build\crashshot.log'
$ppm = Join-Path $root $Out

View file

@ -18,7 +18,7 @@ param(
$ErrorActionPreference = 'Stop'
$root = Split-Path $PSScriptRoot -Parent
$hda = Join-Path $root 'schunix.img'
$hda = Join-Path $root 'schos.img'
$hdb = Join-Path $root 'build\fs.img'
$log = Join-Path $root 'build\fbshot.log'
$ppm = Join-Path $root "build\fb-$Mode.ppm"

View file

@ -1,4 +1,4 @@
# How much of Schunix is actually Schunix.
# How much of SchOS is actually SchOS.
#
# `wc -l` over the whole tree answers a question nobody asked: it counts musl,
# toybox, mksh and a NetBSD checkout, which between them are
@ -136,13 +136,13 @@ $fmt = @(
)
Write-Host ''
Write-Host ' Schunix — first-party source' -ForegroundColor Cyan
Write-Host ' SchOS — first-party source' -ForegroundColor Cyan
Write-Host ''
Write-Host (($results | Where-Object { $_.Files -gt 0 } | Sort-Object Lines -Descending | Format-Table $fmt -AutoSize | Out-String))
# Two totals, because they answer different questions and conflating them
# flatters the number. "The OS" is what boots and runs on the machine; docs,
# host-side tools and the projects/ stubs are first-party but are not Schunix
# host-side tools and the projects/ stubs are first-party but are not SchOS
# running on hardware. Linux 0.01's 10,239 lines were kernel, headers and boot
# -- no documentation and no build tooling -- so only the first total is a fair
# comparison.
@ -182,7 +182,7 @@ Write-Host ''
# measure -- every line of every file in the tarball, comments included.
$lin = 10239
Write-Host (' For scale: Linux 0.01 was {0:N0} lines (kernel, headers, boot -- the' -f $lin) -ForegroundColor DarkGray
Write-Host (' same things counted above as THE OS ITSELF). Schunix is {0:N1}x that.' -f ($osT / $lin)) -ForegroundColor DarkGray
Write-Host (' same things counted above as THE OS ITSELF). SchOS is {0:N1}x that.' -f ($osT / $lin)) -ForegroundColor DarkGray
Write-Host ''
if ($PerFile) {

View file

@ -1,4 +1,4 @@
# Build a bootable Schunix ISO, ready for VMware or a real machine.
# Build a bootable SchOS ISO, ready for VMware or a real machine.
#
# Wraps `make iso`, which builds the ramdisk-root variant and wraps it in an
# El Torito image. The ramdisk root is the point: the ISO carries a complete
@ -8,7 +8,7 @@
# tools\makeiso.ps1 -Run build it, then boot it under QEMU to check
# tools\makeiso.ps1 -Clean force a full rebuild first
#
# Afterwards the ISO is schunix.iso in the repository root; point a VM's optical
# Afterwards the ISO is schos.iso in the repository root; point a VM's optical
# drive at it and boot from CD.
param(
@ -88,8 +88,8 @@ if ($code -ne 0) {
Fail "make iso returned $code"
}
$iso = Join-Path $root 'schunix.iso'
if (-not (Test-Path $iso)) { Fail "schunix.iso was not produced" }
$iso = Join-Path $root 'schos.iso'
if (-not (Test-Path $iso)) { Fail "schos.iso was not produced" }
# `make iso` leaves the tree holding objects compiled with -DRAMDISK_ROOT. A
# following plain `make` would then fail to link, on a missing ramdisk symbol,
@ -106,7 +106,7 @@ Write-Host " New VM -> I will install the OS later -> Other / Other 64-bit"
Write-Host " CD/DVD -> Use ISO image file -> $iso, and tick Connect at power on"
Write-Host " Boot order: CD-ROM first (F2 at power on for the firmware setup)"
Write-Host ""
Write-Host " Set the VM to BIOS, not UEFI. Schunix's loader is 16-bit real"
Write-Host " Set the VM to BIOS, not UEFI. SchOS's loader is 16-bit real"
Write-Host " mode and there is no EFI stub yet, so a UEFI-only VM will not boot."
Write-Host ""
Write-Host " Processors: as many as you like. SMP works as of 2026-08-08;"

View file

@ -1,15 +1,15 @@
#!/bin/sh
# Build a bootable Schunix ISO.
# Build a bootable SchOS ISO.
#
# tools/mkiso.sh [output.iso]
#
# The disc boots through El Torito's "no emulation" mode, which is the only
# one of the three that fits how Schunix actually loads itself.
# one of the three that fits how SchOS actually loads itself.
#
# floppy emulation caps the image at 2.88 MB; the ramdisk-root kernel
# alone is bigger than that.
# hard disk emulation presents the image through the BIOS's INT 13h, and
# Schunix's loader does not use INT 13h -- it drives
# SchOS's loader does not use INT 13h -- it drives
# the IDE controller's registers directly, which
# cannot reach a BIOS-emulated drive.
# no emulation the BIOS loads a chosen run of sectors at 0x7C00
@ -23,7 +23,7 @@
#
# STAGE2_SECTORS comes from the environment, set by the Makefile, because this
# same number also lives in boot/bootasm.S, boot/stage2main.c and the dd offsets
# in schunix.img's recipe. It was previously written out by hand in three
# in schos.img's recipe. It was previously written out by hand in three
# separate spots in this file alone, and raising it for the boot logo is what
# turned that from a latent hazard into a broken image.
#
@ -34,7 +34,7 @@
set -e
BUILD=${BUILD:-build}
OUT=${1:-schunix.iso}
OUT=${1:-schos.iso}
STAGE2_SECTORS=${STAGE2_SECTORS:-48}
STAGE2_BYTES=$((STAGE2_SECTORS * 512))
LOAD_SIZE=$((1 + STAGE2_SECTORS))
@ -59,7 +59,7 @@ stage2_sz=$(wc -c < "$STAGE2")
rm -rf "$STAGING"
mkdir -p "$STAGING/boot"
cat "$CDBOOT" "$STAGE2" "$KERNEL" > "$STAGING/boot/schunix.bin"
cat "$CDBOOT" "$STAGE2" "$KERNEL" > "$STAGING/boot/schos.bin"
# xorriso if it is here, mkisofs otherwise. Both accept the El Torito flags
# below unchanged -- xorriso's -as mkisofs mode exists precisely to be
@ -79,9 +79,9 @@ fi
$MKISOFS \
-quiet \
-V SCHUNIX \
-A "Schunix" \
-b boot/schunix.bin \
-V SCHOS \
-A "SchOS" \
-b boot/schos.bin \
-no-emul-boot \
-boot-load-size "$LOAD_SIZE" \
-o "$OUT" \

View file

@ -13,7 +13,7 @@ is ink -- which lets the kernel composite it in whatever the theme's accent
happens to be, anti-aliased, at one byte per pixel. Storing RGB would be four
times the size and would hardcode a colour into the kernel image.
python3 tools/mklogo.py "Assets/Schunix Small Logo.png" include/logo.h 128
python3 tools/mklogo.py "Assets/SchOS Small Logo.png" include/logo.h 128
"""
import sys, zlib, struct

View file

@ -547,7 +547,7 @@ add_tree(uint64_t dirino, const char *hostdir)
int
main(int argc, char **argv)
{
const char *out = NULL, *sysroot = NULL, *label = "schunix";
const char *out = NULL, *sysroot = NULL, *label = "schos";
uint64_t nblocks = 6000;
for (int i = 1; i < argc; i++) {

View file

@ -8,7 +8,7 @@
# say -- would otherwise look exactly like a passing mutation test, which is
# the same failure this script exists to catch.
set -e
cd /mnt/d/DEV/Schunix
cd /mnt/d/DEV/SchOS
OBJ=kernel/fs/schfs/obj.c
OBJW=kernel/fs/schfs/objw.c

View file

@ -126,10 +126,10 @@ alpha = lambda n: "".join(chr(65 + i % 26) for i in range(n))
CASES = [
"HELLO",
"SCHUNIX",
"SCHOS",
"a",
"0123456789",
"SCHUNIX PANIC\ntrap 14 err 4 cpu 0\nrip ffffffff80104e2a",
"SCHOS PANIC\ntrap 14 err 4 cpu 0\nrip ffffffff80104e2a",
bytes(range(1, 40)).decode("latin-1"), # non-printable payload
]
# One payload that exactly fills each version, and one just under, so both the

View file

@ -297,7 +297,7 @@ main(int argc, char **argv)
const char *out = argc > 1 ? argv[1] : "build/qr.png";
const char *text = argc > 2 ? argv[2] :
"SCHUNIX PANIC\n"
"SCHOS PANIC\n"
"build 8f2a91c4\n"
"trap 14 err 4 cpu 0\n"
"rip ffffffff80104e2a\n"

View file

@ -29,7 +29,7 @@ Remove-Item -Recurse -Force $dir -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force $dir | Out-Null
Remove-Item -Force $log -ErrorAction SilentlyContinue
$hda = Join-Path $root 'schunix.img'
$hda = Join-Path $root 'schos.img'
$hdb = Join-Path $root 'build\fs.img'
$monPort = 55556 # not crashshot's port, so the two can run back to back

View file

@ -1,4 +1,4 @@
# Boot Schunix, run the text-rendering self-test, and capture the result as an image.
# Boot SchOS, run the text-rendering self-test, and capture the result as an image.
#
# The display class cannot be checked without a display: the assertion is "did
# the right pixels reach the screen", and the only instrument for that is a
@ -26,7 +26,7 @@ param(
$ErrorActionPreference = 'Stop'
$root = Split-Path $PSScriptRoot -Parent
$hda = Join-Path $root 'schunix.img'
$hda = Join-Path $root 'schos.img'
$hdb = if ($SchFS) { Join-Path $root 'build\schfs.img' } else { Join-Path $root 'build\fs.img' }
$log = Join-Path $root 'build\crashshot.log'
$ppm = Join-Path $root $Out

View file

@ -17,7 +17,7 @@ param(
$ErrorActionPreference = 'Stop'
$root = Split-Path $PSScriptRoot -Parent
$hda = Join-Path $root 'schunix.img'
$hda = Join-Path $root 'schos.img'
$hdb = Join-Path $root 'build\fs.img'
$log = Join-Path $root 'build\ttyshot.log'
$ppm = Join-Path $root $Out