# FDS/OS — Felis Data Systems Operating System FDS/OS is an operating system project for the **Felis FP-85**, a planned retro portable computer built around a Raspberry Pi 5, a Dasung Paperlike 13K grayscale E-Ink display, a removable battery, and 12 USB cartridge bays. The idea is to make the computer's software and data removable. A **SYSTEM** cartridge carries the operating system, a **DATA** cartridge carries the user's files, and **PROGRAM** or **ENVIRONMENT** cartridges add applications or select an environment such as WindowMaker. The internal NVMe holds the boot machinery, recovery environment, and machine configuration. Swapping a SYSTEM cartridge is the intended update and rollback mechanism. The project aims to combine familiar Linux software with fast, predictable startup and shutdown. It uses the Void/XBPS package ecosystem for ordinary Linux applications, uses native s6 service management, and builds FDS-owned system tools as small, self-contained Rust executables. ## What you can use today **M0–M12 software acceptance is complete, including a signed local FDS/OS 0.1.0 release.** Current development also adds [Linux workstation software cartridges and a QEMU emulator](docs/workstation.md). These changes are separate from the frozen 0.1.0 release. Physical Pi testing is deferred; see the [implementation ledger](docs/implementation-status.md). The cross-build environment is implemented and verified on x86_64 Arch Linux. You can build and inspect ARM Linux software from your Arch machine without owning a Pi. | Available now | What it gives you | | --- | --- | | `out/fds-os-0.1.0/` | Signed local images, preserved source/build inputs and independent-build comparison; start with its `README.md` | | `make workstation` | Native Linux `fds-cartridge` and `fds-emulator`: build xz bundles, create/verify 1+m GPT images, preview USB writes, and hotplug images into twelve virtual bays | | `make bootstrap` | Project-local XBPS tools, a Void build container, and the pinned Rust toolchain | | `make all` / `make packages` | The complete image set, or just the FDS base packages; see [Complete builds](docs/reproducible-builds.md#prepare-the-snapshot) | | `make smoke-test` | An ARM glibc XBPS package and an ARM static-musl Rust executable, with automated checks | | `make check` | Checks for invalid binaries, source pin drift, unsafe overlay replacement, and Rust formatting | | `make tooling` / `make tooling-test` | Static ARM `fds` and stage0 diagnostic tools, with parsing/discovery tests | | `make dasung` / `make dasung-test` | Static ARM monitor daemon, base XBPS package, s6 definitions, and simulated monitor tests | | `make rootfs PROFILE=cli` / `make rootfs-test` | Configured ARM rootfs archive, emulated shell access, and archive acceptance checks | | `make init-test` / `make vm` | Full ARM boot test, native s6 PID 1, service control, and a temporary development shell | | `make kernel`, `make initramfs`, `make system-card`, `make boot-volume` | Pi kernel, early userspace, GPT/EROFS SYSTEM and FAT32 boot partition; see [Boot images](docs/boot.md) | | `make boot-test` | Actual stage0 handoff, missing-media insertion, recovery and archive-format checks in an ARM VM | | `make console-vm`, `make console-test`, `make performance-test` | Ordinary-user FDS console, boot tracing and measured VM optimization comparison; see [M5 evidence](docs/m5-validation.md) | | `make cartridge-test` | Virtual USB bay mapping, hardware recognition, metadata/mount rejection checks and safe read-only eject | | `make data-test` | Writable `/data`, managed background programs, sustained writes, safe eject and independent ext4 checks; see [DATA usage](docs/data.md) | | `make rootfs PROFILE=development` / `make desktop-test` | WindowMaker, grayscale styling, trusted ENVIRONMENT activation, managed PROGRAM execution and on-demand Ethernet; see [Desktop usage](docs/desktop.md) | | `make media-image-test` / `make media-test` | SYSTEM/DATA/ENVIRONMENT creation, legacy PROGRAM compatibility, confirmed writes, readback verification and boot of a newly written SYSTEM; see [Media tools](docs/media-tools.md) | | `make recovery` / `make recovery-test` | Separate recovery rootfs and EROFS, local maintenance console, DATA checks/repairs and replacement SYSTEM workflow; software checks passed, see [Recovery](docs/recovery.md) | | `make internal-image` / `make internal-test` | Complete internal GPT image and persistent bay/hardware settings; see [Internal storage](docs/internal-storage.md) | | `make development-test` | Native C/C++/Rust builds, debuggers, build systems, Git and Vim inside the ARM development image | | `make signing` / `make signing-test` | Host and ARM release signing/verification tools, checked independently against OpenSSL | | `make eeprom` / `make eeprom-test` | Reversible, verified EEPROM configuration files without applying anything to hardware; see [EEPROM](docs/eeprom.md) | | Source pinning and input records | A fixed Void source commit plus logs and hashes of the actual build inputs | **The kernel → stage0 → SYSTEM → s6 path boots in an ARM virtual machine.** The filesystem includes native s6 init, runtime mounts, console and device services, and Dasung supervision. The ordinary-user FDS console and boot tracing are available. M6 adds the cartridge daemon and `fds bays`, `fds bay`, `fds cartridge`, and `fds eject`; see [Cartridge usage](docs/cartridges.md). The complete internal NVMe image and independent recovery are implemented; [release signature tooling](docs/releases.md) has passed host and ARM checks. [Frozen inputs, offline rebuilds and complete release assembly](docs/reproducible-builds.md) passed two independent offline builds with all 27 artifacts identical. The local release is at `out/fds-os-0.1.0/`; [M12 validation](docs/m12-validation.md#final-local-release-acceptance) records the signing identity, verification commands and exact evidence. M10's `fds poweroff` and `fds reboot` have passed software validation; see [Shutdown usage](docs/power.md). The `fds` tool also provides identity, boot tracing and manifest inspection; see [Rust tooling](docs/tooling.md). See the [roadmap](docs/roadmap.md). ## Start here - **I want to build software cartridges or try virtual insertion/removal:** follow the [workstation walkthrough](docs/workstation.md). - **I want to understand the project:** read [Architecture](docs/architecture.md). - **I want to try the working code:** follow [Your first build](docs/getting-started.md). - **I want to build the OS filesystem:** follow [Rootfs](docs/rootfs.md). - **I want to boot it and control services:** follow [Native init and ARM VM](docs/init.md). - **I want to build the Pi boot files and SYSTEM image:** follow [Boot images](docs/boot.md). - **I want to use the desktop, applications or Ethernet:** follow [Desktop usage](docs/desktop.md). - **I want to create or write a cartridge:** follow [Media tools](docs/media-tools.md). - **I want persistent bay settings and an internal NVMe image:** follow [Internal storage](docs/internal-storage.md). - **SYSTEM will not boot, or DATA needs checking:** follow [Recovery](docs/recovery.md). - **I have already built it and want to develop:** use the [Development guide](docs/development.md). - **A command failed:** look up its message in [Troubleshooting](docs/troubleshooting.md). - **I do not know the terminology:** keep the [Glossary](docs/glossary.md) open. The [documentation index](docs/README.md) organizes the remaining guides. The [master plan](docs/master-plan.md) is the full specification, rather than the recommended starting point for learning to use the repository. ## Quick start: software cartridges and emulation On a Linux workstation, build the native tools with `make workstation`, then follow [the complete walkthrough](docs/workstation.md) to package the included hello/report examples, assemble a cartridge, boot FDS and insert it. This tooling uses normal Linux QEMU, EROFS and xz utilities; it does not run on the Pi. Building the complete OS images still uses the environment below. ## Quick start on Arch Linux You need an **x86_64 Arch Linux host**, a regular user account with access to sudo for installing prerequisites, a network connection, and several GB of free disk space. The kernel must permit unprivileged user namespaces. A Pi, Docker, and a separate musl C compiler are not required for the current smoketest. Use a checkout path without spaces. In the current workspace: ```sh cd /home/felis/source/fds ``` On another machine, enter your own FDS checkout directory instead. Use an actual Git checkout so the pinned Void submodule can be initialized for a normal online build. A complete [frozen-input snapshot](docs/reproducible-builds.md) instead restores the source and its bundled Void checkout for offline building; a bare source archive alone does not supply those inputs. This repository does not currently configure a public Git remote, so no public clone URL is assumed here. Install the prerequisites once: ```sh sudo pacman -S --needed bash coreutils binutils git curl make file tar xz gzip zstd \ bubblewrap rustup ca-certificates findutils diffutils grep sed gawk util-linux ``` Then run these commands **in order, as your regular user**: ```sh make bootstrap make smoke-test make check ``` `make bootstrap` downloads and prepares the build tools. `make smoke-test` compiles the two ARM artifacts and verifies their architectures and library requirements. `make check` exercises the validation failure cases and checks formatting. If a command fails, stop at that step and use the linked [troubleshooting guide](docs/troubleshooting.md); a partially completed run is not a successful build. The first run downloads hundreds of MB of compiler and build dependencies and may take a while on a slow connection. Later runs reuse caches, although XBPS operations may still access the network. `cargo --offline` applies only to Rust crate downloads, not to the whole pipeline. Successful smoke-test output ends with: ```text PASS: aarch64 static ELF ... PASS: XBPS package hello-2.12.3_1 architecture=aarch64 (glibc) SKIP: ARM execution (optional qemu-aarch64 not installed); ELF verification passed PASS: M0 smoke test complete ``` The QEMU line is a documented optional skip. If QEMU is installed, a runtime PASS replaces it. The [first-build guide](docs/getting-started.md) explains how to run the executable with QEMU and interpret every result. To build the current OS filesystem and boot its development VM, continue with: ```sh sudo pacman -S --needed python e2fsprogs libarchive lz4 make rootfs PROFILE=cli make rootfs-test make init-test make vm ``` Python must be version 3.14 or newer. Additional emulation tools are installed inside the project-local build container. `make init-test` boots ARM Linux, checks native init and service control, and powers off. `make vm` repeats those checks and opens a temporary root shell; type `exit` to shut it down. Nothing is flashed to a physical disk. The [VM guide](docs/init.md) explains the console, service commands, logs, and limits in detail. To build the complete operating-system image set and try its ordinary user console, continue from that prepared workstation: The complete images require substantially more space than the initial smoke test: the offline diagnostic build occupied about 24 GB, before additional VM test copies. See [build-space observations](docs/reproducible-builds.md#what-is-frozen) before preparing two independent release builds. ```sh make all make init-test make boot-test make console-vm ``` `make all` builds CLI and development SYSTEM cartridges, independent recovery and the internal disk. `make init-test` prepares the full QEMU environment and checks native init. `make boot-test` checks startup, missing-media recovery and all initramfs formats. `make console-vm` opens the actual `FDS>` console. Enter these commands **inside that console**: ```sh fds info fds bays fds boot-profile fds poweroff ``` This VM has no physical USB devices attached, so empty cartridge bays are expected. Its home directory is temporary; use a DATA cartridge for persistent files on the real machine. `fds poweroff` performs an orderly shutdown. The [boot guide](docs/boot.md#use-the-ordinary-fds-console) explains console controls, and the [internal-storage guide](docs/internal-storage.md) covers physical installation when the Pi hardware is ready. ## Dasung monitor support The existing Rust `dasungd` from the monitor troubleshooting task is integrated as a required base-system package, with a native s6 boot service. Build it with `make dasung`, then run `make dasung-test`. The [Dasung guide](docs/dasung.md) explains the exact monitor profile, dependencies, configuration, and Pi validation still needed. M2 starts the controller under native s6 in the ARM VM; the VM has no physical monitor. ## What the build produces | Path | Contents | How to use it | | --- | --- | --- | | `out/fds-internal.img` | Complete GPT disk with BOOT, independent RECOVERY and persistent machine-settings partitions | Use the [internal installation procedure](docs/internal-storage.md); this belongs on the internal NVMe | | `out/fds-system-cli.img` | Immutable CLI SYSTEM cartridge, including base Dasung support | Build with `make system-card PROFILE=cli`; use the [media writer](docs/media-tools.md) to write a SYSTEM cartridge | | `out/fds-system-development.img` | SYSTEM with native compilers, debugging tools and the optional desktop runtime | Build with `make rootfs PROFILE=development` followed by `make system-card PROFILE=development` | | `out/fds-boot.img` / `out/fds-recovery.img` | Individual FAT32 BOOT and EROFS RECOVERY partition payloads | Normally use the complete internal image; these are component images, not interchangeable whole disks | | `out/fds-initramfs.img` | Early boot program and base display support | Included in BOOT; four compressed/uncompressed formats are also under `out/initramfs/` | | `out/rootfs-aarch64.tar` | Configured ARM glibc userspace, including Dasung | Follow [M1 rootfs](docs/rootfs.md) to build, inspect, and run it | | `out/m2-vm-latest/` | Last successful ARM test disk, serial log, environment and hashes | Use `make vm` to boot it; see [Native init](docs/init.md) | | `out/fds-smoketest` | Static-musl AArch64 Rust executable | Inspect with `file`/`readelf`; optionally run with `qemu-aarch64` | | `out/packages/hello-2.12.3_1.aarch64.xbps` | GNU hello packaged for ARM glibc | Query or extract it with the [package guide](docs/packages.md) | | `out/packages/aarch64-repodata` | Local package index | Lets XBPS query the exported package | | `out/logs/` | Bootstrap and build logs | Diagnose a failed or apparently stalled step | | `out/manifests/` | Package inventories and SHA-256 digests | Inspect which inputs and outputs were used | `make all` produces the complete image set above in order. It prepares files and does not write physical disks. Build and test commands share a build container; run them sequentially. Stable paths point to the latest successful versioned build directories. See [Offline rebuilds](docs/reproducible-builds.md) for the separate frozen-input and release-verification workflow. The rootfs tar and individual binaries are not flashable Pi images. The separate VM disk boots with the generic ARM test kernel. The Rust executable is ARM code and normally cannot run directly on the x86_64 host. The XBPS package is not an Arch package and is not installed with pacman. ## How the build relates to the future machine ```text Working today: x86_64 Arch workstation ├─ pinned Void + xbps-src + GNU cross compiler → aarch64 glibc package └─ pinned Rust + bundled musl + rust-lld → static AArch64 executable Pi boot path, software-tested in a VM; physical validation pending: internal NVMe kernel/initramfs → SYSTEM cartridge → native s6 → FDS console ``` The first line supplies conventional Linux packages. The second supplies FDS's own control tools without a dependency on the installed glibc version. Both produce ARM code; only their library/linking strategy differs. See [the architecture guide](docs/architecture.md#two-library-strategies). ## Where to find things | Directory or file | Purpose today | | --- | --- | | `rust/fds-smoketest/`, `rust/dasungd/`, `rust/fds-common/`, `rust/fds-cli/`, `rust/fds-stage0/` | Static-linking smoketest, monitor controller, shared contracts, CLI and early boot | | `tools/` | Bootstrap, package build, overlay preparation, and ELF checks | | `config/` | Pinned host tool download and Void build configuration | | `vendor/void-packages/` | Unmodified upstream source at the recorded commit | | `tests/integration/m0-checks` | Executable validation and protection checks | | `docs/` | Tutorials, design explanations, references, and validation evidence | | `packages/fds-dasungd/`, `s6/source/`, `image/base-packages.list` | Monitor package, native service definitions, and mandatory base inclusion | | `packages/fds-base/`, `packages/fds-base-files/`, `packages/fds-init/` | Base dependencies, identity, accounts, layout and native init | | `packages/fds-kernel/`, `packages/fds-cli/`, `image/` | Pi kernel delta, static CLI package and filesystem/boot builders | | `profiles/` | CLI, development and recovery package selections | | `rust/fds-release/`, `tools/frozen-inputs`, `tools/assemble-release` | Signature verification, input preservation and local release assembly | Generated `.host/`, `target/`, and `out/` contents are ignored by Git. Rustup also installs the pinned toolchain in your user account's Rustup directory. The [build reference](docs/build-host.md) details prerequisites, storage, and pins. ## Project status and evidence The [M0 validation report](docs/m0-validation.md) records the actual build commands, results, and initial artifact hashes. QEMU execution and Pi hardware were not validated in that initial run. Later milestones measured VM boot and shutdown; physical Pi performance remains unmeasured. Source and toolchain pins are in place, and the complete frozen-input/offline release workflow is undergoing M12 acceptance. See [current evidence](docs/m12-validation.md) for the distinction. The [M1 guide](docs/rootfs.md) explains rootfs usage; [M1 validation](docs/m1-validation.md) records the results. M2 usage is in [Native init and ARM VM](docs/init.md), with results in [M2 validation](docs/m2-validation.md). M3 adds [static-musl FDS tooling](docs/tooling.md). Work continues through M12 under [AGENTS.md](AGENTS.md), with physical hardware checks deferred. Project-owned source comments, documentation, diagnostics, and development discussions use English.