feat(kernel): the GPT reader, and Zuse from a GPT identity partition

The stick, increment 2 (plan 2026-10-26-stick-2-gpt-reader; docs/v4.0.0/
STICK.md 3 and 4: GPT for boot media and installed disks). kernel/src/gpt.c:
a CRC-32; gpt_read(), which checks the protective MBR, the primary header and
the partition-entry array (both CRCs, the revision, the sizes, the geometry);
and a partition as a blkio device, refusing blocks past its end. The two
StarshipOS partition types: identity 23BEBFE1-4817-4CF3-A537-9069BF159788,
Artemis BCD7B586-1C8E-4EEF-86A3-273A8D8EE624.

The v4 drive path: a GPT disk is used only through its StarshipOS identity
partition, and that partition -- never the disk -- is given to the block
subsystem, in a raw identity drive's place; a GPT disk with no StarshipOS
partition, or a damaged table ("GPT: a USB drive has a damaged partition
table -- not used"), is not attached (Captain Bob's ruling on the plan); a
disk with no GPT is read raw, as always. Pulling the drive detaches the
partition and ends her session. Reads only.

Red (amd64): gpt_zuse 193158, gpt_hotplug 193804, gpt_foreign 194713,
gpt_bad_crc 194947. Green: 195409, 195627, 195854, 200136; gpt_zuse aarch64
200424, riscv64 200839 (the 64 MiB partition attached, 48724 user blocks,
not the 72 MiB disk); the identity gate's and increment 1's sessions,
201119-203403, all pass.
Accepted (with the KERNEL_ARGS fix that follows): suite EXIT 0; 214300,
214507, 214911, POST 538/538, dict_hash 0xfec8c47cfc6f437f; test-32, 39
modules, 0 failures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-26 21:56:31 -04:00
co-authored by Claude Opus 5.5
parent 03099f2c51
commit 3cc4937c93
43 changed files with 3428 additions and 12 deletions
+66 -3
View File
@@ -34,6 +34,11 @@ the stick's, plan 2026-10-26-stick-1-screen-and-keyboard.md):
alttab_before_pull Alt+TAB, then the drive pulled: black; re-attach draws the console
emergency_pull EMERGENCY_CONSOLE_ENABLED=1: Zuse added and pulled, the screen
still shows the running console, and it types
gpt_zuse a GPT drive, Zuse in its StarshipOS identity partition: recognised; the partition
is attached (run with --make KERNEL_ARGS=--log-level=info)
gpt_hotplug ... pulled: session ended; added again: prompt
gpt_foreign a GPT drive with only a Linux partition: no identity, not attached (info level)
gpt_bad_crc the gpt_zuse image with its header CRC broken: not used, said so, not attached
virtio_kbd aarch64/riscv64: QEMU's virtio keyboard types 7 ok
Needs only Python 3. One QEMU at a time (.claude/CLAUDE.md).
@@ -52,7 +57,7 @@ ap.add_argument("--make", default="")
ap.add_argument("--no-zuse", action="store_true")
a = ap.parse_args()
NO_ZUSE_MODES = {"headless", "hotplug", "midpull", "waitpull", "typeahead", "emergency",
NO_ZUSE_MODES = {"gpt_zuse", "gpt_hotplug", "gpt_foreign", "gpt_bad_crc", "headless", "hotplug", "midpull", "waitpull", "typeahead", "emergency",
"alttab_after_logout", "alttab_before_pull", "emergency_pull",
"screen_dark_until_login", "screen_console_after_login", "screen_dark_after_logout",
"kbd_typeahead"}
@@ -181,6 +186,32 @@ def key_line(line):
time.sleep(0.1)
# The two StarshipOS partition type GUIDs (docs/v4.0.0/plans/2026-10-26-stick-2-gpt-reader.md)
GPT_IDENTITY = "23BEBFE1-4817-4CF3-A537-9069BF159788"
GPT_LINUX = "0FC63DAF-8483-4772-8E79-3D69D8477DE4"
def make_gpt_image(path, ptype, payload, mib=72, break_crc=False):
"""A GPT disk image: one partition at LBA 2048, 131072 sectors (64 MiB), of type
`ptype`, holding `payload` from its start; optionally the primary header's CRC broken."""
subprocess.run(["truncate", "-s", f"{mib}M", path], check=True)
sf = shutil.which("sfdisk") or "/usr/sbin/sfdisk"
subprocess.run([sf, "--quiet", path], input=f"label: gpt\nstart=2048, size=131072, type={ptype}\n",
text=True, check=True)
subprocess.run(["dd", f"if={payload}", f"of={path}", "bs=512", "seek=2048", "conv=notrunc,sparse",
"status=none"], check=True)
if break_crc:
with open(path, "r+b") as f:
f.seek(512 + 16) # the primary header's HeaderCRC32
b = f.read(1)
f.seek(512 + 16)
f.write(bytes([b[0] ^ 0xFF]))
def blk_lines():
return count(r"blk: ")
def alt_tab():
qcmd("send-key", keys=[{"type": "qcode", "data": "alt"}, {"type": "qcode", "data": "tab"}])
time.sleep(1)
@@ -208,9 +239,9 @@ def screen():
return w, h, lit, px
def add_zuse(n):
def add_zuse(n, img=None):
qcmd("blockdev-add", driver="raw", **{"node-name": f"zuse{n}"},
file={"driver": "file", "filename": zimg})
file={"driver": "file", "filename": img or zimg})
qcmd("device_add", driver="usb-storage", bus="xhci0.0", port="1",
drive=f"zuse{n}", id=f"zusedev{n}")
@@ -406,6 +437,38 @@ elif m == "emergency_pull":
_, _, _, px2 = screen()
check("the screen changed with what was typed", px2 != px1)
elif m in ("gpt_zuse", "gpt_hotplug", "gpt_foreign", "gpt_bad_crc"):
gimg = os.path.join(work, "gpt.img")
make_gpt_image(gimg, GPT_LINUX if m == "gpt_foreign" else GPT_IDENTITY, zimg,
break_crc=(m == "gpt_bad_crc"))
check("no ok> for 10 s with no drive", not wait_for(ANYPROMPT, 10))
b0 = blk_lines()
add_zuse(1, gimg)
if m in ("gpt_zuse", "gpt_hotplug"):
check("Zuse: identity confirmed", wait_for(r"Zuse: identity confirmed from attached thumbdrive", 120))
check("[zuse@Hera] ok>", wait_for(PROMPT, 60))
# the identity partition (64 MiB), not the whole 72 MiB disk: a 64 MiB identity drive
# shows 48724 user blocks (the raw minted drive, logs/20261026-091010); the disk, 54868
users = re.findall(r"blk: disk .*?\((\d+) user", text())
check(f"the partition, not the disk, was attached (blk: lines {b0} -> {blk_lines()}, "
f"user blocks {users[-1] if users else None})",
blk_lines() > b0 and users and users[-1] == "48724")
n = count(PROMPT)
type_line("3 4 + .")
check("7 ok", wait_for(PROMPT, 60, n) and re.search(r"7\s+ok", text()[-400:]) is not None)
if m == "gpt_hotplug":
del_zuse(1)
check("session ended on detach", wait_for(r"Zuse: session ended -- reattach to re-authenticate", 60))
p = count(PROMPT)
add_zuse(2, gimg)
check("[zuse@Hera] ok> again", wait_for(PROMPT, 120, p))
else:
if m == "gpt_bad_crc":
check("the damaged table is said so", wait_for(r"GPT: a USB drive has a damaged partition table -- not used", 60))
check("no ok> for 30 s", not wait_for(ANYPROMPT, 30))
check("no identity", count(r"Zuse: identity confirmed") == 0)
check(f"not attached (blk: lines {b0} -> {blk_lines()})", blk_lines() == b0)
else:
check(f"known mode {m}", False)