uefi.h: the UEFI device path and Block I/O protocols, a typed LocateDevicePath, and BootDisk
{gpt, is_stick, disk_guid[16]} appended to BootInfo after args (boot_info_offsets.h unchanged).
The loader, before ExitBootServices, cuts its image's device path at the partition's HardDrive
node, locates the whole disk's Block I/O (whole path consumed, not a logical partition, 512-byte
blocks), reads it as 1 KiB blocks through a loader-side blkio adapter, and runs the kernel's own
gpt_read: is it a StarshipOS stick (identity and Artemis partitions), and its DiskGUID
(gpt_disk_guid, new). No HardDrive node (an ISO/CD boot), no GPT, or any failure: not a stick.
Monolithic builds only (the non-monolithic loader does not link gpt.c, and does not build today:
kernel/src/vm/vm_core.c -- reported, not fixed).
The kernel prints 'Boot disk: a StarshipOS stick' or '... not a StarshipOS stick', and on a stick
system=v3 gives 'System: v3 is not on this stick -- StarForth v4' and boots v4.
Tests: stick_v3 (new), stick_boot and zuse x3 failed on the new lines before, pass after; v3_keys
still boots v3 off a stick. Acceptance: amd64, aarch64, riscv64 to [zuse@Hera] ok>, POST 538/538,
dict_hash 0xfec8c47cfc6f437f; v4 suite and test-32 0 failures.
Plan: docs/v4.0.0/plans/2026-10-27-stick-4-one-disk.md, Task 3.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sk_v4_block_chain calls rng_init() after pci_init, with v3's two lines ("entropy: ready" / "entropy:
not available (continuing without)"); genesis on a fresh stick (increment 5) needs it. amd64 QEMU
runs -cpu qemu64,+rdrand (qemu, qemu-stick, qemu-esp) and the amd64 qemu target drops virtio-rng,
so QEMU takes the PC's RDRAND path; aarch64 and riscv64 keep virtio-rng, their only backend.
qemu_session.py: mode entropy (rdrand on amd64, both targets; virtio-rng on aarch64/riscv64; then
entropy: ready). system=v3 sessions get Zuse's raw identity image: v3 never reads a GPT, so the
Zuse stick (Task 1) left v3_keys headless -- found here; CLAUDE.md says so for v3 boots.
Tests: entropy FAIL x4 before, PASS x4 after; v3_keys PASS (rng: backend = rdrand). Acceptance:
amd64, aarch64, riscv64 to [zuse@Hera] ok>, POST 538/538, dict_hash 0xfec8c47cfc6f437f; v4 suite
and test-32 0 failures.
Plan: docs/v4.0.0/plans/2026-10-27-stick-4-one-disk.md, Task 2.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mkdiskimage.sh --starship-from IDENT ART lays a minted pair out as a StarshipOS stick: an identity
partition holding IDENT's bytes and an Artemis partition holding ART's, each exactly its file's
size (Artemis's signature and fence are placed from the volume's size). kernel/Makefile: a
zusestick target, made fresh for every boot, is ZUSEDISK's default (ZUSE_PAIR names the pair);
STICK_PAIR puts the pair in the PC stick. qemu_session.py's Zuse drive is the pair as a stick.
check_images.sh checks both forms byte for byte against the pair (60 PASS).
On today's kernel all 23 sessions pass on the Zuse stick, and acceptance: amd64, aarch64,
riscv64 to [zuse@Hera] ok>, POST 538/538, dict_hash 0xfec8c47cfc6f437f; v4 suite and test-32
0 failures. The plan gains Task 5, screen=boot (ruled 2026-10-28).
Plan: docs/v4.0.0/plans/2026-10-27-stick-4-one-disk.md, Task 1 (R1 as recommended).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
qemu-stick boots the amd64 stick image (build/boards/pc/lithos-pc.img,
copied per run) as a USB drive on q35, exactly as hardware would.
DATASTICK=1 adds the data stick to any qemu run as a second USB drive.
qemu_session.py gains --target and the stick_boot and datastick modes.
Checks: stick_boot (the stick's own identity partition attaches, headless
on a blank identity); datastick on amd64/aarch64/riscv64 (both drives
found, the data stick's 500 MiB identity attaches); the seven GPT modes,
the identity-gate and increment 1 sessions, emergency; the suite; three
acceptance boots to [zuse@Hera] ok> with POST 538/538 and
dict_hash=0xfec8c47cfc6f437f; test-32 0 failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
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>
From the fresh review of the stick's increment 1 (With fixes):
- Critical: after logout Zuse's last screen, her prompt included, could be
drawn back on a headless machine. The logout clear (ESC[2J) blanked the
pixels only: Alt+TAB, still read while headless, redrew the terminal
from its saved text; and if she had Alt+TABbed to the graphics view
before the pull, the clear did nothing and her session stayed on screen
(and the console did not draw at her next login). Now vt100_reset()
forgets everything the terminal has shown -- the on-screen text, the
scrollback and their boot snapshots -- makes it visible again and fills
the screen; and Alt+TAB does nothing while the screen is off (v3's never
is, so v3 is unchanged).
- Important: an EMERGENCY_CONSOLE_ENABLED build no longer clears the screen
when Zuse's drive is pulled: its console goes on running.
Red: alttab_after_logout 183308 (4515 lit), alttab_before_pull 183529
(4539 lit; the console not redrawn), emergency_pull 183759 (0 lit).
Green: 184115, 184328, 184552; regression 184805-185956 (screens,
keyboard, hotplug, emergency, v3 typed by keyboard) all pass.
Accepted: 190111, 190312, 190710, POST 538/538, dict_hash
0xfec8c47cfc6f437f; test-32, 39 modules, 0 failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stick, increment 1, task 2 (plan 2026-10-26-stick-1-screen-and-keyboard;
docs/v4.0.0/STICK.md 2, 5.3, 5.4). On the v4 path:
- the framebuffer is brought up after POST, cleared and dark: console text
goes to serial only ("splash only, log on serial") until Zuse logs in;
then the screen is the console (TTF, a blinking cursor, as v3's), and
when she logs out it is cleared and dark again (console_fb_mirror(),
console_fb_clear(); the mirror is on by default, so v3 is unchanged);
- the line editor and the node's KEY read every keyboard -- PS/2, USB, the
virtio keyboard -- through the shared bridge (sk_input_getc()); the
headless wait drops keyboard input as well as serial bytes;
- an EMERGENCY_CONSOLE_ENABLED build has the screen from the start.
The framebuffer setup is one helper both paths call (kernel_main.c).
Red (before): screen_dark_until_login 153051 (10835 lit), console/keys
153309, logout 153609, kbd_typeahead 153918, virtio_kbd aarch64 154245
and riscv64 154718; no_framebuffer 155546 passed before and after.
Green: 155926 (0 lit), 160156, 160409 (0 lit after logout), 160630,
virtio_kbd 161414 and 161820, no_framebuffer 161206; usb_kbd with the USB
keyboard the only one (-machine i8042=off) 164548, v3 control 164757;
the identity gate's sessions 162245-163802 all pass; v3 typed by keyboard
164009, 164115. (usb_kbd 160857 and 164313 failed in the harness:
input-send-event's device names a display, not a keyboard.)
Accepted: suite EXIT 0; three clean qemu boots, POST 538/538, dict_hash
0xfec8c47cfc6f437f unchanged (174704, 174911, 175315); test-32, 39
modules, 0 failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stick, increment 1, task 1 (plan 2026-10-26-stick-1-screen-and-keyboard).
repl.c's keyboard bridge -- the key tables, Shift/Alt/Caps Lock/Num Lock and
their lights, the keypad, Alt+TAB, and the per-tick USB keyboard servicing --
moves unchanged to kernel/src/hal/kbd_input.c as sk_input_getc() (and
sk_input_drop()), so that the v4 boot's console reads the same keyboards
(docs/v4.0.0/STICK.md 5.4). v3's behaviour is unchanged.
scripts/qemu_session.py: the typed-QEMU-session harness, kept in the repo
from here on (the identity gate's sessions, and v3_keys: system=v3 typed on
QEMU's keyboard with send-key).
Yardstick, system=v3 typed by keyboard: before, amd64 PS/2 134805 PASS,
aarch64 virtio keyboard 135549 PASS; after, 135746 and 135835 PASS.
(riscv64 134850: v3 never reached its prompt -- Artemis virtio_blk writes
time out; v3's block path, before this change; being investigated.)
Accepted: suite EXIT 0; three clean qemu boots to [zuse@Hera] ok>, POST
538/538, dict_hash 0xfec8c47cfc6f437f (145722, 145859, 150231); test-32,
39 modules, 0 failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>