L4 was listed as "free -- H2 built all of this" and never actually tested,
which is a claim rather than a result. Tested now, and it holds:
ldlsd running ping 2/2; holds index 7 and DMA slots 3 and 4
killed interface DOWN, device released, bus mastering
cleared, DMA reclaimed -- back to vgpud's 3 blocks
ping fails honestly: sendto: -5
a second ldlsd ping 3/3, and the arena hands back the same addresses
pciuser_release_all() and netuser_release_all() sit beside each other in
exit() for the same reason, and that they apply unchanged to a foreign driver
is the whole point of having built them against our own.
With that, every milestone on ldls.md is done, so it leaves docs/plan/ for
docs/architecture/ -- the rule docs/plan/README.md states and the one that
keeps the two directories meaning different things. The new document describes
what is, not what was planned: the five rules, the four pieces, what it costs
(polling, no stack protector, locks that are no-ops), that it can be killed,
and a "what it does not do" that leads with one driver, one kernel version,
tried once.
Sixteen source files pointed at docs/plan/ldls.md and would have been dangling
the moment it moved. All repointed, and the milestone references -- which the
architecture doc deliberately does not have -- rewritten to name sections
instead, so a reader lands somewhere real.
The register row closes with it. hybrid.md freed a slot, ldls.md took it, and
it is now free again.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
342 lines
15 KiB
Markdown
342 lines
15 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 Apache-2.0
|
|
|
|
Copyright Nexoniarz. See `LICENSE`.
|
|
|
|
Apache-2.0 was chosen over MIT/BSD for one reason that actually matters at OS
|
|
scale: it contains an **express patent grant** and a patent-retaliation clause.
|
|
MIT and BSD are silent on patents, which means a contributor can hand you code
|
|
and later assert a patent over it. For a kernel that is intended to accept
|
|
outside contributions, that silence is the expensive kind.
|
|
|
|
What that grant means in practice: Apache-2.0 §2 gives everyone a perpetual,
|
|
worldwide, irrevocable licence to reproduce, modify, sublicense and distribute
|
|
SchOS. Any additional restriction stated elsewhere — in a README, a website,
|
|
or a policy — does not narrow it. The licence text is what holds up.
|
|
|
|
If restricted distribution is ever genuinely wanted, that is a licence change
|
|
(a bespoke proprietary licence, or something like BUSL-1.1 with a conversion
|
|
date), not a wording change, and it means giving up the Apache grant.
|
|
|
|
---
|
|
|
|
## 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) | **Avoid** — see §3 | Notice *and* an acknowledgement in advertising materials |
|
|
| Apache-2.0 | **Yes** | Keep NOTICE contents |
|
|
| MPL-2.0 | Case by case | File-level copyleft; keep those files separate |
|
|
| **GPL-2.0-only** | **No** | — |
|
|
| **GPL-3.0 / LGPL-3.0** | **No** for linked code | — |
|
|
|
|
**Every "yes" above requires an entry in `NOTICE`.** That file is the project's
|
|
attribution record and the thing that makes the permissive licences actually
|
|
satisfied rather than merely tolerated.
|
|
|
|
### Why GPL-2.0-only is a hard no
|
|
|
|
Apache-2.0 imposes conditions GPLv2 treats as "further restrictions" under its
|
|
§6 — principally the patent-retaliation term. The FSF and the ASF agree on
|
|
this: **Apache-2.0 code and GPL-2.0-only code cannot be combined into one
|
|
distributable work.** It is not a matter of taste or of how carefully the files
|
|
are kept apart in the tree; it is that the combined binary cannot satisfy both
|
|
licences at once.
|
|
|
|
GPL-3.0 fixed this in the other direction (Apache-2.0 is compatible *into*
|
|
GPLv3), but that does not help: the result would have to ship under GPLv3, and
|
|
SchOS does not.
|
|
|
|
**Practical consequence:** BSD drivers can be adopted. Linux drivers cannot,
|
|
ever, no matter how convenient. This is why the USB stack was written from the
|
|
specification rather than ported.
|
|
|
|
**"Cannot be adopted" is not the same as "cannot be run."** A driver the *user*
|
|
obtains and loads on their own machine is their act, not a distribution by us —
|
|
see §4 and [architecture/ldls.md](architecture/ldls.md), which is the layer built on exactly
|
|
that distinction and which ships no Linux code of any kind.
|
|
|
|
---
|
|
|
|
## 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 | **Avoid.** Berkeley's rescission covers Berkeley's copyright, not other people's |
|
|
|
|
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 and still redistributable; the burden is an
|
|
advertising obligation that accumulates quietly and is tedious to honour
|
|
properly. Prefer a 2-clause or UC-Regents file. If a 4-clause file is genuinely
|
|
the right answer, it goes into `NOTICE` with the full clause quoted.
|
|
|
|
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.
|
|
|
|
That is not fatal — 4-clause is still permissive — but 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.
|
|
|
|
### 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 the same licence as SchOS, so it is the easy case: a NOTICE entry
|
|
and nothing else.
|
|
|
|
OFL is permissive and bundling is precisely what it is for, with two conditions
|
|
worth knowing before anyone subsets or converts a font:
|
|
|
|
- **The font stays under OFL** even inside an Apache-2.0 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 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 the distribution boundary
|
|
|
|
[architecture/ldls.md](architecture/ldls.md) runs Linux drivers. That sounds like it should
|
|
contradict §2, and it does not, because the two questions below are different
|
|
ones and only the first is about us.
|
|
|
|
### LDLS is Apache-2.0
|
|
|
|
Every file under `ldls/` is ours. 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). **No Linux code is in it and none ever will
|
|
be**, which is the same standard the xHCI and USB stacks already meet (§5).
|
|
|
|
### The combination is not ours to make
|
|
|
|
| | licence | who distributes it |
|
|
|---|---|---|
|
|
| `ldls/` — loader, shim, host | **Apache-2.0** | 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: we ship Apache-2.0 code containing no GPL. The user obtains a GPL module
|
|
from wherever they get their software. The user runs them together on their own
|
|
machine. No combined work is distributed by anyone, and no GPL obligation is
|
|
triggered — not on us, and not on them.
|
|
|
|
This is the position FreeBSD has shipped from for about a decade: a
|
|
BSD-licensed `linuxkpi` in base, GPL `drm-kmod` installed by the user from
|
|
ports.
|
|
|
|
**The consequence for the user, stated plainly:** they cannot redistribute the
|
|
combination either. An image with a `.ko` baked into it is a single work that
|
|
would have to satisfy Apache-2.0 and GPL-2.0-only at once, which §2 explains is
|
|
impossible. That is why `RAMDISK_EXCLUDE` exists, and why `.gitignore` refuses
|
|
`*.ko` outright — the boundary is kept mechanically rather than by intention.
|
|
|
|
### `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 Apache-2.0. 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
|
|
|
|
§3 of the plan 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.
|