Files
LithosAnanake/docs/v4.0.0/plans/2026-10-26-stick-2-gpt-reader.md
T
rajamesandClaude Opus 5.5 7f297f4e99 docs(v4): the stick, increment 2 plan: the GPT reader
Approved by Captain Bob 2026-10-26, with his ruling on review: a GPT disk is
never attached whole -- the identity partition is attached in the raw
identity drive's place; a GPT disk with no StarshipOS partition, or a damaged
one, is not attached.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 19:28:42 -04:00

9.4 KiB

The stick, increment 2: the GPT reader — Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:executing-plans (Captain Bob prefers native execution). Steps use checkbox (- [ ]) syntax for tracking.

Goal: The kernel reads a disk's GPT and makes a block device of each StarshipOS partition on it, on every ISA; the v4 boot recognises Zuse on a GPT drive's identity partition, and raw identity drives are read exactly as now.

Architecture: One kernel file, gpt.c: a CRC-32, a reader that checks the protective MBR, the primary GPT header and its partition-entry array (both CRCs) and lists the partitions, and a thin blkio backend whose block 0 is a partition's first 1 KiB. The v4 boot's drive-arrival path tries GPT first: a disk with a valid GPT is used through its StarshipOS identity partition, and that partition device -- not the disk -- is what the block subsystem is given, in the place a raw identity drive has today (everything past its metadata is the identity's own block storage); a GPT disk with no StarshipOS partition, or a damaged one, is given to nothing; a disk with no GPT is read raw, exactly as today. Artemis from a partition, the boot disk, and genesis are increments 4 and 5; this one only reads.

Tech Stack: freestanding C99 kernel; QEMU (blockdev-add/device_add of a GPT test image); sfdisk + dd to build the test images; scripts/qemu_session.py.

Spec: docs/v4.0.0/STICK.md §3 (GPT for boot media and installed disks, raw identity drives still accepted), §4 (the layout, the GPT reader, partition devices, "the identity and Artemis formats do not change"), §11 increment 2.

Global Constraints

  • As increment 1's plan (2026-10-26-stick-1-screen-and-keyboard.md): branch, commits, strict C99, -Werror, v3 unchanged, QEMU/bare-metal parity, no fix outside the plan, full acceptance on every kernel-affecting task (three clean qemu boots to [zuse@Hera] ok> , POST 538/538, dict_hash 0xfec8c47cfc6f437f equal on all three, make -C v4 test-32 0 failures, logs committed).
  • The two StarshipOS partition type GUIDs (generated 2026-10-26, fixed from here; mkdiskimage.sh uses the same values in increment 3):
    • StarshipOS identity: 23BEBFE1-4817-4CF3-A537-9069BF159788
    • StarshipOS Artemis: BCD7B586-1C8E-4EEF-86A3-273A8D8EE624
  • GPT as UEFI 2.x defines it: protective MBR (type 0xEE at LBA 0), header at LBA 1, signature "EFI PART", revision 0x00010000, header size 92..512, header CRC-32 over HeaderSize bytes with its own CRC field zeroed, entry array CRC-32 over NumberOfPartitionEntries * SizeOfPartitionEntry bytes, entry size a multiple of 128. Little-endian GUIDs on disk (mixed-endian first three fields).
  • 512-byte logical sectors only (USB sticks and the data stick). A disk reporting another sector size is not read as GPT (said once, used raw). 4 KiB-sector disks are INSTALL's, later.
  • A partition is used only if its first LBA and its sector count are both even (it starts and ends on a 1 KiB blkio block); otherwise it is skipped with a message. Every image this project builds starts partitions at 1 MiB.
  • No v3 change: the v3 path does not read GPT (system=v3 is refused on a stick, STICK.md §5, in increment 4).

Ruled (Captain Bob, 2026-10-26, on reviewing this plan): a GPT disk is never attached whole. The identity partition device is attached in the raw identity drive's place; a GPT disk with no StarshipOS partition, or a damaged one, is not attached at all. So a plain GPT data stick does not appear as raw block storage on v4, as it would on v3 -- a change from today, accepted.

Review Focus

  1. A GPT whose header CRC or entry-array CRC is wrong is not used: no partition device, not attached, not read raw either (a damaged stick is not a raw identity drive), one message. Pinned in Task 1 (gpt_bad_crc).
  2. A GPT disk with no StarshipOS partition (an ordinary data stick) gives no identity, is not attached, no fault, no prompt. Pinned in Task 1 (gpt_foreign).
  3. A partition device reading past its end is refused (BLKIO_EINVAL), never reaching the neighbouring partition. Covered by the backend's bound and by gpt_zuse's identity check, which reads offsets taken from the drive.
  4. Raw identity drives (disk/zuse-scratch/) still work: the identity gate's sessions all pass.
  5. The partition device detaches with its disk: pulling a GPT Zuse drive ends her session exactly as pulling a raw one does. Pinned in Task 1 (gpt_hotplug).

Task 1: The GPT reader, and Zuse from a GPT identity partition

Files:

  • Create: kernel/src/gpt.c, kernel/include/starkernel/gpt.h
  • Modify: kernel/Makefile (add $(KERNEL_SRC)/gpt.c beside homeblocks_sig.c in both source lists)
  • Modify: kernel/src/v4/sk_v4_identity.c (sk_v4_drive_arrived / sk_v4_drive_left)
  • Modify: scripts/qemu_session.py (modes below; it builds the GPT test images)

Interfaces (produces):

  • extern const uint8_t gpt_type_starship_identity[16], gpt_type_starship_artemis[16]; — the on-disk (mixed-endian) bytes of the two GUIDs above.
  • typedef struct { uint8_t type[16]; uint64_t first_lba; uint64_t last_lba; } gpt_part_t;
  • int gpt_read(blkio_dev_t *disk, gpt_part_t *parts, unsigned max, unsigned *count); — returns GPT_OK (0, a valid GPT; *count partitions with a non-zero type, at most max), GPT_NONE (no protective MBR or no "EFI PART": not a GPT disk), or GPT_BAD (a GPT, but a CRC, the revision, the sizes or the geometry is wrong). Reads only; uses blkio_read.
  • int gpt_find(const gpt_part_t *parts, unsigned count, const uint8_t type[16]); — the index of the first partition of that type, or -1.
  • typedef struct { blkio_dev_t *disk; uint32_t first_fblock; uint32_t fblocks; } gpt_part_dev_t;
  • int gpt_part_open(blkio_dev_t *dev, gpt_part_dev_t *st, blkio_dev_t *disk, const gpt_part_t *p); — opens dev as that partition: fblock n is the disk's first_lba/2 + n; total_blocks is the sector count / 2; reads and writes past the end are BLKIO_EINVAL; flush/info pass through. BLKIO_EINVAL for an odd first LBA or sector count.
  • uint32_t gpt_crc32(const void *buf, size_t len); — IEEE 802.3, reflected, poly 0xEDB88320, init and final XOR 0xFFFFFFFF (gpt_crc32("123456789", 9) == 0xCBF43926).

Interfaces (the v4 drive path, sk_v4_identity.c): on arrival, after blkio_usb_open_msc, gpt_read on the raw device:

  • GPT_OK with a StarshipOS identity partition: open the partition device (kept per slot beside the raw blkio_dev_t); give the partition device to the block subsystem (blk_subsys_attach_device), never the raw disk; run the signature check and capsule_zuse_boot_check on the partition device; the device remembered as Zuse's is the partition device.

  • GPT_OK with no StarshipOS partition: nothing attached, no identity check, no message.

  • GPT_BAD: "GPT: a USB drive has a damaged partition table -- not used"; nothing attached.

  • GPT_NONE: exactly today's raw path.

  • On detach (sk_v4_drive_left, called with the raw slot): if that slot has an open partition device, it is the partition device that is detached from the block subsystem and compared with Zuse's; the raw device otherwise, as today. A slot that was never attached detaches nothing.

  • Step 1: Failing tests — the harness gains make_gpt_image(path, parts) (truncate, sfdisk with the type GUIDs above, dd a payload into a partition at its start) and these modes (amd64; then gpt_zuse on aarch64 and riscv64):

    • gpt_zuse: no drive at boot; hot-add a 72 MiB GPT image whose partition 1 (LBA 2048, 131072 sectors, type StarshipOS identity) holds disk/zuse-scratch/zuse-thumb-ident.img; expect "Zuse: identity confirmed from attached thumbdrive", [zuse@Hera] ok> , 3 4 + . gives 7 ok. Booted with KERNEL_ARGS=--log-level=info, the block subsystem's attach line for the partition (blk: disk ... LBN ..., 64 MiB) appears -- the positive control for the two modes below. Today: FAIL (the raw check at the disk's devblock 1 finds partition entries, not LAHB).
    • gpt_hotplug: as gpt_zuse, then device_del → "Zuse: session ended"; re-add → prompt. Today: FAIL.
    • gpt_foreign: hot-add a GPT image with one Linux-filesystem partition (0FC63DAF-…) holding the Zuse image; no identity, no ok> for 30 s, no fault, and -- booted with KERNEL_ARGS=--log-level=info, since the attach line is an INFO message the v4 boot otherwise hides after POST -- no block-subsystem attach line for it (the log's blk: disk ... LBN lines do not grow). Today: FAIL on the attach (the raw disk is attached).
    • gpt_bad_crc: the gpt_zuse image with one byte of the primary header's CRC field flipped; no identity, no ok> for 30 s, the log says the table is damaged, and (booted with KERNEL_ARGS=--log-level=info) no attach line for it. Today: FAIL on the message and the attach.
  • Step 2: Run each; record the failures.

  • Step 3: Implement gpt.c and the drive-path change as above.

  • Step 4: Every mode passes (gpt_zuse on all three ISAs); the identity gate's sessions (headless, zuse, hotplug, midpull, waitpull, typeahead, emergency) and increment 1's (screen_dark_until_login, screen_dark_after_logout, kbd_typeahead) still pass.

  • Step 5: Suite; full acceptance; commit feat(kernel): the GPT reader, and Zuse from a GPT identity partition with the logs.