198 lines
8.8 KiB
Markdown
198 lines
8.8 KiB
Markdown
# Using cartridges and configuring bays
|
|
|
|
[Documentation index](README.md) · [Boot images](boot.md) · [Services](services.md)
|
|
|
|
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](m6-validation.md). [Writable DATA integration](data.md) has passed M7 software acceptance;
|
|
[desktop/program activation](desktop.md) passed M8 and [media creation tools](media-tools.md)
|
|
passed M9 software acceptance. [M10 ordered shutdown](power.md) has passed software acceptance.
|
|
|
|
## Inspect the current machine
|
|
|
|
At the FDS console:
|
|
|
|
```sh
|
|
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.
|
|
|
|
1. On the assembled machine, insert one known USB device into one physical bay.
|
|
2. Run `fds topology`. This diagnostic explicitly shows controller/port paths;
|
|
ordinary bay commands omit those implementation details.
|
|
3. 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.
|
|
4. Put the measured map in your machine configuration directory and build the
|
|
[internal image](internal-storage.md), or use `fds machine install DIRECTORY`
|
|
from recovery and reboot. Machine settings persist independently of SYSTEM.
|
|
The packaged `/etc/fds/` files are fallback defaults for missing/invalid internal
|
|
storage; `fds machine status` shows which source is active.
|
|
5. 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:
|
|
|
|
```toml
|
|
[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](software-format.md) |
|
|
| 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:
|
|
|
|
```toml
|
|
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
|
|
|
|
```sh
|
|
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](data.md) 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:
|
|
|
|
```toml
|
|
[[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.
|