2565 lines
33 KiB
Markdown
2565 lines
33 KiB
Markdown
# FDS/OS MASTER IMPLEMENTATION PLAN
|
||
|
||
This is the complete design specification, including future components and
|
||
command interfaces. **M0–M12 software acceptance is complete, including Dasung base
|
||
integration and the signed local 0.1.0 release.**
|
||
Tests requiring physical Pi hardware are deferred; software and VM checks remain
|
||
in scope. See the [implementation ledger](implementation-status.md). A command appearing
|
||
here is not evidence that it exists in the checkout. Start with the
|
||
[project overview](../README.md) and [first-build walkthrough](getting-started.md)
|
||
for current usage, or the [roadmap](roadmap.md) for implementation status.
|
||
The 67 numbered sections below retain the full project requirements.
|
||
|
||
## 1. Project objective
|
||
|
||
Implement an independent Linux distribution for Raspberry Pi 5:
|
||
|
||
**FDS/OS — Felis Data Systems Operating System**
|
||
|
||
FDS/OS targets a retro portable computer with these characteristics:
|
||
|
||
- Raspberry Pi 5
|
||
- aarch64
|
||
- 12 USB cartridge bays
|
||
- removable SYSTEM / DATA / PROGRAM / ENVIRONMENT cartridges
|
||
- Dasung Paperlike 13K grayscale E-Ink display
|
||
- removable battery
|
||
- Very fast boot
|
||
- Very fast shutdown
|
||
- native s6 init
|
||
- Void/XBPS package ecosystem
|
||
- glibc as the system ABI
|
||
- Rust + static musl for FDS-owned programs wherever practical
|
||
|
||
Core design principle:
|
||
|
||
> Preserve compatibility with modern Linux software while making FDS-owned software as independent of distribution runtime libraries as practical.
|
||
|
||
---
|
||
|
||
# 2. ABI and libc strategy
|
||
|
||
The system must have two distinct userspace domains.
|
||
|
||
## 2.1 General userspace
|
||
|
||
Use:
|
||
|
||
```text
|
||
glibc
|
||
```
|
||
|
||
Applies to:
|
||
|
||
```text
|
||
GNU coreutils
|
||
GNU binutils
|
||
bash
|
||
grep
|
||
sed
|
||
gawk
|
||
findutils
|
||
util-linux
|
||
procps-ng
|
||
|
||
Xorg
|
||
WindowMaker
|
||
|
||
XBPS packages
|
||
|
||
Python
|
||
GCC
|
||
LLVM
|
||
third-party software
|
||
```
|
||
|
||
The system package architecture is:
|
||
|
||
```text
|
||
aarch64
|
||
```
|
||
|
||
Do not use:
|
||
|
||
```text
|
||
aarch64-musl
|
||
```
|
||
|
||
---
|
||
|
||
## 2.2 FDS control plane
|
||
|
||
FDS-maintained programs default to:
|
||
|
||
```text
|
||
Rust
|
||
+
|
||
aarch64-unknown-linux-musl
|
||
+
|
||
static linking
|
||
```
|
||
|
||
Include at least:
|
||
|
||
```text
|
||
fds-stage0
|
||
fds
|
||
fds-cartridged
|
||
fds-burn
|
||
fds-inspect
|
||
fds-eject
|
||
fds-profile
|
||
fds-power
|
||
fds-boottrace
|
||
```
|
||
|
||
Principle:
|
||
|
||
```text
|
||
FDS-owned runtime program
|
||
↓
|
||
static musl where practical
|
||
↓
|
||
Linux syscall ABI
|
||
```
|
||
|
||
These programs should not depend on the system's glibc version.
|
||
|
||
The following checks must pass:
|
||
|
||
```bash
|
||
file /usr/bin/fds
|
||
ldd /usr/bin/fds
|
||
```
|
||
|
||
Expected output resembles:
|
||
|
||
```text
|
||
statically linked
|
||
not a dynamic executable
|
||
```
|
||
|
||
---
|
||
|
||
# 3. Do not convert the entire system to musl
|
||
|
||
Do not force the following components to use musl:
|
||
|
||
```text
|
||
Xorg
|
||
WindowMaker
|
||
general XBPS packages
|
||
GNU toolchain
|
||
graphics stack
|
||
plugin-heavy applications
|
||
```
|
||
|
||
Do not attempt to maintain two complete repositories:
|
||
|
||
```text
|
||
glibc repository
|
||
musl repository
|
||
```
|
||
|
||
The purpose of musl is limited to:
|
||
|
||
> Providing a stable, self-contained static linking environment for FDS-owned control-plane executables.
|
||
|
||
---
|
||
|
||
# 4. Init architecture
|
||
|
||
FDS/OS must be a native s6 system.
|
||
|
||
Final architecture:
|
||
|
||
```text
|
||
Linux
|
||
↓
|
||
/sbin/init
|
||
↓
|
||
s6-linux-init
|
||
↓
|
||
s6-svscan
|
||
↓
|
||
s6-rc
|
||
```
|
||
|
||
Prohibited:
|
||
|
||
```text
|
||
systemd → s6
|
||
runit → s6
|
||
OpenRC → s6
|
||
custom shell PID1 → s6
|
||
```
|
||
|
||
PID 1 must ultimately belong to the s6 architecture.
|
||
|
||
Use:
|
||
|
||
```text
|
||
skalibs
|
||
execline
|
||
s6
|
||
s6-linux-init
|
||
s6-rc
|
||
```
|
||
|
||
The s6-rc source database resides at:
|
||
|
||
```text
|
||
/etc/s6-rc/source
|
||
```
|
||
|
||
compiled database:
|
||
|
||
```text
|
||
/etc/s6-rc/compiled
|
||
```
|
||
|
||
live database:
|
||
|
||
```text
|
||
/run/s6-rc
|
||
```
|
||
|
||
**The compiled database must be generated during image construction.**
|
||
|
||
Normal boot must never run:
|
||
|
||
```text
|
||
s6-rc-compile
|
||
```
|
||
|
||
---
|
||
|
||
# 5. Package architecture
|
||
|
||
Use Void Linux only for:
|
||
|
||
```text
|
||
upstream package ecosystem
|
||
XBPS
|
||
xbps-src
|
||
glibc packages
|
||
GNU packages
|
||
kernel packaging reference
|
||
third-party packages
|
||
```
|
||
|
||
FDS defines its own:
|
||
|
||
```text
|
||
fds-base
|
||
```
|
||
|
||
Do not directly depend on an all-inclusive Void base metapackage.
|
||
|
||
Initial dependencies of `fds-base`:
|
||
|
||
```text
|
||
glibc
|
||
glibc-locales
|
||
|
||
coreutils
|
||
binutils
|
||
findutils
|
||
diffutils
|
||
grep
|
||
sed
|
||
gawk
|
||
bash
|
||
tar
|
||
gzip
|
||
xz
|
||
|
||
util-linux
|
||
procps-ng
|
||
shadow
|
||
kbd
|
||
|
||
e2fsprogs
|
||
dosfstools
|
||
erofs-utils
|
||
|
||
eudev
|
||
kmod
|
||
|
||
iproute2
|
||
iputils
|
||
|
||
pciutils
|
||
usbutils
|
||
|
||
ca-certificates
|
||
tzdata
|
||
|
||
xbps
|
||
|
||
skalibs
|
||
execline
|
||
s6
|
||
s6-linux-init
|
||
s6-rc
|
||
|
||
fds-base-files
|
||
fds-cartridged
|
||
fds-cli
|
||
fds-dasungd
|
||
```
|
||
|
||
FDS-owned static-musl binaries must not require:
|
||
|
||
```text
|
||
musl runtime package
|
||
```
|
||
|
||
musl is already statically linked into each executable.
|
||
|
||
---
|
||
|
||
# 6. Build host
|
||
|
||
Primary build machine:
|
||
|
||
```text
|
||
x86_64 Arch Linux
|
||
```
|
||
|
||
Target:
|
||
|
||
```text
|
||
aarch64 Raspberry Pi 5
|
||
```
|
||
|
||
Normal development **must not require an ARM build host**.
|
||
|
||
The Pi 5 serves as:
|
||
|
||
```text
|
||
deployment target
|
||
hardware validation target
|
||
performance target
|
||
```
|
||
|
||
It is not the primary build machine.
|
||
|
||
Void's xbps-src supports foreign Linux hosts. Cross-build with:
|
||
|
||
```bash
|
||
./xbps-src -a aarch64 pkg PACKAGE
|
||
```
|
||
|
||
This performs a cross build.
|
||
|
||
Rust FDS components use:
|
||
|
||
```text
|
||
aarch64-unknown-linux-musl
|
||
```
|
||
|
||
This Rust target explicitly supports cross-compilation from other hosts.
|
||
|
||
---
|
||
|
||
# 7. Repository layout
|
||
|
||
Create:
|
||
|
||
```text
|
||
fds-os/
|
||
│
|
||
├── README.md
|
||
├── Makefile
|
||
├── Cargo.toml
|
||
│
|
||
├── docs/
|
||
│ ├── architecture.md
|
||
│ ├── boot.md
|
||
│ ├── cartridges.md
|
||
│ ├── services.md
|
||
│ ├── packages.md
|
||
│ ├── performance.md
|
||
│ └── recovery.md
|
||
│
|
||
├── vendor/
|
||
│ └── void-packages/
|
||
│
|
||
├── packages/
|
||
│ ├── fds-base/
|
||
│ ├── fds-base-files/
|
||
│ ├── fds-kernel/
|
||
│ ├── fds-cartridged/
|
||
│ ├── fds-cli/
|
||
│ └── fds-eink/
|
||
│
|
||
├── rust/
|
||
│ ├── fds-common/
|
||
│ ├── fds-stage0/
|
||
│ ├── fds-cli/
|
||
│ ├── fds-cartridged/
|
||
│ ├── fds-burn/
|
||
│ └── fds-boottrace/
|
||
│
|
||
├── s6/
|
||
│ └── source/
|
||
│
|
||
├── profiles/
|
||
│ ├── cli.toml
|
||
│ ├── development.toml
|
||
│ ├── windowmaker.toml
|
||
│ └── recovery.toml
|
||
│
|
||
├── image/
|
||
│ ├── build-rootfs
|
||
│ ├── build-system-cartridge
|
||
│ ├── build-boot-volume
|
||
│ ├── build-initramfs
|
||
│ └── build-recovery
|
||
│
|
||
├── tools/
|
||
│ ├── bootstrap-host
|
||
│ ├── build-package
|
||
│ ├── qemu-test
|
||
│ ├── burn
|
||
│ └── configure-pi-eeprom
|
||
│
|
||
├── tests/
|
||
│ ├── unit/
|
||
│ ├── integration/
|
||
│ └── hardware/
|
||
│
|
||
└── out/
|
||
```
|
||
|
||
---
|
||
|
||
# 8. Managing the Void upstream
|
||
|
||
Do not maintain a long-lived fork with changes throughout void-packages.
|
||
|
||
Use:
|
||
|
||
```text
|
||
vendor/void-packages
|
||
```
|
||
|
||
Pin it to a specific commit.
|
||
|
||
Record:
|
||
|
||
```text
|
||
VOID_PACKAGES_COMMIT
|
||
```
|
||
|
||
Inject FDS packages through an overlay.
|
||
|
||
Required relationship:
|
||
|
||
```text
|
||
same FDS commit
|
||
+
|
||
same Void commit
|
||
=
|
||
same package input
|
||
```
|
||
|
||
Do not drift with daily changes to the Void rolling repository.
|
||
|
||
---
|
||
|
||
# 9. Rust workspace
|
||
|
||
Create the workspace:
|
||
|
||
```toml
|
||
[workspace]
|
||
members = [
|
||
"rust/fds-common",
|
||
"rust/fds-stage0",
|
||
"rust/fds-cli",
|
||
"rust/fds-cartridged",
|
||
"rust/fds-burn",
|
||
"rust/fds-boottrace",
|
||
]
|
||
```
|
||
|
||
Default release profile:
|
||
|
||
```toml
|
||
[profile.release]
|
||
opt-level = "z"
|
||
lto = true
|
||
codegen-units = 1
|
||
panic = "abort"
|
||
strip = true
|
||
```
|
||
|
||
Benchmark performance-critical binaries with:
|
||
|
||
```text
|
||
opt-level = z
|
||
vs
|
||
opt-level = 2
|
||
vs
|
||
opt-level = 3
|
||
```
|
||
|
||
Do not assume that the smallest executable starts fastest.
|
||
|
||
---
|
||
|
||
# 10. Rust dependency policy
|
||
|
||
Use Clap for every Rust command-line interface, including test helpers. Declare
|
||
typed commands, options, validation, and generated help; do not hand-parse the
|
||
argument vector. The workspace shares the version already used by Dasung and
|
||
pins it in `Cargo.lock`. Kernel command-line files and cartridge metadata remain
|
||
separate domain formats with their own strict parsers.
|
||
|
||
FDS core programs should avoid:
|
||
|
||
```text
|
||
tokio
|
||
openssl
|
||
glibc-specific crates
|
||
libudev-sys
|
||
large asynchronous runtimes
|
||
```
|
||
|
||
Prefer:
|
||
|
||
```text
|
||
std
|
||
libc crate
|
||
rustix
|
||
nix
|
||
serde
|
||
toml
|
||
small synchronous event loop
|
||
netlink/sysfs directly where reasonable
|
||
```
|
||
|
||
Do not introduce a large runtime merely to listen for a few uevents.
|
||
|
||
---
|
||
|
||
# 11. Boot architecture
|
||
|
||
The machine's internal NVMe belongs to the:
|
||
|
||
```text
|
||
machine firmware layer
|
||
```
|
||
|
||
The SYSTEM cartridge contains the:
|
||
|
||
```text
|
||
operating system userspace
|
||
```
|
||
|
||
Boot sequence:
|
||
|
||
```text
|
||
Raspberry Pi EEPROM
|
||
↓
|
||
internal NVMe
|
||
↓
|
||
kernel
|
||
↓
|
||
tiny FDS initramfs
|
||
↓
|
||
fds-stage0
|
||
↓
|
||
locate SYSTEM cartridge
|
||
↓
|
||
mount EROFS
|
||
↓
|
||
switch_root
|
||
↓
|
||
s6
|
||
↓
|
||
READY
|
||
```
|
||
|
||
Do not make Raspberry Pi firmware search all 12 USB cartridges for a boot device.
|
||
|
||
---
|
||
|
||
# 12. Internal NVMe layout
|
||
|
||
Recommended layout:
|
||
|
||
```text
|
||
GPT
|
||
|
||
p1 FDS_BOOT
|
||
FAT32
|
||
512 MB
|
||
|
||
p2 FDS_RECOVERY
|
||
EROFS
|
||
1–2 GB
|
||
|
||
p3 FDS_INTERNAL
|
||
ext4
|
||
```
|
||
|
||
## FDS_BOOT
|
||
|
||
Contains:
|
||
|
||
```text
|
||
Pi firmware
|
||
kernel
|
||
DTBs
|
||
config.txt
|
||
cmdline.txt
|
||
FDS initramfs
|
||
```
|
||
|
||
## FDS_RECOVERY
|
||
|
||
Contains a complete, independent recovery environment.
|
||
|
||
## FDS_INTERNAL
|
||
|
||
Record:
|
||
|
||
```text
|
||
hardware configuration
|
||
Bay topology
|
||
boot performance history
|
||
cached cartridge metadata
|
||
diagnostics
|
||
```
|
||
|
||
Do not store ordinary user files here.
|
||
|
||
---
|
||
|
||
# 13. SYSTEM cartridge
|
||
|
||
SYSTEM cartridge:
|
||
|
||
```text
|
||
GPT
|
||
+
|
||
partition name FDS_SYSTEM
|
||
+
|
||
EROFS
|
||
```
|
||
|
||
For example:
|
||
|
||
```text
|
||
/dev/???
|
||
└── GPT PARTNAME=FDS_SYSTEM
|
||
```
|
||
|
||
Never depend on:
|
||
|
||
```text
|
||
/dev/sda
|
||
/dev/sdb
|
||
```
|
||
|
||
With 12 USB devices, these names are completely unreliable identifiers.
|
||
|
||
root:
|
||
|
||
```text
|
||
read-only
|
||
```
|
||
|
||
---
|
||
|
||
# 14. fds-stage0
|
||
|
||
`fds-stage0` is a static-musl Rust executable.
|
||
|
||
Target:
|
||
|
||
```text
|
||
single executable initramfs control program
|
||
```
|
||
|
||
Avoid including the following wherever practical:
|
||
|
||
```text
|
||
shell
|
||
BusyBox
|
||
glibc
|
||
Python
|
||
udev
|
||
```
|
||
|
||
Its responsibilities are limited to:
|
||
|
||
```text
|
||
mount /proc
|
||
mount /sys
|
||
mount devtmpfs
|
||
|
||
enumerate block devices
|
||
|
||
find GPT PARTNAME FDS_SYSTEM
|
||
|
||
mount EROFS root
|
||
|
||
move /proc /sys /dev
|
||
|
||
switch_root
|
||
|
||
exec /sbin/init
|
||
```
|
||
|
||
Prefer direct use of:
|
||
|
||
```text
|
||
mount(2)
|
||
openat
|
||
read
|
||
ioctl
|
||
netlink/sysfs
|
||
pivot_root/switch_root equivalent
|
||
```
|
||
|
||
Do not invoke a shell or external commands.
|
||
|
||
---
|
||
|
||
# 15. Missing SYSTEM cartridge
|
||
|
||
For the selected Dasung monitor, early userspace must provide the display's
|
||
control/keepalive and correct video mode before showing this prompt. The base
|
||
SYSTEM daemon starts later and cannot satisfy missing-SYSTEM display requirements
|
||
by itself. Implement and verify this handoff as part of Pi boot integration.
|
||
|
||
When no SYSTEM cartridge is present:
|
||
|
||
Display:
|
||
|
||
```text
|
||
FELIS DATA SYSTEMS
|
||
PORTABLE COMPUTER FP-85
|
||
|
||
BOOT ROM 0.1
|
||
|
||
SYSTEM MEDIA NOT PRESENT
|
||
|
||
INSERT SYSTEM CARTRIDGE
|
||
```
|
||
|
||
Then:
|
||
|
||
```text
|
||
continue listening for block device changes
|
||
```
|
||
|
||
When a SYSTEM cartridge is inserted:
|
||
|
||
**Resume boot immediately.**
|
||
|
||
A reboot must not be required.
|
||
|
||
---
|
||
|
||
# 16. Multiple SYSTEM cartridges
|
||
|
||
When multiple partitions are found with:
|
||
|
||
```text
|
||
FDS_SYSTEM
|
||
```
|
||
|
||
Do not choose one arbitrarily.
|
||
|
||
Display:
|
||
|
||
```text
|
||
MULTIPLE SYSTEM CARTRIDGES
|
||
|
||
BAY 02 FDS/OS 0.1
|
||
BAY 08 FDS/OS DEVELOPMENT
|
||
|
||
SELECT SYSTEM:
|
||
```
|
||
|
||
Version 1 may enter a recovery/debug console.
|
||
|
||
Add interactive selection in version 2.
|
||
|
||
---
|
||
|
||
# 17. Kernel strategy
|
||
|
||
Start the first version from Void's Raspberry Pi 5 kernel packaging.
|
||
|
||
Do not maintain a large kernel fork from day one.
|
||
|
||
Create:
|
||
|
||
```text
|
||
fds-kernel
|
||
```
|
||
|
||
Maintain only:
|
||
|
||
```text
|
||
config delta
|
||
packaging
|
||
version policy
|
||
```
|
||
|
||
Build boot-critical drivers into the kernel wherever practical:
|
||
|
||
```text
|
||
BCM2712
|
||
RP1
|
||
PCIe
|
||
USB host
|
||
USB hub
|
||
USB mass storage
|
||
SCSI disk
|
||
NVMe
|
||
devtmpfs
|
||
EROFS
|
||
ext4
|
||
FAT
|
||
HID keyboard
|
||
console
|
||
DRM/KMS
|
||
```
|
||
|
||
optional:
|
||
|
||
```text
|
||
Wi-Fi
|
||
Bluetooth
|
||
USB Ethernet
|
||
USB Serial
|
||
audio
|
||
SDR
|
||
```
|
||
|
||
These optional drivers may be modules.
|
||
|
||
---
|
||
|
||
# 18. Initramfs
|
||
|
||
Target:
|
||
|
||
```text
|
||
As close as practical to:
|
||
|
||
/init -> fds-stage0
|
||
```
|
||
|
||
Test these formats:
|
||
|
||
```text
|
||
uncompressed cpio
|
||
lz4
|
||
zstd
|
||
gzip
|
||
```
|
||
|
||
Benchmark on a real Pi 5.
|
||
|
||
The following observation:
|
||
|
||
```text
|
||
zstd image smaller
|
||
```
|
||
|
||
does not establish that boot will be faster.
|
||
|
||
NVMe capacity is inexpensive.
|
||
|
||
Boot milliseconds matter.
|
||
|
||
---
|
||
|
||
# 19. Raspberry Pi firmware optimisation
|
||
|
||
production EEPROM:
|
||
|
||
Disable unnecessary network installation behavior.
|
||
|
||
In particular:
|
||
|
||
```text
|
||
NET_INSTALL_ENABLED=0
|
||
NET_INSTALL_AT_POWER_ON=0
|
||
```
|
||
|
||
Raspberry Pi's official guidance states that USB controller initialization and device enumeration to detect a network-install keyboard add about one second to boot, making these features worth disabling on embedded devices that need fast startup.
|
||
|
||
Provide:
|
||
|
||
```text
|
||
tools/configure-pi-eeprom
|
||
```
|
||
|
||
Together with:
|
||
|
||
```text
|
||
development.conf
|
||
production.conf
|
||
```
|
||
|
||
All EEPROM changes must be:
|
||
|
||
```text
|
||
documented
|
||
reversible
|
||
```
|
||
|
||
---
|
||
|
||
# 20. Filesystem model
|
||
|
||
SYSTEM:
|
||
|
||
```text
|
||
EROFS
|
||
read-only
|
||
```
|
||
|
||
runtime:
|
||
|
||
```text
|
||
/run tmpfs
|
||
/tmp tmpfs
|
||
/var/tmp tmpfs
|
||
/var/log tmpfs
|
||
```
|
||
|
||
Do not run root filesystem fsck during boot.
|
||
|
||
Do not write logs to SYSTEM.
|
||
|
||
Do not update SYSTEM in place.
|
||
|
||
---
|
||
|
||
# 21. User data
|
||
|
||
DATA cartridge:
|
||
|
||
```text
|
||
GPT PARTNAME=FDS_DATA
|
||
filesystem=ext4
|
||
```
|
||
|
||
After insertion:
|
||
|
||
```text
|
||
/data
|
||
```
|
||
|
||
Alternatively:
|
||
|
||
```text
|
||
/home/fds
|
||
```
|
||
|
||
Mount this path from the DATA cartridge.
|
||
|
||
When no DATA cartridge is present:
|
||
|
||
```text
|
||
ephemeral tmpfs home
|
||
```
|
||
|
||
Therefore:
|
||
|
||
> The machine itself does not own user data.
|
||
|
||
---
|
||
|
||
# 22. Native s6 service graph
|
||
|
||
Minimum boot bundle:
|
||
|
||
```text
|
||
boot
|
||
├── runtime-fs
|
||
├── hostname
|
||
├── console
|
||
├── eudevd
|
||
├── udev-trigger
|
||
├── cartridged
|
||
├── getty
|
||
└── dasungd
|
||
```
|
||
|
||
Explicitly excluded from the boot bundle:
|
||
|
||
```text
|
||
network
|
||
DHCP
|
||
NTP
|
||
sshd
|
||
D-Bus
|
||
Xorg
|
||
WindowMaker
|
||
Bluetooth
|
||
Wi-Fi
|
||
```
|
||
|
||
---
|
||
|
||
# 23. Fast boot principle
|
||
|
||
The interactive shell should depend only on:
|
||
|
||
```text
|
||
root mounted
|
||
console ready
|
||
/dev minimally usable
|
||
```
|
||
|
||
It must not depend on:
|
||
|
||
```text
|
||
all USB devices enumerated
|
||
cartridge catalog scan
|
||
network
|
||
clock synchronization
|
||
GUI
|
||
```
|
||
|
||
The intended sequence is:
|
||
|
||
```text
|
||
power on
|
||
↓
|
||
kernel
|
||
↓
|
||
root
|
||
↓
|
||
s6
|
||
↓
|
||
FDS>
|
||
```
|
||
|
||
Everything else proceeds in parallel afterward.
|
||
|
||
---
|
||
|
||
# 24. eudev
|
||
|
||
The normal system uses:
|
||
|
||
```text
|
||
eudev
|
||
```
|
||
|
||
However, do not use:
|
||
|
||
```text
|
||
udevadm settle
|
||
```
|
||
|
||
as a global boot barrier.
|
||
|
||
Correct sequence:
|
||
|
||
```text
|
||
start eudevd
|
||
↓
|
||
trigger existing devices
|
||
↓
|
||
continue boot
|
||
```
|
||
|
||
Services that need a particular device must handle their own readiness.
|
||
|
||
---
|
||
|
||
# 25. cartridged
|
||
|
||
Implement:
|
||
|
||
```text
|
||
fds-cartridged
|
||
```
|
||
|
||
static-musl Rust.
|
||
|
||
Responsibilities:
|
||
|
||
```text
|
||
listen for USB/block events
|
||
identify physical hub/port
|
||
map device → BAY 01..12
|
||
inspect storage metadata
|
||
mount/unmount cartridges
|
||
activate FDS profiles
|
||
communicate state to fds CLI
|
||
```
|
||
|
||
Do not depend on:
|
||
|
||
```text
|
||
/dev/sdX ordering
|
||
```
|
||
|
||
Use:
|
||
|
||
```text
|
||
sysfs USB topology
|
||
```
|
||
|
||
to identify physical bays.
|
||
|
||
---
|
||
|
||
# 26. Bay topology
|
||
|
||
Configuration:
|
||
|
||
```text
|
||
/etc/fds/bays.toml
|
||
```
|
||
|
||
Example:
|
||
|
||
```toml
|
||
[front]
|
||
hub = "usb-topology-id"
|
||
|
||
[front.ports]
|
||
1 = 1
|
||
2 = 2
|
||
3 = 3
|
||
4 = 4
|
||
5 = 5
|
||
6 = 6
|
||
|
||
[rear]
|
||
hub = "usb-topology-id"
|
||
|
||
[rear.ports]
|
||
1 = 7
|
||
2 = 8
|
||
3 = 9
|
||
4 = 10
|
||
5 = 11
|
||
6 = 12
|
||
```
|
||
|
||
Users see:
|
||
|
||
```text
|
||
BAY 01
|
||
...
|
||
BAY 12
|
||
```
|
||
|
||
They must not see:
|
||
|
||
```text
|
||
1-2.4.1
|
||
```
|
||
|
||
except in debug mode.
|
||
|
||
---
|
||
|
||
# 27. Cartridge metadata
|
||
|
||
At the root of a storage cartridge:
|
||
|
||
```text
|
||
/FDS/CARTRIDGE.TOML
|
||
```
|
||
|
||
Format:
|
||
|
||
```toml
|
||
format = 1
|
||
|
||
[cartridge]
|
||
id = "fds.windowmaker"
|
||
name = "WINDOW SYSTEM"
|
||
class = "environment"
|
||
version = "0.1"
|
||
|
||
[media]
|
||
writable = false
|
||
|
||
[activation]
|
||
profile = "windowmaker"
|
||
```
|
||
|
||
classes:
|
||
|
||
```text
|
||
system
|
||
data
|
||
program
|
||
environment
|
||
hardware
|
||
utility
|
||
```
|
||
|
||
---
|
||
|
||
# 28. Hardware cartridges
|
||
|
||
USB hardware without a filesystem includes:
|
||
|
||
For example:
|
||
|
||
```text
|
||
USB Ethernet
|
||
USB Serial
|
||
USB Wi-Fi
|
||
USB Audio
|
||
```
|
||
|
||
Identify it using:
|
||
|
||
```text
|
||
VID
|
||
PID
|
||
serial
|
||
USB class
|
||
physical bay
|
||
```
|
||
|
||
Use these identifiers for recognition.
|
||
|
||
Maintain:
|
||
|
||
```text
|
||
/etc/fds/hardware-catalog.toml
|
||
```
|
||
|
||
Do not require every hardware cartridge to contain storage.
|
||
|
||
---
|
||
|
||
# 29. ENVIRONMENT cartridge v1
|
||
|
||
Do not place the entire Xorg and WindowMaker runtime on cartridges in version 1.
|
||
|
||
Implement the activation logic first:
|
||
|
||
The SYSTEM image already contains:
|
||
|
||
```text
|
||
Xorg
|
||
WindowMaker
|
||
fonts
|
||
theme
|
||
```
|
||
|
||
The ENVIRONMENT cartridge initially provides only:
|
||
|
||
```text
|
||
capability key
|
||
+
|
||
configuration
|
||
```
|
||
|
||
On insertion:
|
||
|
||
```text
|
||
WINDOW SYSTEM
|
||
↓
|
||
cartridged
|
||
↓
|
||
fds-profile activate windowmaker
|
||
↓
|
||
s6-rc change +desktop
|
||
```
|
||
|
||
On removal:
|
||
|
||
```text
|
||
desktop down
|
||
↓
|
||
return CLI
|
||
```
|
||
|
||
Move the GUI runtime onto the cartridge in version 2.
|
||
|
||
---
|
||
|
||
# 30. WindowMaker stack
|
||
|
||
Display managers are prohibited.
|
||
|
||
Do not use:
|
||
|
||
```text
|
||
GDM
|
||
SDDM
|
||
LightDM
|
||
```
|
||
|
||
Use:
|
||
|
||
```text
|
||
s6
|
||
↓
|
||
Xorg
|
||
↓
|
||
WindowMaker
|
||
```
|
||
|
||
A single-user machine may use:
|
||
|
||
```text
|
||
autologin FDS console
|
||
```
|
||
|
||
Activating a GUI profile starts the user's graphical session directly.
|
||
|
||
---
|
||
|
||
# 31. E-Ink profile
|
||
|
||
The monitor controller is base hardware support, independent of the desktop
|
||
profile. Include the existing Rust `dasungd` for the user's Paperlike 13K grayscale
|
||
in every SYSTEM image and the native s6 boot bundle. Maintain the confirmed
|
||
profile, static-musl target, reconnect handling, and SPI-driver protection.
|
||
See [Dasung integration](dasung.md) for implementation, usage, and the remaining
|
||
Pi and physical recovery checks. It must not require an ENVIRONMENT cartridge.
|
||
|
||
Create:
|
||
|
||
```text
|
||
fds-eink
|
||
```
|
||
|
||
Configuration:
|
||
|
||
```text
|
||
no compositor
|
||
no transparency
|
||
no fade
|
||
no desktop animation
|
||
no smooth window animation
|
||
outline move
|
||
outline resize
|
||
static wallpaper
|
||
high contrast
|
||
```
|
||
|
||
WindowMaker should prioritize:
|
||
|
||
```text
|
||
black
|
||
white
|
||
2–4 grayscale levels
|
||
```
|
||
|
||
Fonts:
|
||
|
||
```text
|
||
Terminus
|
||
other high-contrast bitmap-friendly fonts
|
||
```
|
||
|
||
Do not update the clock every second.
|
||
|
||
---
|
||
|
||
# 32. PROGRAM cartridge
|
||
|
||
Do not design a complex dependency resolver across cartridges in version 1.
|
||
|
||
New PROGRAM software cartridges use GPT with exactly `1 + m` read-only EROFS
|
||
partitions. Partition 1 (`FDS_METADATA`) contains `FDS/CARTRIDGE.TOML` and
|
||
`FDS/SOFTWARE.TOML`. The catalogue describes every software bundle in the next
|
||
`m` partitions, named `FDS_PAYLOAD02` onward. Each software bundle is an
|
||
xz-compressed tarball; multiple bundles may share a payload partition.
|
||
|
||
Software compilation, archive packaging and complete cartridge image creation
|
||
run on a generic Linux workstation. The confirmed USB writer writes and verifies
|
||
that complete disk image. QEMU workstation tooling boots the real FDS kernel,
|
||
initramfs and SYSTEM and inserts/removes these images as virtual USB cartridges.
|
||
|
||
The guest validates metadata and mounts payloads read-only, then verifies and
|
||
extracts a selected bundle to a bounded temporary read-only cache. It executes
|
||
only an explicitly requested `SOFTWARE-ID:COMMAND` as the ordinary user. It never
|
||
runs software build recipes or installation hooks. Eject, physical removal,
|
||
service restart and shutdown release caches and stop managed consumers.
|
||
|
||
Legacy single-partition `FDS_PROGRAM` media with `app/bin`, `app/lib`, and
|
||
`app/share` remain readable. The metadata-first format supersedes that layout
|
||
for newly built software cartridges. See [Workstation usage](workstation.md) and
|
||
[the format contract](software-format.md).
|
||
|
||
Where necessary, use:
|
||
|
||
```text
|
||
RPATH
|
||
wrapper environment
|
||
```
|
||
|
||
to resolve shared libraries.
|
||
|
||
Do not modify the SYSTEM root.
|
||
|
||
---
|
||
|
||
# 33. FDS CLI
|
||
|
||
`fds` is a static-musl Rust binary.
|
||
|
||
Implement at least:
|
||
|
||
```text
|
||
fds info
|
||
|
||
fds bays
|
||
|
||
fds bay 3
|
||
|
||
fds cartridge 3
|
||
|
||
fds eject 3
|
||
|
||
fds profiles
|
||
|
||
fds profile activate windowmaker
|
||
|
||
fds poweroff
|
||
|
||
fds reboot
|
||
|
||
fds boot-profile
|
||
```
|
||
|
||
Output should be concise, fast, and suitable for E-Ink.
|
||
|
||
For example:
|
||
|
||
```text
|
||
FDS> fds bays
|
||
|
||
01 SYSTEM FDS/OS 0.1 ONLINE
|
||
02 DATA FELIS ONLINE
|
||
03 ENVIRONMENT WINDOW SYSTEM ONLINE
|
||
04 PROGRAM TEXT TOOLS ONLINE
|
||
05 EMPTY
|
||
06 EMPTY
|
||
|
||
07 ETHERNET EC-1 ONLINE
|
||
08 EMPTY
|
||
09 EMPTY
|
||
10 EMPTY
|
||
11 EMPTY
|
||
12 EMPTY
|
||
```
|
||
|
||
---
|
||
|
||
# 34. fds-burn
|
||
|
||
The target media client remains static-musl Rust. New software creation and
|
||
writing use native Linux workstation `fds-cartridge`: build bundles, construct
|
||
and verify the complete metadata-first GPT image, preview the USB target, then
|
||
write and verify that full image. Never assemble software partitions piecemeal
|
||
on the destination drive. See [the workstation workflow](workstation.md).
|
||
|
||
Responsible for:
|
||
|
||
```text
|
||
inspect target
|
||
partition media
|
||
write image
|
||
verify
|
||
write cartridge metadata
|
||
```
|
||
|
||
Typical usage:
|
||
|
||
```text
|
||
fds burn system fds-system-cli.img BAY04
|
||
```
|
||
|
||
Alternatively:
|
||
|
||
```text
|
||
fds burn data BAY04 --label FELIS
|
||
```
|
||
|
||
Destructive operations require explicit confirmation.
|
||
|
||
---
|
||
|
||
# 35. Package installation model
|
||
|
||
A running SYSTEM cartridge must not use:
|
||
|
||
```text
|
||
sudo xbps-install -Su
|
||
```
|
||
|
||
to modify itself in place.
|
||
|
||
Use XBPS for:
|
||
|
||
```text
|
||
building images
|
||
resolving package dependencies
|
||
resolving libraries for workstation-built PROGRAM bundles
|
||
development profile
|
||
```
|
||
|
||
SYSTEM update sequence:
|
||
|
||
```text
|
||
build new SYSTEM image
|
||
↓
|
||
write new cartridge
|
||
↓
|
||
swap cartridge
|
||
```
|
||
|
||
rollback:
|
||
|
||
```text
|
||
put old cartridge back
|
||
```
|
||
|
||
---
|
||
|
||
# 36. Image builder
|
||
|
||
Implement:
|
||
|
||
```text
|
||
make rootfs PROFILE=cli
|
||
```
|
||
|
||
Internal workflow:
|
||
|
||
```text
|
||
create empty root
|
||
↓
|
||
xbps-install -r ROOT ...
|
||
↓
|
||
install FDS packages
|
||
↓
|
||
apply profile
|
||
↓
|
||
generate locales
|
||
↓
|
||
generate caches
|
||
↓
|
||
compile s6-rc database
|
||
↓
|
||
remove build junk
|
||
↓
|
||
make EROFS
|
||
```
|
||
|
||
All of the following must happen at build time:
|
||
|
||
```text
|
||
locale generation
|
||
font cache generation
|
||
s6-rc compilation
|
||
ldconfig
|
||
package configuration
|
||
```
|
||
|
||
Do not perform them during boot.
|
||
|
||
---
|
||
|
||
# 37. Build interface
|
||
|
||
Eventually support:
|
||
|
||
```text
|
||
make bootstrap
|
||
|
||
make packages
|
||
|
||
make rootfs PROFILE=cli
|
||
|
||
make rootfs PROFILE=development
|
||
|
||
make system-card PROFILE=cli
|
||
|
||
make system-card PROFILE=development
|
||
|
||
make initramfs
|
||
|
||
make kernel
|
||
|
||
make boot-volume
|
||
|
||
make recovery
|
||
|
||
make all
|
||
```
|
||
|
||
output:
|
||
|
||
```text
|
||
out/
|
||
├── fds-boot.img
|
||
├── fds-initramfs.img
|
||
├── fds-recovery.img
|
||
├── fds-system-cli.img
|
||
├── fds-system-development.img
|
||
└── packages/
|
||
```
|
||
|
||
---
|
||
|
||
# 38. Cross compilation policy
|
||
|
||
All FDS Rust binaries must support building on x86_64 with:
|
||
|
||
```bash
|
||
cargo build \
|
||
--release \
|
||
--target aarch64-unknown-linux-musl
|
||
```
|
||
|
||
All FDS XBPS packages should support the following wherever practical:
|
||
|
||
```bash
|
||
./xbps-src -a aarch64 pkg PACKAGE
|
||
```
|
||
|
||
For cross-built packages, xbps-src selects the corresponding cross environment and exposes variables such as `XBPS_CROSS_BASE` and `XBPS_RUST_TARGET`.
|
||
|
||
If a package cannot be cross-built:
|
||
|
||
Fallback priority:
|
||
|
||
```text
|
||
1. Use an official Void aarch64 binary
|
||
2. Fix the cross build
|
||
3. QEMU native-aarch64 build
|
||
4. Build natively on the Pi only as a last resort
|
||
```
|
||
|
||
The normal build pipeline must not require a Pi.
|
||
|
||
---
|
||
|
||
# 39. Host-side QEMU testing
|
||
|
||
Set up this workflow on the Framework:
|
||
|
||
```text
|
||
x86_64 Arch
|
||
↓
|
||
cross build
|
||
↓
|
||
aarch64 image
|
||
↓
|
||
QEMU smoke test
|
||
↓
|
||
real Pi test
|
||
```
|
||
|
||
Use QEMU to test:
|
||
|
||
```text
|
||
s6 graph
|
||
shell
|
||
package contents
|
||
static-musl binaries
|
||
config parsing
|
||
filesystem layout
|
||
shutdown logic
|
||
cartridge metadata
|
||
```
|
||
|
||
Use a real Pi to test:
|
||
|
||
```text
|
||
firmware
|
||
RP1
|
||
USB topology
|
||
12 bays
|
||
E-Ink
|
||
power behaviour
|
||
actual boot timing
|
||
```
|
||
|
||
---
|
||
|
||
# 40. Boot performance targets
|
||
|
||
Define:
|
||
|
||
```text
|
||
T0 power applied
|
||
T1 kernel entered
|
||
T2 fds-stage0 entered
|
||
T3 switch_root
|
||
T4 s6 running
|
||
T5 CLI accepts input
|
||
T6 WindowMaker accepts input
|
||
```
|
||
|
||
Target:
|
||
|
||
```text
|
||
kernel → CLI:
|
||
< 1.5 seconds target
|
||
< 2.0 seconds maximum target
|
||
|
||
s6 → CLI:
|
||
< 400 ms target
|
||
|
||
cold power → CLI:
|
||
< 3 seconds stretch goal
|
||
< 5 seconds hard goal
|
||
|
||
CLI → WindowMaker:
|
||
< 2 seconds
|
||
```
|
||
|
||
These are targets, not claimed performance results.
|
||
|
||
Actual measurements are required.
|
||
|
||
---
|
||
|
||
# 41. fds-boottrace
|
||
|
||
Implement:
|
||
|
||
```text
|
||
fds-boottrace
|
||
```
|
||
|
||
Record:
|
||
|
||
```text
|
||
kernel timestamp
|
||
stage0 start
|
||
SYSTEM found
|
||
root mounted
|
||
switch_root
|
||
s6 start
|
||
console ready
|
||
desktop ready
|
||
```
|
||
|
||
Output:
|
||
|
||
```text
|
||
FDS BOOT PROFILE
|
||
|
||
KERNEL .............. 0.713 s
|
||
STAGE0 .............. 0.094 s
|
||
SYSTEM DISCOVERY .... 0.082 s
|
||
ROOT SWITCH ......... 0.031 s
|
||
S6 .................. 0.047 s
|
||
CONSOLE ............. 0.073 s
|
||
|
||
KERNEL → READY ...... 1.040 s
|
||
```
|
||
|
||
Save benchmarks in:
|
||
|
||
```text
|
||
docs/performance.md
|
||
```
|
||
|
||
---
|
||
|
||
# 42. Performance regression rule
|
||
|
||
Any commit that causes:
|
||
|
||
```text
|
||
boot regression > 100ms
|
||
```
|
||
|
||
must:
|
||
|
||
```text
|
||
explain it
|
||
or fix it
|
||
```
|
||
|
||
Do not add an artificial delay for a retro splash screen:
|
||
|
||
```text
|
||
sleep 1
|
||
```
|
||
|
||
If FDS can boot in 800 ms, let it boot in 800 ms.
|
||
|
||
---
|
||
|
||
# 43. Fast boot blacklist
|
||
|
||
Prohibited on the critical path:
|
||
|
||
```text
|
||
DHCP
|
||
DNS
|
||
NTP
|
||
sshd
|
||
Wi-Fi setup
|
||
Bluetooth setup
|
||
package updates
|
||
package verification
|
||
font cache generation
|
||
locale generation
|
||
s6-rc compilation
|
||
global udev settle
|
||
GUI login manager
|
||
Python
|
||
filesystem fsck for read-only root
|
||
persistent log flush
|
||
```
|
||
|
||
These activities must run:
|
||
|
||
```text
|
||
build time
|
||
on demand
|
||
or parallel after READY
|
||
```
|
||
|
||
---
|
||
|
||
# 44. Networking
|
||
|
||
network bundle:
|
||
|
||
```text
|
||
network
|
||
```
|
||
|
||
By default, it is not part of:
|
||
|
||
```text
|
||
boot
|
||
```
|
||
|
||
When an Ethernet cartridge is present or the user explicitly requests networking:
|
||
|
||
```text
|
||
s6-rc change +network
|
||
```
|
||
|
||
DHCP must never delay the appearance of:
|
||
|
||
```text
|
||
FDS>
|
||
```
|
||
|
||
The prompt must remain independent of DHCP.
|
||
|
||
---
|
||
|
||
# 45. Logging
|
||
|
||
Normal logging location:
|
||
|
||
```text
|
||
/run/log
|
||
```
|
||
|
||
tmpfs.
|
||
|
||
Persist only:
|
||
|
||
```text
|
||
important errors
|
||
explicit debug captures
|
||
boot performance
|
||
```
|
||
|
||
Do not persist tens of megabytes of journal data as a server distribution might.
|
||
|
||
FDS does not use a journal service.
|
||
|
||
This is intentional.
|
||
|
||
---
|
||
|
||
# 46. Shutdown
|
||
|
||
Provide:
|
||
|
||
```text
|
||
fds poweroff
|
||
```
|
||
|
||
Sequence:
|
||
|
||
```text
|
||
freeze new cartridge operations
|
||
↓
|
||
stop GUI
|
||
↓
|
||
stop program services
|
||
↓
|
||
stop network
|
||
↓
|
||
sync DATA filesystems
|
||
↓
|
||
unmount DATA
|
||
↓
|
||
stop remaining services
|
||
↓
|
||
poweroff
|
||
```
|
||
|
||
SYSTEM root:
|
||
|
||
```text
|
||
read-only
|
||
```
|
||
|
||
It therefore does not need to wait for journal writes to SYSTEM.
|
||
|
||
---
|
||
|
||
# 47. Shutdown performance
|
||
|
||
Target:
|
||
|
||
```text
|
||
idle poweroff:
|
||
< 1 second target
|
||
|
||
normal writable DATA:
|
||
< 1.5 seconds target
|
||
```
|
||
|
||
Do not use:
|
||
|
||
```text
|
||
sleep 5
|
||
```
|
||
|
||
to wait for daemons.
|
||
|
||
s6 must base shutdown on actual process exit and readiness.
|
||
|
||
---
|
||
|
||
# 48. Eject semantics
|
||
|
||
Users cannot safely unplug writable DATA without ejecting it first.
|
||
|
||
Command:
|
||
|
||
```text
|
||
fds eject 02
|
||
```
|
||
|
||
Behavior:
|
||
|
||
```text
|
||
identify dependent programs
|
||
↓
|
||
stop them
|
||
↓
|
||
syncfs()
|
||
↓
|
||
unmount
|
||
↓
|
||
mark SAFE
|
||
```
|
||
|
||
Output:
|
||
|
||
```text
|
||
BAY 02
|
||
|
||
DATA CARTRIDGE FELIS
|
||
|
||
SAFE TO REMOVE
|
||
```
|
||
|
||
A physical LED or eject mechanism may be integrated later.
|
||
|
||
---
|
||
|
||
# 49. Recovery environment
|
||
|
||
FDS_RECOVERY must not depend on a SYSTEM cartridge.
|
||
|
||
Include at least:
|
||
|
||
```text
|
||
bash
|
||
GNU coreutils
|
||
util-linux
|
||
filesystem tools
|
||
XBPS tools
|
||
|
||
fds
|
||
fds-burn
|
||
fds-inspect
|
||
```
|
||
|
||
FDS tools in recovery remain static-musl binaries.
|
||
|
||
Recovery supports:
|
||
|
||
```text
|
||
inspect SYSTEM
|
||
burn SYSTEM
|
||
repair DATA
|
||
diagnose USB bays
|
||
inspect boot log
|
||
```
|
||
|
||
---
|
||
|
||
# 50. Security
|
||
|
||
Strictly prohibited:
|
||
|
||
```text
|
||
/FDS/autorun.sh
|
||
```
|
||
|
||
executed automatically as root when a cartridge is inserted.
|
||
|
||
Cartridge manifests must be declarative.
|
||
|
||
For example:
|
||
|
||
```text
|
||
profile = "windowmaker"
|
||
```
|
||
|
||
Instead of:
|
||
|
||
```text
|
||
run = "/media/card/haha.sh"
|
||
```
|
||
|
||
PROGRAM cartridges run with ordinary user privileges by default.
|
||
|
||
---
|
||
|
||
# 51. Initial boot UI
|
||
|
||
Production boot should suppress Linux kernel console noise.
|
||
|
||
Display:
|
||
|
||
```text
|
||
FELIS DATA SYSTEMS
|
||
PORTABLE COMPUTER FP-85
|
||
|
||
FDS BOOT ROM 0.1
|
||
|
||
MEMORY ........ READY
|
||
SYSTEM ........ FDS/OS 0.1
|
||
CARTRIDGE BUS . READY
|
||
|
||
READY.
|
||
_
|
||
```
|
||
|
||
However:
|
||
|
||
**Do not delay startup to display these lines one at a time.**
|
||
|
||
A single repaint is sufficient.
|
||
|
||
A retro appearance does not require a four-second delay.
|
||
|
||
---
|
||
|
||
# 52. Development SYSTEM cartridge
|
||
|
||
The development profile may include a large toolset:
|
||
|
||
```text
|
||
gcc
|
||
clang
|
||
binutils
|
||
make
|
||
cmake
|
||
meson
|
||
ninja
|
||
pkg-config
|
||
|
||
rust
|
||
cargo
|
||
|
||
git
|
||
gdb
|
||
strace
|
||
perf
|
||
|
||
vim/neovim
|
||
```
|
||
|
||
Provided that these tools:
|
||
|
||
```text
|
||
do not start daemons
|
||
```
|
||
|
||
they should not significantly slow boot.
|
||
|
||
Disk usage is not boot latency.
|
||
|
||
---
|
||
|
||
# 53. Milestone M0 — Host build environment
|
||
|
||
Implement:
|
||
|
||
```text
|
||
repo skeleton
|
||
pin void-packages
|
||
install/use XBPS host tools
|
||
xbps-src bootstrap
|
||
aarch64 cross toolchain
|
||
Rust musl target
|
||
```
|
||
|
||
Acceptance:
|
||
|
||
On the x86_64 Framework, it must be possible to:
|
||
|
||
```text
|
||
build aarch64 package
|
||
build static-musl hello-world
|
||
```
|
||
|
||
Verify that the executable is static.
|
||
|
||
---
|
||
|
||
# 54. M1 — FDS base rootfs
|
||
|
||
Implement:
|
||
|
||
```text
|
||
fds-base
|
||
fds-base-files
|
||
glibc system
|
||
GNU userland
|
||
XBPS
|
||
```
|
||
|
||
Acceptance:
|
||
|
||
Generate:
|
||
|
||
```text
|
||
out/rootfs-aarch64.tar
|
||
```
|
||
|
||
Verify:
|
||
|
||
```text
|
||
glibc present
|
||
GNU coreutils present
|
||
GNU binutils present
|
||
|
||
musl runtime package not required
|
||
BusyBox absent
|
||
systemd absent
|
||
runit absent
|
||
```
|
||
|
||
---
|
||
|
||
# 55. M2 — Native s6
|
||
|
||
Implement the complete stack:
|
||
|
||
```text
|
||
s6-linux-init
|
||
s6-svscan
|
||
s6-rc
|
||
```
|
||
|
||
Acceptance:
|
||
|
||
In the booted rootfs:
|
||
|
||
```text
|
||
PID1 belongs to s6 architecture
|
||
```
|
||
|
||
Also verify that:
|
||
|
||
```text
|
||
s6-rc change
|
||
```
|
||
|
||
can control a test service.
|
||
|
||
---
|
||
|
||
# 56. M3 — static-musl FDS tooling
|
||
|
||
Implement:
|
||
|
||
```text
|
||
fds-common
|
||
fds CLI skeleton
|
||
fds-stage0 skeleton
|
||
```
|
||
|
||
All components use:
|
||
|
||
```text
|
||
Rust
|
||
aarch64-unknown-linux-musl
|
||
static
|
||
```
|
||
|
||
Acceptance:
|
||
|
||
```text
|
||
readelf
|
||
file
|
||
ldd
|
||
```
|
||
|
||
must demonstrate the absence of a glibc runtime dependency.
|
||
|
||
---
|
||
|
||
# 57. M4 — Pi boot
|
||
|
||
Implement:
|
||
|
||
```text
|
||
FDS_BOOT
|
||
kernel
|
||
initramfs
|
||
fds-stage0
|
||
SYSTEM EROFS
|
||
switch_root
|
||
s6
|
||
```
|
||
|
||
Acceptance:
|
||
|
||
Pi:
|
||
|
||
```text
|
||
power on
|
||
↓
|
||
internal NVMe kernel
|
||
↓
|
||
USB SYSTEM cartridge
|
||
↓
|
||
FDS>
|
||
```
|
||
|
||
---
|
||
|
||
# 58. M5 — Fast CLI
|
||
|
||
Optimize:
|
||
|
||
```text
|
||
firmware
|
||
kernel
|
||
initramfs
|
||
stage0
|
||
s6 graph
|
||
getty
|
||
shell startup
|
||
```
|
||
|
||
Acceptance:
|
||
|
||
```text
|
||
kernel → FDS> <2 sec
|
||
```
|
||
|
||
Create the first measured version of:
|
||
|
||
```text
|
||
docs/performance.md
|
||
```
|
||
|
||
---
|
||
|
||
# 59. M6 — Cartridge daemon
|
||
|
||
Implement:
|
||
|
||
```text
|
||
udev/netlink events
|
||
hub discovery
|
||
12 bay topology
|
||
metadata
|
||
mounting
|
||
eject
|
||
```
|
||
|
||
Acceptance:
|
||
|
||
With 12 USB devices inserted simultaneously:
|
||
|
||
```text
|
||
every device maps to the correct physical BAY
|
||
```
|
||
|
||
---
|
||
|
||
# 60. M7 — DATA cartridge
|
||
|
||
Implement:
|
||
|
||
```text
|
||
mount
|
||
home/data integration
|
||
safe eject
|
||
```
|
||
|
||
Acceptance:
|
||
|
||
After a sustained write test:
|
||
|
||
```text
|
||
fds eject
|
||
```
|
||
|
||
must leave the filesystem clean.
|
||
|
||
---
|
||
|
||
# 61. M8 — WindowMaker
|
||
|
||
Implement:
|
||
|
||
```text
|
||
Xorg
|
||
WindowMaker
|
||
E-Ink theme
|
||
environment profile
|
||
```
|
||
|
||
Acceptance:
|
||
|
||
On insertion of an ENVIRONMENT cartridge:
|
||
|
||
```text
|
||
CLI → WindowMaker
|
||
```
|
||
|
||
On cartridge removal or profile deactivation:
|
||
|
||
```text
|
||
WindowMaker → CLI
|
||
```
|
||
|
||
No reboot is required.
|
||
|
||
---
|
||
|
||
# 62. M9 — Cartridge image tools
|
||
|
||
Implement:
|
||
|
||
```text
|
||
fds burn
|
||
fds inspect
|
||
fds format
|
||
```
|
||
|
||
Acceptance:
|
||
|
||
The machine itself can create:
|
||
|
||
```text
|
||
SYSTEM
|
||
DATA
|
||
PROGRAM
|
||
ENVIRONMENT
|
||
```
|
||
|
||
cartridge.
|
||
|
||
---
|
||
|
||
# 63. M10 — Shutdown optimisation
|
||
|
||
Complete:
|
||
|
||
```text
|
||
service stop graph
|
||
DATA sync
|
||
DATA unmount
|
||
fast halt
|
||
```
|
||
|
||
Acceptance:
|
||
|
||
```text
|
||
idle shutdown <1s target
|
||
normal shutdown <1.5s target
|
||
```
|
||
|
||
Filesystem corruption is unacceptable.
|
||
|
||
---
|
||
|
||
# 64. M11 — 12-device stress testing
|
||
|
||
Hardware:
|
||
|
||
```text
|
||
12 USB devices
|
||
```
|
||
|
||
Test:
|
||
|
||
```text
|
||
cold boot
|
||
hot insert
|
||
hot remove
|
||
simultaneous enumeration
|
||
simultaneous IO
|
||
reboot
|
||
shutdown
|
||
```
|
||
|
||
Check:
|
||
|
||
```text
|
||
bay mapping stability
|
||
USB resets
|
||
kernel errors
|
||
boot regression
|
||
power issues
|
||
```
|
||
|
||
---
|
||
|
||
# 65. M12 — Production hardening
|
||
|
||
Complete:
|
||
|
||
```text
|
||
release signing
|
||
image versioning
|
||
package pinning
|
||
reproducible build work
|
||
recovery
|
||
documentation
|
||
production EEPROM config
|
||
```
|
||
|
||
Release:
|
||
|
||
```text
|
||
FDS/OS 0.1
|
||
```
|
||
|
||
---
|
||
|
||
# 66. Codex implementation rules
|
||
|
||
Codex must follow these rules:
|
||
|
||
1. Implement only the current milestone at a time.
|
||
2. Do not implement later features ahead of schedule.
|
||
3. Keep the repository buildable at every milestone.
|
||
4. Default every custom FDS binary to static musl.
|
||
5. Keep general userspace on glibc.
|
||
6. Do not introduce systemd.
|
||
7. Do not introduce runit.
|
||
8. Do not use BusyBox to implement early userspace.
|
||
9. Do not use `sleep` to hide races.
|
||
10. Do not let networking block the console.
|
||
11. Do not generate caches during boot when they can be generated at build time.
|
||
12. Do not depend on `/dev/sdX` ordering.
|
||
13. Do not automatically execute arbitrary root scripts from cartridge contents.
|
||
14. Explain the necessity of each new dependency.
|
||
15. Support every boot optimization with benchmarks.
|
||
16. Support x86_64 to aarch64 cross builds for all FDS packages wherever practical.
|
||
17. Use native Pi builds only as a documented fallback.
|
||
18. Keep documentation synchronized with the implementation.
|
||
|
||
---
|
||
|
||
# 67. First Codex task
|
||
|
||
Implement only M0 now.
|
||
|
||
Specific requirements:
|
||
|
||
```text
|
||
A. Create the repository skeleton.
|
||
|
||
B. Add vendor/void-packages,
|
||
pinned to a specific commit.
|
||
|
||
C. Write tools/bootstrap-host,
|
||
supporting Arch Linux x86_64.
|
||
|
||
D. Verify the static XBPS host tools.
|
||
|
||
E. bootstrap xbps-src build environment.
|
||
|
||
F. Verify:
|
||
|
||
./xbps-src -a aarch64 pkg <simple-package>
|
||
|
||
G. Initialize the Rust workspace.
|
||
|
||
H. Configure:
|
||
|
||
aarch64-unknown-linux-musl
|
||
|
||
I. Build:
|
||
|
||
rust/fds-smoketest
|
||
|
||
J. Verify:
|
||
|
||
- architecture = AArch64
|
||
- static executable
|
||
- no glibc dependency
|
||
|
||
K. Provide:
|
||
|
||
make bootstrap
|
||
make smoke-test
|
||
|
||
L. Create docs/build-host.md,
|
||
accurately documenting all dependencies and commands.
|
||
|
||
M. Add automated checks that exit nonzero on failure.
|
||
|
||
N. Do not begin s6, kernel, GUI, or cartridge daemon implementation.
|
||
|
||
On completion, report:
|
||
|
||
1. changed files
|
||
2. exact build commands
|
||
3. smoke-test output
|
||
4. known limitations
|
||
5. next milestone proposal
|
||
```
|
||
|
||
The original M0 gate above has been satisfied. The user explicitly authorized
|
||
M1; its workflow and evidence are in [M1 rootfs](rootfs.md) and
|
||
[M1 validation](m1-validation.md). The user subsequently authorized M2; see [Native init](init.md).
|
||
The user subsequently authorized implementation through M12, with physical Pi
|
||
testing deferred. The implementation ledger above records the current evidence
|
||
and remaining work.
|