The increment 2 final review's minors 1-4 (Captain Bob, 2026-10-27: "fix 1-4"): 1. A protective MBR with no "EFI PART" header is GPT_BAD, not GPT_NONE: the MBR says it is a GPT disk, and a GPT disk is never attached whole. 2. A disk whose block 0 cannot be read is GPT_EIO: "GPT: a USB drive could not be read -- not used", nothing attached (it was read raw, attached whole, and a raw Zuse drive behind it logged her in). 3. The entry array's LBA is checked against the disk's size directly. 4. gpt_bad_entries: the entry array changed, the header valid -- refused. Harness modes gpt_no_header, gpt_read_error (blkdebug EIO on sector 0), gpt_bad_entries. The plan carries the amendment. Red (amd64): gpt_no_header 070335, gpt_read_error 070717 FAIL; gpt_bad_entries 070048 PASS (existing check, now pinned). Green: every GPT mode on amd64 071113-072933; gpt_zuse, gpt_read_error, gpt_no_header on aarch64 073222-074047 and riscv64 074526-075535; the identity gate's and increment 1's sessions 080036-082345, emergency 083130 (082635 was run without EMERGENCY_CONSOLE_ENABLED=1 -- a harness invocation error). Accepted: suite EXIT 0; 093121, 093352, 093750, POST 538/538, dict_hash 0xfec8c47cfc6f437f; test-32, 0 failures. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
10 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 (threeclean qemuboots to[zuse@Hera] ok>, POST 538/538,dict_hash0xfec8c47cfc6f437fequal on all three,make -C v4 test-320 failures, logs committed). - The two StarshipOS partition type GUIDs (generated 2026-10-26, fixed from here;
mkdiskimage.shuses the same values in increment 3):- StarshipOS identity:
23BEBFE1-4817-4CF3-A537-9069BF159788 - StarshipOS Artemis:
BCD7B586-1C8E-4EEF-86A3-273A8D8EE624
- StarshipOS identity:
- GPT as UEFI 2.x defines it: protective MBR (type
0xEEat LBA 0), header at LBA 1, signature"EFI PART", revision0x00010000, header size 92..512, header CRC-32 overHeaderSizebytes with its own CRC field zeroed, entry array CRC-32 overNumberOfPartitionEntries * SizeOfPartitionEntrybytes, 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
blkioblock); 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=v3is 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
- 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). - 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). - A partition device reading past its end is refused (
BLKIO_EINVAL), never reaching the neighbouring partition. Covered by the backend's bound and bygpt_zuse's identity check, which reads offsets taken from the drive. - Raw identity drives (
disk/zuse-scratch/) still work: the identity gate's sessions all pass. - 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.cbesidehomeblocks_sig.cin 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);— returnsGPT_OK(0, a valid GPT;*countpartitions with a non-zero type, at mostmax),GPT_NONE(no protective MBR or no"EFI PART": not a GPT disk), orGPT_BAD(a GPT, but a CRC, the revision, the sizes or the geometry is wrong). Reads only; usesblkio_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);— opensdevas that partition:fblockn is the disk'sfirst_lba/2 + n;total_blocksis the sector count / 2; reads and writes past the end areBLKIO_EINVAL;flush/infopass through.BLKIO_EINVALfor an odd first LBA or sector count.uint32_t gpt_crc32(const void *buf, size_t len);— IEEE 802.3, reflected, poly0xEDB88320, init and final XOR0xFFFFFFFF(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_OKwith a StarshipOS identity partition: open the partition device (kept per slot beside the rawblkio_dev_t); give the partition device to the block subsystem (blk_subsys_attach_device), never the raw disk; run the signature check andcapsule_zuse_boot_checkon the partition device; the device remembered as Zuse's is the partition device.GPT_OKwith 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.
Amended (Captain Bob, 2026-10-27, after the final review: "fix 1-4"): a disk with a protective MBR
but no "EFI PART" header is GPT_BAD, not GPT_NONE -- the MBR already says it is a GPT disk, and
a GPT disk is never attached whole. A disk whose block 0 cannot be read is GPT_EIO (3): "GPT: a USB
drive could not be read -- not used", nothing attached. The entry array's LBA is checked against the
disk's size directly. Pinned by gpt_no_header, gpt_read_error and gpt_bad_entries (the entry
array's CRC, the header intact).
-
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,sfdiskwith the type GUIDs above,dda payload into a partition at its start) and these modes (amd64; thengpt_zuseon 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) holdsdisk/zuse-scratch/zuse-thumb-ident.img; expect "Zuse: identity confirmed from attached thumbdrive",[zuse@Hera] ok>,3 4 + .gives7 ok. Booted withKERNEL_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, notLAHB).gpt_hotplug: asgpt_zuse, thendevice_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, nook>for 30 s, no fault, and -- booted withKERNEL_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'sblk: disk ... LBNlines do not grow). Today: FAIL on the attach (the raw disk is attached).gpt_bad_crc: thegpt_zuseimage with one byte of the primary header's CRC field flipped; no identity, nook>for 30 s, the log says the table is damaged, and (booted withKERNEL_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.cand the drive-path change as above. -
Step 4: Every mode passes (
gpt_zuseon 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 partitionwith the logs.