238 lines
12 KiB
Markdown
238 lines
12 KiB
Markdown
# Building and using the ARM root filesystem
|
|
|
|
[Documentation index](README.md) · [First build](getting-started.md) · [Validation](m1-validation.md)
|
|
|
|
The assembler produces a configured **aarch64 glibc Linux userspace** at
|
|
`out/rootfs-aarch64.tar`. It contains GNU tools, XBPS, the s6 tools, the cartridge manager, optional desktop stack, and the Dasung
|
|
Paperlike 13K controller. You can inspect it and run its ARM programs on the build
|
|
workstation. M2 adds native s6 init, runtime mounts and getty. The tar itself has
|
|
no bootable partition table or Pi boot volume; do not flash the tar to a disk.
|
|
Follow [Native init and ARM VM](init.md) to boot it and open a development shell.
|
|
M12 also adds `make rootfs PROFILE=recovery` and `make recovery`; see
|
|
[Recovery](recovery.md) for its distinct local maintenance console and read-only
|
|
cartridge defaults. Each build preserves a profile-specific
|
|
`out/rootfs-PROFILE.tar` pointer in addition to the latest-rootfs pointer.
|
|
|
|
## 1. Prepare the workstation
|
|
|
|
Use the x86_64 Arch setup in [Your first build](getting-started.md). M0 should pass
|
|
before you build M1:
|
|
|
|
```sh
|
|
make bootstrap
|
|
make smoke-test
|
|
make check
|
|
```
|
|
|
|
M1 also needs **Python 3.14 or newer** on Arch. It inspects XBPS metadata and zstd
|
|
package archives and produces the tar using only the standard library:
|
|
|
|
```sh
|
|
sudo pacman -S --needed python
|
|
python3 --version
|
|
```
|
|
|
|
The rootfs builder installs `qemu-user-aarch64` and `util-linux` into the existing
|
|
project-local Void build container. Static QEMU executes ARM programs; util-linux
|
|
supplies namespace-local mount and capability setup. Linux 6.7+ provides a private
|
|
`binfmt_misc` registry inside the new user namespace, allowing ARM child programs
|
|
to execute without PRoot's syscall translation. Mount/setup capabilities are
|
|
dropped before package scripts run; only namespace-local file-capability support
|
|
remains. These are build tools, not additional target requirements. No host-wide
|
|
binfmt registration, sudo chroot, or host boot configuration is needed.
|
|
The Dasung musl compiler dependencies remain documented
|
|
in [Dasung integration](dasung.md#dependencies-and-source-provenance).
|
|
|
|
Allow several additional GB for package downloads, staging trees, the archive,
|
|
and retained inputs. Build commands share one Void container; run them sequentially.
|
|
|
|
## 2. Build the CLI base
|
|
|
|
From the checkout root:
|
|
|
|
```sh
|
|
make rootfs PROFILE=cli
|
|
```
|
|
|
|
The first run downloads signed Void ARM packages and may take several minutes.
|
|
Later runs reuse the download cache, rebuild the local FDS packages, and assemble
|
|
a fresh root. Success ends with:
|
|
|
|
```text
|
|
PASS: FDS rootfs built and verified: out/rootfs-aarch64.tar
|
|
```
|
|
|
|
`cli` boots to the ordinary-user FDS console and includes optional desktop and
|
|
Ethernet services. They start only when requested by the user or eligible media.
|
|
`PROFILE=development` adds native C/C++/Rust compilers, build systems, Git,
|
|
debuggers and Vim, plus virtual display diagnostics; see
|
|
[Development](development.md) and the [desktop guide](desktop.md).
|
|
Each archive embeds its profile identity. Unknown
|
|
profiles and mismatched SYSTEM image labels fail explicitly.
|
|
|
|
| Output | Purpose |
|
|
| --- | --- |
|
|
| `out/rootfs-aarch64.tar` | Exported root filesystem, with target ownership, permissions and file capabilities |
|
|
| `out/rootfs-aarch64/` | Staging tree for inspection and emulated commands; owned by your host user |
|
|
| `out/manifests/rootfs-latest/` | Exact package list, checksums, metadata, scripts and build inputs |
|
|
| `out/manifests/rootfs-latest/packages/` | Copies of every selected XBPS package and available upstream signatures |
|
|
| `out/packages/fds-base-0.1.0_1.aarch64.xbps` | Explicit base dependency metapackage |
|
|
| `out/packages/fds-base-files-0.1.0_1.aarch64.xbps` | FDS identity, accounts, defaults and layout specification |
|
|
| `out/logs/rootfs-build.log` | Package installation, configuration and acceptance output |
|
|
|
|
The first three paths are links into one retained `out/rootfs-build.*` directory.
|
|
A failed build keeps its workspace for diagnosis and does not publish a partial
|
|
archive over the last successful one. Copy the tar itself when moving the result
|
|
to another machine; copying only the link does not copy the artifact.
|
|
|
|
## 3. Inspect the result
|
|
|
|
```sh
|
|
tar -tf out/rootfs-aarch64.tar | head -40
|
|
cat out/rootfs-aarch64/etc/os-release
|
|
cat out/manifests/rootfs-latest/packages.json
|
|
(cd out/manifests/rootfs-latest && sha256sum -c rootfs.sha256 packages.sha256)
|
|
```
|
|
|
|
The default hostname is `fds`, the timezone is UTC, and the default language is
|
|
English (`en_US.UTF-8`). Account passwords are locked and no SSH server starts.
|
|
CLI and development boot to the local `fds` account (UID 1000) through autologin;
|
|
recovery has a local root maintenance console. The build shell below runs as
|
|
emulated root so it can inspect and configure the staging tree. It is separate
|
|
from the normal booted user session.
|
|
|
|
## 4. Run ARM programs on the workstation
|
|
|
|
```sh
|
|
./tools/in-rootfs out/rootfs-aarch64 /usr/bin/ls --version
|
|
./tools/in-rootfs out/rootfs-aarch64 /usr/bin/readelf --version
|
|
./tools/in-rootfs out/rootfs-aarch64 /usr/bin/xbps-query -l
|
|
./tools/in-rootfs out/rootfs-aarch64 /usr/bin/dasungd check
|
|
./tools/in-rootfs out/rootfs-aarch64 /bin/bash --login
|
|
```
|
|
|
|
Inside the shell, try `getconf GNU_LIBC_VERSION`, `locale charmap`, `ls /usr/bin`,
|
|
or `xbps-query fds-base`. Type `exit` to return to the workstation.
|
|
|
|
This runs ARM userspace on the host kernel through QEMU. It does not boot an ARM
|
|
kernel or validate Pi drivers. Bubblewrap makes the target the actual process
|
|
root, supplies minimal devices, and mounts temporary `/run` and `/tmp`. Native
|
|
emulation tools are mounted read-only under `/tmp/fds-build-host`. Physical USB
|
|
and DRM are absent, so this helper cannot control your monitor. Use it for trusted
|
|
image-build commands. Do not use
|
|
this shell to test disk formatting, mounts, power-off, or real device access.
|
|
|
|
Commands can modify the staging tree. Those changes do **not** change the exported
|
|
tar. Rebuild to get a clean staging tree and archive. Built SYSTEM images remain
|
|
read-only: change packages at image build time, not by upgrading a live SYSTEM.
|
|
For the booted target's on-demand Ethernet and DNS policy, see
|
|
[Desktop and Ethernet](desktop.md).
|
|
|
|
## 5. Run the acceptance checks
|
|
|
|
```sh
|
|
make rootfs-test
|
|
```
|
|
|
|
This verifies the archive and saved package checksums, restores a disposable
|
|
tree, and runs ARM glibc, GNU tools, a shell pipeline, locale, XBPS integrity,
|
|
Dasung configuration, and s6 database queries under QEMU. It also checks every
|
|
ELF file for the target architecture, validates archive permissions and ping
|
|
capabilities, and tests rejection of forbidden packages, unfinished configuration,
|
|
wrong ABIs, a host executable, missing boot entries, a shell init replacement,
|
|
and unsupported profiles.
|
|
|
|
The image has no BusyBox, systemd, runit, or musl runtime package. Dasung carries
|
|
its own statically linked musl and libusb. Its service database is compiled at
|
|
build time and includes the base monitor bundle. M2 boots the current graph under native s6 PID 1 in a full ARM VM. Physical
|
|
monitor recovery still requires a Pi test.
|
|
|
|
## What goes into the base
|
|
|
|
`packages/fds-base/template` owns the explicit dependency set. The assembler also
|
|
consumes `image/base-packages.list`, so the required hardware package cannot be
|
|
lost when selecting a profile.
|
|
|
|
| Package group | Reason |
|
|
| --- | --- |
|
|
| glibc, glibc-locales | GNU C runtime and compiled English UTF-8 locale |
|
|
| coreutils, binutils, findutils, diffutils, grep, sed, gawk, bash, tar, gzip, xz | GNU command-line tools, ELF inspection, scripting and archives |
|
|
| util-linux, procps-ng, shadow, kbd | Standard system, process, account and console utilities |
|
|
| e2fsprogs, dosfstools, erofs-utils | Tools for the planned ext4, FAT and EROFS media |
|
|
| eudev, kmod | Device discovery tools and module management |
|
|
| iproute2, iputils | Network inspection and configuration tools |
|
|
| pciutils, usbutils | Hardware inspection |
|
|
| ca-certificates, tzdata, xbps | TLS trust, timezones, and the package database/tools |
|
|
| skalibs, execline, s6, s6-linux-init, s6-rc | Native init, process supervision, and service dependency tools |
|
|
| fds-base-files, fds-init, fds-dasungd | FDS defaults, native init/service graph, and the mandatory monitor controller |
|
|
|
|
XBPS resolves shared libraries and other transitive dependencies. The exact
|
|
resolved set is in `packages.json`; do not mistake the direct dependency list for
|
|
the entire installed set. Planned `fds-cli` and `fds-cartridged` packages are
|
|
deliberately absent until their implementation milestones.
|
|
|
|
## Assembly details
|
|
|
|
The FDS base-files package supplies `usr/share/fds/layout.json`. The assembler
|
|
applies that manifest before XBPS extraction to create merged `/usr` links and
|
|
empty mountpoints. Upstream xbps-src reserves these links for Void's own
|
|
`base-files`; this approach keeps its tracked files and lint rules unchanged.
|
|
|
|
Remote packages are signature-checked using Void keys from the pinned checkout.
|
|
Local FDS packages are built here and are unsigned development artifacts. A
|
|
foreign-architecture XBPS transaction unpacks them; the target's own XBPS then
|
|
configures every package under QEMU. Locales, CA certificates, the udev hardware
|
|
database, the dynamic linker cache, native init environment, and the complete
|
|
s6 service database are ready before export. Certificate generation also runs as
|
|
an explicit checked step: the upstream CA package wrapper suppresses updater
|
|
errors. There is no first-boot package configuration step.
|
|
|
|
Unused upstream runit service files are excluded by the shipped XBPS `noextract`
|
|
rules. This does not replace upstream package templates or add runit to the image.
|
|
|
|
The staging directory cannot preserve arbitrary target UID/GID values as a normal
|
|
host user. Export restores ownership from the exact XBPS archive headers, applies
|
|
the util-linux `wall`/`write` tty-group and XBPS `xbps-uchroot` xbuilder-group adjustments, and gives generated
|
|
files root ownership. Namespaced Linux capabilities are converted to the portable
|
|
root-owned encoding. The archive, not the host-owned staging tree, is the authority
|
|
for installation metadata. When eventually restoring as root, use GNU tar with
|
|
`--numeric-owner --same-permissions --xattrs --xattrs-include=security.capability`.
|
|
For complete disk images and the deferred physical installation procedure, see
|
|
[Internal storage](internal-storage.md). Do not write this rootfs tar to a disk.
|
|
|
|
The rootless configuration log therefore reports group-change failures for
|
|
`wall`, `write`, and `xbps-uchroot`. These three known adjustments are applied
|
|
and checked in the exported archive. Other installation errors require investigation.
|
|
The builder also reapplies and verifies ping's `CAP_NET_RAW` with direct QEMU
|
|
inside a user namespace and checks the actual stored xattr.
|
|
|
|
Package versions, input hashes and selected archives are retained for inspection.
|
|
The Void binary repository is rolling; a fresh build later may resolve different
|
|
versions. Those records alone do not establish reproducibility. Use the
|
|
separate [frozen-input and offline rebuild workflow](reproducible-builds.md) for
|
|
release construction and consult its recorded acceptance status.
|
|
|
|
## If a build fails
|
|
|
|
Read the last error in `out/logs/rootfs-build.log`; keep the printed build-workspace
|
|
path. A package setup error is a build failure, not a reason to publish an
|
|
unconfigured filesystem. Correct the issue and run the build again; downloads
|
|
already in `out/cache/rootfs` are reused.
|
|
|
|
If you changed an overlay and receive `Stale overlay`, compare your edited
|
|
`packages/fds-*` directory with the named generated copy under
|
|
`vendor/void-packages/srcpkgs/`. Move only that generated copy out of the way and
|
|
rerun. Never discard tracked upstream changes to silence the pin check. See
|
|
[Troubleshooting](troubleshooting.md) for the existing build-container checks.
|
|
|
|
References: [Void chroot installation](https://docs.voidlinux.org/installation/guides/chroot.html),
|
|
[XBPS configuration](https://man.voidlinux.org/xbps.d.5),
|
|
[Linux binary-format handlers](https://docs.kernel.org/admin-guide/binfmt-misc.html), and
|
|
[QEMU userspace emulation](https://www.qemu.org/docs/master/user/main.html).
|
|
|
|
The rootless exporter restores ownership changes that package install scripts
|
|
cannot represent in a single-UID user namespace. This includes tty ownership for
|
|
`wall`/`write`, the xbuilder group for `xbps-uchroot`, and the utmp group for the
|
|
terminal-accounting helper. Archive checks validate these identities explicitly;
|
|
the ARM boot check also inspects the installed helper's actual group.
|