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
347 lines
16 KiB
Markdown
347 lines
16 KiB
Markdown
# Licensing
|
|
|
|
The one page to check before copying anyone else's code into SchOS.
|
|
|
|
Referenced from `LICENSE`, `LICENSE.MIT` and `NOTICE`, all three of which
|
|
pointed here long before this file existed.
|
|
|
|
---
|
|
|
|
## 1. SchOS is GPL-2.0-or-later
|
|
|
|
Copyright Nexoniarz. See `LICENSE`. Until 2026-10 SchOS was Apache-2.0; it was
|
|
never published under that licence, and as the sole author Nexoniarz relicensed
|
|
it outright.
|
|
|
|
**Why the GPL.** Two reasons, one about others and one about us:
|
|
|
|
- **Copyleft.** Anyone may use, study, modify and redistribute SchOS — but
|
|
whoever ships it, or something built from it, must ship the source of that
|
|
too, under the same terms. Under Apache-2.0 a fork could be closed and sold
|
|
with no changes given back. The GPL does not forbid commercial use; it forbids
|
|
taking the work private.
|
|
- **Linux.** Linux is GPL-2.0-only, and Apache-2.0 could not be combined with
|
|
it. Under the GPL, Linux drivers and code can be adopted (§2).
|
|
|
|
**Why "or later".** It keeps one door open that "only" would close: GPLv3 and
|
|
Apache-2.0 code can still be combined with SchOS code, with that combination
|
|
shipping under GPLv3. See §2 for why the kernel should not walk through it.
|
|
|
|
**What was given up.** Apache-2.0 had an express patent grant; GPLv2 has only
|
|
an implied one. That mattered most for outside contributions, and there are
|
|
none yet.
|
|
|
|
New first-party files carry `SPDX-License-Identifier: GPL-2.0-or-later`.
|
|
|
|
---
|
|
|
|
## 2. What can be copied in
|
|
|
|
| Licence | Verdict | Obligation |
|
|
|---|---|---|
|
|
| Public domain, 0BSD, CC0 | **Yes** | None |
|
|
| MIT, ISC | **Yes** | Keep the notice |
|
|
| BSD 2-clause | **Yes** | Keep the notice |
|
|
| BSD 3-clause | **Yes** | Keep the notice; no endorsement claims |
|
|
| BSD **4-clause** (advertising) | **No** — see §3 | GPL-incompatible |
|
|
| GPL-2.0-only, GPL-2.0-or-later, LGPL-2.1 | **Yes** | Source for the combined work; keep the notices |
|
|
| MPL-2.0 | Case by case | Compatible through its secondary-licence clause, unless marked otherwise |
|
|
| Apache-2.0, GPL-3.0, LGPL-3.0 | **Not in the kernel**; separate programs and files fine | See below |
|
|
|
|
**Every "yes" above requires an entry in `NOTICE`.** That file is the project's
|
|
attribution record and the thing that makes the licences actually satisfied
|
|
rather than merely tolerated.
|
|
|
|
### One binary, one GPL version
|
|
|
|
"Or later" means SchOS code can go out under GPLv2 *or* GPLv3. A single linked
|
|
binary still has to pick one:
|
|
|
|
- Add **Linux code** (GPL-2.0-only) and that binary is GPLv2.
|
|
- Add **Apache-2.0 or GPLv3 code** and that binary is GPLv3, because
|
|
Apache-2.0's patent terms are "further restrictions" under GPLv2 §6.
|
|
|
|
Those two cannot meet in one binary. Linux is the main reason for the GPL, so
|
|
**the kernel stays GPLv2-compatible**: no Apache-2.0 or GPLv3 code is linked
|
|
into it. Userland programs are separate works, so one may be GPLv3 or
|
|
Apache-2.0 on its own without affecting anything else.
|
|
|
|
Data files such as fonts are not linked code. Roboto (Apache-2.0) sits beside
|
|
the system as an aggregate, and that holds inside the ramdisk too: the image is
|
|
a filesystem carried by the kernel binary, not code linked with it.
|
|
|
|
---
|
|
|
|
## 3. NetBSD in particular
|
|
|
|
`src-trunk/` is a NetBSD checkout kept as reference material and a parts bin
|
|
(see [plan/schapi.md](plan/schapi.md) §5). NetBSD is **not
|
|
uniformly licensed**, and the difference matters per file:
|
|
|
|
| Template | Status |
|
|
|---|---|
|
|
| 2-clause BSD — modern NetBSD Foundation files | **Fine** |
|
|
| 3-clause, "Regents of the University of California" | **Fine.** Berkeley formally rescinded the advertising clause in 1999 |
|
|
| 4-clause with the advertising clause, **non-UC** copyright holder | **No.** Berkeley's rescission covers Berkeley's copyright, not other people's, and the clause is GPL-incompatible |
|
|
|
|
The last row is real, not hypothetical. Measured on this checkout:
|
|
|
|
```
|
|
sys/kern 26 of 220 files carry the advertising clause
|
|
sys/dev 500 of 3565
|
|
lib/libc 101 of 1575
|
|
sys/net 5 of 180 ← the TCP/IP stack is nearly clean
|
|
```
|
|
|
|
4-clause is still permissive on its own, but the advertising clause is a
|
|
further restriction the GPL does not allow, so **a 4-clause file cannot be
|
|
combined with SchOS at all**. Use a 2-clause or UC-Regents file, or write it.
|
|
|
|
Check before copying, not after:
|
|
|
|
```sh
|
|
grep -l "All advertising materials" <file>
|
|
```
|
|
|
|
### And check *whose* clause it is
|
|
|
|
A file can carry several licence blocks from several copyright holders. Finding
|
|
the advertising clause is only half the check — Berkeley's rescission covers
|
|
Berkeley's copyright and nobody else's, so the question is always *whose*
|
|
clause you found.
|
|
|
|
Measured on `src-trunk`, the networking tree:
|
|
|
|
```
|
|
sys/net 106 files, 5 with the advertising clause
|
|
sys/netinet 121 files, 25 " " "
|
|
sys/netinet6 51 files, 5 " " "
|
|
```
|
|
|
|
Encouraging at first glance — the 25 in `sys/netinet` are almost all SCTP,
|
|
DCCP and multicast routing, none of which SchOS needs. `ip_input.c`,
|
|
`ip_output.c`, `udp_usrreq.c`, `if_arp.c`, `ip_icmp.c`, `if.c` and `route.c`
|
|
are all UC 3-clause, i.e. fine.
|
|
|
|
**But `tcp_input.c` and `tcp_output.c` are not.** Their advertising clause
|
|
belongs to the **WIDE Project** (the KAME IPv6 people), whose copyright sits at
|
|
the top of the file; the UC block is a separate licence further down. Berkeley
|
|
never spoke for WIDE, so the rescission does not reach it. The two most
|
|
valuable files in the stack are the two encumbered ones.
|
|
|
|
Under the GPL that rules them out, and it is exactly the case
|
|
where a **second BSD tree earns its disk space**: FreeBSD's TCP has been
|
|
through a relicensing effort NetBSD's has not, so the same file there may well
|
|
be 2-clause. Check it the same way before assuming either:
|
|
|
|
```sh
|
|
grep -n "Copyright" <file> | head # who claims it
|
|
grep -n -B6 "All advertising" <file> # whose clause is it
|
|
```
|
|
|
|
### FreeBSD's TCP is clean where NetBSD's is not
|
|
|
|
Checked, 2026-08-08, exactly that way. Against FreeBSD `main`:
|
|
`sys/netinet/tcp_input.c` contains **no advertising clause at all**. Its
|
|
copyright holders are the UC Regents, Swinburne University, Lawrence Stewart,
|
|
the FreeBSD Foundation and Juniper Networks -- all BSD-2 or BSD-3.
|
|
|
|
So if BSD networking code is taken, it must come from **FreeBSD, not NetBSD**,
|
|
and the specific reason is TCP. This reverses the earlier assumption in
|
|
`docs/plan/roadmap.md` that NetBSD was the intended starting point; NetBSD remains
|
|
the better-written reference to *read*, but FreeBSD is the one that can be
|
|
copied from.
|
|
|
|
|
|
### The third option: lwIP
|
|
|
|
Before porting either BSD stack, weigh **lwIP** against both. Verified
|
|
2026-08-08 from its `COPYING`: 3-clause BSD, Swedish Institute of Computer
|
|
Science, **no advertising clause anywhere in the file**. Compatible, one NOTICE
|
|
entry, done.
|
|
|
|
The licence is the smaller half of the argument. The larger half is that
|
|
FreeBSD's `sys/netinet` is not a library -- `tcp_input.c` alone is 122 KB and
|
|
reaches into mbufs, `epoch(9)`, netisr, VNET, `uma(9)`, sockbufs, inpcb hash
|
|
tables and FreeBSD's locking. Taking it means porting FreeBSD's kernel
|
|
infrastructure first and finding the TCP somewhere underneath, which is the same
|
|
conclusion `docs/guides/adding-a-driver.md` already reached about `sys/dev/usb`.
|
|
|
|
lwIP was written for the case SchOS is in: a small operating system with a raw
|
|
Ethernet driver and no infrastructure to speak of. Its port layer is a handful
|
|
of files, it has no dependency on the host kernel's allocator or locking, and it
|
|
brings ARP, IPv4, ICMP, UDP, TCP, DHCP and DNS.
|
|
|
|
### uACPI
|
|
|
|
The AML interpreter, `ports/uacpi`, compiled into the kernel like lwIP.
|
|
Verified 2026-10-22 from its `LICENSE`: MIT, Daniil Tatianin. Compatible, one
|
|
NOTICE entry. The choice over ACPICA was not about licensing but size: uACPI
|
|
asks a host for far less, and its whole host side is `kernel/acpi/host.c`.
|
|
|
|
### Fonts
|
|
|
|
Chosen 2026-08-09, both licences checked at source rather than assumed:
|
|
|
|
| Font | Where | Licence |
|
|
|---|---|---|
|
|
| Roboto | desktop, window manager, compositor | **Apache-2.0** |
|
|
| JetBrains Mono | terminal, TTY | **SIL OFL 1.1** |
|
|
|
|
Roboto is Apache-2.0, which is fine for a font: it is a data file beside the
|
|
system, not code linked into it (§2). A NOTICE entry and nothing else.
|
|
|
|
OFL is permissive and bundling is precisely what it is for, with two conditions
|
|
worth knowing before anyone subsets or converts a font:
|
|
|
|
- **The font stays under OFL** even inside a GPL-licensed system. It does not
|
|
infect anything else; it just cannot be relicensed.
|
|
- **It may not be sold on its own.** Shipping it as part of an OS is fine.
|
|
- **Reserved Font Names.** JetBrains Mono declares *none* -- its copyright line
|
|
names no reserved name -- so a modified version may keep the name. Most OFL
|
|
fonts do reserve theirs, and then a derivative must be renamed.
|
|
Pre-rasterising a font into bitmaps at build time **is** a modification, so
|
|
this is not a theoretical point for this project.
|
|
|
|
---
|
|
|
|
## 4. Things that are deliberately not shipped
|
|
|
|
Some code is fine to *build and run locally* and impossible to *distribute*
|
|
with SchOS. Keeping the distinction sharp is what stops it eroding:
|
|
|
|
- **`Refrence/`** — a FreeBSD checkout (`Refrence/freebsd-src`), kept as
|
|
reference material and a parts bin. Never built, never in an image. The
|
|
directory name is spelled as it is on disk; renaming it is a one-line change
|
|
if it ever grates.
|
|
- **`src-trunk/`** — a NetBSD checkout, same rules. Currently absent; it was
|
|
deleted for disk space and can be re-fetched sparsely if needed.
|
|
- **`dist/`** — upstream tarballs and other downloaded blobs. Cached so a
|
|
rebuild never needs the network; not part of any image, and not all of it is
|
|
redistributable.
|
|
|
|
### The userland, and why it is permissive anyway
|
|
|
|
While SchOS was Apache-2.0, **BusyBox** (GPL-2.0-only) and **nano** (GPL-3.0)
|
|
were ruled out, and the userland was built from toybox (0BSD), mksh and kilo
|
|
(BSD-2-Clause) instead. Both would be possible now — nano as a separate program
|
|
— but nothing needs replacing: toybox gives 268 applets, kilo is installed as
|
|
`/bin/edit`, and `cmd/httpd` is first-party.
|
|
|
|
The `wget` failure that started that discussion was not a userland problem:
|
|
SchOS had no DNS reachable from a process, which BusyBox would have hit
|
|
identically. See [architecture/networking.md](architecture/networking.md).
|
|
|
|
The mechanisms that keep this from eroding, since good intentions have already
|
|
failed once here:
|
|
|
|
- `NOTPORTS` in `ports/Makefile` — a port that lives in the tree but is never
|
|
built by `make`.
|
|
- `RAMDISK_EXCLUDE` in the root `Makefile` — paths kept out of the ramdisk root.
|
|
This one matters more than it looks: the ramdisk image is linked *into the
|
|
kernel binary*, so anything sitting in `sysroot/` when that image is built
|
|
becomes part of a distributable artifact. A GPL-2.0 or non-redistributable
|
|
file staged there does not merely ride along, it makes the kernel itself
|
|
undistributable.
|
|
|
|
A previous acceptance test — a ported 1993 shooter, GPL-2.0 engine on
|
|
non-redistributable shareware data — was carried under exactly these rules and
|
|
has since been removed. It is worth recording *why* it was safe: it was never in
|
|
`PORTS`, and its 33 MB of data was excluded from the ramdisk. It is equally
|
|
worth recording that the safety depended on two separate opt-outs staying
|
|
correct, which is a lot of standing risk for a test that had stopped finding
|
|
bugs. See `docs/guides/testing.md`.
|
|
|
|
---
|
|
|
|
## 5. Specifications are not code
|
|
|
|
A published specification carries no copyright over an independent
|
|
implementation of it. The xHCI, USB, PCI, fbdev and ELF specifications were all
|
|
read and implemented directly, which is why those drivers have no licence
|
|
entanglement at all despite equivalents existing in both Linux and BSD.
|
|
|
|
When a subsystem is small enough to write from the spec, that is usually the
|
|
cheapest option in the long run — not because copying is hard, but because a
|
|
copied file is a file to be understood, attributed and maintained forever.
|
|
|
|
---
|
|
|
|
## 6. LDLS, and shipping Linux's drivers
|
|
|
|
[architecture/ldls.md](architecture/ldls.md) runs Linux drivers. This section used to be about a
|
|
distribution boundary: written when SchOS was Apache-2.0, it said a GPL-2.0-only `.ko` could not be
|
|
shipped and so SchOS would ship the layer and never the modules. **That no longer holds.** SchOS is
|
|
GPL-2.0-or-later, GPL-2.0-only code combines with it, and the owner has decided that Linux code and
|
|
firmware blobs are shipped. The ISO carries Linux's **r8169 set** — `mdio-bus`, `libphy`,
|
|
`mdio_devres`, the Realtek PHY driver and `r8169`, unmodified — and the RTL8168 PHY firmware.
|
|
|
|
### 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
|
|
|
|
Every file under `ldls/` is ours, GPL-2.0-or-later. The loader was written from the ELF-64 gABI and the
|
|
x86-64 psABI; the shim is written under the rule in [architecture/ldls.md](architecture/ldls.md). Copying
|
|
Linux code into it would no longer be a licence problem, but the shim's value is that it is small and
|
|
understood, so the existing rule stands.
|
|
|
|
### `EXPORT_SYMBOL_GPL` does not apply
|
|
|
|
Linux marks much of its internal API `EXPORT_SYMBOL_GPL`, and modules carry
|
|
`MODULE_LICENSE`. Supplying those symbols while asserting a licence one does
|
|
not hold would be circumvention, and it is worth saying why LDLS is not doing
|
|
that.
|
|
|
|
**LDLS has no Linux symbols to gate.** `EXPORT_SYMBOL_GPL` is Linux marking
|
|
*Linux's own* symbols, and the check it drives protects those. Every symbol
|
|
LDLS provides is ours — reimplemented from facts, under GPL-2.0-or-later. There is no
|
|
gate being bypassed, because there is no Linux symbol being exposed.
|
|
|
|
So LDLS implements no licence check. It **reads** the module's declared licence
|
|
and prints it before loading anything, because that is the one property that
|
|
decides whether an object should be on a machine at all and it costs nothing to
|
|
show.
|
|
|
|
### BTF: the layouts are not in our source at all
|
|
|
|
Rule 3 of [architecture/ldls.md](architecture/ldls.md) has one uncomfortable row — struct layouts. A compiled driver
|
|
indexes fields by offset, so the shim has to reproduce them exactly, and a
|
|
field-for-field match *looks* like transcription even when it is not.
|
|
|
|
It does not have to be in our source. Kernels built with `CONFIG_DEBUG_INFO_BTF`
|
|
— which is most distribution kernels — publish `/sys/kernel/btf/vmlinux`, and
|
|
that file carries both halves of what the shim needs:
|
|
|
|
```
|
|
struct pci_dev {
|
|
struct list_head bus_list; /* 0 16 */
|
|
struct pci_bus * bus; /* 16 8 */
|
|
...
|
|
|
|
[97814] FUNC 'pci_iomap' type_id=97813 linkage=static
|
|
[97815] FUNC_PROTO '(anon)' ret_type_id=108 vlen=4
|
|
```
|
|
|
|
Layouts **and** prototypes, as generated binary type data describing the kernel
|
|
the user already has installed. LDLS can read them at load time, on the user's
|
|
machine, from the user's own kernel — so our source contains neither, and there
|
|
is nothing to have transcribed.
|
|
|
|
Three things improve together: the provenance question largely disappears, the
|
|
version-pinning problem (plan §4) mostly dissolves because BTF describes the
|
|
kernel that is actually there, and it is less work than writing hundreds of
|
|
struct definitions by hand.
|
|
|
|
**What BTF does not give is behaviour.** It says `napi_complete_done` takes
|
|
these arguments and returns that type. What it *does* is still ours to
|
|
implement from documentation, and that is the real work — BTF does not touch
|
|
it.
|