3
Internal Storage
Felis edited this page 2026-09-27 00:29:40 +08:00
Table of Contents
include_toc
include_toc
true

Internal storage and machine settings

Documentation index · Boot images · Recovery

Internal storage contains boot files, an independent recovery system and persistent machine settings. The operating system itself lives on a removable SYSTEM cartridge. This guide covers preparing the internal disk and updating its settings from recovery.

For the complete first-install sequence, including cabling, EEPROM and a first bay map without DATA, use the real-hardware setup guide.

Build the complete disk image

Build the component images first, in this order:

make kernel
make initramfs
make boot-volume BOOT_MODE=production
make recovery
make internal-image

The result is out/fds-internal.img, a complete GPT disk image. Its versioned build directory contains layout.json, source payload checksums, and readback verification. This differs from out/fds-boot.img (a raw FAT partition) and out/fds-recovery.img (a raw EROFS partition).

Partition Format Default allocation Purpose
1: FDS_BOOT FAT32, EFI system type 512 MiB Pi firmware, kernel, DTBs, configuration and initramfs
2: FDS_RECOVERY EROFS 1 GiB Complete independent maintenance system
3: FDS_INTERNAL ext4 256 MiB Machine settings and explicitly saved diagnostics

The builder pads the recovery partition without changing its EROFS contents, aligns partitions to 1 MiB, writes both GPT copies, verifies each payload, and checks the table independently with sfdisk. Internal ext4 is fully initialized before deployment. It contains root-owned config/ and private diagnostics/. The default whole image is about 1.75 GiB, so a 32 GB card has ample capacity. Unused capacity beyond this initial layout is not automatically expanded. SYSTEM stays on its separate USB cartridge. For a Raspberry Pi OS rescue USB, follow the maintenance setup.

For a 2 GiB recovery allocation or larger settings partition:

./image/build-internal --recovery-mib 2048 --internal-mib 512

Install the internal disk

Use an SD reader on the workstation while the Pi is off. The same disk layout remains available for legacy PCIe NVMe installations. First verify a downloaded release using a separately trusted public key as described in Release signatures. A local build uses out/fds-internal.img. The frozen 0.1.0 release predates native SD settings support; build a matching new internal image and SYSTEM when moving to SD. Use the complete disk image, not the separate BOOT or RECOVERY payload.

Install the workstation fds-tools package or run make workstation-binaries, then use fds-flash for interactive or unattended installation:

sudo ./out/workstation/fds-flash \
  --image out/fds-internal.img \
  --device /dev/disk/by-id/REPLACE_WITH_THE_SD_DISK

Replace the destination with the verified whole-disk path. The tool shows model, serial, capacity, partitions and image hash, then requires an exact erase phrase. It refuses mounted or occupied disks and handles flushing, readback, backup-GPT relocation and kernel partition-table refresh. Partitions and filesystems retain their image sizes. The flashing guide covers dry runs, JSON output, unattended identity/checksum bindings and failure handling.

Prepare the first SYSTEM cartridge separately:

sudo ./out/workstation/fds-flash \
  --image out/fds-system-cli.img \
  --device /dev/disk/by-id/REPLACE_WITH_THE_SYSTEM_DISK

Use a different disk for SYSTEM. Both confirmed writes replace the selected media's contents; the internal image also replaces stored machine settings. The alternative development image is out/fds-system-development.img. Versioned release images use the same commands.

Confirm FDS_BOOT, FDS_RECOVERY, FDS_INTERNAL on SD and FDS_SYSTEM on SYSTEM with lsblk -o NAME,PARTLABEL,FSTYPE,MOUNTPOINTS. Unmount any automatic desktop mounts after flashing, safely disconnect the media, and insert SD in the powered-off Pi's native slot. Insert exactly one SYSTEM cartridge before normal boot. Continue with real-hardware setup and the separately reviewed EEPROM configuration.

Configure the machine before building

Copy config/machine/ to your own directory. It contains three files:

  • machine.toml: format = 1 and a short human-readable name.
  • bays.toml: the measured controller/port map described in Cartridges and bay calibration.
  • hardware-catalog.toml: optional USB identification names using the same schema as the base catalog. Entries are data and cannot run commands.

The supplied bay map is empty. Record actual controller/port identities for each physical slot before installing settings. USB 2 and USB 3 companion ports need explicit aliases for the same bay.

cp -a config/machine out/my-machine
# Edit the three files in out/my-machine using your editor.
make internal-image MACHINE_CONFIG=out/my-machine

The builder compiles a native host copy of fds and uses the same strict parser as the target system. You can also validate or pack settings yourself:

cargo build --locked --offline --release --target x86_64-unknown-linux-gnu -p fds-cli
./target/x86_64-unknown-linux-gnu/release/fds machine validate out/my-machine
./target/x86_64-unknown-linux-gnu/release/fds machine pack out/my-machine out/my-machine.json

The three source files become one atomic config/machine.json document on FDS_INTERNAL. Names, lengths, bay aliases, catalog fields and unknown keys are validated before use. Do not put passwords or private keys in this configuration: its active snapshot is readable by the local FDS user.

What happens at boot

The machine-config native s6 oneshot precedes cartridged. It does not precede the console or Dasung controller. It accepts exactly one native SD card or non-removable PCIe NVMe disk with the three named partitions in the order above. Native SD is identified through the MMC subsystem and card type SD, regardless of the block device's removable flag. USB ancestry is always rejected; USB readers, eMMC and SDIO cannot supply machine settings. Device names such as mmcblk0 are not identities. Multiple eligible disks, including an old NVMe alongside SD, are rejected instead of choosing by name.

The settings partition must be clean ext4 with the expected label. Loading uses ro,noload,nosuid,nodev,noexec in a private mount namespace, validates the entire settings bundle, copies it into /run/fds/machine/, and unmounts. No filesystem repair, journal replay, cache compilation or persistent write occurs during normal boot. The cartridge service uses that snapshot throughout this boot, including after a service restart.

If internal storage is missing, unclean, invalid or ambiguous, the service records an explanation and uses the immutable image's /etc/fds/ defaults. The console still opens. Check the actual source before treating bays as calibrated:

fds machine status
fds --json machine status
fds machine export /tmp/current-machine

Export creates a new directory with the three editable source files. It never overwrites an existing directory. The status source is internal_sd, internal_nvme or image_defaults. Temporarily unavailable internal storage is not adopted later in the same boot; resolve the issue and reboot to load its settings. This prevents changing bay identities underneath active cartridge operations.

Update settings from recovery

Bring the edited source directory on a DATA cartridge. At the local root RECOVERY# console, identify its bay with fds bays; healthy DATA is mounted read-only under /run/fds/media/NN. For example, if it is in BAY 02:

fds machine validate /run/fds/media/02/my-machine
fds machine install /run/fds/media/02/my-machine
fds reboot

Installation is restricted to root in the recovery image. It writes the complete validated bundle atomically, saves the old bytes as config/previous.json, flushes and unmounts the internal filesystem, and reports success only after those steps. A reboot activates the new settings. The currently running bay map is unchanged, so active media does not move to a different bay mid-operation. Keep a copy of your previous source directory on DATA or the build host to reinstall it if the new calibration is wrong.

An invalid existing JSON document can be replaced this way. Wrong ownership, symlinks, an unclean filesystem or a damaged directory require offline filesystem maintenance first. Recovery does not automatically repair internal SD/NVMe; its fds recovery repair command is deliberately limited to DATA cartridges.

Save and retrieve diagnostics

Logs and boot records stay in RAM by default. Root may explicitly save a file of up to 16 MiB. Saved names cannot contain paths, and existing names are refused. These operations mount internal ext4 only for the operation and then unmount it. For example, from recovery:

fds --json boot-profile >/tmp/boot.json
fds machine store boot-first.json /tmp/boot.json
fds --json bays >/tmp/cartridge-inventory.json
fds machine store cartridges-first.json /tmp/cartridge-inventory.json
bash /usr/share/fds/capture-hardware /tmp/hardware-capture
tar -C /tmp -czf /tmp/hardware-capture.tar.gz hardware-capture
fds machine store hardware-first.tar.gz /tmp/hardware-capture.tar.gz
fds machine fetch boot-first.json /tmp/retrieved-boot.json

Use distinct names for subsequent sessions. A failed flush or unmount is an error, not a successful save. These are machine diagnostics; do not use this facility as ordinary user storage. The saved cartridge inventory is a persistent diagnostic snapshot, including metadata already inspected during this boot. Retrieve it with fds machine fetch cartridges-first.json /tmp/saved-inventory.json. The daemon's live metadata cache remains volatile and is rebuilt from currently attached devices; saved snapshots are never used to authorize media actions.