2
Developer Boot
Felis edited this page 2026-09-27 00:29:40 +08:00
Table of Contents
include_toc
include_toc
true

Boot images and stage0

Development reference and historical context. For current operating instructions, use the user manual. Acceptance applies only to the source and artifacts identified in each record.

Documentation index · First build · Implementation status

FDS keeps the machine's boot files on native microSD and its operating system on a removable SYSTEM cartridge. The Pi firmware loads the kernel and a small initial filesystem. Its Rust fds-stage0 program finds the partition named FDS_SYSTEM, mounts it read-only, and hands control to native s6. Device names such as sda are never used as cartridge identities.

The software boot path has passed on an ARM virtual machine using the actual FDS Pi kernel. That does not verify Pi firmware, SD/NVMe, RP1, display output, USB power or physical boot speed. Those checks still require physical testing; follow the real-hardware setup guide. M5 now provides an ordinary-user FDS> console with a temporary home and measured boot events. Password login remains locked; this is an intentional local single-user session. The M2 test VM separately offers a temporary root development shell. See native init and performance reports.

Build on the workstation

Use the Arch host setup first. In addition to its original tools, install host lz4, zstd, util-linux, e2fsprogs and libarchive if missing. They supply initramfs compression, independent GPT inspection and the initial VM's filesystem/archive tools; these are build/test dependencies. Python 3.14+ reads zstd-compressed XBPS archives. Filesystem builders are obtained as verified Void packages in .host/image-tools, separate from the build container.

From the repository root, run sequentially:

make bootstrap
make rootfs PROFILE=cli
make initramfs
make system-card PROFILE=cli
make boot-volume
make rootfs-test
make init-test
make boot-test

The rootfs build includes the FDS CLI, base Dasung daemon, native s6 database, and the kernel's matching modules. Its first kernel cross-build is substantial; progress is recorded in out/logs/xbps-fds-kernel.log. make kernel also builds that kernel independently. Later calls reuse its package only when recorded source inputs and every exported payload hash still match. To force a kernel rebuild, run ./tools/build-kernel --rebuild. This source/payload cache is not yet a complete lock of rolling binary build dependencies. No command here opens or writes a physical target disk. On a new build host, make init-test installs QEMU's system emulator into the project-local Void environment before make boot-test uses it.

Output Meaning
out/kernel/boot/kernel_2712.img Pi 5 kernel with boot-critical drivers built in
out/kernel/usr/lib/modules/ Matching optional drivers
out/fds-initramfs.img Uncompressed default initramfs; a symlink to a versioned build
out/initramfs/initramfs.cpio* Uncompressed, gzip, legacy-LZ4 and Zstandard variants
out/rootfs-aarch64.tar Configured userspace archive with target ownership and capabilities
out/fds-system-cli.img Whole GPT cartridge image, containing an EROFS FDS_SYSTEM partition
out/fds-boot.img 512 MiB FAT32 partition image, labeled FDS_BOOT; not a whole SD or NVMe disk
out/boot-volume/manifest.json Boot image hash, firmware input and every boot file hash
out/m4-vm-latest/ Logs and exact inputs from the last passing full boot matrix

make internal-image combines BOOT, independent RECOVERY and INTERNAL settings into out/fds-internal.img; see Internal storage for the full procedure. The FAT partition image alone is not that complete disk layout. Use the media tools for confirmed removable-cartridge writes.

What stage0 does

The initial filesystem contains static-musl stage0 and Dasung executables, configuration, the monitor's EDID, mountpoint directories and /dev/console. There is no shell, BusyBox, Python, glibc, or udev in it. Stage0 mounts proc, sysfs and devtmpfs itself and binds its kernel-event socket before scanning devices.

If a single SYSTEM partition is present, stage0 verifies its block-device identity, mounts EROFS read-only, and checks the FDS identity and native init executables. It stops and reaps the early Dasung process before the base service starts, moves the kernel filesystems into the new root, removes the old in-memory root, and executes the s6 launcher. It refuses this path outside root PID 1 on ramfs/tmpfs.

Without SYSTEM, the console displays a missing-media prompt and keeps processing device events. Inserting media resumes boot without rebooting or polling sleeps. When more than one matching partition is visible, stage0 refuses to choose one. Its waiting console accepts:

list       Show the discovered kernel partition identities
rescan     Repeat discovery immediately
recovery   Select FDS_RECOVERY instead of FDS_SYSTEM
reboot     Reboot from early userspace
poweroff   Power off from early userspace

An invalid filesystem or incomplete FDS root remains at the prompt. list is a diagnostic view and can show technical device paths; physical bay labels arrive with the cartridge daemon. Version 1 uses explicit recovery rather than an interactive choice between multiple SYSTEMs. Detection applies to devices visible at selection time; a cartridge inserted after root handoff cannot replace root.

Pi display and development output

image/pi5/config.txt selects the Pi 5 kernel, initramfs, external PCIe and VC4 KMS, disables HDMI audio, and avoids automatic camera/DSI setup. It does not overclock the Pi or PCIe link. The pinned Pi kernel retains 16 KiB pages and disables the CH341 SPI driver required by the Dasung protection policy.

The production command line uses the display console and quiet kernel output. It loads the Paperlike 13K's recorded EDID from the initramfs before SYSTEM exists. The unqualified drm.edid_firmware setting applies this EDID to connected DRM outputs: this image is intended for the user's dedicated Dasung display. The actual adapter, connector, mode acceptance and picture still need Pi validation. Early USB control and the later base daemon share the same monitor identity.

For serial diagnosis, build:

make boot-volume BOOT_MODE=development

This replaces the convenience output link with a separate development build; previous versioned directories remain. Development enables kernel/daemon output and makes the Pi 5 ttyAMA10 debug UART the primary userspace console. That is the Pi 5 debug connector, not an assumption about the 40-pin GPIO UART. Rebuild with BOOT_MODE=production to restore the display-console configuration.

fds.boot=recovery on the kernel command line selects FDS_RECOVERY immediately. fds.emulator=1 is reserved for the workstation emulator: the SYSTEM loader requires QEMU virt and its fixed xHCI controller before enabling the twelve virtual bay mappings. Default Pi boot is unchanged. fds.debug=1 exposes the early controller's diagnostics. Duplicate or unknown fds.* options fail clearly rather than being silently ignored.

What the automated test proves

make boot-test appends a test-only checker to a copy of the exported rootfs; the original stage-2 script and compiled service graph still run. It checks:

  • All four initramfs formats reach native s6 on read-only EROFS.
  • Missing SYSTEM waits; a virtual USB insertion resumes boot.
  • Two SYSTEM partitions remain unselected; the console can enter recovery.
  • Explicit recovery mode selects RECOVERY even when SYSTEM is also present.
  • Invalid filesystems and foreign OS roots are refused; recovery remains usable.
  • Kernel page size, root ownership, ping capability, temporary filesystems, single Dasung ownership, service start/restart/stop and orderly power-off.
  • Input disk hashes remain unchanged; the VM has no network or host-device access.

QEMU uses its max ARM CPU because the Pi kernel needs 16 KiB page support; the earlier M2 Cortex-A72 fixture cannot run this kernel. These are compatibility and behavior checks, not Pi performance measurements. Test RECOVERY is a relabeled fixture for selection; the independent recovery product is tracked separately.

Reference material: Pi kernel builds, boot configuration, Pi UARTs, and Linux initramfs.

Use the ordinary FDS console

After building the CLI rootfs, initramfs and SYSTEM image:

make console-vm

The ARM virtual machine boots the real stage0 and read-only SYSTEM image. At FDS> you are the ordinary fds user (UID 1000), with a temporary writable home. Try fds info, fds inspect /FDS/CARTRIDGE.TOML, and fds boot-profile. The console deliberately uses local autologin; both account passwords are locked. Use fds poweroff for an orderly shutdown through native s6. Enter exit to restart the console. Press Ctrl-a, then x to close QEMU immediately. Closing QEMU this way ends the test immediately; it is not a graceful-shutdown test. No host USB devices or physical disks are attached to this VM.

Run make console-test for automated console/readiness checks and make performance-test for the software optimization comparison. Read M5 validation and measurement boundaries before interpreting VM timing as hardware evidence.

Native SD and legacy NVMe

The current boot configuration targets native microSD and no longer forces the external PCIe connector on. MMC block and Pi SD host drivers are built in, since recovery/settings may be needed before SYSTEM can provide any modules. Generic PCI SDHCI is built in solely to exercise native MMC cards in the ARM VM. The package exporter checks the complete boot-driver configuration and rejects stale kernels. No new userspace dependency is introduced.

Legacy NVMe installations need their corresponding EEPROM boot order and may need PCIE_PROBE=1 on non-HAT+ adapters. Add dtparam=pciex1 (alias nvme) under [pi5] in that installation's config.txt when required. Those options do not belong to the SD setup; see Raspberry Pi PCIe boot guidance.

For current SD setup, matching SYSTEM installation and a Raspberry Pi OS USB rescue drive, use Hardware setup. Current software evidence is in SD migration validation; historical M4 records remain unchanged.