build: an apk-managed root, with SchOS as a package
make aroot builds a SchFS root from Alpine's minirootfs, the packages ports/alpine/world lists, and SchOS itself as the signed apk package schos-base, in its own repository inside the root. apk add installs from Alpine; apk upgrade updates both. Booted: zsh is Alpine's, apk update sees 28669 packages, apk add htop works, and so does xorg-server. world.lock pins every package with its sha256; a build fetches only what dist/alpine/ lacks and never looks for newer versions. make alpine-lock is the one step that does. Alpine's zsh, busybox commands and hwdata replace SchOS's copies; SchOS keeps its own tools, toybox's other commands, and static mksh, which schinit's recovery shell now tries first. Also: the dependency-file include matched Alpine's usr/lib/sysctl.d, a directory, and stopped every make. See docs/plan/alpine.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
parent
2c5a278d56
commit
406cff2ec0
9 changed files with 473 additions and 1 deletions
|
|
@ -23,6 +23,7 @@ Taken together, because they turn out to need the same foundation.
|
|||
|
||||
| | |
|
||||
|---|---|
|
||||
| **[alpine.md](alpine.md)** | **Packages.** The root is managed by Alpine's apk: Alpine's binaries run unmodified, and SchOS itself is the apk package schos-base. |
|
||||
| **[xorg.md](xorg.md)** | **The desktop.** Xorg on the framebuffer with the fbdev and evdev drivers; twm, then Window Maker. Replaces wayland.md for Gate 3. |
|
||||
| **[wayland.md](wayland.md)** | *Not being worked on; see xorg.md.* The GUI stack becomes Wayland. SchWM and SchDE are **deleted** — actually gone from the tree, not marked; Schcom survives and changes its wire format. |
|
||||
| ~~**hybrid.md**~~ | **Built.** All four mechanisms exist, the GPU driver runs outside the kernel, it survives being killed, and the display mode can be changed from a process. H4 (USB) was *withdrawn* rather than left open — USB is the bus peripherals arrive on, not a peripheral. |
|
||||
|
|
|
|||
73
docs/plan/alpine.md
Normal file
73
docs/plan/alpine.md
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# apk: Alpine's packages on SchOS
|
||||
|
||||
Alpine is musl with a different init, and SchOS is musl with a different
|
||||
kernel. Alpine's binaries run on SchOS unmodified: its dynamic linker, its
|
||||
busybox, and apk itself, fetching over TLS through SchOS's network stack.
|
||||
So instead of porting programs one at a time, SchOS can install them.
|
||||
|
||||
## The model
|
||||
|
||||
The root filesystem is an apk-managed root:
|
||||
|
||||
| Part | Where it comes from |
|
||||
|---|---|
|
||||
| musl, busybox, apk-tools, alpine-keys, CA certificates | Alpine's minirootfs (`ports/alpine`) |
|
||||
| what `ports/alpine/world` lists (zsh, terminfo, ...) | Alpine's packages, pinned in `world.lock` |
|
||||
| schinit, its jobs, SchOS's tools, toybox, mksh, configuration | **schos-base**, an apk package the build makes from `sysroot/` |
|
||||
|
||||
`apk add` installs anything from Alpine's main and community repositories.
|
||||
`apk upgrade` updates Alpine's packages, and schos-base from the SchOS
|
||||
repository at `/var/lib/schos/repo`.
|
||||
|
||||
PID 1 is still schinit. Alpine's OpenRC is not installed, and packages that
|
||||
ship OpenRC services install them where nothing reads them.
|
||||
|
||||
## Who owns what
|
||||
|
||||
Where Alpine and SchOS both have a program, Alpine's wins, and SchOS keeps
|
||||
only what is its own (see `tools/posix/mkaroot.sh`):
|
||||
|
||||
- `/bin/sh`, `cat`, `sed`, `find` and the rest are busybox. Alpine's package
|
||||
scripts are written against busybox.
|
||||
- zsh is Alpine's. SchOS keeps its `zshrc` and `zshenv` (`replaces=zsh`).
|
||||
- `/etc/os-release` and `/etc/motd` are SchOS's (`replaces=`).
|
||||
- `passwd`, `group` and `profile` are Alpine's. schos-base's post-install
|
||||
sets root's shell to zsh, and SchOS's profile is `/etc/profile.d/schos.sh`.
|
||||
- mksh is `/bin/mksh`. schinit's recovery shell looks for it first because it
|
||||
is static: a broken musl cannot take recovery down with it.
|
||||
|
||||
## Building
|
||||
|
||||
make aroot build/aroot.img: the root, as a SchFS volume
|
||||
make qemu-aroot boot it
|
||||
make alpine-lock re-resolve world against Alpine (needs the network)
|
||||
|
||||
Only `alpine-lock` asks Alpine what is current. A normal build installs
|
||||
exactly what `world.lock` names: files in `dist/alpine/`, fetched once and
|
||||
checked against the lock's sha256, and against Alpine's signatures by apk.
|
||||
|
||||
schos-base and its repository index are signed with a key made on the first
|
||||
build (`build/apk-keys/`, never committed). The root trusts it beside
|
||||
Alpine's keys.
|
||||
|
||||
## Kernel work this needed
|
||||
|
||||
All of it found by running apk:
|
||||
|
||||
- **TCP receive window:** it reopened before the reader drained, so lwIP
|
||||
refused data and the sender waited on retransmission timers (5 KB/s). It
|
||||
now reopens on read, with a 32-segment window.
|
||||
- **mmap address reuse:** freed ranges were never reused, so musl's malloc
|
||||
used up the 256 mapping records with 780 MB of RAM free.
|
||||
- **unlinkat / renameat:** bare `-1`, read as EPERM, where apk expects ENOENT;
|
||||
renameat could not replace its target, and wrote v1 dirents into SchFS.
|
||||
- **`#!` scripts in execve**, and ENOEXEC: apk runs triggers directly.
|
||||
- **chroot**, and mounting devtmpfs and proc more than once.
|
||||
|
||||
## Next
|
||||
|
||||
- The live ISO and USB stick are still the ramdisk root. They need the apk
|
||||
root on the stick itself, or an installer that writes it to a disk.
|
||||
- Xorg from apk (`xorg-server xf86-video-fbdev xf86-input-evdev`) instead of
|
||||
the hand port in [xorg.md](xorg.md). The packages install; running them is
|
||||
the next test.
|
||||
Loading…
Reference in a new issue