update docs
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
# M2: native s6 init and the ARM development VM
|
||||
|
||||
Development reference and historical context. For current operating instructions, use the [user manual](../README.md). Acceptance applies only to the source and artifacts identified in each record.
|
||||
|
||||
|
||||
[Documentation index](README.md) · [Rootfs build](rootfs.md) · [Services](services.md)
|
||||
|
||||
M2 adds the system's real init path. The kernel enters the generated execline
|
||||
launcher at `/sbin/init`; that immediately executes `s6-linux-init`, which prepares
|
||||
`/run` and replaces itself with `s6-svscan`. The supervisor remains
|
||||
PID 1. Bash is used for some stage-2 configuration tasks, as an ordinary child
|
||||
process. No shell loop, systemd, runit, or BusyBox owns PID 1.
|
||||
|
||||
You can boot and inspect this system on the x86_64 workstation using a complete
|
||||
ARM QEMU machine. This is a generic development VM, not a Raspberry Pi image.
|
||||
It does not test Pi firmware, a cartridge boot path, or the physical monitor.
|
||||
|
||||
## Build and verify
|
||||
|
||||
First complete the [build-host setup](getting-started.md) and the
|
||||
[rootfs prerequisites](rootfs.md#1-prepare-the-workstation). M2 additionally uses
|
||||
the Arch `e2fsprogs` and `libarchive` packages to create an ext4 VM disk directly
|
||||
from the tar, without mounting it or requiring root:
|
||||
|
||||
```sh
|
||||
sudo pacman -S --needed e2fsprogs libarchive
|
||||
make rootfs PROFILE=cli
|
||||
make rootfs-test
|
||||
make init-test
|
||||
```
|
||||
|
||||
`make init-test` installs `qemu-system-aarch64` inside the project-local Void build
|
||||
container when missing. Void packages its emulator with display, audio, and other
|
||||
libraries, even though this test uses only a serial console. Those dependencies
|
||||
stay in the build container; they do not become target packages or host services.
|
||||
|
||||
The test also downloads a signed generic ARM kernel, pinned by version and SHA-256
|
||||
in `config/vm-test.conf`. Its AHCI, ext4, serial console and PCI drivers are built
|
||||
in and devtmpfs is automounted by the kernel, so no test initramfs or replacement stage 0 is needed. The kernel package is
|
||||
approximately 161 MB; only its boot files are extracted. Its module collection is
|
||||
not installed into FDS. The separate [M4 boot test](boot.md) uses the actual
|
||||
FDS Pi kernel and its initramfs-to-EROFS handoff.
|
||||
|
||||
The VM uses software CPU emulation, 1 GiB of RAM, two virtual CPUs, no network,
|
||||
and no host USB, display, filesystem sharing, or block-device passthrough.
|
||||
Its root filesystem is mounted read-only. QEMU discards any block changes in a
|
||||
temporary disk overlay, preserving the generated test disk.
|
||||
|
||||
Successful output includes:
|
||||
|
||||
```text
|
||||
FDS_M2_PID1: /usr/bin/s6-svscan
|
||||
FDS_M2_FILESYSTEM: read-only root, writable tmpfs, root ownership and capabilities
|
||||
FDS_M2_BOOT: getty, eudev and Dasung supervised without a monitor
|
||||
FDS_M2_SERVICE: s6-rc start, echo, supervised restart, stop and start passed
|
||||
FDS_M2_PASS
|
||||
PASS: M2 ARM boot, native s6 PID 1, service control, and orderly power-off
|
||||
```
|
||||
|
||||
The test must finish within 180 seconds. This is a failure deadline, not a boot
|
||||
performance target. A panic, failed assertion, missing marker, timeout, or missing
|
||||
power-off message makes the command fail. Retained logs explain the result.
|
||||
|
||||
## Open a real booted ARM shell
|
||||
|
||||
After `make init-test` succeeds:
|
||||
|
||||
```sh
|
||||
make vm
|
||||
```
|
||||
|
||||
The same guest checks run, then the VM opens a temporary root shell on its serial
|
||||
console. Try:
|
||||
|
||||
```sh
|
||||
readlink /proc/1/exe
|
||||
findmnt /
|
||||
findmnt /run
|
||||
s6-rc -l /run/s6-rc -a list
|
||||
s6-svstat /run/service/dasungd
|
||||
dasungd status
|
||||
```
|
||||
|
||||
The rootfs's ordinary getty still requires authentication and root remains locked.
|
||||
The VM hook stops getty before opening its shell so they do not compete for the
|
||||
serial console; `s6-svstat` therefore reports getty down during that shell session.
|
||||
The password-free shell exists only in the disposable VM test overlay, when
|
||||
`make vm` explicitly requests it. The checker and shell hook do not ship in the
|
||||
normal rootfs archive. Type `exit` to request orderly VM power-off. Ctrl+C stops
|
||||
the emulator immediately if the guest is stuck; it does not shut down your host.
|
||||
|
||||
The shell's `/run`, `/tmp`, `/var/tmp`, and `/var/log` writes disappear at power-off.
|
||||
Changes to `/etc` or `/usr` fail because SYSTEM is read-only. Rebuild the rootfs
|
||||
and rerun `make init-test` after changing packages or init configuration; `make vm`
|
||||
otherwise boots the previous successful test disk.
|
||||
|
||||
## Control the test service
|
||||
|
||||
The `test-echo` service is an actual Unix-socket echo server, supervised by s6.
|
||||
It is included in the service database but excluded from the normal boot bundle.
|
||||
In the VM shell:
|
||||
|
||||
```sh
|
||||
s6-rc -l /run/s6-rc -u change test-echo
|
||||
s6-svstat -o up,ready,pid /run/service/test-echo
|
||||
printf 'hello from ARM\n' | s6-ipcclient /run/fds-test/echo.sock s6-ioconnect -t 3000
|
||||
s6-svc -wR -T 5000 -r /run/service/test-echo
|
||||
s6-rc -l /run/s6-rc -d change test-echo
|
||||
```
|
||||
|
||||
Its socket is root-only, under `/run/fds-test` with mode 0700. The server sends an
|
||||
actual readiness notification when it is listening. The automated test checks
|
||||
the reply, confirms the PID changes on restart, stops the service, and starts it
|
||||
again. No arbitrary boot delay substitutes for readiness.
|
||||
|
||||
## What starts at boot
|
||||
|
||||
| Component | Role and dependencies |
|
||||
| --- | --- |
|
||||
| Native stage 1 | Consume the kernel-provided `/dev`, mount `/run`; start s6 supervision and the catch-all logger |
|
||||
| `runtime-fs` | Mount proc, sysfs, devpts and volatile temporary/log filesystems |
|
||||
| `hostname` | Apply the image's `/etc/hostname` |
|
||||
| `console` | Create volatile login accounting files after runtime mounts |
|
||||
| `getty` | Offer a login on `/dev/console`, after console and hostname setup |
|
||||
| `eudevd` | Process device events; readiness requires a successful control request |
|
||||
| `udev-trigger` | Request initial subsystem and device events after eudev readiness |
|
||||
| `dasungd-runtime`, `dasungd-log`, `dasungd` | Prepare private state/log paths and supervise the base monitor controller |
|
||||
|
||||
Console startup does not depend on eudev enumeration, a monitor connection, the
|
||||
network, or a cartridge scan. No global `udevadm settle` is used. The eudev package
|
||||
has no native s6 notification, so `s6-notifyoncheck` performs a bounded check of
|
||||
its control channel. It signals readiness only after a successful response.
|
||||
|
||||
Cartridge discovery, the FDS CLI, desktop activation and on-demand Ethernet were
|
||||
added after the original M2 milestone. The current image includes their real
|
||||
implementations; see [Services](services.md), [Cartridges](cartridges.md) and
|
||||
[Desktop](desktop.md). This page focuses on the native init mechanism and its
|
||||
generic test fixture. SSH remains outside the default boot bundle.
|
||||
|
||||
## Files and build-time work
|
||||
|
||||
| Location | Meaning |
|
||||
| --- | --- |
|
||||
| `packages/fds-init/` | Init skeleton, runtime mount/accounting helpers, and package template |
|
||||
| `s6/source/` | Complete current service graph, split between init, Dasung and cartridge/desktop packages |
|
||||
| `/etc/s6-linux-init/current/` | Generated native init environment and stage scripts in the image |
|
||||
| `/etc/s6-rc/compiled/` | Compiled service database, produced during image construction |
|
||||
| `/run/service/`, `/run/s6-rc/` | Writable supervision and live service state |
|
||||
| `/run/uncaught-logs/` | Catch-all service log, also copied to the console |
|
||||
| `/run/log/dasungd/` | Rotating monitor-controller log |
|
||||
| `out/m2-vm-latest/serial.log` | Last successful full ARM boot test |
|
||||
| `out/m2-vm-latest/rootfs.ext4` | Disposable test disk; not a Pi or SYSTEM cartridge image |
|
||||
|
||||
`s6-linux-init-maker` and `s6-rc-compile` run during the rootfs build under ARM
|
||||
emulation. Boot only reads their output. The VM test preserves that exact compiled
|
||||
database. Its only init hook runs the original stage-2 script to completion, then
|
||||
runs the checker as a child process. Normal `out/rootfs-aarch64.tar` contains
|
||||
neither the checker nor the development-shell hook.
|
||||
|
||||
The s6-generated template contains FIFOs. Archive validation permits them only
|
||||
inside its `run-image` directory; those templates are copied into writable `/run`
|
||||
at boot. Before entering `/sbin/init`, the kernel or later stage 0 must provide
|
||||
a mounted devtmpfs at `/dev`. Stage 1 deliberately does not mount it twice.
|
||||
Services never place their live FIFOs or status files on read-only SYSTEM.
|
||||
|
||||
M10 adds cartridge-aware preparation before s6-rc stops the remaining services.
|
||||
Its native shutdown hook stays alive if DATA cannot be verified and unmounted.
|
||||
`s6-linux-init-shutdownd` still performs final process cleanup and the kernel
|
||||
power action. See [Shutdown and reboot](power.md) for usage, blocked-request
|
||||
recovery, and the current M10 acceptance status.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **`make vm` asks you to run `make init-test`:** no successful VM disk has been
|
||||
published yet. Build the rootfs, then run the test.
|
||||
- **Kernel pin/hash failure:** do not substitute an unverified kernel. The exact
|
||||
configured package must remain available or be deliberately updated and retested.
|
||||
- **Disk creation reports missing tar support:** use an `e2fsprogs` build with
|
||||
libarchive support and install `libarchive`. No loop mount or sudo fallback is used.
|
||||
- **No guest success marker:** read `out/logs/init-checks.log` and the printed
|
||||
`out/m2-vm.*` directory's `serial.log`. Failed test workspaces are retained.
|
||||
- **Root login is denied on the ordinary getty:** this is expected with the locked
|
||||
base accounts. Use the explicit development VM shell, not a default password.
|
||||
- **Dasung says disconnected:** the VM intentionally has no physical monitor.
|
||||
Use [Dasung integration](dasung.md) for its eventual hardware validation.
|
||||
|
||||
Upstream references: [s6-linux-init](https://skarnet.org/software/s6-linux-init/overview.html),
|
||||
[init generation](https://skarnet.org/software/s6-linux-init/s6-linux-init-maker.html),
|
||||
[s6-rc initialization](https://skarnet.org/software/s6-rc/s6-rc-init.html), and
|
||||
[ext4 creation](https://man7.org/linux/man-pages/man8/mke2fs.8.html).
|
||||
Reference in New Issue
Block a user