From ef88914454b46bf905cc2a37ce1e1f46af0539c6 Mon Sep 17 00:00:00 2001 From: Felis Date: Thu, 24 Sep 2026 14:41:41 +0800 Subject: [PATCH] Document interactive and unattended disk installation with fds-flash --- Developer-Build-Host.md | 4 +- Developer-Guide.md | 1 + Developer-Implementation-Status.md | 11 +- Developer-Internal-Storage.md | 96 +---------- Developer-Versioning.md | 2 +- Developer-Workstation-Tooling-Plan.md | 13 +- Developer-Workstation.md | 3 +- Flashing.md | 223 ++++++++++++++++++++++++++ Hardware-Setup.md | 34 ++-- Home.md | 1 + Internal-Storage.md | 90 +++-------- Overview.md | 4 +- Page-Index.md | 1 + Workstation.md | 37 ++--- _Sidebar.md | 1 + 15 files changed, 317 insertions(+), 204 deletions(-) create mode 100644 Flashing.md diff --git a/Developer-Build-Host.md b/Developer-Build-Host.md index eda7004..ab9738a 100644 --- a/Developer-Build-Host.md +++ b/Developer-Build-Host.md @@ -51,8 +51,8 @@ indexing also explicitly sets `XBPS_ARCH=aarch64`. ## Generic Linux workstation tools and desktop additions `make workstation` builds the Arch `fds-tools` package; `make workstation-install` -installs it with pacman. `make workstation-binaries` builds native `fds-cartridge` -and `fds-emulator` on generic Linux. Python 3 and Git resolve build versions; +installs it with pacman. `make workstation-binaries` builds native `fds-cartridge`, +`fds-emulator` and `fds-flash` on generic Linux. Python 3 and Git resolve build versions; Dasung builds install these tools in the project-local Void container as well. Runtime requirements are QEMU, erofs-utils, bubblewrap and native XBPS with a prepared Void source checkout for software creation. `fds-cartridge` invokes xbps-src, diff --git a/Developer-Guide.md b/Developer-Guide.md index 6ffbd94..b1875bb 100644 --- a/Developer-Guide.md +++ b/Developer-Guide.md @@ -14,6 +14,7 @@ the inputs named in those reports; a changed source tree needs fresh checks. ## Design and build references +- [Workstation disk flashing](Flashing) - [Editing the Gitea wiki](Gitea-Wiki) - [Clean upstream and writable Void workspace](Developer-Void-Workspace) diff --git a/Developer-Implementation-Status.md b/Developer-Implementation-Status.md index bb51582..875933d 100644 --- a/Developer-Implementation-Status.md +++ b/Developer-Implementation-Status.md @@ -28,11 +28,12 @@ own strict format parsers; they are not process argument parsers. ## Workstation software and emulator extension Current sources extend the frozen 0.1.0 checkpoint with native Linux -`fds-cartridge` and `fds-emulator` tools. The software format uses metadata plus -`m` payload partitions containing xz tarballs. Software builds and complete -image creation run on the workstation; the guest verifies, extracts and runs -selected commands as UID 1000. See [usage](Developer-Workstation), -[format](Developer-Software-Format), and [current acceptance](Developer-Workstation-Validation). +`fds-cartridge`, `fds-emulator` and `fds-flash` tools. The current software format +uses metadata plus `m` EROFS payload partitions containing installed Void package +trees. Software builds and image creation run on the workstation; the guest +verifies and executes those trees directly as UID 1000. Legacy archive readers +remain available. See [usage](Workstation), [format](Software-Format), +[disk installation](Flashing), and [cartridge/desktop acceptance](Developer-Current-Revision). Historical M0–M12 and Clap reports describe their recorded artifacts; they do not by themselves validate these new sources. diff --git a/Developer-Internal-Storage.md b/Developer-Internal-Storage.md index 1534af3..1a37fc5 100644 --- a/Developer-Internal-Storage.md +++ b/Developer-Internal-Storage.md @@ -54,97 +54,13 @@ empty. The builder accepts ordinary image files, never a host block-device output. Final hardware provisioning and identity checks belong to the physical acceptance procedure; do not confuse a partition payload with the complete disk. -## Install the internal disk when hardware is available +## Install the internal disk -This is a **deferred physical procedure**. The image and virtual NVMe workflow -are software-tested; writing and booting the user's actual NVMe still require -the hardware. Installation erases the selected disk, including any existing -machine settings. Retain backups before replacing an existing installation. - -Use an NVMe enclosure or another Linux machine that can access the target drive -while the Pi is off. First verify a downloaded release using a separately trusted -public key as described in [Release signatures](Developer-Releases). Its complete disk -is named `fds-internal-0.1.0.img`; a local build uses `out/fds-internal.img`. -Use the complete disk image, not the separate BOOT or RECOVERY payload. - -List disks before and after connecting the intended drive: - -```sh -lsblk -d -o NAME,PATH,MODEL,SERIAL,SIZE,TRAN,LOG-SEC -ls -l /dev/disk/by-id/ -``` - -Match the physical model, serial and capacity. Choose a persistent **whole-disk** -`/dev/disk/by-id/` path without a `-partN` suffix; never guess a `/dev/sdX` name. -Unmount every target partition and disable any swap on it. Do not select the -workstation's system disk. The current images require 512-byte logical sectors -and a disk at least as large as the image; 4 KiB logical-sector media is not -supported by this layout. - -Open Bash (`bash`), replace both paths below, then run the block. It checks the -selected disk again, requires a typed confirmation, writes and reads back the -complete image, and relocates the backup GPT when the disk is larger than the -image. It does not expand any partition or filesystem. - -```bash -( - set -euo pipefail - fds_image="$PWD/out/fds-internal.img" - fds_disk=/dev/disk/by-id/REPLACE_WITH_THE_TARGET_DISK - [[ -f "$fds_image" && -s "$fds_image" && -b "$fds_disk" ]] - [[ $(lsblk -dnro TYPE "$fds_disk") == disk ]] - [[ $(sudo blockdev --getss "$fds_disk") == 512 ]] - fds_bytes=$(stat -Lc %s "$fds_image") - (( $(sudo blockdev --getsize64 "$fds_disk") >= fds_bytes )) - lsblk -p -o NAME,TYPE,MODEL,SERIAL,SIZE,MOUNTPOINTS "$fds_disk" - if lsblk -nrpo MOUNTPOINTS "$fds_disk" | grep '[^[:space:]]' >/dev/null; then - echo 'Target has mounted filesystems or swap; stop and release them first.' >&2 - exit 1 - fi - if lsblk -nrpo TYPE "$fds_disk" | grep -Ev '^(disk|part)$' >/dev/null; then - echo 'Target has device-mapper or other active descendants; stop.' >&2 - exit 1 - fi - read -r -p "Type ERASE $fds_disk to erase this disk: " fds_confirmation - [[ "$fds_confirmation" == "ERASE $fds_disk" ]] - sudo dd if="$fds_image" of="$fds_disk" bs=4M conv=fsync status=progress - sudo blockdev --flushbufs "$fds_disk" - sudo cmp -n "$fds_bytes" "$fds_image" "$fds_disk" - sudo sfdisk --lock=yes --relocate gpt-bak-std "$fds_disk" - sudo sfdisk --verify "$fds_disk" - sudo blockdev --flushbufs "$fds_disk" -) -``` - -Every command must succeed. The byte comparison occurs before relocating GPT, -because relocation intentionally changes disk-table headers. GNU `dd`'s `fsync` -flushes output before it returns; `sfdisk`'s `gpt-bak-std` moves the backup header -to the end of the target. See the [GNU dd manual](https://www.gnu.org/s/coreutils/manual/html_node/dd-invocation.html) -and [sfdisk manual](https://man7.org/linux/man-pages/man8/sfdisk.8.html). -These commands use the already documented coreutils, diffutils and util-linux -host tools; they do not add a target daemon. - -Confirm that the disk shows `FDS_BOOT`, `FDS_RECOVERY` and `FDS_INTERNAL` in that -order using `lsblk -o NAME,PARTLABEL,FSTYPE,MOUNTPOINTS`. Unmount anything the -desktop automatically mounted, then safely disconnect the enclosure and install -the NVMe in the powered-off Pi. Follow [EEPROM preparation](Developer-EEPROM) for the -separately reviewed NVMe boot settings. - -Prepare the **first SYSTEM cartridge on the workstation** using the same guarded -write block, with its two path assignments changed to the chosen SYSTEM image -and a different, empty USB cartridge disk. For a local build select -`out/fds-system-cli.img` or `out/fds-system-development.img`; release files are -`fds-system-cli-0.1.0.img` and `fds-system-development-0.1.0.img`. They are -alternative complete GPT images, each containing one `FDS_SYSTEM` partition. -Readback and backup-GPT relocation apply to this disk too. Check its partition -label, safely disconnect it, and insert exactly one SYSTEM cartridge in the Pi -before normal boot. Subsequent cartridge creation and updates can use FDS's -confirmed [media workflow](Developer-Media-Tools) after bay calibration. - -On the first physical boot, check `fds info`, `fds machine status`, and -`fds bays`. The supplied bay map is empty until calibration. Follow -[physical acceptance](Developer-Stress-Testing) to measure ports, test the Dasung -display, and record actual boot/shutdown behavior before relying on the machine. +Current workstation installation uses [fds-flash](Flashing), with guided or +unattended operation, image/target validation, readback and backup-GPT relocation. +Follow [the installation commands](Internal-Storage#install-the-internal-disk). +Historical M12 acceptance describes the artifacts and procedures recorded then; +it does not validate this new workstation tool. ## Configure the machine before building diff --git a/Developer-Versioning.md b/Developer-Versioning.md index 563433f..f18f7a2 100644 --- a/Developer-Versioning.md +++ b/Developer-Versioning.md @@ -73,7 +73,7 @@ checks. `make workstation-test` exercises the installed-tree cartridge creator; `make emulator-test` covers stopping and starting the same directory, preserved logs/overlays/mappings, and rejecting a restart of a live VM. `make workstation-package-test` installs the real Arch package with pacman in a -disposable root and executes both installed commands. After building matching +disposable root and executes all three installed commands. After building matching images, `python3 tests/integration/version-images.py` reads the identity and metadata directly from the GPT/EROFS image and executes its twelve FDS commands under ARM emulation to compare their versions. Image acceptance diff --git a/Developer-Workstation-Tooling-Plan.md b/Developer-Workstation-Tooling-Plan.md index 09ab0cf..403c99b 100644 --- a/Developer-Workstation-Tooling-Plan.md +++ b/Developer-Workstation-Tooling-Plan.md @@ -5,8 +5,8 @@ include_toc: true # Workstation tooling plan The current source of requirements is [the active revision](Developer-Current-Revision). -The public tools remain native Linux Clap applications: `fds-cartridge` and -`fds-emulator`. Full OS cross builds keep their separate pinned Void environment. +The public tools remain native Linux Clap applications: `fds-cartridge`, `fds-emulator` and +`fds-flash`. Full OS cross builds keep their separate pinned Void environment. New software creation uses Void source templates and `xbps-src`. The image builder installs packages and dependencies on the workstation, verifies installed trees, @@ -31,3 +31,12 @@ The Arch distribution package is `fds-tools`, built by `make workstation` and installed by `make workstation-install`. `make workstation-binaries` preserves the generic Linux build. Stopped emulator directories support a fresh boot while retaining logs, DATA overlays and archived cartridge mappings. + +`fds-flash` installs complete internal and cartridge GPT images. Its interactive +mode requires terminal confirmation; unattended mode binds a specific image +SHA-256 and target identity. Installation includes exclusive block access, +readback, backup-GPT relocation and kernel partition refresh. The tool reuses +existing Rust dependencies; it does not invoke shell disk-writing commands. +See [flashing](Flashing) and validate with `make flash-test`, +`make flash-vm-test`, `make workstation-test`, `make emulator-test` and +`make workstation-package-test`. Physical-drive behavior remains a separate gate. diff --git a/Developer-Workstation.md b/Developer-Workstation.md index 28e999e..95b8ab0 100644 --- a/Developer-Workstation.md +++ b/Developer-Workstation.md @@ -16,7 +16,8 @@ source software to a cartridge disk image, runs that image in FDS, and explains how to write the same complete image to USB. All commands run from the checkout root unless marked as guest commands. -The two native host tools are `fds-cartridge` and `fds-emulator`. They use typed +The original native host tools are `fds-cartridge` and `fds-emulator`. The current +workstation package also includes [fds-flash](Flashing) for complete disk installation. All use typed Clap interfaces; append `--help` to any command or subcommand. The target's `fds` command remains a static AArch64 executable. The new host tools are never part of the Pi base image. Dasung support remains in the base boot bundle. diff --git a/Flashing.md b/Flashing.md new file mode 100644 index 0000000..99032de --- /dev/null +++ b/Flashing.md @@ -0,0 +1,223 @@ +--- +include_toc: true +--- + +# Flash disk images with fds-flash + +[Home](Home) · [Real hardware](Hardware-Setup) · [Workstation tools](Workstation) · [Release verification](Releases) + +`fds-flash` installs a complete FDS disk image from a Linux workstation. It has +an interactive guide and an unattended mode for scripts. It validates the image, +checks the destination, writes it, flushes it, reads the written bytes back, and +relocates the backup GPT automatically when the destination is larger. +You no longer need the manual `dd`, `cmp` and `sfdisk` installation sequence. + +## Install the tool + +From the OS checkout on Arch Linux: + +```sh +make workstation +make workstation-install +fds-flash --help +``` + +The `fds-tools` package includes `fds-flash`, `fds-cartridge` and `fds-emulator`. +For another Linux distribution, or to use the checkout without installing: + +```sh +make workstation-binaries +out/workstation/fds-flash --help +``` + +Build as an ordinary user. Only physical disk writes require root. The examples +below use the checkout binary; substitute `fds-flash` after package installation. +The flasher adds no crates or external runtime utilities: it uses the existing +Clap, serde/JSON, SHA-256 and libc dependencies plus Linux block-device APIs. +The Python commands in the scripting example only read saved JSON; Python is +not required by the installed flasher. + +## Choose the correct image + +| Image | Destination | +| --- | --- | +| `out/fds-internal.img` | Whole NVMe disk, normally connected through an enclosure | +| `out/fds-system-cli.img` | Whole USB SYSTEM cartridge | +| `out/fds-system-development.img` | Alternative SYSTEM cartridge with development tools | +| A complete PROGRAM, DATA or ENVIRONMENT `.img` | Its separate cartridge disk | + +Versioned release filenames are supported too. First verify downloaded releases +with a separately trusted key as described in [Release verification](Releases). +The flasher's SHA-256 check detects changed input; it does not authenticate a +publisher. PROGRAM images should also pass `fds-cartridge inspect` to check +software metadata and installed program trees before deployment. + +Use an uncompressed, complete FDS GPT disk image. The raw `fds-boot.img` and +`fds-recovery.img` partition payloads, compressed archives, arbitrary operating +system images and 4 KiB logical-sector destinations are rejected. A disk must +have 512-byte logical sectors and enough space for the complete image. + +## Interactive mode + +Keep the Pi powered off while preparing its NVMe. Connect only the intended +installation media, then launch the guide: + +```sh +sudo ./out/workstation/fds-flash +``` + +1. Enter the image's path. +2. Select a disk by its model, serial and capacity. Mounted or otherwise occupied + disks are marked **BLOCKED**. There is no default disk selection. +3. Review the image type, partitions, SHA-256, destination and target ID. +4. Type the exact `ERASE /dev/...` phrase shown. Any other response cancels. +5. Wait for `VERIFIED`. Errors or interruption return a nonzero exit status. + +You can provide either path in advance. With both supplied, the command still +shows the plan and requires terminal confirmation: + +```sh +sudo ./out/workstation/fds-flash \ + --image out/fds-internal.img \ + --device /dev/disk/by-id/REPLACE_WITH_THE_NVME_DISK +``` + +Replace the destination with the verified **whole-disk** path, without a +`-partN` suffix. The confirmation uses the resolved kernel path shown in the +review. Repeat for SYSTEM with its image and a different disk: + +```sh +sudo ./out/workstation/fds-flash \ + --image out/fds-system-cli.img \ + --device /dev/disk/by-id/REPLACE_WITH_THE_SYSTEM_DISK +``` + +Every confirmed write replaces the destination's partition table and the image +region. Reinstalling an internal disk also replaces its saved machine settings. +The tool does not automatically unmount filesystems, disable swap or select an +alternative disk. Release the intended disk yourself and rerun if it is blocked. + +## Inspect without writing + +List physical disks and reasons they are unavailable: + +```sh +out/workstation/fds-flash list +out/workstation/fds-flash list --json +``` + +To inspect an image and destination together, without opening the disk for writing: + +```sh +out/workstation/fds-flash \ + --image out/fds-internal.img \ + --device /dev/disk/by-id/REPLACE_WITH_THE_NVME_DISK \ + --dry-run --json >out/nvme-plan.json +``` + +Read the saved plan. `plan.target` contains model, serial, capacity, logical-sector +size, canonical device path, host boot ID and kernel insertion identity. `plan.target_id` +binds those fields together. `plan.sha256` identifies the complete source image. +After a host reboot, or if the device is reinserted, replaced, resized or otherwise changes identity, +obtain and review a new plan. + +## Unattended mode + +Unattended writes require all of `--image`, `--device`, `--expect-target` and +`--sha256`. There is no bare `--yes` that can silently accept a newly discovered +disk. Obtain the expected values from a reviewed dry run or from your controlled +provisioning inventory, then pass them explicitly: + +```sh +sudo -n ./out/workstation/fds-flash \ + --image out/fds-internal.img \ + --device /dev/disk/by-id/REPLACE_WITH_THE_NVME_DISK \ + --unattended \ + --expect-target TARGET_ID_FROM_THE_REVIEWED_PLAN \ + --sha256 EXPECTED_IMAGE_SHA256 \ + --json >out/nvme-flash.json +``` + +Replace both hash placeholders with their full 64 hexadecimal characters. +`sudo -n` refuses to ask for a password, so privileges must already be available. +A script already running as root can invoke the binary directly. The flasher +never prompts or invokes sudo in unattended mode. + +For an already reviewed `out/nvme-plan.json`, this complete shell example loads +the bindings without adding a JSON utility dependency: + +```sh +fds_target_id=$(python3 -c 'import json; print(json.load(open("out/nvme-plan.json"))["plan"]["target_id"])') +fds_sha256=$(python3 -c 'import json; print(json.load(open("out/nvme-plan.json"))["plan"]["sha256"])') +sudo -n ./out/workstation/fds-flash \ + --image out/fds-internal.img \ + --device /dev/disk/by-id/REPLACE_WITH_THE_NVME_DISK \ + --unattended --expect-target "$fds_target_id" --sha256 "$fds_sha256" \ + --json >out/nvme-flash.json +``` + +A successful JSON response has `status: "verified"`; a dry run has +`status: "dry_run"`. Progress and diagnostics go to stderr. Exit status 0 means +success for the requested operation; status 2 means an error, rejected input +or cancelled confirmation. Treat a killed/interrupted process as a failed flash +and reflash before using that disk. Check the process exit status before reading +an output file; failures may leave that redirected file empty. + +## What verification covers + +Before writing, the tool checks GPT headers and tables, partition bounds, expected +FDS labels/types, basic filesystem signatures, image size/hash and target identity. +It rejects partitions, virtual/loop/device-mapper destinations, mounted disks or +children, swap, kernel holders, read-only media and unsupported sector sizes. +The destination is opened exclusively and checked again through block-device +ioctls before the first write. A target replacement or changed source aborts. + +Readback compares the written image region and relocated backup GPT, after +flushing and invalidating the kernel block cache. Partition starts, sizes and +filesystem contents stay unchanged. Unallocated capacity is not expanded or +securely erased. Success also requires the kernel to reload the partition table. + +After an internal installation, check `FDS_BOOT`, `FDS_RECOVERY` and `FDS_INTERNAL` +with `lsblk -o NAME,PARTLABEL,FSTYPE,MOUNTPOINTS`. If udev is still processing +partition events, run `udevadm settle` before checking labels. SYSTEM should show +`FDS_SYSTEM`. +Unmount any filesystems the desktop mounted after completion, safely disconnect +the media, and continue with [first boot](Hardware-Setup#6-power-on-and-reach-the-console). + +## Disposable tests and hardware acceptance + +`--file-target` is only for existing disposable regular files, as an ordinary user. +It is never inferred from a path, and root use of this test mode is rejected. +`make flash-test` covers the public CLI, interactive terminal confirmation, +unattended bindings, cancellation, changed inputs, corruption, and exact/larger +destinations. `make flash-vm-test` also exercises block-device writes and failures +on isolated virtual NVMe/USB disks. These tests do not write host block devices. +`make clean` recognizes these generated test directories and retains their latest +recorded results. + +Physical acceptance remains separate: use a spare drive, record its model, +serial and logical-sector size, retain the dry-run and verified JSON plus image +hash, safely disconnect/reconnect it, and check its GPT and payloads independently. +Then perform the [real-hardware boot procedure](Hardware-Setup). Drive firmware +flush behavior, USB enclosure recovery and physical power-loss behavior remain +unverified until measured on that hardware. + +## Software validation record + +The 2026-09-24 run passed `make flash-vm-test`, including native CLI and transfer +unit tests, real pseudo-terminal interaction, disposable-file writes, inspection +of the current internal/SYSTEM build images, and isolated ARM NVMe/USB writes. +The VM checks covered the full wizard, unattended operation, kernel partition +refresh, reinstallation, mounted/partition/read-only/4 KiB rejection, USB +replacement, and injected write, flush and readback errors. These are software +and virtual-disk results; they do not establish physical durability. + +The existing workstation software-image tests, twelve-bay emulator lifecycle +checks and `make check` also passed. Source and binary hashes, the latest test +record paths and package-validation evidence are recorded locally in +`out/manifests/fds-flash-validation.json`. Detailed logs are in +`out/logs/flash-validation-final.log` and +`out/logs/flash-workstation-regression.log`. The existing frozen 0.1.0 release +was not modified. + +Linux interface reference: [kernel block-device ABI](https://www.kernel.org/doc/html/latest/admin-guide/abi-stable.html). diff --git a/Hardware-Setup.md b/Hardware-Setup.md index 7204287..4c77824 100644 --- a/Hardware-Setup.md +++ b/Hardware-Setup.md @@ -184,24 +184,30 @@ boot order until the rescue and normal boot paths have been checked. ## 5. Write the two disks -On the **workstation**, follow the complete -[guarded disk-writing procedure](Internal-Storage#install-the-internal-disk). -It includes disk identification by model/serial, an explicit erase confirmation, -readback, and backup-GPT relocation. Run it separately for these assignments: +On the **workstation**, build the native tools and run `fds-flash` once per disk: -| Pass | `fds_image` | `fds_disk` | -| --- | --- | --- | -| Internal disk | `$PWD/out/fds-internal.img` | The verified NVMe enclosure's whole-disk `/dev/disk/by-id/…` path | -| SYSTEM | `$PWD/out/fds-system-cli.img` | A different, verified USB cartridge's whole-disk `/dev/disk/by-id/…` path | +```sh +make workstation-binaries +sudo ./out/workstation/fds-flash --image out/fds-internal.img +sudo ./out/workstation/fds-flash --image out/fds-system-cli.img +``` -Both writes erase the selected disk. Follow all checks in that procedure; a -`-part1` path is not a whole-disk destination. The disks must use 512-byte logical -sectors and be at least as large as their respective images. +Each invocation lists disks by model, serial and capacity. Select the NVMe +enclosure for the internal image and a different USB disk for SYSTEM, review the +plan, and enter the displayed erase phrase. Both writes replace the selected +media. The tool refuses mounted/occupied disks and non-512-byte logical sectors; +it writes, flushes, verifies readback and relocates the backup GPT automatically. +Wait for `VERIFIED` before proceeding. + +Use `--device /dev/disk/by-id/...` to preselect a whole disk while retaining +interactive confirmation. The [flashing guide](Flashing) covers dry runs and +unattended mode with explicit image checksum and target identity. Confirm the three internal partition labels and the USB's single `FDS_SYSTEM` -label after writing. Safely disconnect the disks, install NVMe on the powered-off -Pi, and connect exactly one SYSTEM. Do not leave the NVMe enclosure connected as -a duplicate source of FDS partitions. +label with `lsblk -o NAME,PARTLABEL,FSTYPE,MOUNTPOINTS`. Unmount any automatic +desktop mounts after flashing, safely disconnect the disks, install NVMe on the +powered-off Pi, and connect exactly one SYSTEM. Do not leave the NVMe enclosure +connected as a duplicate source of FDS partitions. ## 6. Power on and reach the console diff --git a/Home.md b/Home.md index 33303fe..cc5ce40 100644 --- a/Home.md +++ b/Home.md @@ -17,6 +17,7 @@ Use the sidebar or [all pages](Page-Index) to find a guide. | --- | --- | | [Overview](Overview) | How the computer, internal storage and cartridges fit together | | [Run on a Raspberry Pi 5](Hardware-Setup) | Wire HDMI/USB/power, prepare NVMe and SYSTEM, reach the first console, calibrate bays and diagnose hardware | +| [Flash disk images](Flashing) | Install NVMe and cartridges interactively or unattended with verification | | [Build and start FDS](Getting-Started) | Prepare the OS build workstation, create images and boot the emulator | | [Software and emulator walkthrough](Workstation) | Build Void source packages, assemble cartridges, insert them and write USB media | | [Using cartridges](Cartridges) | Inspect bays, run applications, resolve command names and eject safely | diff --git a/Internal-Storage.md b/Internal-Storage.md index 5662295..3bdb340 100644 --- a/Internal-Storage.md +++ b/Internal-Storage.md @@ -57,79 +57,41 @@ public key as described in [Release signatures](Releases). Its complete disk is named `fds-internal-0.1.0.img`; a local build uses `out/fds-internal.img`. Use the complete disk image, not the separate BOOT or RECOVERY payload. -List disks before and after connecting the intended drive: +Install the workstation `fds-tools` package or run `make workstation-binaries`, +then use [fds-flash](Flashing) for interactive or unattended installation: ```sh -lsblk -d -o NAME,PATH,MODEL,SERIAL,SIZE,TRAN,LOG-SEC -ls -l /dev/disk/by-id/ +sudo ./out/workstation/fds-flash \ + --image out/fds-internal.img \ + --device /dev/disk/by-id/REPLACE_WITH_THE_NVME_DISK ``` -Match the physical model, serial and capacity. Choose a persistent **whole-disk** -`/dev/disk/by-id/` path without a `-partN` suffix; never guess a `/dev/sdX` name. -Unmount every target partition and disable any swap on it. Do not select the -workstation's system disk. The current images require 512-byte logical sectors -and a disk at least as large as the image; 4 KiB logical-sector media is not -supported by this layout. +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](Flashing) covers dry runs, JSON output, +unattended identity/checksum bindings and failure handling. -Open Bash (`bash`), replace both paths below, then run the block. It checks the -selected disk again, requires a typed confirmation, writes and reads back the -complete image, and relocates the backup GPT when the disk is larger than the -image. It does not expand any partition or filesystem. +Prepare the first SYSTEM cartridge separately: -```bash -( - set -euo pipefail - fds_image="$PWD/out/fds-internal.img" - fds_disk=/dev/disk/by-id/REPLACE_WITH_THE_TARGET_DISK - [[ -f "$fds_image" && -s "$fds_image" && -b "$fds_disk" ]] - [[ $(lsblk -dnro TYPE "$fds_disk") == disk ]] - [[ $(sudo blockdev --getss "$fds_disk") == 512 ]] - fds_bytes=$(stat -Lc %s "$fds_image") - (( $(sudo blockdev --getsize64 "$fds_disk") >= fds_bytes )) - lsblk -p -o NAME,TYPE,MODEL,SERIAL,SIZE,MOUNTPOINTS "$fds_disk" - if lsblk -nrpo MOUNTPOINTS "$fds_disk" | grep '[^[:space:]]' >/dev/null; then - echo 'Target has mounted filesystems or swap; stop and release them first.' >&2 - exit 1 - fi - if lsblk -nrpo TYPE "$fds_disk" | grep -Ev '^(disk|part)$' >/dev/null; then - echo 'Target has device-mapper or other active descendants; stop.' >&2 - exit 1 - fi - read -r -p "Type ERASE $fds_disk to erase this disk: " fds_confirmation - [[ "$fds_confirmation" == "ERASE $fds_disk" ]] - sudo dd if="$fds_image" of="$fds_disk" bs=4M conv=fsync status=progress - sudo blockdev --flushbufs "$fds_disk" - sudo cmp -n "$fds_bytes" "$fds_image" "$fds_disk" - sudo sfdisk --lock=yes --relocate gpt-bak-std "$fds_disk" - sudo sfdisk --verify "$fds_disk" - sudo blockdev --flushbufs "$fds_disk" -) +```sh +sudo ./out/workstation/fds-flash \ + --image out/fds-system-cli.img \ + --device /dev/disk/by-id/REPLACE_WITH_THE_SYSTEM_DISK ``` -Every command must succeed. The byte comparison occurs before relocating GPT, -because relocation intentionally changes disk-table headers. GNU `dd`'s `fsync` -flushes output before it returns; `sfdisk`'s `gpt-bak-std` moves the backup header -to the end of the target. See the [GNU dd manual](https://www.gnu.org/s/coreutils/manual/html_node/dd-invocation.html) -and [sfdisk manual](https://man7.org/linux/man-pages/man8/sfdisk.8.html). -These commands use the already documented coreutils, diffutils and util-linux -host tools; they do not add a target daemon. +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 that the disk shows `FDS_BOOT`, `FDS_RECOVERY` and `FDS_INTERNAL` in that -order using `lsblk -o NAME,PARTLABEL,FSTYPE,MOUNTPOINTS`. Unmount anything the -desktop automatically mounted, then safely disconnect the enclosure and install -the NVMe in the powered-off Pi. Follow [EEPROM preparation](EEPROM) for the -separately reviewed NVMe boot settings. - -Prepare the **first SYSTEM cartridge on the workstation** using the same guarded -write block, with its two path assignments changed to the chosen SYSTEM image -and a different, empty USB cartridge disk. For a local build select -`out/fds-system-cli.img` or `out/fds-system-development.img`; release files are -`fds-system-cli-0.1.0.img` and `fds-system-development-0.1.0.img`. They are -alternative complete GPT images, each containing one `FDS_SYSTEM` partition. -Readback and backup-GPT relocation apply to this disk too. Check its partition -label, safely disconnect it, and insert exactly one SYSTEM cartridge in the Pi -before normal boot. Subsequent cartridge creation and updates can use FDS's -confirmed [media workflow](Developer-Media-Tools) after bay calibration. +Confirm `FDS_BOOT`, `FDS_RECOVERY`, `FDS_INTERNAL` on NVMe and `FDS_SYSTEM` on +SYSTEM with `lsblk -o NAME,PARTLABEL,FSTYPE,MOUNTPOINTS`. Unmount any automatic +desktop mounts after flashing, safely disconnect the media, and install NVMe in +the powered-off Pi. Insert exactly one SYSTEM cartridge before normal boot. +Continue with [real-hardware setup](Hardware-Setup) and the separately reviewed +[EEPROM configuration](EEPROM). ## Configure the machine before building diff --git a/Overview.md b/Overview.md index e97ee82..73e725e 100644 --- a/Overview.md +++ b/Overview.md @@ -62,7 +62,7 @@ Run these from the repository root: | Command | Result | | --- | --- | | `make wiki-check` | Check the documentation in `fds-os.wiki` | -| `make workstation` | Arch `fds-tools` package containing both workstation commands | +| `make workstation` | Arch `fds-tools` package containing all three workstation commands | | `make workstation-install` | Install that package using pacman | | `make workstation-binaries` | Native commands for other Linux distributions | | `make bootstrap` | Prepares the complete OS build environment on x86_64 Arch Linux | @@ -78,7 +78,7 @@ programs and dependencies directly. FDS does not extract those programs at launc The workstation walkthrough includes prerequisites, complete example commands, expected outputs, emulator lifecycle and the confirmed USB-writing workflow. -Append `--help` to either native tool for its command reference; run `make help` +Append `--help` to any native tool for its command reference; run `make help` for the complete build target list. Build identities come from Git release tags. See [versioning](Developer-Versioning) for release, development and source-export behavior. diff --git a/Page-Index.md b/Page-Index.md index 0ede5ea..bbf1069 100644 --- a/Page-Index.md +++ b/Page-Index.md @@ -6,6 +6,7 @@ include_toc: true ## User manual +- [Flash disk images with fds-flash](Flashing) - [Build and start FDS](Getting-Started) - [Build software cartridges and use the emulator](Workstation) - [Dasung Paperlike display](Dasung) diff --git a/Workstation.md b/Workstation.md index 15094fe..f47e120 100644 --- a/Workstation.md +++ b/Workstation.md @@ -11,7 +11,7 @@ as guest commands. ## Prepare the tools -The native tools are `fds-cartridge` and `fds-emulator`. On Arch Linux, build +The native tools are `fds-cartridge`, `fds-emulator` and `fds-flash`. On Arch Linux, build and install their `fds-tools` package from the checkout: ```sh @@ -21,7 +21,7 @@ make workstation-install ``` `make workstation` produces `out/workstation/fds-tools-VERSION-1-ARCH.pkg.tar.zst` -with both commands, documentation, examples and license notices. It does not +with all three commands, documentation, examples and license notices. It does not install packages. `make workstation-install` builds that package and invokes `sudo pacman -U` to install it into `/usr/bin`. Pacman tracks upgrades and removal; remove it later with `sudo pacman -R fds-tools`. The exact latest package path is @@ -246,33 +246,24 @@ preserved by `make clean`; keep them under your own names, such as `my-emulator` ## Write a cartridge to USB -Identify the intended whole USB drive, unmount its partitions, then preview: +Use `fds-flash` to write the complete cartridge image interactively: ```sh -fds-cartridge preview out/demo-tools.img /dev/sdX out/usb-preview.json +sudo fds-flash --image out/demo-tools.img ``` -Replace `/dev/sdX` with the actual destination. The JSON identifies the drive, -capacity, image hash and exact confirmation phrase. Check those values before -writing: this replaces the selected drive's contents. +Choose the intended whole USB disk, review its model, serial and capacity, and +type the displayed erase phrase. The tool writes, flushes and verifies the disk, +including backup-GPT relocation on a larger destination. For a checkout build, +use `sudo ./out/workstation/fds-flash` instead of the installed command. -```sh -sudo /absolute/path/to/fds-cartridge write out/usb-preview.json \ - --confirm 'COPY THE EXACT confirmation VALUE FROM THE PREVIEW' -``` +The [flashing guide](Flashing) covers explicit device paths, dry-run JSON, +unattended writes and disposable-file testing. It also covers the internal +NVMe and first SYSTEM disk; `fds-flash` accepts those complete disk images too. -The writer rechecks identity, writes the entire disk image, flushes it and verifies -readback. On a larger drive it moves the backup GPT to the end. A changed image -or reinserted drive requires a fresh preview. Use the image-tool runner for -preview and inspection if your EROFS utilities are in the local container. - -To rehearse with a disposable regular file: - -```sh -truncate -s "$(stat -c %s out/demo-tools.img)" out/disposable-usb.img -fds-cartridge preview out/demo-tools.img out/disposable-usb.img out/file-preview.json --file-target -fds-cartridge write out/file-preview.json --confirm 'COPY THE EXACT confirmation VALUE' -``` +The older `fds-cartridge preview` / `write --confirm` interface remains supported +for USB cartridge workflows. It performs deeper cartridge content inspection and +retains its protection against overwriting internal FDS partitions. See [troubleshooting](Troubleshooting) for failed builds, namespace errors, busy consoles, invalid media and blocked ejects. diff --git a/_Sidebar.md b/_Sidebar.md index fefadda..f8cf902 100644 --- a/_Sidebar.md +++ b/_Sidebar.md @@ -17,6 +17,7 @@ **Install and maintain** +- [Flash disk images](Flashing) - [Internal storage and machine settings](Internal-Storage) - [Pi 5 EEPROM configuration](EEPROM) - [Recovery and rollback](Recovery)