include: one folder per subsystem, and includes that name it

Sixty-five headers sat side by side in include/, so `#include "irq.h"`
said nothing about where irq.h was or what it belonged to, and errno.h,
stat.h and fcntl.h at the top shadowed the system's for any host tool
built with -I./include. They are in folders now -- arch/ core/ fs/
dev/ gfx/ net/ uapi/ (and ldls/ for the Linux driver layer) -- and
every include names the folder, as Linux's do: "core/proc.h".

Done mechanically and checked the hard way: the kernel built from this
tree disassembles identically to the one built from the tree before
it. The full image boots, and userland is the same set of programs.
Paths in docs and comments follow; docs/guides/layout.md has a table
of what is where, and tools/fix-includes.py rewrites old-style
includes from the folders in the tree, for code written before this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
Nexoniarz 2026-10-23 15:05:12 +02:00
commit a1c965da1e
267 changed files with 1560 additions and 1440 deletions

View file

@ -19,7 +19,7 @@
- [SchFS phase 2: real mount](schfs-phase2-mount.md) — mkschfs writes images, the kernel mounts them read-only; `make schfs-check`, plus four traps worth remembering.
- [SchFS phase 3: writes](schfs-phase3-writes.md) — full write API, free map derived not stored, and `mount -t schfs` works; the VFS now dispatches through `struct fs_ops`.
- [DIRSIZ 14 -> 30](schunix-dirsiz-14.md) — filenames used to truncate silently; fixed by holding the HTree bucket at 256 bytes.
- [Linux open flags](schunix-linux-open-flags.md) — include/fcntl.h must hold Linux's values; a mismatch made `>>` truncate.
- [Linux open flags](schunix-linux-open-flags.md) — include/uapi/fcntl.h must hold Linux's values; a mismatch made `>>` truncate.
- [Shared memory and mmap](schunix-shm-and-mmap.md) — shm + file-backed mmap work; pages you don't own must never reach kfree.
- [Wall clock](schunix-wall-clock.md) — the RTC was never read, so `date` said 1970; kernel/core/time.c fixes it, plus the stale-image trap.
- [TTF rasteriser](schunix-ttf-rasteriser.md) — glyf outlines (not CFF, and why); the composite-glyph trap that loses the letter "i".

View file

@ -13,7 +13,7 @@ The filesystem is called **SchFS** — not "SchFS v2". Design: `docs/architectur
**Phase 1 is done** (2026-08-01): the copy-on-write B-tree exists and passes its
torture harness.
- `include/schfs.h` — on-disk format: 4096-byte blocks, 24-byte
- `include/fs/schfs.h` — on-disk format: 4096-byte blocks, 24-byte
`(objectid, type, offset)` keys, node header with a self-pointer, uberblock ring.
- `kernel/fs/schfs/btree.{c,h}` — portable C against an abstract
`struct schfs_bdev`, so the same code runs on a host file and in the kernel.

View file

@ -17,7 +17,7 @@ mkdir /mnt && mount -t schfs /dev/hdb /mnt
then ordinary `ls`/`cat`/`>`/`>>`/`mkdir`/`cp`/`rm`/`rmdir` all work on it.
**The VFS now has a real dispatch layer**: `struct fs_ops` in `include/file.h`,
**The VFS now has a real dispatch layer**: `struct fs_ops` in `include/fs/file.h`,
one table per filesystem, chosen by `iget()` from the device number and hung off
the inode. v1's implementations kept their bodies and are named `v1_*`; SchFS's
live in `kernel/fs/schfs/vfs.c`. **Adding a filesystem is a new table, not
@ -105,7 +105,7 @@ retry.
if (dev == PROCFS_DEV) return &procfs_ops;
return &v1_ops; // legacy, only because it is the default
`struct fs_ops` (include/file.h:35) is a complete vtable -- iload, istore,
`struct fs_ops` (include/fs/file.h:35) is a complete vtable -- iload, istore,
ifree, read, write, truncate, dirops -- and **SchFS implements all of it**. So
`fs.c` is no longer "the filesystem"; it is the fallback branch. Killing it is
three edits, not a rewrite:

View file

@ -27,7 +27,7 @@ the bug.
Three coupled changes, all required together:
1. `BSIZE` 1024 → 4096 (`include/fs.h`). Keep it equal to `SCHFS_BLKSIZE`.
1. `BSIZE` 1024 → 4096 (`include/fs/fs.h`). Keep it equal to `SCHFS_BLKSIZE`.
2. `NBUF` 90 → 256 blocks (1 MB). At 90 KB the cache was **smaller than the
binary every command execs**, so nothing was ever resident on the next
command. This is what makes the *second* command fast.

View file

@ -32,7 +32,7 @@ clone has no `/etc/passwd` or `/etc/motd` (still an open gap).
malloc, no printf, no strlen. Static storage and hand-rolled helpers only.
**`getdents64` was exposed for this.** The kernel has had syscall 96/217 since
the Linux ABI landed, but nothing declared it in `include/user.h` or
the Linux ABI landed, but nothing declared it in `include/uapi/user.h` or
`lib/usys.S`, so first-party programs could not list a directory at all. Step
records by `d_reclen`, never `sizeof`.

View file

@ -25,7 +25,7 @@ hands over long mode already, and dropping back down to climb out again is a
mode switch whose failure mode is a triple fault with no console. So entry.S
publishes a 64-bit entry the same way it publishes the multiboot header: magic
`SCH64BOO`, 8-byte aligned in the first 16 KB, then a 64-bit physical address.
`include/schboot.h` owns the constants so loader and kernel cannot disagree —
`include/arch/schboot.h` owns the constants so loader and kernel cannot disagree —
the first attempt defined them twice and searched for `SCH6` while the
assembler had written `6HCS`.

View file

@ -24,10 +24,10 @@ deleting the loader's copy.
**Pipeline:** `tools/mklogo.py` (host Python, has its own PNG inflate +
un-filter) crops to the mark, box-downscales, normalises to full strength, packs
to a 4-bit coverage mask, and writes `include/logo.h`. Run `make logo` — it is
*not* a build dependency, and `include/logo.h` is committed, on the same
reasoning as `include/font.h`. The mask is coverage, not colour, so the palette
stays in [[schunix-console-tty]]'s `include/theme.h`; the loader composites it in
to a 4-bit coverage mask, and writes `include/gfx/logo.h`. Run `make logo` — it is
*not* a build dependency, and `include/gfx/logo.h` is committed, on the same
reasoning as `include/gfx/font.h`. The mask is coverage, not colour, so the palette
stays in [[schunix-console-tty]]'s `include/gfx/theme.h`; the loader composites it in
`SCH_FG` because the source art is a silver gradient and the accent is reserved
for the one rule. 4 bits rather than 8 because the header is included by the
*bootloader*, where size is a boot constraint.

View file

@ -35,7 +35,7 @@ Two real bugs found in the Makefile while doing this:
- **`$(BUILD)/kernel/**/*.d` only matched one directory level.** make's wildcard
has no recursive `**`. `arch/x86_64/` and `fs/schfs/` therefore had **no
header dependency tracking at all** — editing `include/schfs.h` left stale
header dependency tracking at all** — editing `include/fs/schfs.h` left stale
objects that linked fine. It uses `$(shell find ...)` now.
- **`CFLAGS` is recursively expanded and had a `$(shell)` appended**, so the
stack-protector probe re-ran on every expansion: one extra gcc per object

View file

@ -19,7 +19,7 @@ you whether the escape parser works; it holds the raw bytes either way. Use
`pwsh -File tools/ttyshot.ps1`, which drives colour/cursor/erase/UTF-8 and
screendumps the result.
**The font is CP437, not Latin-1.** `include/font.h`'s per-glyph comments
**The font is CP437, not Latin-1.** `include/gfx/font.h`'s per-glyph comments
label index N with Unicode codepoint N, which is fiction above 127: index 0xE9
is annotated "e-acute" and draws a capital theta. Trusting it turned "café"
into "caf" + theta. `console.c` maps Unicode through `latin1_to_cp437[]` plus

View file

@ -60,7 +60,7 @@ framebuffer. See [[schunix-verify-by-driving-shell]].
## 2026-09-21: the face is gone, and a bug it exposed
PSOGM draws **Shift**, the system logo, where the Guru face used to be —
`gfx_draw_logo()` from `include/logo.h`, the same mask the loader splash and
`gfx_draw_logo()` from `include/gfx/logo.h`, the same mask the loader splash and
the boot console use, at its native 128 px. `draw_guru()` and its geometry
constants are deleted; so are `docs/branding/guru.svg` and the mascot brief.
The *name* "Purple Screen of Guru Meditation" stays — that is the Amiga nod,

View file

@ -8,7 +8,7 @@ metadata:
modified: 2026-08-08T18:05:13.551Z
---
Built 2026-08-08. `include/device.h` + `kernel/dev/device.c`, readable at
Built 2026-08-08. `include/dev/device.h` + `kernel/dev/device.c`, readable at
`/proc/devices`. Written up in `docs/architecture/devices.md`. Supersedes the two separate
arrays in `kernel/drivers/registry.c` as the answer to "what is attached".
@ -35,7 +35,7 @@ break both assumptions** and needs a spinlock plus a reader lock in procfs.
## The display class
`include/display.h` + ops in `kernel/dev/vga.c`, published on the device by
`include/gfx/display.h` + ops in `kernel/dev/vga.c`, published on the device by
`vga_pci_driver.ops`. `struct pci_driver` gained an `ops` field for this —
**it has to live on the driver, not be set inside probe()**, because
`pci_bind()` registers the device *after* probe returns.

View file

@ -5,7 +5,7 @@ metadata:
type: project
---
Found 2026-08-09 while staging fonts. `DIRSIZ` in `include/fs.h` is **14**, an
Found 2026-08-09 while staging fonts. `DIRSIZ` in `include/fs/fs.h` is **14**, an
xv6 inheritance, and the v1 filesystem truncates to it **silently**.
`JetBrainsMono-Regular.ttf` was stored as `JetBrainsMono-`. Two consequences,
@ -30,7 +30,7 @@ of every directory.
DIRSIZ 30 makes `struct dirent` exactly **32 bytes**, so a 256-byte bucket holds
**8** slots instead of 16 and **every byte offset in the layout is unchanged**.
`DIRENT_BUCKET_BYTES` in `include/fs.h` is now the constant the maths is written
`DIRENT_BUCKET_BYTES` in `include/fs/fs.h` is now the constant the maths is written
against; `kernel/fs/fs.c` and `tools/mkfs.c` both use it instead of
`16 * sizeof(struct dirent)`. Cost: more overflow use in heavily collided
directories.

View file

@ -11,7 +11,7 @@ metadata:
**Built 2026-08-04**, before USB, because xHCI, any NIC and virtio-gpu all
need the same three things and none of them existed.
- **`kernel/dev/irq.c` + `include/irq.h`** — `irq_register(irq, fn, arg,
- **`kernel/dev/irq.c` + `include/core/irq.h`** — `irq_register(irq, fn, arg,
name, level_low)`. `trap.c` used to be a switch listing every interrupt by
name, which cannot work for a PCI device: its line comes out of config
space at probe time, so there is no constant to write a `case` label for.
@ -19,7 +19,7 @@ need the same three things and none of them existed.
handler must recognise that its own device is idle and return.
Registration publishes an entry then bumps `n` with a barrier, so dispatch
needs no lock. `/proc/interrupts` (minor 12) shows counts and trigger mode.
- **`kernel/core/dma.c` + `include/dma.h`** — `dma_alloc(size, align)` /
- **`kernel/core/dma.c` + `include/core/dma.h`** — `dma_alloc(size, align)` /
`dma_free(p, size)` (Linux's contract: caller remembers the size). Carved
off the top of physical memory in `main.c` *before* `kinit1`, because
kalloc's free list makes no contiguity promise. x86 PCI is cache coherent

View file

@ -23,7 +23,7 @@ One directory per *driver*, not per class (Nexoniarz asked for this
specifically), so a driver that grows a register header, a second source file or
a firmware blob has somewhere to put it.
Matches `DEVCLASS_*` in `include/device.h`. Flat was eight files with four
Matches `DEVCLASS_*` in `include/dev/device.h`. Flat was eight files with four
called `usb_something`, and each driver added made it worse.
**Makefile note:** the compile rule is now

View file

@ -10,10 +10,10 @@ metadata:
**`/dev/fb0` (major 2) is a real framebuffer device** as of 2026-08-04:
`kernel/dev/fb.c` (read/write by byte offset, plus `fb_ioctl`), declared in
`include/fb.h`. Before this it was wired to `{ nullread, nullwrite }` — writing
`include/gfx/fb.h`. Before this it was wired to `{ nullread, nullwrite }` — writing
pixels to it succeeded and did nothing.
**`include/fb.h` holds Linux's fbdev request numbers and struct layouts**
**`include/gfx/fb.h` holds Linux's fbdev request numbers and struct layouts**
(`FBIOGET_VSCREENINFO` 0x4600, `fb_var_screeninfo` 160 bytes,
`fb_fix_screeninfo` 80 bytes). Same reasoning as
[[schunix-linux-open-flags]]: a shared number must mean the shared thing, or a

View file

@ -9,7 +9,7 @@ metadata:
---
**Never reach a device's registers with `P2V(bar.base)`.** Use
`ioremap(pa, size)` from `kernel/arch/x86_64/vm.c` (declared in `include/defs.h`).
`ioremap(pa, size)` from `kernel/arch/x86_64/vm.c` (declared in `include/core/defs.h`).
Every driver used to do the `P2V` thing, which silently assumes the BAR lands
inside the 0-4 GB that `kvmalloc()` direct-maps with four 1 GB pages. Under

View file

@ -1,6 +1,6 @@
---
name: schunix-linux-open-flags
description: "include/fcntl.h must hold Linux's open-flag values — the userland is all Linux-ABI, and a mismatch silently corrupts files"
description: "include/uapi/fcntl.h must hold Linux's open-flag values — the userland is all Linux-ABI, and a mismatch silently corrupts files"
metadata:
node_type: memory
type: project
@ -8,7 +8,7 @@ metadata:
modified: 2026-08-03T13:59:19.392Z
---
**`include/fcntl.h` holds Linux x86-64 open-flag values, and must keep holding
**`include/uapi/fcntl.h` holds Linux x86-64 open-flag values, and must keep holding
them.** Every program in the userland is built against a libc that sends Linux
values; the kernel reads them with these constants. Do not "tidy" them into a
neat sequence — they are an external interface.

View file

@ -40,6 +40,6 @@ driver in brackets (`[-]` when unclaimed). Under QEMU's default i440fx it
should show six devices; `tools/bootcheck.ps1` asserts on the host bridge and
the IDE controller by ID, and on `[vga]` having bound.
`inl`/`outl` were added to include/x86.h for this — config space is only
`inl`/`outl` were added to include/arch/x86.h for this — config space is only
reachable in dwords, so `pci_read16`/`pci_read8` shift and mask the containing
dword rather than doing a narrower bus cycle.

View file

@ -8,7 +8,7 @@ metadata:
modified: 2026-08-08T16:22:01.468Z
---
Built 2026-08-08. `kernel/core/qr.c` + `include/qr.h`, the Phase 8 crash channel
Built 2026-08-08. `kernel/core/qr.c` + `include/gfx/qr.h`, the Phase 8 crash channel
(see [[schunix-crash-screen]] and `docs/plan/roadmap.md`).
**Wired into the crash screen the same day.** `panic.c` builds a compact payload

View file

@ -8,8 +8,8 @@ metadata:
modified: 2026-08-05T07:12:20.950Z
---
Unix domain sockets (`kernel/net/unix.c`, `include/socket.h`, `kernel/sys/sys_net.c`)
and raw input events (`kernel/dev/input.c`, `include/input.h`) are both done and
Unix domain sockets (`kernel/net/unix.c`, `include/net/socket.h`, `kernel/sys/sys_net.c`)
and raw input events (`kernel/dev/input.c`, `include/dev/input.h`) are both done and
verified — `tools\bootcheck.ps1 -Sock` and `-Evdev`.
**One lock for the whole socket table, deliberately.** A pipe gets a lock per

View file

@ -17,7 +17,7 @@ SYSCALL_ALIAS(linux_nr, name) // extra Linux number -> existing handler
and implemented as `SYSCALL_DEFINE(name) { ... }` in a `kernel/sys/sys_*.c`.
Generated from that one line: the `SYS_*` enum (`include/syscall.h`), the
Generated from that one line: the `SYS_*` enum (`include/core/syscall.h`), the
dispatch table (`kernel/sys/syscall.c`), and the Linux ABI translation map
(`kernel/sys/linux_abi.c`).

View file

@ -8,7 +8,7 @@ metadata:
modified: 2026-08-08T22:45:34.934Z
---
Built 2026-08-09. `include/text.h` + `kernel/dev/text.c`. Nexoniarz: "using ANSI
Built 2026-08-09. `include/gfx/text.h` + `kernel/dev/text.c`. Nexoniarz: "using ANSI
fonts in 2026 is a not funny joke."
**The font was never the problem — the grid was.** The console indexes
@ -44,7 +44,7 @@ a useful side-by-side.
## Traps hit
- `include/font.h` **defines** `font_data` rather than declaring it, so
- `include/gfx/font.h` **defines** `font_data` rather than declaring it, so
including it from a second file duplicates the symbol under `-fno-common`.
text.c declares `extern unsigned char font_data[256][16];` instead; the header
is generated data and is better left alone.

View file

@ -5,7 +5,7 @@ metadata:
type: project
---
Built 2026-08-09. `include/ttf.h` + `kernel/dev/ttf.c`, the second `font_ops`
Built 2026-08-09. `include/gfx/ttf.h` + `kernel/dev/ttf.c`, the second `font_ops`
provider behind [[schunix-text-rendering]]. Host harness: `tools/ttftest.c` →
`build/tools/ttftest font.ttf px "text" out.pgm`.

View file

@ -9,7 +9,7 @@ metadata:
---
Written 2026-08-08 from the OASIS virtio 1.1 specification (chapters 2, 4.1,
5.7). `include/virtio.h` + `kernel/drivers/virtio_gpu.c`. Worked on the first
5.7). `include/dev/virtio.h` + `kernel/drivers/virtio_gpu.c`. Worked on the first
boot.
virtio-gpu: 1280x800, 4000 KB framebuffer, queue 64

View file

@ -34,7 +34,7 @@ KERN_DEV = $(addprefix $(BUILD)/kernel/dev/, \
#
# drivers/<class>/<driver>/ -- one directory per driver, so a driver that grows
# a register header, a second source file or a firmware blob has somewhere to
# put it. Classes match include/device.h's DEVCLASS_*. Everything flat was
# put it. Classes match include/dev/device.h's DEVCLASS_*. Everything flat was
# already eight files with four called usb_something, and each driver added made
# the directory harder to read. The compile rule uses `mkdir -p $(dir $@)`, so
# the depth costs nothing.
@ -563,7 +563,7 @@ kernel: $(BUILD)/kernel/kernel
# make DEBUG=1
#
# What it turns on is the *boot menu's* remote-debugging entry, and nothing
# else -- see SCHBOOT_DEBUG_FLAG in include/schboot.h. A release build has no
# else -- see SCHBOOT_DEBUG_FLAG in include/arch/schboot.h. A release build has no
# way to switch a network debugger on, because the code that would set the flag
# is not compiled into it. That is the point: a menu item that is present and
# refuses is an invitation to find out how to make it not refuse.
@ -599,9 +599,9 @@ UEFI_CFLAGS = $(UEFI_DEBUG_FLAGS) --target=x86_64-unknown-windows -ffreestanding
# looking at the wrong thing.
#
# Hence the check and the message. It is worth the four lines.
$(BUILD)/uefi/BOOTX64.EFI: boot/uefi/main.c boot/uefi/efi.h include/schboot.h \
$(BUILD)/uefi/BOOTX64.EFI: boot/uefi/main.c boot/uefi/efi.h include/arch/schboot.h \
boot/common/ui.c boot/common/ui.h \
include/logo.h include/theme.h include/font.h
include/gfx/logo.h include/gfx/theme.h include/gfx/font.h
@mkdir -p $(BUILD)/uefi
@command -v clang >/dev/null 2>&1 || { \
echo ""; \
@ -1085,7 +1085,7 @@ SCHFS_SRC = kernel/fs/schfs/btree.c kernel/fs/schfs/btree.h \
kernel/fs/schfs/space.c kernel/fs/schfs/vol.c \
kernel/fs/schfs/obj.c kernel/fs/schfs/objw.c \
kernel/fs/schfs/attr.c \
kernel/fs/schfs/schfs_int.h include/schfs.h
kernel/fs/schfs/schfs_int.h include/fs/schfs.h
# -iquote, not -I: include/ has its own errno.h, stat.h, fcntl.h and types.h,
# and -I would put them ahead of the system ones for a host program that needs
@ -1115,7 +1115,7 @@ schfs-objtest: $(SCHFS_OBJT)
# page-to-cache lookup, and whether pages actually come back -- is asserted in
# a second rather than in a boot.
KMEMTEST = $(BUILD)/tools/kmemtest$(EXE)
$(KMEMTEST): tools/kmemtest.c kernel/core/kmem.c include/kmem.h
$(KMEMTEST): tools/kmemtest.c kernel/core/kmem.c include/core/kmem.h
@mkdir -p $(BUILD)/tools
$(HOSTCC) $(HOSTCFLAGS) -I include -o $@ tools/kmemtest.c
@ -1239,9 +1239,9 @@ ldls-unstage:
ldls-check: $(LDLS_INSPECT) $(LDLS_RUN) $(LDLS_TYPES) $(LDLS_REFMOD)
$(PYTHON) tools/python/ldls_check.py $(LDLS_INSPECT) $(LDLS_REFMOD) $(LDLS_RUN)
$(MKFS): tools/mkfs.c include/fs.h include/stat.h include/param.h
$(MKFS): tools/mkfs.c include/fs/fs.h include/uapi/stat.h include/core/param.h
@mkdir -p $(BUILD)/tools
$(HOSTCC) $(HOSTWARN) -I. -o $(MKFS) tools/mkfs.c
$(HOSTCC) $(HOSTWARN) -I. -iquote ./include -o $(MKFS) tools/mkfs.c
# Stage everything a running system needs into sysroot/, then image it.
#
@ -1504,7 +1504,7 @@ qemu-schfs: esp $(BUILD)/schfs.img $(OVMF_CODE) $(OVMF_VARS)
# re-run its four dd commands -- including zeroing five megabytes -- on every
# single invocation, including ones where nothing had changed. The file is gone
# with the BIOS loader, but the rule it taught applies to whatever replaces it.
# include/logo.h is generated but committed, exactly as include/font.h is: it
# include/gfx/logo.h is generated but committed, exactly as include/gfx/font.h is: it
# derives from art that changes about never, and making it a build dependency
# would put Python on the critical path of every clean build for no benefit.
# Run this by hand after changing the art.
@ -1515,7 +1515,7 @@ LOGO_SRC = docs/branding/shift-mask.png
LOGO_PX = 128
logo:
$(PYTHON) tools/python/mklogo.py "$(LOGO_SRC)" include/logo.h $(LOGO_PX)
$(PYTHON) tools/python/mklogo.py "$(LOGO_SRC)" include/gfx/logo.h $(LOGO_PX)
# The USB vendor/product name database, from linux-usb.org.
#
@ -1559,7 +1559,7 @@ hwdata: usb-ids pci-ids
# verified mechanically and the PNG covers the rest: point a phone at it.
QRTEST = $(BUILD)/tools/qrtest$(EXE)
$(QRTEST): tools/qrtest.c kernel/core/qr.c include/qr.h
$(QRTEST): tools/qrtest.c kernel/core/qr.c include/gfx/qr.h
@mkdir -p $(BUILD)/tools
$(HOSTCC) $(HOSTWARN) -I./include -o $@ tools/qrtest.c
@ -1599,6 +1599,6 @@ distclean: clean
# exactly one level, so build/kernel/core/*.d was picked up while
# build/kernel/arch/x86_64/*.d and build/kernel/fs/schfs/*.d were not.
# Everything under arch/ and schfs/ therefore had NO header dependency
# tracking at all -- editing include/schfs.h or include/mmu.h left stale
# tracking at all -- editing include/fs/schfs.h or include/arch/mmu.h left stale
# objects that linked without complaint. find actually recurses.
-include $(shell find $(BUILD) -name '*.d' 2>/dev/null)

View file

@ -111,7 +111,7 @@ make schfs-check # SchFS B-tree, object and image suites
```
kernel/ arch/ core/ dev/ drivers/ fs/ net/ proc/ sys/
fs/schfs/ the filesystem -- same source the host tools compile
include/ kernel and userland headers
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

View file

@ -39,7 +39,7 @@ a second loader is correct exactly when it satisfies it.
| Framebuffer | `VBE_INFO_ADDR` | address, pitch, width, height, depth |
| Verbose flag | `BOOT_VERBOSE_FLAG_ADDR` | set by the F8 menu |
The addresses are defined once, in `include/memlayout.h` and `include/schboot.h`.
The addresses are defined once, in `include/arch/memlayout.h` and `include/arch/schboot.h`.
The kernel does not care which firmware produced them.
## The entry point
@ -50,7 +50,7 @@ triple fault with no console, so the kernel publishes an entry that takes the
machine as it already is.
`kernel/arch/x86_64/entry.S` carries a `sch64_header` — magic `SCH64BOO`,
8-byte aligned within the first 16 KB, followed by a 64-bit physical address —
found by scanning. `include/schboot.h` holds the magic so loader and kernel
found by scanning. `include/arch/schboot.h` holds the magic so loader and kernel
cannot disagree.
The 32-bit multiboot entry is still in `entry.S` and now has no caller: the

View file

@ -10,9 +10,9 @@
*/
#include "ui.h"
#include "../../include/theme.h"
#include "../../include/font.h"
#include "../../include/logo.h"
#include "../../include/gfx/theme.h"
#include "../../include/gfx/font.h"
#include "../../include/gfx/logo.h"
/* "Draw the glyph, leave the background alone." Not a colour anyone can mean:
* the palette is 24-bit, so the high byte is free for a sentinel. */

View file

@ -25,7 +25,7 @@
// computed before.
#include "efi.h"
#include "../../include/schboot.h"
#include "../../include/arch/schboot.h"
#include "../common/ui.h"
// Where the kernel expects to find things comes from schboot.h, included
@ -108,7 +108,7 @@ static int VERBOSE_BOOT;
// Remote debugging, off unless somebody picks it out of the boot menu -- and
// the entry that picks it only exists in a build made with DEBUG=1. See
// SCHBOOT_DEBUG_FLAG in include/schboot.h for why the consent is asked for at
// SCHBOOT_DEBUG_FLAG in include/arch/schboot.h for why the consent is asked for at
// this particular moment.
static int DEBUG_BOOT;
@ -395,7 +395,7 @@ open_kernel(EFI_HANDLE image)
// ---------------------------------------------------------------------------
// The console typeface
//
// See SCHBOOT_FONT_ADDR in include/schboot.h for why this is the loader's job
// See SCHBOOT_FONT_ADDR in include/arch/schboot.h for why this is the loader's job
// and not the kernel's. Everything here is best-effort: a machine with no
// console.ttf on its ESP boots with the font in the kernel image, which is
// the same font, and says nothing about it.

View file

@ -27,10 +27,10 @@
// Whatever the modifiers are, they also bind minus and equals to the previous
// and next terminal in use -- AltGr+- and AltGr+= by default.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "posix.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#include "uapi/posix.h"
// No printf in lib/, and this needs one string and two small numbers.
static void

View file

@ -16,12 +16,12 @@
// if it is the other way round, the reverse. Having both makes a failure say
// which half broke.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "fb.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#include "gfx/fb.h"
#include "posix.h" /* PROT_*, MAP_* -- one definition, shared */
#include "uapi/posix.h" /* PROT_*, MAP_* -- one definition, shared */
static void
puts(const char *s)

View file

@ -20,12 +20,12 @@
// **The path check is the only security-relevant code here**, and it is done
// by rejecting rather than by normalising. See resolve() below.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "stat.h"
#include "socket.h"
#include "posix.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#include "uapi/stat.h"
#include "net/socket.h"
#include "uapi/posix.h"
#define DEFAULT_PORT 80
#define DEFAULT_ROOT "/srv"

View file

@ -22,11 +22,11 @@
// kernel does not publish them), and the MSDM and SLIC tables, which hold a
// Windows licence key. A report is meant to be handed to somebody.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "posix.h"
#include "stat.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#include "uapi/posix.h"
#include "uapi/stat.h"
// ---------------------------------------------------------------------------
// Small things a libc would have

View file

@ -12,10 +12,10 @@
// Prints one line per event: type, code and value, decoded where there is a
// name for it.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "input.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#include "dev/input.h"
static void
puts_(const char *s)

View file

@ -19,16 +19,16 @@
// is L3c. So the useful output here is the same as `ldls-run`'s: what the
// driver asks for, in what order, and how far it gets.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "posix.h"
#include "stat.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#include "uapi/posix.h"
#include "uapi/stat.h"
#include "ko.h"
#include "stub.h"
#include "btf.h"
#include "pciuser.h"
#include "dev/pciuser.h"
#include "kpi/kpi.h"
extern void kpi_unregister_netdev(void *dev);
extern void *kpi_skb_alloc(unsigned int len);

View file

@ -16,10 +16,10 @@
// The setting is machine-wide, not per-terminal: there is one keyboard, and
// switching to tty3 does not move anybody's fingers.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "posix.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#include "uapi/posix.h"
// No printf, memset or strcpy in lib/; this needs a little of each.
static void

View file

@ -17,12 +17,12 @@
// and the reason it had to wait for SCM_RIGHTS is that the *other* process
// gets the same object by being handed the descriptor, not by naming it.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "stat.h"
#include "posix.h"
#include "socket.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#include "uapi/stat.h"
#include "uapi/posix.h"
#include "net/socket.h"
static int failures;

View file

@ -22,10 +22,10 @@
// ARP (RFC 826), IPv4 (RFC 791), ICMP (RFC 792), DHCP (RFC 2131). All
// published, all specifications, which is docs/licensing.md §5.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "netuser.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#include "net/netuser.h"
// Us, and the address we hand out. Numbers chosen not to collide with QEMU's
// 10.0.2.0/24 user network, so both interfaces can be up at once.

View file

@ -22,9 +22,9 @@
// host$ nc -u -l -p 9000
// guest# nettest -u 10.0.2.2 9000
#include "types.h"
#include "user.h"
#include "socket.h"
#include "core/types.h"
#include "uapi/user.h"
#include "net/socket.h"
static void
puts_(const char *s)

View file

@ -18,11 +18,11 @@
// like from the kernel's side, and the case that used to
// leave a level-triggered line asserted with no handler
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "posix.h"
#include "pciuser.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#include "uapi/posix.h"
#include "dev/pciuser.h"
static void
puts(const char *s)

View file

@ -17,9 +17,9 @@
// the IP header and the caller reads and writes the ICMP message alone. See
// inet_icmp_recv_cb in kernel/net/inet.c.
#include "types.h"
#include "user.h"
#include "socket.h"
#include "core/types.h"
#include "uapi/user.h"
#include "net/socket.h"
#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0

View file

@ -10,9 +10,9 @@
// Uses FICLONE, which is Linux's ioctl for exactly this, so the same call works
// against any filesystem that supports cloning.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#define FICLONE 0x40049409

View file

@ -24,9 +24,9 @@
// policy question. A machine with a hand-written one should keep it, which is
// why -f exists and why it is not the default.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#define SRC "/proc/resolv.conf"
#define DST "/etc/resolv.conf"

View file

@ -14,8 +14,8 @@
// Indexing covers values written *after* the index is declared. There is no
// reindexing pass, so declare the index first.
#include "types.h"
#include "user.h"
#include "core/types.h"
#include "uapi/user.h"
static void
puts_(const char *s)

View file

@ -20,9 +20,9 @@
// which is the point, and is what you fall back to on a system where this
// program is one of the things that is broken.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
static void
puts_(const char *s)

View file

@ -44,16 +44,16 @@
// register, and arming one is a fine thing for a debugger to do and not a thing
// for a stranger on a socket to do. The refusal is in the kernel, driven by the
// view's own registration, so it cannot be got round from here and does not go
// stale when a new view is added. See include/dbg.h.
// stale when a new view is added. See include/core/dbg.h.
//
// One connection at a time, because /dev/dbg holds one answer at a time: two
// clients would read each other's. A second caller waits rather than
// interleaving.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "socket.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#include "net/socket.h"
#define DEFAULT_PORT 4444

View file

@ -28,12 +28,12 @@
// nothing -- it comes back, reads /proc/schinit, and finds the world exactly
// as it left it. A supervisor that forked its own jobs could not have that.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "posix.h"
#include "socket.h"
#include "schinit.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#include "uapi/posix.h"
#include "net/socket.h"
#include "uapi/schinit.h"
#define SUPERVISOR "/bin/schinitd"

View file

@ -18,12 +18,12 @@
// either losing them to reparenting or racing the new copy to adopt them --
// the split-brain failure docs/architecture/init.md rejects the two-init scheme for.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "posix.h"
#include "socket.h"
#include "schinit.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#include "uapi/posix.h"
#include "net/socket.h"
#include "uapi/schinit.h"
#define JOBDIR "/etc/schinit"
@ -103,7 +103,7 @@ out(const char *s)
static int verbose_boot;
// Whether the boot menu was asked for a network debugger. See
// SCHBOOT_DEBUG_FLAG in include/schboot.h -- the kernel only publishes it, and
// SCHBOOT_DEBUG_FLAG in include/arch/schboot.h -- the kernel only publishes it, and
// this is what acts on it, because what it turns on is a job.
static int debug_boot;

View file

@ -17,9 +17,9 @@
// schmode 1024 768 set it
// schmode 1024x768 the same
#include "types.h"
#include "user.h"
#include "socket.h"
#include "core/types.h"
#include "uapi/user.h"
#include "net/socket.h"
#define VGPUD_SOCKET "/run/vgpud"

View file

@ -11,9 +11,9 @@
//
// Prints one line per check, and a final verdict a script can grep for.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#define PROT_READ 0x1
#define PROT_WRITE 0x2

View file

@ -24,9 +24,9 @@
// Getting that backwards is a real bug this tree has had, so the masks below
// are spelled out rather than built by a macro.
#include "types.h"
#include "user.h"
#include "posix.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/posix.h"
#define U_SIGCHLD_BIT (1ULL << (SIGCHLD - 1))

View file

@ -9,11 +9,11 @@
//
// Prints one line per check and a final verdict a script can grep for.
#include "types.h"
#include "user.h"
#include "socket.h"
#include "stat.h"
#include "fcntl.h"
#include "core/types.h"
#include "uapi/user.h"
#include "net/socket.h"
#include "uapi/stat.h"
#include "uapi/fcntl.h"
static int failures;

View file

@ -11,11 +11,11 @@
// Deliberately not a WAV player. A player has to parse a header, and a header
// is a second thing to get wrong while testing the first.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "audio.h"
#include "errno.h"
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#include "dev/audio.h"
#include "uapi/errno.h"
// A quarter-amplitude sine, from a table rather than a libm that does not
// exist here. 64 points is audibly a sine and arithmetically exact.

View file

@ -20,20 +20,20 @@
// over a PCI device and this decided it was a GPU, which is the property that
// makes the interface general rather than a hole shaped like one thing.
#include "types.h"
#include "user.h"
#include "fcntl.h"
#include "posix.h"
#include "pciuser.h"
#include "virtio.h"
#include "schinit.h"
#include "socket.h"
#include "theme.h" // SCH_BG, SCH_ACCENT -- one palette, see docs/branding
#include "logo.h" // the mark, the same bytes the loader and console draw
#include "fb.h" // the console framebuffer, which this mirrors
#include "core/types.h"
#include "uapi/user.h"
#include "uapi/fcntl.h"
#include "uapi/posix.h"
#include "dev/pciuser.h"
#include "dev/virtio.h"
#include "uapi/schinit.h"
#include "net/socket.h"
#include "gfx/theme.h" // SCH_BG, SCH_ACCENT -- one palette, see docs/branding
#include "gfx/logo.h" // the mark, the same bytes the loader and console draw
#include "gfx/fb.h" // the console framebuffer, which this mirrors
// lib/glue.c has these -- they exist because the compiler emits calls to them
// whether or not anything asks -- but include/user.h never declared them.
// whether or not anything asks -- but include/uapi/user.h never declared them.
void *memcpy(void *, const void *, unsigned long);
int memcmp(const void *, const void *, unsigned long);
@ -114,7 +114,7 @@ die(const char *why)
// Not a failure: a report. There is no virtio-gpu here, or the kernel will not
// give it up, and neither of those changes by trying again -- so this tells the
// supervisor to stop, rather than being restarted every three seconds for the
// rest of the uptime. See SCHINIT_EXIT_NORESTART in include/schinit.h.
// rest of the uptime. See SCHINIT_EXIT_NORESTART in include/uapi/schinit.h.
static void
nothing_to_do(const char *why)
{
@ -625,7 +625,7 @@ present(void)
//
// The mark answers the same question a black screen cannot -- something is
// driving this device -- and answers it as the system rather than as a test
// rig. Same include/logo.h the loader splash and the kernel console draw, so
// rig. Same include/gfx/logo.h the loader splash and the kernel console draw, so
// there is one mark and one set of bytes.
static void
draw_mark(void)
@ -812,7 +812,7 @@ mirror_pass(void)
//
// So the kernel is told, in advance, where to paint: it writes the report into
// this framebuffer and asks the kernel driver it took this device from to
// reset it and flush one frame. See PCIIOC_PANICFB in include/pciuser.h.
// reset it and flush one frame. See PCIIOC_PANICFB in include/dev/pciuser.h.
//
// Called again after every modeset, because the size is half of what was
// registered. Failing is not fatal to anything: it costs the crash screen on

View file

@ -17,7 +17,7 @@
It is marked twice over: it carries the accent, the same colour as the root at
the centre, and it reaches outward past the ring while sharing the inner edge
with every other slot. The colour is the reading on screen; the size is what
survives include/logo.h, which is a single coverage channel and keeps no
survives include/gfx/logo.h, which is a single coverage channel and keeps no
colour at all.
Stands alone, with no reference to SchOS, as projects/schfs-linux/README.md

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Before After
Before After

View file

@ -30,7 +30,7 @@ is a token. A hex value in that file means the system is missing something, and
the answer is to add it to Niveus rather than to work around it here.
What that replaced was a 21 KB `style.css` that transcribed
[`include/theme.h`](../../include/theme.h) by hand — palette, type scale,
[`include/gfx/theme.h`](../../include/theme.h) by hand — palette, type scale,
shadows, the lot. The intent was right and the mechanism was a copy: two files
that had to be kept in step by remembering to. Now the whole identity is one
declaration, in the `<head>` of each page:

View file

@ -9,7 +9,7 @@
answer is to add one rather than to work around it.
The one exception is `--nv-brand`, which is declared in the pages: it is
SCH_ACCENT from include/theme.h, and it is an input to the system rather
SCH_ACCENT from include/gfx/theme.h, and it is an input to the system rather
than a restatement of it.
========================================================================== */

View file

@ -26,7 +26,7 @@
</script>
<!-- The whole identity, and it is not a design decision: SCH_ACCENT, copied
from include/theme.h. A site describing an operating system should look
from include/gfx/theme.h. A site describing an operating system should look
like the operating system. -->
<style>
:root { --nv-brand: #7C5CFF; }

View file

@ -44,7 +44,7 @@ because there are none.** Everything the jump needs is computed before.
### The hand-off block
One page of low memory at `0x30000`, defined once in
[`include/schboot.h`](../../include/schboot.h) and included by both the loader
[`include/arch/schboot.h`](../../include/schboot.h) and included by both the loader
and `entry.S` so the two cannot disagree.
| Offset | What |
@ -463,7 +463,7 @@ what makes a loop over candidates legal at all.
| 6 | IDE 0 | usually the ESP, so usually not SchFS |
The **registered** devices are the ones found at probe time rather than known
at build time, numbered from 4 (`include/blkdev.h`): a SATA disk behind AHCI
at build time, numbered from 4 (`include/fs/blkdev.h`): a SATA disk behind AHCI
(`sata0`), an NVMe namespace (`nvme0n1`), each USB stick (`usb0`..`usb3`, the
first of them also seen as device 3), and every partition on any of them
(`sata0p2`, `nvme0n1p2`, `usb0p2`). When a disk registers, its GPT is read, or its MBR

View file

@ -11,7 +11,7 @@ Moving drivers out of the kernel entirely is [../plan/hybrid.md](../plan/hybrid.
## One list of everything attached
There is one list of everything attached, whatever bus found it:
`include/device.h` and `kernel/dev/device.c`, readable at `/proc/devices`.
`include/dev/device.h` and `kernel/dev/device.c`, readable at `/proc/devices`.
```
name bus class driver device

View file

@ -344,7 +344,7 @@ both need the `..` fixup and the ancestor-loop check that are not written.
A name is at most 255 bytes and a path 4096 including its NUL, Linux's
`NAME_MAX` and `PATH_MAX` (`VFS_NAME_MAX` and `VFS_PATH_MAX` in
`include/file.h`). Longer is `ENAMETOOLONG`. A filesystem may hold less: the v1
`include/fs/file.h`). Longer is `ENAMETOOLONG`. A filesystem may hold less: the v1
format stores `DIRSIZ` bytes and refuses longer names rather than matching on
their first 30.

View file

@ -265,7 +265,7 @@ is the mutual exclusion; the socket node never was.
## Text
[`include/text.h`](../../include/text.h) + `kernel/dev/text.c`.
[`include/gfx/text.h`](../../include/text.h) + `kernel/dev/text.c`.
**The font was never the problem — the character-cell grid was.** The console
draws text by indexing `font_data[256][16]` and stepping the cursor eight
@ -554,7 +554,7 @@ captured framebuffer.
## One palette
[`include/theme.h`](../../include/theme.h). There were three unrelated designs
[`include/gfx/theme.h`](../../include/theme.h). There were three unrelated designs
and the seams showed: the splash was deep purple with gold text deliberately
matching the *panic* screen, the console was cream with near-black text, and so
a healthy boot was dressed as a crash and then abruptly became an amber

View file

@ -61,7 +61,7 @@ one's bug.
### The protocol
`include/schinit.h`. **Every message is exactly one struct**, and PID 1 reads
`include/uapi/schinit.h`. **Every message is exactly one struct**, and PID 1 reads
`sizeof(struct)` or nothing: no length prefix to get wrong, no partial-message
state machine, and no allocation in the process that must not fail. The socket is
a `socketpair` inherited as fd 3.

View file

@ -108,7 +108,7 @@ one per-CPU block and everything that changes per CPU belongs in it.
> calls. But `%fs` here is per *CPU*, and a kernel thread changes CPU at every
> `sched()`. So the assumption is false for exactly the variables that most need
> to be right, and the failure is a null dereference deep in the scheduler on any
> machine with more than one core. `include/proc.h` carries the disassembly that
> machine with more than one core. `include/core/proc.h` carries the disassembly that
> proves it.
## Memory
@ -119,7 +119,7 @@ no buddy system, no zones, no page-frame database.
### Small objects
`kernel/core/kmem.c`, `include/kmem.h`. A slab is one page from `kalloc()` with
`kernel/core/kmem.c`, `include/core/kmem.h`. A slab is one page from `kalloc()` with
a header at the front and objects packed after it; free objects hold the free
list in their own first eight bytes.
@ -196,7 +196,7 @@ contiguous multi-page allocator, which is a separate thing and is not written.
## Processes
`struct proc` in [`include/proc.h`](../../include/proc.h). A fixed table of
`struct proc` in [`include/core/proc.h`](../../include/proc.h). A fixed table of
`NPROC` entries, allocated by linear scan.
**The field order at the top of the struct is fixed by assembly.** `trapasm.S`

View file

@ -334,7 +334,7 @@ format bugs are found on the host where a test takes a second instead of a boot.
## The source
```
include/schfs.h on-disk format + compile-time layout assertions
include/fs/schfs.h on-disk format + compile-time layout assertions
kernel/fs/schfs/btree.{c,h} the copy-on-write B-tree and its cursor
kernel/fs/schfs/schfs_int.h volume + object layer interface
kernel/fs/schfs/space.c allocation bitmap, derived from the tree at mount
@ -345,7 +345,7 @@ kernel/fs/schfs/kmount.c kernel: block device, mount slots, transaction brac
kernel/fs/schfs/vfs.c the fs_ops table: SchFS behind open/read/write
tools/mkschfs.c build an image from a directory tree
tools/schfs_fsck.c verify, list, extract
include/fsstat.h counters behind /proc/fsstat: where the time goes
include/fs/fsstat.h counters behind /proc/fsstat: where the time goes
tools/schfs_test.c B-tree torture harness
tools/schfs_objtest.c object layer: files, directories, space accounting
tools/posix/schfs_roundtrip.sh end-to-end filesystem test

View file

@ -20,7 +20,7 @@ hand-maintained:
| Generated | Where |
|---|---|
| The `SYS_*` constants | `include/syscall.h` |
| The `SYS_*` constants | `include/core/syscall.h` |
| The dispatch table | `kernel/sys/syscall.c` |
| The Linux translation map | `kernel/sys/linux_abi.c` |

View file

@ -55,7 +55,7 @@ Eight bytes:
| `pad` | to eight, so the grid indexes without a multiply |
`ch` was one byte holding a CP437 glyph, not a codepoint: the console mapped
UTF-8 down to CP437 on the way in, because that is what `include/font.h`
UTF-8 down to CP437 on the way in, because that is what `include/gfx/font.h`
contained. Widening it to the codepoint is what made Ą, Ę, Ś, Ω and the rest
possible, and no font change could have done it alone — a byte cannot *hold*
U+0104 whatever is drawing it. Mapping on the way in also meant the decision
@ -249,7 +249,7 @@ terminals behind your back. Right Alt is tracked as its own bit (`RALT`) for
the same reason; it used to share `ALT`, which is harmless for typing — neither
is used to look up a character — and wrong for chords.
`include/posix.h`'s `VTC_*` bits mirror `include/kbd.h`'s modifier bits, and a
`include/uapi/posix.h`'s `VTC_*` bits mirror `include/dev/kbd.h`'s modifier bits, and a
`_Static_assert` in `kbd.c` holds them together. A mismatch would be silent:
a chord set from userspace would simply never match, and the only symptom
would be a key that does nothing.

View file

@ -27,7 +27,7 @@ Linux's drivers are GPL-2.0-only and are not — see
## What the spec gives you for free
Everything in [`include/usb.h`](../../include/usb.h) comes from USB 2.0
Everything in [`include/dev/usb.h`](../../include/usb.h) comes from USB 2.0
chapter 9, which every device implements regardless of speed, class or vendor.
**That is what makes enumeration possible at all:** before you know anything

View file

@ -30,8 +30,8 @@ a brief for one is not worth carrying until somebody is going to draw it.
## The one constraint everything answers to
**The kernel draws its mark as a 128×128 single-channel coverage mask.**
`include/logo.h` holds no colour at all — two pixels per byte, sixteen levels of
ink — and the kernel composites it in whatever `include/theme.h` says.
`include/gfx/logo.h` holds no colour at all — two pixels per byte, sixteen levels of
ink — and the kernel composites it in whatever `include/gfx/theme.h` says.
So any mark that will end up there has to survive as **a solid shape in one
colour at 128 px, and be recognisable at 24**. That rules out hairlines, thin
@ -64,7 +64,7 @@ the kernel's name (**SchIFT**) as a shape.
## Colour
From `include/theme.h`, which is the source of truth. Nothing here restates a
From `include/gfx/theme.h`, which is the source of truth. Nothing here restates a
value it does not already define.
| | | |
@ -128,7 +128,7 @@ superseded-*.png the old wordmark, kept for reference only
The pipeline is three stages:
```
shift-mask.svg --(inkscape)--> shift-mask.png --(make logo)--> include/logo.h
shift-mask.svg --(inkscape)--> shift-mask.png --(make logo)--> include/gfx/logo.h
```
**Both intermediates are committed, and that is deliberate.** `inkscape` is not
@ -154,7 +154,7 @@ If either is edited, edit both.
| | |
|---|---|
| Loader splash | Shift, from `include/logo.h`, shaded per row by `metal()` in `boot/common/ui.c` — silver, not accent. |
| Loader splash | Shift, from `include/gfx/logo.h`, shaded per row by `metal()` in `boot/common/ui.c` — silver, not accent. |
| Kernel console / early boot | Shift, same mask, composited flat in a theme colour by `gfx_draw_logo`. |
| A display with no compositor | Shift again, drawn by `vgpud` on `SCH_BG`. It replaced a test card — colour bands, gradients, a checkerboard and the driver's pid in binary — which was scaffolding for [../plan/hybrid.md](../plan/hybrid.md)'s H2 and H3 and outlived them. The mark answers the same question a black screen cannot, *something is driving this device*, and answers it as the system rather than as a test rig. |
| PSOGM | Shift, the same mask again, by `gfx_draw_logo()` from `kernel/core/panic.c`. At its native 128 px — there is no resampler in the crash path, and the mark was only ever drawn at one size there anyway. |

View file

@ -3,7 +3,7 @@
<desc>SAME GEOMETRY AS "shift.svg". Only the fills differ, and they are
greys because they are not colours: tools/python/mklogo.py reads ink as
(255 - luminance) * alpha, so what is stored is coverage. The kernel then
composites that coverage in whatever include/theme.h says the accent is.
composites that coverage in whatever include/gfx/theme.h says the accent is.
The greys run DARK AT THE TOP because the relationship inverts: darkest here
is most ink, which the kernel draws brightest. Copying the violet fills from

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Before After
Before After

View file

@ -17,7 +17,7 @@
It is marked twice over: it carries the accent, the same colour as the root at
the centre, and it reaches outward past the ring while sharing the inner edge
with every other slot. The colour is the reading on screen; the size is what
survives include/logo.h, which is a single coverage channel and keeps no
survives include/gfx/logo.h, which is a single coverage channel and keeps no
colour at all.
Stands alone, with no reference to SchOS, as projects/schfs-linux/README.md

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Before After
Before After

View file

@ -15,7 +15,8 @@ schos/
├─ boot/ uefi/ the PE/COFF loader (splash, F8 menu, kernel load),
│ common/ the UI it shares. UEFI only -- there is no BIOS path.
├─ kernel/ The kernel, by subsystem: arch/ core/ dev/ fs/ proc/ sys/
├─ include/ Headers shared by kernel, userland, and tools/mkfs
├─ include/ Headers shared by kernel, userland, and tools/mkfs, by
│ subsystem -- see "include/" below
├─ lib/ First-party userland runtime: _start glue, syscall stubs,
│ the initcode blob embedded in the kernel, user.ld
├─ cmd/ First-party programs — one directory per program:
@ -57,6 +58,32 @@ schos/
└─ build/ ALL generated output (see below)
```
## include/
One folder per subsystem, and every include names it: `#include
"core/proc.h"`, not `"proc.h"`. The compiler is given `-I./include` and
nothing deeper, so the folder is the only way to reach a header and the
include line says where to find it.
| folder | what is in it |
|---------|---------------|
| `arch/` | the x86-64 machine: `mmu.h`, `x86.h`, `traps.h`, `memlayout.h`, `mp.h`, `ioperm.h`, `vmap.h`, `asm.h`, and `schboot.h`, the loader's handoff block |
| `core/` | the kernel proper: `types.h`, `param.h`, `defs.h`, `proc.h`, the locks, `kmem.h`, `dma.h`, `irq.h`, `klog.h`, `dbg.h`, `sbuf.h`, `syscall.h`, `uaccess.h`, `hwinfo.h`, `elf.h`, `date.h` |
| `fs/` | the VFS and what is under it: `fs.h`, `file.h`, `buf.h`, `blkdev.h`, `schfs.h`, `fat.h`, `fsstat.h` |
| `dev/` | devices and buses: `device.h`, `pci.h`, `pciuser.h`, `usb.h`, `virtio.h`, `acpi.h`, `input.h`, `kbd.h`, `keymap.h`, `vt.h`, `audio.h`, `netdev.h` |
| `gfx/` | pixels: `display.h`, `fb.h`, `gfx.h`, `font.h`, `text.h`, `ttf.h`, `theme.h`, `logo.h` (generated), `qr.h` |
| `net/` | `socket.h`, `netuser.h` |
| `uapi/` | what userland is built against: `user.h`, `posix.h`, `errno.h`, `stat.h`, `fcntl.h`, `schinit.h` |
| `ldls/` | the Linux driver layer's headers |
A side effect worth having: `errno.h`, `stat.h` and `fcntl.h` are no longer
at the top of `include/`, so a host tool built with `-I./include` gets the
system's versions of them rather than ours.
`tools/fix-includes.py` rewrites a bare `#include "proc.h"` to the folder the
header is in, reading the folders from the tree. Run it with `--modified` on
code written before the split, or after moving a header.
## build/
```

View file

@ -61,7 +61,7 @@ Fixed:
it's touched, with a clear message.
- No TLB invalidation existed anywhere except the full `lcr3` reload on
context switch — `mappages()`/`vm_unmap_range()` never called `invlpg`.
Fixed by adding `invlpg()` (`include/x86.h`) to both functions.
Fixed by adding `invlpg()` (`include/arch/x86.h`) to both functions.
- **`MSR_STAR` was misconfigured** (`syscallinit()`, `kernel/arch/x86_64/vm.c`):
`SYSRETQ` computes the returned `cs`/`ss` as `STAR[63:48]+16`/`+8`, which
requires the *compat* 32-bit code selector (`SEG_UCODE32`) in that field —
@ -76,7 +76,7 @@ Fixed:
length. A single allocation over 8MB (e.g. `realloc()` growth past that
size) mapped straight into a neighboring live mapping and hit
`mappages()`'s `panic("remap")`. Replaced with a real bump allocator
(`proc->mmap_next`, `include/proc.h`), so every mapping gets its own
(`proc->mmap_next`, `include/core/proc.h`), so every mapping gets its own
disjoint, exactly-sized range regardless of size.
- **`uva2ka()`** (`kernel/arch/x86_64/vm.c`) returned only the page-aligned
base address of a user pointer's page, silently dropping the in-page byte
@ -105,7 +105,7 @@ Bringing in toybox (see "Coreutils" below) surfaced four more, all fixed:
- `sys_open`/`sys_openat` required `omode == O_RDONLY` *exactly* to open a
directory, but `opendir()`-style calls legitimately OR in `O_DIRECTORY`/
`O_CLOEXEC` alongside it. Fixed to check just the access-mode bits
(`O_ACCMODE`, added to `include/fcntl.h`).
(`O_ACCMODE`, added to `include/uapi/fcntl.h`).
- `sys_getdents64` read one `struct dirent` (16 bytes) at a time — a full
`bmap()`+`bread()` per slot. Directories here are hash-indexed (see
`tree_search()`/`tree_expand()` below), so a directory with a few dozen
@ -207,7 +207,7 @@ independently re-reads mode fields from the same block.
Splash/progress bar/boot menu rendering is a small standalone pixel
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.
pointer) reusing the kernel's own font data (`include/gfx/font.h`) directly.
It fills the framebuffer with PSOGM's purple (matching
`kernel/core/console.c`'s panic screen) and draws "SCHOS" centered, then:
@ -359,7 +359,7 @@ one tick and returned `-EINTR` unconditionally. mksh's wait loop had no
way to ever learn the child had exited, hanging forever.
Real signal delivery was implemented from scratch:
- `struct proc` (`include/proc.h`) gained `sig_handler[32]`/
- `struct proc` (`include/core/proc.h`) gained `sig_handler[32]`/
`sig_restorer[32]` (populated by `sys_rt_sigaction()`,
`kernel/sys/sys_sig.c`), `saved_sigtf` (stashed pre-signal trapframe),
and `in_signal` (re-entrancy guard). `allocproc()` zeroes these for a
@ -682,7 +682,7 @@ boot rather than being wiped a few hundred milliseconds in.
**There were three unrelated designs.** The splash was deep purple with gold
text, deliberately matching the *panic* screen. The console was cream with
near-black text. So a healthy boot was dressed as a crash, then abruptly
became an amber terminal. `include/theme.h` is now the one palette, and the
became an amber terminal. `include/gfx/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.

View file

@ -74,7 +74,7 @@ ls /mnt ; echo hi > /mnt/tmp/w ; cat /mnt/tmp/w ; mkdir /mnt/tmp/d
```
The VFS grew a real dispatch layer rather than a set of `if (dev == SCHFS_DEV)`
checks. `struct fs_ops` (include/file.h) is one table per filesystem, chosen by
checks. `struct fs_ops` (include/fs/file.h) is one table per filesystem, chosen by
`iget()` from the device number and hung off the inode; v1's implementations
keep their bodies and are simply named `v1_*`. Adding a third filesystem is a
new table and nothing else. `kernel/fs/schfs/vfs.c` is SchFS's, and it is pure
@ -100,7 +100,7 @@ Three things had to change on the way, none of them SchFS's fault:
Three long-standing bugs surfaced the moment real commands ran against it, all
in the shared VFS rather than in SchFS:
- `include/fcntl.h` used xv6's open flags while every program in the userland
- `include/uapi/fcntl.h` used xv6's open flags while every program in the userland
sends Linux's. `O_APPEND` (0x400) landed on `O_TRUNC`, so `cmd >> file`
*truncated* it; `O_TRUNC` (0x200) landed on `O_CREATE`, so `cmd > file` left
whatever was past the new end in place. Nothing about either pointed at a
@ -273,7 +273,7 @@ because asking a filesystem a question does not.
Not starting from zero:
- **`struct schfs_extent`** is already defined in `include/fs.h` and unused.
- **`struct schfs_extent`** is already defined in `include/fs/fs.h` and unused.
The extent concept is already sketched; v2 gives it refcounts and 64-bit
fields.
- **CRC32c checksum fields** already exist in `dinode` and `superblock`, and

View file

@ -256,7 +256,7 @@ These are the galling ones — the replacement exists, is tested, and is unused.
rest of it retired — which needs explaining, because the item as written
asked for something a terminal cannot be.
`include/text.h` made the case against the grid in four charges: it
`include/gfx/text.h` made the case against the grid in four charges: it
cannot do variable-width glyphs, cannot position text off a multiple of
eight, cannot anti-alias, and cannot hold a codepoint above 255. **All
four were about the drawing layer, and all four are now false** — glyphs

View file

@ -45,7 +45,7 @@ the one that survives contact with a real machine.
## Built so far
**Mechanisms 2 and 4 exist.** `/dev/pci` (include/pciuser.h, kernel/dev/pciuser.c)
**Mechanisms 2 and 4 exist.** `/dev/pci` (include/dev/pciuser.h, kernel/dev/pciuser.c)
enumerates the bus, hands a device to a process exclusively, maps a BAR into it
and allocates memory a device can be pointed at. `pcitest` proves it end to end:
@ -378,7 +378,7 @@ a panic, so the process holding the device is never going to run again, and the
kernel let go of the device deliberately.
**So the userspace driver says in advance where it is scanning out**, with
`PCIIOC_PANICFB` (see `include/pciuser.h`), and the kernel does the rest:
`PCIIOC_PANICFB` (see `include/dev/pciuser.h`), and the kernel does the rest:
1. paints the report into that memory,
2. asks the *kernel* driver the device was taken from to put it on screen —

View file

@ -11,7 +11,7 @@
# There is now a third way, and it is the one for a machine that will not boot:
# pick "Remote debugging" in the F8 menu of a build made with DEBUG=1, and
# schinitd starts this job despite the line below. That entry does not exist in
# an ordinary build -- see SCHBOOT_DEBUG_FLAG in include/schboot.h.
# an ordinary build -- see SCHBOOT_DEBUG_FLAG in include/arch/schboot.h.
#
# Off rather than loopback-only-and-on, even though loopback-only is already the
# default bind, because "a listener nobody asked for" is a different kind of
@ -20,7 +20,7 @@
#
# What it can reach is bounded in the kernel rather than here: schdbgd opens
# /dev/dbgro, which refuses any view that declared itself as changing state.
# See include/dbg.h.
# See include/core/dbg.h.
Label = os.schos.schdbgd
Program = /bin/schdbgd

View file

@ -1,6 +1,6 @@
# An interactive shell on /dev/tty3.
#
# NVT is 6 (include/vt.h) and the kernel creates all six terminals, but only
# NVT is 6 (include/dev/vt.h) and the kernel creates all six terminals, but only
# two ever had anything running on them -- so Alt+F3 switched to a terminal
# that was working perfectly and had nobody to talk to, which looks exactly
# like a broken one.

View file

@ -1,6 +1,6 @@
# An interactive shell on /dev/tty4.
#
# NVT is 6 (include/vt.h) and the kernel creates all six terminals, but only
# NVT is 6 (include/dev/vt.h) and the kernel creates all six terminals, but only
# two ever had anything running on them -- so Alt+F4 switched to a terminal
# that was working perfectly and had nobody to talk to, which looks exactly
# like a broken one.

View file

@ -1,6 +1,6 @@
# An interactive shell on /dev/tty5.
#
# NVT is 6 (include/vt.h) and the kernel creates all six terminals, but only
# NVT is 6 (include/dev/vt.h) and the kernel creates all six terminals, but only
# two ever had anything running on them -- so Alt+F5 switched to a terminal
# that was working perfectly and had nobody to talk to, which looks exactly
# like a broken one.

View file

@ -1,6 +1,6 @@
# An interactive shell on /dev/tty6.
#
# NVT is 6 (include/vt.h) and the kernel creates all six terminals, but only
# NVT is 6 (include/dev/vt.h) and the kernel creates all six terminals, but only
# two ever had anything running on them -- so Alt+F6 switched to a terminal
# that was working perfectly and had nobody to talk to, which looks exactly
# like a broken one.

View file

@ -104,7 +104,7 @@ zstyle ':completion:*:descriptions' format '%F{244}%d%f'
# ---------------------------------------------------------------------------
# Prompt
# ---------------------------------------------------------------------------
# The accent violet from include/theme.h, which is 99 in the 256-colour cube
# The accent violet from include/gfx/theme.h, which is 99 in the 256-colour cube
# and falls back to magenta on the 8-colour console. The last-status marker is
# the only thing here that ever turns red -- same rule as the rest of the
# system: normal states are calm, only failure is loud.

View file

@ -25,7 +25,7 @@
// It is the same bargain as kpi_io_ok() in ldls/kpi/io.c, one level down and
// enforced by hardware rather than by the driver's host being polite.
#include "types.h"
#include "core/types.h"
struct proc;

View file

@ -107,7 +107,7 @@ stosb(void *addr, int data, int cnt)
// 64-bit-only helpers. `rep stosq` and `xchgq` do not exist in 32-bit mode, so
// these must not even be parsed by the -m32 bootloader build -- they compiled
// there before only because uint64 was accidentally 32 bits wide, which is the
// bug include/types.h now asserts against.
// bug include/core/types.h now asserts against.
#ifdef __x86_64__
static inline void
stosq(void *addr, uint64 data, int cnt)

View file

@ -1,6 +1,6 @@
#pragma once
#include "types.h"
#include "core/types.h"
struct sbuf;

View file

@ -371,7 +371,7 @@ void ioapicmask(int irq);
extern uchar ioapicid;
void ioapicinit(void);
// dma.c — see include/dma.h for the full contract
// dma.c — see include/core/dma.h for the full contract
void dma_init(void*, void*);
// watch.c -- hardware watchpoints on DR0-DR3. See docs/architecture/debugging.md, D4.
@ -388,13 +388,13 @@ int netuser_ready(struct inode*);
int netuser_ioctl(uint64 request, uint64 argp);
void netuser_release_all(struct proc*);
// dbg.c -- /dev/dbg, the introspection registry. See include/dbg.h.
// dbg.c -- /dev/dbg, the introspection registry. See include/core/dbg.h.
int dbg_read(struct inode*, uint64, char*, int);
void dbg_request_dump(void);
void dbg_thread_start(void);
int dbg_write(struct inode*, uint64, char*, int);
// klog.c -- the kernel log that outlives the kernel. See include/klog.h.
// klog.c -- the kernel log that outlives the kernel. See include/core/klog.h.
void klog_init(void *base, uint64 bytes);
void klog_putc(int c);
int klog_read(uint64 off, char *dst, int n);
@ -608,8 +608,8 @@ void uartintr(void);
void uartputc(int);
// Drawing, the text console and the framebuffer geometry are NOT declared
// here: they live in include/gfx.h, and the display drivers that back them in
// include/display.h. Declaring vga_fill_rect() here is what let the crash
// here: they live in include/gfx/gfx.h, and the display drivers that back them in
// include/gfx/display.h. Declaring vga_fill_rect() here is what let the crash
// screen draw on one named driver.
// fb.c -- /dev/fb0, major 2.
@ -618,7 +618,7 @@ void fbclose(struct inode*);
// further syscalls, so it is the last the kernel hears about it.
void fb_mapped(void);
// AudioEngine and /dev/dsp. kernel/dev/audio.c, include/audio.h.
// AudioEngine and /dev/dsp. kernel/dev/audio.c, include/dev/audio.h.
int dspread(struct inode*, uint64, char*, int);
int dspwrite(struct inode*, uint64, char*, int);
void dspclose(struct inode*);
@ -644,7 +644,7 @@ int fb_ioctl(int request, addr_t arg);
int diskread(struct inode*, uint64, char*, int);
int diskwrite(struct inode*, uint64, char*, int);
// Network *drivers* are not declared here at all. They are reached through the
// netdev class in include/netdev.h -- a driver publishes a vtable and nothing
// netdev class in include/dev/netdev.h -- a driver publishes a vtable and nothing
// above it ever learns its name. Declaring e1000_transmit() here was what let
// the protocol stack call it directly.
@ -684,7 +684,7 @@ struct device *net_eth_device(int i);
// the loader handed over, because bringing that up is the first thing it does.
void platform_register_devices(uint64 fb_addr);
// drivers/gpu/vga -- the VBE framebuffer the loader programmed. Called only
// from registry.c; everything else draws through include/gfx.h.
// from registry.c; everything else draws through include/gfx/gfx.h.
void vga_fb_init(uint64 phys_addr);
uint64 vga_fb_phys(void);
int vga_fb_restore(void); // 0 = there is no fallback

View file

@ -1,6 +1,6 @@
#pragma once
#include "types.h"
#include "core/types.h"
// The kernel log that outlives the kernel.
//

Some files were not shown because too many files have changed in this diff Show more