# M1 root filesystem validation 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) · [Build and usage](rootfs.md) · [Roadmap](roadmap.md) Validated on **2026-09-21 (Asia/Shanghai)** on the x86_64 Arch workstation. The archive build timestamp is `2026-09-20T16:58:35Z`. This is userspace and archive validation, not a Pi boot or native PID 1 result. ## Artifact produced | Item | Recorded result | | --- | --- | | Output | `out/rootfs-aarch64.tar` | | Archive size | 346,705,920 bytes | | Configured packages | 108 | | ARM ELF paths inspected | 1,167 | | SHA-256 | `b2f0472d49aeb1565d124bc30f250cb304dc265be4d049f1ac9e8cb533742a34` | | Void source pin | `02a3cbc132c3c4a3a9d59e9b98f517af5dd11cd1` | | Emulation tools | PRoot 5.2.0_1 and QEMU aarch64 userspace 11.1.1_1 | The successful build is retained in `out/rootfs-build.Ewfkl2/`. Convenience links point to its archive, staging root, and manifests. Future rebuilds may replace the convenience links; this report describes the result above. Selected package versions: ```text fds-base-0.1.0_1 fds-base-files-0.1.0_1 fds-dasungd-0.1.0_1 glibc-2.41_1 coreutils-9.4_3 binutils-2.44_2 xbps-0.60.7_1 s6-2.15.0.0_1 s6-rc-0.6.1.1_1 ``` Every selected package archive is retained with its SHA-256 in the build directory. Remote packages were verified against Void's RSA keys; local FDS packages are unsigned development builds. The package archives total 71,371,822 bytes, excluding signature files. This is input retention, not a complete upstream repository snapshot or a reproducible-release claim. ## Acceptance completed ```sh make rootfs PROFILE=cli make rootfs-test ``` Both commands exited successfully. Checks established: - `fds-base` selects GNU userspace, glibc, XBPS and the mandatory Dasung package. Neither the Void `base-system` nor its `base-files` package is installed. - Every installed package is `aarch64` or `noarch` and configured. All scanned ELF files are little-endian 64-bit ARM. Dynamic interpreters resolve to glibc. Dasung is statically linked and has no dynamic interpreter or shared-library dependency. No BusyBox, systemd, runit, or musl runtime package is present. - The target's package setup ran under QEMU. English UTF-8, CA certificates, the udev hardware database, the dynamic linker cache, and the Dasung s6 database were generated before export. `_uuidd` was created and root remains locked. - ARM GNU coreutils/binutils, glibc, shell pipelines, locale lookup, XBPS queries, package integrity checking, Dasung configuration/EDID checking, and s6 database queries succeeded. Tests do not open a real USB or DRM device. - Exported ownership and permissions were checked, including locked account files, sticky temporary directories, the tty group for `wall`/`write`, the xbuilder group for `xbps-uchroot`, and portable `CAP_NET_RAW` for ping. - GNU tar restored the exported ping capability successfully inside a private user namespace, verifying the archive's actual extended-attribute encoding. - A fresh extraction of the exported archive passed the same userspace checks. - Failure tests rejected a forbidden package, an unconfigured package, a musl package ABI, an injected x86_64 executable, a missing Dasung boot entry, and an unsupported image profile. The build leaves upstream Void tracked files unchanged. The FDS layout manifest avoids changing upstream lint rules. The tests use the exported tar rather than trusting the original staging tree alone. ## Regression checks The following also exited successfully after the M1 changes: ```sh make bootstrap make smoke-test make check make dasung-test ``` The Dasung rerun passed all six Rust unit tests, the serial simulator cases, package inspection, and the s6 boot/logger/socket/restart/stop check with a read-only root and no monitor. Its physical-hardware checks remain skipped. The existing M0 smoke script still reports its optional host-PATH QEMU skip: the emulator is installed only inside the project-local build container. M1's explicit container-based ARM runtime tests passed independently. Shell syntax checks were updated to recognize shell files by their interpreter, so adding Python image tools does not make the older test suites parse Python as shell. Python syntax, documentation file links, English project context, and upstream tracked-file cleanliness were also checked. ## Emulation and rootless-build limitations addressed The packaged PRoot version does not translate every modern syscall reliably. The helper therefore makes the ARM filesystem the actual root with bubblewrap, and uses direct QEMU for XBPS integrity checking and capability operations. PRoot is used for child-process execution during package configuration and shell sessions, not as evidence of successful ownership or capability changes. Rootless configuration emits expected group-change failures for `wall`, `write`, and `xbps-uchroot`. Archive generation restores their intended numeric groups and the archive tests verify the result. Other package payload ownership comes from the retained XBPS headers. No host user ID is exported as the target root. ## Remaining boundaries - M2: native s6 PID 1, complete boot graph, runtime mounts and booted service control. - M4 and later: Pi firmware/kernel/initramfs, EROFS SYSTEM image, console, and media creation. - Hardware: monitor picture, cold-power recovery, USB hotplug under Pi boot, and 12-bay behavior. - Performance: no boot, shutdown, or monitor readiness benchmark was measured. The rootfs is not flashable, does not provide `fds` or a cartridge daemon, and does not provision a login password. See [Rootfs](rootfs.md) for the working emulated-shell workflow and the [roadmap](roadmap.md) for later acceptance gates.