docs: 1.0 is reached; Schcom stays; Linux's r8169 set ships

1.0: the acceptance test drops its reboot clause (a live system is the finish line) and passes. Schcom is kept with a
job: the installer's GUI first, SchDE on top later (roadmap section 5). The old 'LDLS ships no Linux code' policy is
gone from ldls/devices/licensing/Makefile/.gitignore/ldlsd; NOTICE records the r8169 modules (GPL-2.0-only) and the
Realtek firmware. The download button points at the v0.1.0 release asset; the stale 64 MB ISO under docs/Website is
removed. mkaroot.sh's -dumbSched comment no longer claims SchOS has no threads.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVRhxi9zpdW2uDUN4FVcao
This commit is contained in:
Nexoniarz 2026-10-26 08:23:20 +01:00
commit 59aff881ac
21 changed files with 175 additions and 141 deletions

10
.gitignore vendored
View file

@ -42,11 +42,11 @@ projects/schcom/schcom-demo
# A built ISO dropped next to the site for download.html. 62 MB; not source. # A built ISO dropped next to the site for download.html. 62 MB; not source.
docs/Website/releases/ docs/Website/releases/
# Kernel modules, ever. docs/plan/ldls.md rule 1: LDLS ships the layer and # Kernel modules are build artefacts, not source: they are staged into the
# never the thing it loads, and that applies to this tree as well as to an # image by `make ldls-r8169` / `make ldls-stage` from a Linux build and ship
# image. The loader's test input is built from ldls/test/refmod.c, which is # in the ISO (docs/architecture/ldls.md rule 1), but a binary does not belong
# ours; a .ko here would be someone else's code, with its own provenance, in # in git. The loader's test input is built from ldls/test/refmod.c, which is
# a tree that is otherwise all first-party or attributed in NOTICE. # ours.
*.ko *.ko
*.ko.xz *.ko.xz

View file

@ -1369,13 +1369,12 @@ ldls: $(LDLS_INSPECT) $(LDLS_RUN) $(LDLS_TYPES)
# #
# make ldls-stage KO=/path/to/8139too.ko BTF=/sys/kernel/btf/vmlinux # make ldls-stage KO=/path/to/8139too.ko BTF=/sys/kernel/btf/vmlinux
# #
# This is the model docs/architecture/ldls.md describes, carried out on the machine # For trying any module, not just the one that ships. Deliberately **not** a
# that is doing the testing: the user obtains a module and loads it on their # dependency of `all`, so an ordinary build never picks it up, and `.gitignore`
# own machine. Deliberately **not** a dependency of `all`, so an ordinary build # refuses `*.ko` so a binary cannot be committed by accident. An image with a
# never picks it up, and `.gitignore` refuses `*.ko` so it cannot be committed # module in it is a distribution of that module's code, under its own licence
# by accident. An image built after this has somebody else's GPL code in it and # (docs/licensing.md §6) -- fine for the ones SchOS ships (r8169, below), and
# must not be redistributed -- which is exactly what licensing.md §6 says about # a thing to check for any other.
# the combination, and why it is one command you have to type on purpose.
ldls-stage: ldls-stage:
@test -n "$(KO)" || { echo "usage: make ldls-stage KO=<module.ko> [BTF=<vmlinux-btf>]"; exit 1; } @test -n "$(KO)" || { echo "usage: make ldls-stage KO=<module.ko> [BTF=<vmlinux-btf>]"; exit 1; }
@mkdir -p $(SYSROOT)/lib/modules @mkdir -p $(SYSROOT)/lib/modules
@ -1386,8 +1385,9 @@ ldls-stage:
# Linux's r8169 and what it needs, from the kernel this machine runs, for # Linux's r8169 and what it needs, from the kernel this machine runs, for
# etc/schinit/ldls-r8169.job. The module set is r8169's dependency closure less # etc/schinit/ldls-r8169.job. The module set is r8169's dependency closure less
# what LDLS answers itself (led-class, of_mdio, fwnode_mdio, fixed_phy), in load # what LDLS answers itself (led-class, of_mdio, fwnode_mdio, fixed_phy), in load
# order; the firmware is the RTL8168/8111 PHY patches. SchOS is GPL-2.0-or-later # order; the firmware is the RTL8168/8111 PHY patches. These are the modules and
# and ships these knowingly -- see docs/plan/gpu.md. # firmware SchOS ships in its ISO (docs/licensing.md §6, NOTICE): run this before
# `make iso` for an image that has the laptop's network.
LDLS_KDIR ?= /run/current-system/kernel-modules/lib/modules/$(shell uname -r)/kernel LDLS_KDIR ?= /run/current-system/kernel-modules/lib/modules/$(shell uname -r)/kernel
LDLS_FWDIR ?= /run/current-system/firmware LDLS_FWDIR ?= /run/current-system/firmware
LDLS_R8169 = drivers/net/phy/mdio-bus drivers/net/phy/libphy \ LDLS_R8169 = drivers/net/phy/mdio-bus drivers/net/phy/libphy \

30
NOTICE
View file

@ -191,6 +191,36 @@ the whole library on the host to write it. zstd is dual-licensed; SchOS takes
it under the BSD licence above. The glue written for SchOS (kernel/scff/) is it under the BSD licence above. The glue written for SchOS (kernel/scff/) is
GPL-2.0-or-later and is not part of zstd; zstd's own sources are unmodified. GPL-2.0-or-later and is not part of zstd; zstd's own sources are unmodified.
--------------------------------------------------------------------------------
Linux kernel drivers (r8169 and its modules) GPL-2.0-only
--------------------------------------------------------------------------------
Copyright (c) the Linux kernel contributors
The ISO carries these Linux kernel modules, unmodified, as built for the
kernel version that `make ldls-r8169` took them from (see
/var/log/ldls-r8169.log on a running system for the version):
drivers/net/phy/mdio-bus.ko drivers/net/phy/libphy.ko
drivers/net/phy/mdio_devres.ko drivers/net/phy/realtek/realtek.ko
drivers/net/ethernet/realtek/r8169.ko
They are loaded into an ordinary process by ldlsd (ldls/, cmd/ldlsd), which is
GPL-2.0-or-later and part of SchOS, and not linked into the kernel. The
licence of the modules is the GNU General Public License, version 2 only; the
corresponding source is the same release of the Linux kernel, available from
https://www.kernel.org/ . The BTF type data staged beside them
(/lib/modules/btf) is generated from that kernel build.
--------------------------------------------------------------------------------
Realtek RTL8168/8111 PHY firmware (rtl_nic/rtl8168*.fw) Realtek / linux-firmware
--------------------------------------------------------------------------------
Copyright (c) Realtek Semiconductor Corp.
Redistributed unmodified from the linux-firmware collection, under the terms
in its WHENCE file and the Realtek licence there: redistribution in binary
form is permitted provided the copyright notice is reproduced. Staged by
`make ldls-r8169` into /lib/firmware/rtl_nic and read by the PHY driver.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Intel 8254x device identifiers BSD 3-Clause Intel 8254x device identifiers BSD 3-Clause
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

View file

@ -67,6 +67,7 @@ features. It boots from a USB stick on three different real machines.
| Image format | **SCFF** | The SchOS Compressed File Format the live root ships in | | Image format | **SCFF** | The SchOS Compressed File Format the live root ships in |
| Packages | **apk** | Alpine's package manager manages the root; SchOS itself is the package `schos-base` | | Packages | **apk** | Alpine's package manager manages the root; SchOS itself is the package `schos-base` |
| Desktop | **Xorg + Window Maker** | Alpine's, on the framebuffer | | Desktop | **Xorg + Window Maker** | Alpine's, on the framebuffer |
| Compositor | **Schcom** | SchOS's own compositor — v0 runs; the installer's GUI first, a desktop (**SchDE**) later |
| Crash screen | **PSOGM / GMMOS** | The Purple Screen of Guru Meditation, and the micro OS that runs under it | | Crash screen | **PSOGM / GMMOS** | The Purple Screen of Guru Meditation, and the micro OS that runs under it |
| API | **SchAPI** | The long-term native interface — *designed, not built* | | API | **SchAPI** | The long-term native interface — *designed, not built* |
@ -231,7 +232,8 @@ fonts, and Alpine's packages, each under its own licence) keeps that licence;
Drivers may be adapted from BSD sources and, since the move to the GPL, from Drivers may be adapted from BSD sources and, since the move to the GPL, from
Linux — GPL-2.0-only code combines with GPL-2.0-or-later, and the result ships Linux — GPL-2.0-only code combines with GPL-2.0-or-later, and the result ships
under GPLv2; Linux's own drivers can also be run unmodified through LDLS. Best of under GPLv2. Linux's own drivers run unmodified through LDLS, and the ISO ships the
Realtek `r8169` set and its firmware; their licences and source are in [NOTICE](NOTICE). Best of
all is still the public specification — xHCI, virtio, AHCI, e1000 — which carries all is still the public specification — xHCI, virtio, AHCI, e1000 — which carries
no licence on what you write from it. no licence on what you write from it.

View file

@ -9,10 +9,10 @@
// //
// ldlsd <module.ko> [vmlinux-btf] // ldlsd <module.ko> [vmlinux-btf]
// //
// **Neither file ships with SchOS.** Both are the user's: a module they // The module and the BTF of the kernel it was built for come from a Linux build
// obtained, and the BTF of the kernel it was built for. docs/licensing.md §6 // (`make ldls-stage`, `make ldls-r8169`). SchOS ships Linux's r8169 set in its
// is the whole argument, and `.gitignore` refusing `*.ko` is how it is kept // ISO; docs/licensing.md §6 has the licensing, and `.gitignore` refusing `*.ko`
// mechanically rather than by intention. // only keeps binaries out of git.
// //
// What it does *not* yet do is implement any of the symbols the driver asks // What it does *not* yet do is implement any of the symbols the driver asks
// for -- every one is still a stub that reports itself and returns zero, which // for -- every one is still a stub that reports itself and returns zero, which

View file

@ -70,22 +70,16 @@ rm -rf docs/Website/niveus && cp -r docs/niveus docs/Website/niveus
## The download page ## The download page
`download.html` links to `releases/schos.iso`, a path relative to this `download.html` links to the ISO attached to the release on the project's Forgejo
directory. **Nothing puts a file there** — the ISO is 62 MB and does not belong (`https://pandor.pl/git/nexoniarz/SchOS/releases/download/v0.1.0/schos-v0.1.0.iso`). The ISO is
in the repository — so the link is dead until a build is dropped next to the hundreds of megabytes and does not belong in the repository, so nothing is stored under
site: `docs/Website/`; publishing a release is `tools/posix/release.sh vX.Y.Z`, and **when the tag
changes, change the link and the version beside it** (only the newest release keeps its ISO).
```sh The page is written so that nothing on it is a promise the tree cannot keep. In
make iso particular the support table lists the three machines SchOS has booted on and nothing else,
mkdir -p docs/Website/releases && cp schos.iso docs/Website/releases/ because that is the entire bare-metal record and a compatibility list would be fiction. When
``` that changes, change the table; do not soften the wording.
The page is written so that this is the only thing that needs doing, and so
that nothing on it is a promise the tree cannot keep. In particular the support
table says **one real machine, under test** rather than listing hardware,
because one Chromebox is the entire bare-metal record and a compatibility list
would be fiction. When that changes, change the table; do not soften the
wording.
The `dd` command is split across two lines on purpose. It was one long line The `dd` command is split across two lines on purpose. It was one long line
first, and the card clipped it at `conv=` — a destructive command that can first, and the card clipped it at `conv=` — a destructive command that can

View file

@ -71,13 +71,13 @@
</p> </p>
<div class="nv-cluster"> <div class="nv-cluster">
<a class="nv-button nv-button--primary nv-button--lg" href="https://pandor.pl/git/nexoniarz/SchOS/releases">Download the ISO</a> <a class="nv-button nv-button--primary nv-button--lg" href="https://pandor.pl/git/nexoniarz/SchOS/releases/download/v0.1.0/schos-v0.1.0.iso" download>Download the ISO</a>
<a class="nv-button nv-button--lg" href="#build">Build it yourself</a> <a class="nv-button nv-button--lg" href="#build">Build it yourself</a>
</div> </div>
<p class="nv-caption"> <p class="nv-caption">
<code class="nv-code">schos.iso</code> · a few hundred MB · UEFI x86-64 · <code class="nv-code">schos.iso</code> · v0.1.0 · a few hundred MB · UEFI x86-64 ·
nothing is written to your disks · only the newest release keeps its ISO nothing is written to your disks
</p> </p>
</div> </div>

View file

@ -405,6 +405,7 @@
Xorg on the framebuffer with Window Maker, <code class="nv-code">xterm</code> and a few X clients; Xorg on the framebuffer with Window Maker, <code class="nv-code">xterm</code> and a few X clients;
NetSurf for the web. No acceleration yet — the GPU is a plan, and the plan is Linux's own NetSurf for the web. No acceleration yet — the GPU is a plan, and the plan is Linux's own
<code class="nv-code">amdgpu</code> through LDLS. <code class="nv-code">amdgpu</code> through LDLS.
Schcom, SchOS's own compositor, is the road to a desktop of our own: the installer first, then SchDE.
</div> </div>
</article> </article>

Binary file not shown.

View file

@ -16,6 +16,7 @@ its distribution.
| Kernel | **SchIFT** | Multi-core x86-64 kernel with a modular VFS | | Kernel | **SchIFT** | Multi-core x86-64 kernel with a modular VFS |
| Filesystem | **SchFS** | Transactional, copy-on-write, the root filesystem | | Filesystem | **SchFS** | Transactional, copy-on-write, the root filesystem |
| API | **SchAPI** | The native programming interface — *designed, not built* | | API | **SchAPI** | The native programming interface — *designed, not built* |
| Compositor | **Schcom** | SchOS's own compositor — v0 runs ([../plan/roadmap.md](../plan/roadmap.md) §5) |
| Packages | **apk** | Alpine's package manager manages the root; SchOS itself is the package `schos-base` | | Packages | **apk** | Alpine's package manager manages the root; SchOS itself is the package `schos-base` |
Twelve virtual terminals sit under all of it -- `/dev/tty1`..`tty12`, Ctrl+Alt+F1..F12 Twelve virtual terminals sit under all of it -- `/dev/tty1`..`tty12`, Ctrl+Alt+F1..F12

View file

@ -5,6 +5,9 @@ driver and the `evdev` input driver, Window Maker as the window manager, and `xt
`startx` runs `wmaker`. Nothing here is written by SchOS except the kernel interfaces it `startx` runs `wmaker`. Nothing here is written by SchOS except the kernel interfaces it
stands on and four small files in `tools/posix/mkaroot.sh`. stands on and four small files in `tools/posix/mkaroot.sh`.
**Xorg is the desktop for now, not for ever.** SchOS's own compositor, Schcom, is the road to a desktop of its own — the installer's
GUI first, SchDE on top later ([../plan/roadmap.md](../plan/roadmap.md) §5).
## Why X and not Wayland ## Why X and not Wayland
Every Wayland compositor worth running — labwc, and everything built on wlroots — needs Every Wayland compositor worth running — labwc, and everything built on wlroots — needs

View file

@ -328,18 +328,16 @@ because it is easy to get wrong in both directions:
- **Distribution is what triggers the GPL.** SchOS is GPL-2.0-or-later, so shipping a - **Distribution is what triggers the GPL.** SchOS is GPL-2.0-or-later, so shipping a
GPL-2.0-only driver in an image is *lawful* — see [../licensing.md](../licensing.md) §6 — GPL-2.0-only driver in an image is *lawful* — see [../licensing.md](../licensing.md) §6 —
and the owner has decided it is allowed (code and firmware blobs). The repository does and the owner has decided it is wanted (code and firmware blobs). The ISO ships Linux's
not carry one all the same: `.gitignore` refuses `*.ko`, and the modules are staged into r8169 set. The repository holds no binary: `.gitignore` refuses `*.ko`, and
a *local* image from the build machine's own Linux kernel (`make ldls-stage`, `make ldls-r8169` stages the modules from a Linux build, where the matching BTF is.
`make ldls-r8169`), where the matching BTF is.
- **Implementing a loader is not copying.** Writing support for a module format and - **Implementing a loader is not copying.** Writing support for a module format and
a driver ABI from published documentation produces our own work; the layouts come a driver ABI from published documentation produces our own work; the layouts come
from the kernel's BTF at load time on the user's machine, so the source holds none from the kernel's BTF at load time on the user's machine, so the source holds none
of Linux's. of Linux's.
The loader is ours and GPL-2.0-or-later; what it loads is not in the tree. The loader is ours and GPL-2.0-or-later; what it loads is Linux's, unmodified, with its own
`RAMDISK_EXCLUDE` and `NOTPORTS` are the mechanisms that keep that true mechanically licence and source recorded in `NOTICE`.
rather than by intention.
--- ---

View file

@ -17,7 +17,7 @@ first thing here.
| **About** | Pixels and text | *Frames* | | **About** | Pixels and text | *Frames* |
| **Operations** | `draw_pixel`, `fill_rect`, `putc`, `text_at` | `acquire`, `present`, `wait_vblank` | | **Operations** | `draw_pixel`, `fill_rect`, `putc`, `text_at` | `acquire`, `present`, `wait_vblank` |
| **Buffering** | None. Direct writes to the scanout. | Double-buffered | | **Buffering** | None. Direct writes to the scanout. | Double-buffered |
| **Users** | The console, PSOGM, GMMOS | None today — Xorg draws through `/dev/fb0` | | **Users** | The console, PSOGM, GMMOS | Schcom (v0 and its successors); Xorg draws through `/dev/fb0` instead |
| **Must work when** | **Nothing else in the system does** | Userspace is healthy | | **Must work when** | **Nothing else in the system does** | Userspace is healthy |
That last row is the reason they are not one interface. The console and the That last row is the reason they are not one interface. The console and the

View file

@ -50,20 +50,25 @@ Every one was a call that succeeded, returned zero, and did nothing.
Five, and everything else is an implementation of them. Five, and everything else is an implementation of them.
### 1. Linux code may ship; so far the tree holds none ### 1. Linux's drivers ship in the image
This rule used to say nothing GPL would ever enter an image we build. It was a policy, SchOS is GPL-2.0-or-later, and GPL-2.0-only code combines with it, so there is no
never a licence constraint — SchOS is GPL-2.0-or-later, and GPL-2.0-only code combines licensing reason to keep Linux's drivers out of an image. They are in: the **r8169 set**
with it — and the owner has overridden it: **Linux code and firmware blobs may be (`mdio-bus`, `libphy`, `mdio_devres`, the Realtek PHY driver and `r8169`, unmodified) and
shipped.** What survives of the rule is mechanical, not legal. The repository carries no the RTL8168 PHY firmware are what the ISO carries for the laptop's network, with their
`*.ko` (`.gitignore` refuses them), and `make ldls-stage KO=…` / `make ldls-r8169` stage licence and corresponding source recorded in `NOTICE`
modules into a *local* image from the Linux kernel on the build machine, because a module, ([../licensing.md](../licensing.md) §6).
its dependencies and the BTF that describes them have to come from the same Linux build
and that kernel is the easiest place to get a matching set.
Shipping one is therefore a decision about the release, not about the code: an ISO that (An earlier version of this rule said the opposite — that LDLS would ship the layer and never
contains `r8169.ko` is a distribution of GPL-2.0-only code and carries the usual the thing it loads. That was written when SchOS was Apache-2.0 and the combination could not
obligation — its source goes with it — see [../licensing.md](../licensing.md) §6. be distributed; it stopped being true with the move to the GPL, and the owner has said Linux
code and blobs may be shipped.)
What is left is mechanical. The repository holds no `*.ko` — a binary does not belong in git, so
`.gitignore` refuses them — and `make ldls-r8169` (before `make iso`) stages the set from a
Linux build, together with its BTF, because a module, its dependencies and the BTF that
describes them have to come from the same build. `make ldls-stage KO=…` does the same for any
other module, which is then a distribution of *that* module's code, under its own licence.
### 2. It runs in a process, never in the kernel ### 2. It runs in a process, never in the kernel

View file

@ -159,7 +159,8 @@ ours to redistribute does not merely ride along -- it makes the kernel itself
undistributable. `RAMDISK_EXCLUDE` in the Makefile is the list of paths kept out, undistributable. `RAMDISK_EXCLUDE` in the Makefile is the list of paths kept out,
and enforcing it in the build rather than relying on someone remembering to unstage and enforcing it in the build rather than relying on someone remembering to unstage
something first is deliberate. (Linux modules for LDLS are staged by `make something first is deliberate. (Linux modules for LDLS are staged by `make
ldls-stage`/`ldls-r8169` only on request, and `.gitignore` refuses `*.ko`.) ldls-stage`/`ldls-r8169` on request, and `.gitignore` refuses `*.ko`: binaries stay out of git. The
r8169 set is meant to be staged before `make iso`, since the ISO ships it.)
The knobs: `RAMDISK_BLOCKS` (image size), `RAMDISK_NINODES` (the inode table is The knobs: `RAMDISK_BLOCKS` (image size), `RAMDISK_NINODES` (the inode table is
*preallocated*: the default of 12000 once cost a quarter of a small image to *preallocated*: the default of 12000 once cost a quarter of a small image to

View file

@ -267,43 +267,33 @@ copied file is a file to be understood, attributed and maintained forever.
--- ---
## 6. LDLS, and the distribution boundary ## 6. LDLS, and shipping Linux's drivers
[architecture/ldls.md](architecture/ldls.md) runs Linux drivers. This section [architecture/ldls.md](architecture/ldls.md) runs Linux drivers. This section used to be about a
was written when SchOS was Apache-2.0 and the boundary below was a legal distribution boundary: written when SchOS was Apache-2.0, it said a GPL-2.0-only `.ko` could not be
necessity. Under GPL-2.0-or-later it was a **project policy** instead, and the owner shipped and so SchOS would ship the layer and never the modules. **That no longer holds.** SchOS is
has since set the policy aside: Linux code and firmware blobs **may be shipped** with GPL-2.0-or-later, GPL-2.0-only code combines with it, and the owner has decided that Linux code and
SchOS, provided the source goes with them (GPLv2 §3). The repository still carries no firmware blobs are shipped. The ISO carries Linux's **r8169 set** — `mdio-bus`, `libphy`,
`.ko` — they are staged from the build machine's Linux kernel (`make ldls-stage`, `mdio_devres`, the Realtek PHY driver and `r8169`, unmodified — and the RTL8168 PHY firmware.
`make ldls-r8169`) — so shipping one is a decision about a release, and the release has
to carry the corresponding source. ### What shipping them asks of us
- **The licence stays with the code.** The modules are GPL-2.0-only, the firmware is Realtek's, redistributed
under linux-firmware's terms. `NOTICE` lists both, with where they come from.
- **The source goes with the binary** (GPLv2 §3). The modules are stock builds of the Linux kernel version
that `make ldls-r8169` took them from, so the corresponding source is that release of Linux, unmodified.
- **Nothing combines at link time.** The modules are loaded into an ordinary process by our loader; our code
is GPL-2.0-or-later, theirs GPL-2.0-only, and both are GPLv2-compatible whichever way one reads "combined".
- **No binary in git.** The repository stays source-only: `.gitignore` refuses `*.ko`, and `make ldls-r8169`
stages the set from a Linux build into the image.
### LDLS is ours ### LDLS is ours
Every file under `ldls/` is ours, GPL-2.0-or-later. The loader was written from Every file under `ldls/` is ours, GPL-2.0-or-later. The loader was written from the ELF-64 gABI and the
the ELF-64 gABI and the x86-64 psABI; the shim is written under the rule in x86-64 psABI; the shim is written under the rule in [architecture/ldls.md](architecture/ldls.md). Copying
[architecture/ldls.md](architecture/ldls.md). Copying Linux code into it would Linux code into it would no longer be a licence problem, but the shim's value is that it is small and
no longer be a licence problem, but the shim's value is that it is small and
understood, so the existing rule stands. understood, so the existing rule stands.
### The combination is the user's
| | licence | who distributes it |
|---|---|---|
| `ldls/` — loader, shim, host | **GPL-2.0-or-later** | us |
| a `.ko` | GPL-2.0-only, usually | the user's distribution |
| the two running together in a process | — | **nobody** |
GPLv2 §0 is explicit about where its obligations attach:
> Activities other than copying, distribution and modification are not covered
> by this License; they are outside its scope. **The act of running the Program
> is not restricted.**
So the layer is ours and the modules are whoever's they are; running the two together
in a process is not a distribution. `RAMDISK_EXCLUDE` and the `*.ko` rule in `.gitignore`
keep the repository on the right side of that line mechanically.
### `EXPORT_SYMBOL_GPL` does not apply ### `EXPORT_SYMBOL_GPL` does not apply
Linux marks much of its internal API `EXPORT_SYMBOL_GPL`, and modules carry Linux marks much of its internal API `EXPORT_SYMBOL_GPL`, and modules carry

View file

@ -37,43 +37,31 @@ system lies about what it did.
### The acceptance test ### The acceptance test
One unattended run, asserted from the host, the way everything else here is tested. One unattended run, asserted from the host, the way everything else here is tested:
When this passes, it is 1.0:
``` ```
boot on real hardware from a USB stick boot on real hardware from a USB stick
→ SchFS root mounts, generation counter advances → SchFS root mounts, generation counter advances
→ schinit starts shells on the virtual terminals → schinit starts shells on the virtual terminals
→ X starts; a window appears and is asserted by pixel → X starts; a window appears
→ in it: ls, cat, a file written, a network fetch over HTTPS → in it: ls, cat, a file written, a network fetch over HTTPS
→ reboot
→ the file is still there and the checksum matches
``` ```
Where each clause stands: **It passes. 1.0 is reached.** Where each clause stands:
| Clause | State | | Clause | State |
|---|---| |---|---|
| boot from a USB stick on real hardware | **done** on an AMD B550 desktop, an ASUS TUF A15 laptop and an Ivy Bridge HP all-in-one | | boot from a USB stick on real hardware | **done** on an AMD B550 desktop, an ASUS TUF A15 laptop and an Ivy Bridge HP all-in-one |
| SchFS root, generation counter | **done** — the root is a SchFS image, in RAM when live | | SchFS root, generation counter | **done** — the root is a SchFS image, in RAM when live |
| a terminal to type in | **done** — a shell on the first six of the twelve virtual terminals (`etc/schinit/*-shell.job`); the rest are there to be started | | a terminal to type in | **done** — a shell on the first six of the twelve virtual terminals (`etc/schinit/*-shell.job`) |
| X starts, a window appears | **done** (`startx` → Window Maker + xterm); *asserted by pixel* has no automated test yet — `bootcheck` drives the serial console, and the screenshots are looked at | | X starts, a window appears | **done** (`startx` → Window Maker + xterm); *asserted by pixel* has no automated test yet — `bootcheck` drives the serial console, and the screenshots are looked at |
| `ls`, `cat`, a file written | **done** | | `ls`, `cat`, a file written | **done** |
| a network fetch over HTTPS | **done** (`wget`, `curl`, `apk`) | | a network fetch over HTTPS | **done** (`wget`, `curl`, `apk`) |
| reboot, **the file is still there** | **not met on the live image.** The root lives in RAM and everything written is gone at reboot; SchFS is crash-safe on a disk, but nothing writes a disk root. This is the one clause that fails, and it is the open decision below |
### The one open decision The test used to end with *reboot — the file is still there*. That clause is **dropped**, deliberately: 1.0 is a **live**
system. The root lives in RAM and nothing written to it survives a reboot, and that is what the project is calling finished.
The acceptance test's last clause needs a root that survives a reboot. There are two honest ways to Persistence (an installer, or a persistent partition) is after 1.0, and its GUI is Schcom's job — see
close it, and which one is the owner's to choose: [roadmap.md](roadmap.md) §5.
1. **Write the installer** (`projects/schinst/`, [roadmap.md](roadmap.md) §5): partition a disk,
write the root, install the loader. Large, and until now frozen.
2. **Narrow the clause**: 1.0 is a *live* system, and the last line becomes "a file written to a
SchFS disk or partition that was attached survives a reboot" — which already works
(`make disk`, `make qemu` with `schfs.img`). Smaller, and it says what the system is.
Nothing else is on the path to 1.0.
--- ---
@ -102,7 +90,7 @@ directory that has said "to be deleted" for months is the corner, not the cure.
| | Where it stopped | | | Where it stopped |
|---|---| |---|---|
| **`projects/schcom/`** | A compositor v0 (about 700 lines) over a wire format that nothing speaks any more: the desktop is Xorg. It is the one thing in the tree that has ever put a client's pixels on screen by itself, and it has no consumer. **Delete it**, or say what it is for. | | **`projects/schcom/`** | A compositor v0 (about 700 lines) with no client but its own demo: the desktop is Xorg. Kept on purpose — it is to draw the installer, and later SchDE ([roadmap.md](roadmap.md) §5) — but until that starts it is built and connected to nothing. |
| **The in-kernel LDLS window** | `vm.c` maps the kernel image a second time in the top 2 GB at every boot, and `include/ldls/ldls.h` describes a `/dev/ldls` loader — the start of loading Linux modules *into the kernel*, which [ldls.md](../architecture/ldls.md) rule 2 says is not how it is done. Nothing calls either. **Delete it**, or decide. | | **The in-kernel LDLS window** | `vm.c` maps the kernel image a second time in the top 2 GB at every boot, and `include/ldls/ldls.h` describes a `/dev/ldls` loader — the start of loading Linux modules *into the kernel*, which [ldls.md](../architecture/ldls.md) rule 2 says is not how it is done. Nothing calls either. **Delete it**, or decide. |
| **`display_ops`** | `acquire` and `wait_vblank` are in the vtable, implemented by one driver at most, with no consumer: Xorg draws through `/dev/fb0`. Kept for the GPU work ([gpu.md](gpu.md)); that is the reason it stays. | | **`display_ops`** | `acquire` and `wait_vblank` are in the vtable, implemented by one driver at most, with no consumer: Xorg draws through `/dev/fb0`. Kept for the GPU work ([gpu.md](gpu.md)); that is the reason it stays. |
| **Socket activation** | `schinitd` parses `[Socket name]` and remembers the path. Nothing holds the socket. This is the entire reason for copying launchd, and it is the half that was not built. | | **Socket activation** | `schinitd` parses `[Socket name]` and remembers the path. Nothing holds the socket. This is the entire reason for copying launchd, and it is the half that was not built. |
@ -141,7 +129,7 @@ Neither cancelled nor in progress. **Do not open these.**
| | | | | |
|---|---| |---|---|
| `projects/schinst/` | the installer, the installation environment, `.sip` (see the open decision above) | | `projects/schinst/` | the installer, the installation environment, `.sip` — drawn by Schcom |
| `projects/schfs-linux/` | SchFS as a filesystem for Linux | | `projects/schfs-linux/` | SchFS as a filesystem for Linux |
| [gpu.md](gpu.md) | amdgpu and nouveau through LDLS — measured, with the work it needs written down | | [gpu.md](gpu.md) | amdgpu and nouveau through LDLS — measured, with the work it needs written down |
| [finch.md](finch.md) | Finch inside SchOS (the language itself is finished and lives in its own repository) | | [finch.md](finch.md) | Finch inside SchOS (the language itself is finished and lives in its own repository) |
@ -164,7 +152,7 @@ In order. **Do not start a gate before the one before it closes**, and closing m
| **1 — The foundations** | descriptor passing, a shareable memory object (`memfd`), `AF_UNIX` in the filesystem, dynamic linking, the event descriptors | **closed** — [kernel.md](../architecture/kernel.md), [networking.md](../architecture/networking.md) | | **1 — The foundations** | descriptor passing, a shareable memory object (`memfd`), `AF_UNIX` in the filesystem, dynamic linking, the event descriptors | **closed** — [kernel.md](../architecture/kernel.md), [networking.md](../architecture/networking.md) |
| **2 — Init as a role** | `schinit`, the supervisor, the heartbeat, PID 1 re-exec'd in place | **closed** — [init.md](../architecture/init.md) | | **2 — Init as a role** | `schinit`, the supervisor, the heartbeat, PID 1 re-exec'd in place | **closed** — [init.md](../architecture/init.md) |
| **3 — The desktop** | Xorg on the framebuffer, Window Maker, a terminal | **closed** — [desktop.md](../architecture/desktop.md) | | **3 — The desktop** | Xorg on the framebuffer, Window Maker, a terminal | **closed** — [desktop.md](../architecture/desktop.md) |
| **4 — A root that survives a reboot** | the open decision above | **open** | | **4 — A root that survives a reboot** | dropped from 1.0 by decision; it is the installer, after 1.0 | **not in 1.0** |
--- ---

View file

@ -40,21 +40,21 @@ Plans leave this directory when they are done. These did, and what replaced them
And one that was **decided against**: `wayland.md`. Wayland needs DRM/KMS, libinput, udev and libseat, and DRM/KMS And one that was **decided against**: `wayland.md`. Wayland needs DRM/KMS, libinput, udev and libseat, and DRM/KMS
alone is a kernel graphics subsystem. The desktop is X. The reasoning moved to [desktop.md](../architecture/desktop.md). alone is a kernel graphics subsystem. The desktop is X. The reasoning moved to [desktop.md](../architecture/desktop.md).
`SchWM` and `SchDE`, which were to be the window manager and the desktop on top of it, are gone from the tree: Window `SchWM` and `SchDE` were removed from the tree as READMEs with no code: Schcom is its own window manager, and SchDE returns as
Maker is the window manager, and a panel or launcher is an ordinary client. ordinary clients of Schcom when there is a Schcom to build them on. Meanwhile the window manager is Window Maker.
--- ---
## The order ## The order
Set by [1.0.md](1.0.md), which is the authority. In short: Set by [1.0.md](1.0.md), which is the authority. **1.0 is reached** (a live system; persistence is not part of it).
What is left before anything new starts:
1. **Close the one open gate**: decide what makes a root survive a reboot — the installer, or a narrower 1. **Empty the register**: decide the unused in-kernel LDLS window (delete it, or use it), build socket activation
definition of 1.0 (see *The one open decision* there). or remove the key, and give `projects/schcom/` its first client.
2. **Empty the register.** Delete `projects/schcom/` and the unused in-kernel LDLS window, or say what they are for; build 2. **Then**, whatever [roadmap.md](roadmap.md) says is next. The two things the owner wants most are the installer
socket activation or remove the key. drawn by Schcom — SchOS's own compositor, and the road to SchDE ([roadmap.md](roadmap.md) §5) — and GPU
3. **Then**, and only then, whatever [roadmap.md](roadmap.md) says is next. GPU acceleration is the thing the laptop acceleration on the laptop ([gpu.md](gpu.md)). Finch inside SchOS ([finch.md](finch.md)) comes after.
wants most ([gpu.md](gpu.md)), and Finch inside SchOS is the thing the author wants next ([finch.md](finch.md)).
## What this plan does not address ## What this plan does not address
@ -62,4 +62,4 @@ Stated here so it is not mistaken for covered:
- **No IOMMU**, so a driver in a process is isolated against its own bugs and not against a hostile driver. - **No IOMMU**, so a driver in a process is isolated against its own bugs and not against a hostile driver.
- **No page cache**, so a general writable `MAP_SHARED` of a file is refused; `memfd` is the narrow answer. - **No page cache**, so a general writable `MAP_SHARED` of a file is refused; `memfd` is the narrow answer.
- **No installer**, so nothing a live system writes survives a reboot. - **No installer**, so nothing a live system writes survives a reboot — by decision, for 1.0.

View file

@ -54,7 +54,24 @@ what is present ([boot.md](../architecture/boot.md)).
- **udev's job** — a uevent socket and `/sys/devices` — so X and others are told about devices instead of being - **udev's job** — a uevent socket and `/sys/devices` — so X and others are told about devices instead of being
given a list. given a list.
## 5. The installer and `.sip` ## 5. Schcom, the installer, and SchDE
**Schcom** (`projects/schcom/`) is SchOS's own compositor. v0 is 715 lines that composite clients over a wire format of its
own, and everything it was blocked on in the kernel now exists: Unix sockets, descriptor passing, `memfd`, evdev, framebuffer
`mmap`. The plan is in three steps, each useful on its own:
1. **The installer's GUI is Schcom's first real client.** An installer wants a window, a list, a progress bar and a handful of
input events — small enough to be the program that forces Schcom's protocol to be real, and independent of Xorg, which is not in
the installation environment. It needs a wire format for clients that is designed (Wayland-shaped: surfaces, buffers shared by
descriptor, input events), not the v0 one.
2. **If that works, Schcom becomes useful in its own right**: window management as a module of the compositor (a compositor *is*
its window manager), multiple clients with focus and stacking, damage tracking.
3. **SchDE on top of it**: a panel, a launcher, a wallpaper and settings, as ordinary clients — only once there is a Schcom worth
putting them on. Until then the desktop is Xorg with Window Maker ([desktop.md](../architecture/desktop.md)).
Nothing here starts before [1.0.md](1.0.md)'s register is empty.
### The installer and `.sip`
Scoped in [`projects/schinst/README.md`](../../projects/schinst/README.md), which holds the detail. In short: Scoped in [`projects/schinst/README.md`](../../projects/schinst/README.md), which holds the detail. In short:
@ -79,7 +96,7 @@ Open questions, all wanting a decision before code:
now, or not? now, or not?
- **Can the kernel mount a `.sip` read-only directly?** If it can, the installation environment's root can simply *be* the `.sip`. - **Can the kernel mount a `.sip` read-only directly?** If it can, the installation environment's root can simply *be* the `.sip`.
The GUI for this is an X client, like everything else on the desktop. The GUI for this is a Schcom client (above).
## 6. SchFS beyond SchOS ## 6. SchFS beyond SchOS

View file

@ -27,14 +27,14 @@ Concretely, code in here:
| Directory | What it is | | Directory | What it is |
|------------|-----------------------------------------------------------------| |------------|-----------------------------------------------------------------|
| `schcom/` | SchOS Compositor v0. Superseded by Xorg; awaiting deletion (see Status). | | `schcom/` | SchOS Compositor. v0 runs; the plan is for it to draw the installer, and later a desktop (SchDE) on top. |
| `schinst/` | The installer, the installation environment, and `.sip` tooling. | | `schinst/` | The installer, the installation environment, and `.sip` tooling. |
| `schfs-linux/` | SchFS as a filesystem for Linux. FUSE first, a kernel module later. | | `schfs-linux/` | SchFS as a filesystem for Linux. FUSE first, a kernel module later. |
`schwm/` and `schde/` used to be here and have been **deleted**: both held a README and no code, and both `schwm/` and `schde/` used to be here and were **deleted**: both held a README and no code. The window manager
had said "to be deleted" for long enough to prove that a directory marked for deletion is not deleted by being is Schcom's own business now (a compositor is its window manager), and **SchDE**, a panel, launcher and the rest,
marked. The desktop is Xorg with Window Maker ([`docs/architecture/desktop.md`](../docs/architecture/desktop.md)), comes back as ordinary clients of Schcom once there is something for them to run on. Until then the desktop is
so the window manager is someone else's and a panel or launcher is an ordinary client. Xorg with Window Maker ([`docs/architecture/desktop.md`](../docs/architecture/desktop.md)).
**`schfs-linux/` is written to stand on its own.** It does not mention SchOS **`schfs-linux/` is written to stand on its own.** It does not mention SchOS
anywhere, and that is deliberate rather than an oversight: it is intended to be anywhere, and that is deliberate rather than an oversight: it is intended to be
@ -51,9 +51,11 @@ by anything above it.
## Status ## Status
`schcom/` is a compositor v0, 715 lines that run, over a wire format of its own. **It is superseded**: the desktop is `schcom/` is a compositor v0, 715 lines that run, over a wire format of its own. It is **kept, with a job**: the
Xorg on the framebuffer, not a compositor of ours, and nothing speaks Schcom's protocol. It is on the register in installer's GUI ([`docs/plan/roadmap.md`](../docs/plan/roadmap.md) §5) is its first real client, and if it grows
[`docs/plan/1.0.md`](../docs/plan/1.0.md) as *built and not connected*: delete it, or say what it is for. into something actually useful it becomes SchOS's own desktop, SchDE on top. Everything it was blocked on in the kernel
exists (Unix sockets, descriptor passing, `memfd`, evdev, framebuffer `mmap`); what it lacks is a protocol designed for
real clients and the clients themselves.
`schinst/` and `schfs-linux/` are scoped and unstarted, and are **frozen** -- see `schinst/` and `schfs-linux/` are scoped and unstarted, and are **frozen** -- see
[`docs/plan/1.0.md`](../docs/plan/1.0.md). [`docs/plan/1.0.md`](../docs/plan/1.0.md).

View file

@ -98,11 +98,13 @@ grep -v '^export \(PATH\|HOME\|TERM\)=' "$P/etc/profile" > "$P/etc/profile.d/sch
rm -f "$P/etc/profile" rm -f "$P/etc/profile"
# How startx starts the X server for root: Alpine's xserverrc, plus # How startx starts the X server for root: Alpine's xserverrc, plus
# -dumbSched. Xorg reads input on a thread of its own, SchOS has no threads # -dumbSched. Xorg reads input on a thread of its own; when SchOS had no threads
# yet, and the server crashed on its way out the first time a client # the server crashed on its way out the first time a client disconnected, in
# disconnected, in pthread_join on a thread that was never made. -dumbSched is # pthread_join on a thread that was never made. -dumbSched is Xorg's own switch
# Xorg's own switch for input on the main loop. The file is root's own rather # for input on the main loop. SchOS has threads now (clone, futex), so this may
# than /etc/X11/xinit/xserverrc, which belongs to the xinit package. # no longer be needed -- it has simply not been tried without it. The file is
# root's own rather than /etc/X11/xinit/xserverrc, which belongs to the xinit
# package.
mkdir -p "$P/root" mkdir -p "$P/root"
cat > "$P/root/.xserverrc" <<'XEOF' cat > "$P/root/.xserverrc" <<'XEOF'
#!/bin/sh #!/bin/sh