8.8 KiB
Using cartridges and configuring bays
Documentation index · Boot images · Services
M6 adds the base fds-cartridged service, twelve bay states, USB hardware
recognition, strict metadata inspection, read-only storage mounts and eject.
Its ARM VM acceptance checks passed. Writable DATA integration has passed M7 software acceptance;
desktop/program activation passed M8 and media creation tools
passed M9 software acceptance. M10 ordered shutdown has passed software acceptance.
Inspect the current machine
At the FDS console:
fds bays
fds bay 3
fds cartridge 3
fds --json bays
The ordinary fds user can use these commands. bays shows all twelve bays,
including empty and unconfigured ones. cartridge includes validated metadata
and the current mount path. --json exposes a versioned machine-readable report.
fds rescan explicitly refreshes inventory; normal insert/remove events trigger
refresh automatically. The console does not wait for the inventory scan.
| State | Meaning and next action |
|---|---|
| UNCONFIGURED | No measured controller/port mapping exists for this bay |
| EMPTY | Configured bay with no detected USB device |
| HARDWARE | USB device without storage; catalog name or VID/PID is shown |
| UNRECOGNIZED STORAGE | Storage exists but no named FDS partition is available |
| MOUNTED READ ONLY | Manifest validated; filesystem available at the displayed path |
| MOUNTED READ WRITE | Active DATA is writable at /data; eject before removal |
| PROTECTED | The active SYSTEM root; eject is refused |
| AMBIGUOUS | Multiple devices or named partitions match; nothing is selected arbitrarily |
| ERROR | Inspection, mounting or metadata validation failed; read the diagnostic |
| SAFE | The requested unmount succeeded; remove the cartridge |
An unrecognized storage state may briefly appear while the kernel discovers its partitions. It is not permission to remove a device being used elsewhere. Errors and ambiguous media never produce SAFE. An additional mount of the same filesystem also blocks managed eject until it is unmounted.
Calibrate the physical bay map
The shipped /etc/fds/bays.toml is deliberately empty: no Pi bay wiring has yet
been measured. This produces UNCONFIGURED states, not invented assignments.
- On the assembled machine, insert one known USB device into one physical bay.
- Run
fds topology. This diagnostic explicitly shows controller/port paths; ordinary bay commands omit those implementation details. - Record that path and repeat for each bay. Test both USB 2 and USB 3 devices, because their companion root hubs can have different logical port paths.
- Put the measured map in your machine configuration directory and build the
internal image, or use
fds machine install DIRECTORYfrom recovery and reboot. Machine settings persist independently of SYSTEM. The packaged/etc/fds/files are fallback defaults for missing/invalid internal storage;fds machine statusshows which source is active. - Verify all twelve devices together, in different insertion orders and after reboot. That physical acceptance remains deferred.
A syntax example only, using identities that must be replaced by observations:
[front]
hub = "platform/example-controller:usb2/1"
[front.ports]
1 = 1
2 = 2
3 = 3
4 = 4
5 = 5
6 = 6
[front_superspeed]
hub = "platform/example-controller:usb3/1"
[front_superspeed.ports]
1 = 1
2 = 2
3 = 3
4 = 4
5 = 5
6 = 6
hub names the controller and parent port chain. Its numbered ports map the
next downstream port to a bay number from 1 through 12. Additional groups can
map the rear hub. Explicit USB 2/3 aliases may refer to the same bay; duplicate
ports, overlapping parent/child mappings, and duplicate bays within one hub are
rejected. If two devices simultaneously match aliases for one bay, it becomes
AMBIGUOUS. A hub inserted into a cartridge bay with multiple downstream devices
also needs an explicit future composite-device policy; M6 refuses to guess.
The identity excludes the Linux USB bus number and /dev/sdX enumeration order.
It includes the controller's sysfs path, USB protocol generation and port chain.
Moving a hub to another controller or changing wiring requires recalibration.
Storage formats and metadata
| Class | GPT partition name | Filesystem and current behavior |
|---|---|---|
| SYSTEM | FDS_SYSTEM | EROFS; current root is protected, additional media read-only |
| DATA | FDS_DATA | ext4; inspected read-only first, then activated at /data under the M7 policy |
| PROGRAM | FDS_METADATA + FDS_PAYLOAD02… | Metadata and xz bundles in 1+m EROFS partitions; see software format |
| Legacy PROGRAM | FDS_PROGRAM | Existing single EROFS application tree; still readable |
| ENVIRONMENT | FDS_ENVIRONMENT | EROFS; declarative selection of a trusted built-in profile |
| UTILITY | FDS_UTILITY | EROFS; inspection only, no automatic actions |
| HARDWARE | None required | VID/PID, optional serial, device/interface class and bay |
Storage contains /FDS/CARTRIDGE.TOML. For example:
format = 1
[cartridge]
id = "fds.windowmaker"
name = "WINDOW SYSTEM"
class = "environment"
version = "0.1"
[media]
writable = false
[activation]
profile = "windowmaker"
The manifest class must match the GPT partition name. SYSTEM, PROGRAM and
ENVIRONMENT are read-only; DATA declares writable media during the initial read-only inspection. Unknown keys, root commands, unsafe identifiers, control
characters, symlink metadata and nonregular metadata files are rejected.
The parser accepts at most 64 KiB. No /FDS/autorun.sh is run.
Inspect a standalone manifest with fds inspect /path/to/CARTRIDGE.TOML.
For mounted storage, fds cartridge N reports the daemon's validated copy.
Media is inspected in a root-only staging directory, then published at
/run/fds/media/NN after validation, with nodev, nosuid and noexec. Device
major/minor and kernel disk sequence are checked before mounting an opened
block-device descriptor, preventing stale enumeration names from selecting a
replacement disk.
Eject a mounted cartridge
fds eject 2
Leave any shell working directory inside that cartridge and close files first. SAFE is emitted only after an ordinary unmount succeeds. Busy mounts return an error; forced or lazy unmount is never used to declare safe removal. Once SAFE, the daemon keeps that insertion unmounted until removal and reinsertion, including across a service restart. Its root-owned volatile marker is tied to the kernel disk sequence, so a replacement disk is not mistaken for ejected media. The active SYSTEM cannot be ejected. Swap SYSTEM only after shutting down.
Pulling a mounted cartridge without eject is surprise removal. The daemon clears
its inventory and detaches a vanished read-only mount where needed; that cleanup
is not a successful eject. M7 DATA handling extends ejection to writable DATA, consumer
tracking and syncfs. The temporary /home/fds remains usable without DATA and is lost at
power-off.
Hardware recognition
Edit packages/fds-cartridged/files/hardware-catalog.toml, then rebuild SYSTEM.
Entries name devices, never executable actions:
[[device]]
name = "MY SERIAL ADAPTER"
vendor = "1234"
product = "5678"
# Optional exact restrictions:
serial = "UNIT-1"
class = "02"
Replace these example IDs with observed values. Device or interface class may
match class. Multiple matching catalog entries produce an error; unknown
hardware remains identified by VID/PID without being mistaken for empty media.
Dasung control remains in the independent base monitor service.
Implementation and diagnostics
The daemon subscribes to kernel USB/block events before taking its first snapshot.
A receive-buffer overflow causes a fresh snapshot. IPC uses a bounded Unix socket
at /run/fds/control.sock, mode 0660 and group fds, with peer UID checks for
root and the ordinary FDS user. Slow clients have individual deadlines and do not
block other clients. No asynchronous runtime or new external Rust dependency is
introduced: the existing std, libc, serde, serde_json and toml components suffice.
Root diagnostics: s6-svstat /run/service/cartridged and
cat /run/log/cartridged/current. Logs are bounded and volatile. Restart through
s6-rc -l /run/s6-rc -d change cartridged, then the corresponding -u command.
Close users of cartridge mounts first; restart cleanup refuses busy leftovers.
On the build host, make cartridge-test runs fixtures and full virtual USB tests.
These exercise actual kernel events and mounts but cannot establish physical
wiring, USB power stability, or Pi port behavior. M11 expands to twelve-device
stress, and physical calibration must be recorded separately.