feat(build): QEMU boots the stick; the data stick over USB

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>
This commit is contained in:
rajames
2026-10-27 16:31:27 -04:00
co-authored by Claude Opus 5.5
parent e177c5c6b3
commit c416c805cb
66 changed files with 5147 additions and 5 deletions
+70 -1
View File
@@ -174,6 +174,19 @@ ZUSEDISK_QEMU_ARGS := -drive if=none,id=zusedrv,file=$(ZUSEDISK),format=raw -dev
else
ZUSEDISK_QEMU_ARGS :=
endif
# DATASTICK -- set to 1 to attach the data stick (`make ... datastick`: StarshipOS identity
# and Artemis partitions, no ESP, made fresh before the boot) over USB on port 2, beside the
# disks above (docs/v4.0.0/STICK.md 9). Off by default until the first boot of a fresh data
# stick can mint Zuse (increment 5, which turns it on and retires ARTDISK/ZUSEDISK;
# docs/v4.0.0/plans/2026-10-27-stick-3-images.md, ruled 2026-10-27).
DATASTICK ?=
ifneq ($(strip $(DATASTICK)),)
DATASTICK_QEMU_ARGS = -drive if=none,id=datadrv,file=$(DATASTICK_IMG),format=raw -device usb-storage,bus=xhci0.0,port=2,drive=datadrv
DATASTICK_DEP := datastick
else
DATASTICK_QEMU_ARGS :=
DATASTICK_DEP :=
endif
MKCAPSULE_SRC = tools/mkcapsule.c tools/pkcs8_ed25519.c \
kernel/src/crypto/ed25519.c \
kernel/src/crypto/fe25519.c \
@@ -992,7 +1005,7 @@ QEMU_DISPLAY ?= gtk
# above) to give real ports to Zuse plus every identity drive attached this way.
QEMU_EXTRA ?=
qemu: all
qemu: all $(DATASTICK_DEP)
ifeq ($(ARCH),amd64)
@echo "=== Building ISO (amd64) ==="
@mkdir -p $(BUILD_DIR)/iso
@@ -1039,6 +1052,7 @@ ifeq ($(ARCH),amd64)
-device virtio-blk-pci,drive=artdisk \
$(XHCI_ARGS_ROOT) \
$(ZUSEDISK_QEMU_ARGS) \
$(DATASTICK_QEMU_ARGS) \
-object rng-random,id=rng0,filename=/dev/urandom \
-device virtio-rng-pci,rng=rng0 \
-chardev socket,id=cserial,path=$$SERIAL_SOCK,server=on,wait=off,logfile=$$LOG \
@@ -1123,6 +1137,7 @@ else ifeq ($(ARCH),aarch64)
-device virtio-keyboard-pci,addr=0x3 \
$(XHCI_ARGS_SLOT4) \
$(ZUSEDISK_QEMU_ARGS) \
$(DATASTICK_QEMU_ARGS) \
-object rng-random,id=rng0,filename=/dev/urandom \
-device virtio-rng-pci,rng=rng0,addr=0x5 \
-device ramfb \
@@ -1213,6 +1228,7 @@ else ifeq ($(ARCH),riscv64)
-device virtio-keyboard-pci,addr=0x3 \
$(XHCI_ARGS_SLOT4) \
$(ZUSEDISK_QEMU_ARGS) \
$(DATASTICK_QEMU_ARGS) \
-object rng-random,id=rng0,filename=/dev/urandom \
-device virtio-rng-pci,rng=rng0,addr=0x5 \
-device ramfb \
@@ -1232,6 +1248,59 @@ else ifeq ($(ARCH),riscv64)
cp $$CSV $(DOE_LATEST_DIR)/riscv64.csv 2>/dev/null || true
endif
# qemu-stick -- boot the PC stick itself (docs/v4.0.0/STICK.md 9, boards/BRINGUP.md 3.2): the
# image `make boot_image TARGET=PC` writes, a copy of it (the kernel writes to it), as a USB stick
# on the xHCI controller, booted by OVMF from its ESP. No -cdrom, no virtio disk, no ZUSEDISK:
# the kernel finds the stick through the USB storage driver and GPT code a PC uses. amd64 only
# (ARM and RISC-V sticks are later, STICK.md 10). Serial, QMP and logs/<TS>/amd64/ as `qemu`.
STICK_PC_IMG := build/boards/pc/lithos-pc.img
.PHONY: qemu-stick
qemu-stick:
ifneq ($(ARCH),amd64)
@echo "qemu-stick: the stick is the PC's -- ARCH=amd64 (ARM and RISC-V sticks are later, STICK.md 10)"; exit 1
else
@$(MAKE) -f kernel/Makefile ARCH=amd64 BOARD=pc boot_image
@cp --sparse=always $(STICK_PC_IMG) $(BUILD_DIR)/stick-run.img
@if [ ! -f $(OVMF_CODE) ]; then echo "Error: $(OVMF_CODE) not found"; exit 1; fi
@if [ ! -f $(OVMF_VARS_RO) ]; then echo "Error: $(OVMF_VARS_RO) not found"; exit 1; fi
@cp $(OVMF_VARS_RO) $(BUILD_DIR)/OVMF_VARS-stick.fd
@mkdir -p $(QEMU_LOG_DIR) $(DOE_RUNS_DIR) $(DOE_LATEST_DIR)
@TS=$$(date +%Y%m%d-%H%M%S); \
SESSION=$(QEMU_LOG_DIR)/$$TS; \
mkdir -p $$SESSION/amd64; \
LOG=$$SESSION/amd64/qemu-amd64-$$TS.log; \
CSV=$(DOE_RUNS_DIR)/doe-amd64-$$TS.csv; \
SERIAL_SOCK=$(BUILD_DIR)/qemu-serial-amd64-$$TS.sock; \
QMP_SOCK=$(BUILD_DIR)/qemu-qmp-amd64-$$TS.sock; \
echo "=== Launching QEMU (amd64): the PC stick over USB ==="; \
echo " Serial log: $$LOG"; \
echo " QMP socket: $$QMP_SOCK"; \
touch $$LOG; \
tail -n +1 -f $$LOG & TAILPID=$$!; \
qemu-system-x86_64 \
-machine q35,accel=tcg \
-cpu qemu64 \
-m 1024 \
-vga std \
-drive if=pflash,format=raw,readonly=on,file=$(OVMF_CODE) \
-drive if=pflash,format=raw,file=$(BUILD_DIR)/OVMF_VARS-stick.fd \
$(XHCI_ARGS_ROOT) \
-drive if=none,id=stickdrv,file=$(BUILD_DIR)/stick-run.img,format=raw \
-device usb-storage,bus=xhci0.0,port=1,drive=stickdrv,bootindex=0 \
-chardev socket,id=cserial,path=$$SERIAL_SOCK,server=on,wait=off,logfile=$$LOG \
-serial chardev:cserial \
-qmp unix:$$QMP_SOCK,server=on,wait=off \
$(QEMU_EXTRA) \
-display $(QEMU_DISPLAY) \
-no-reboot; \
kill $$TAILPID 2>/dev/null; wait $$TAILPID 2>/dev/null || true; \
rm -f $$SERIAL_SOCK $$QMP_SOCK; \
echo ""; \
echo "=== Serial log: $$LOG ==="; \
echo "=== Extracting DOE CSV ==="; \
bash scripts/extract_doe.sh $$LOG $$CSV || true
endif
# thumbdrive — build a generic UEFI-bootable GPT/FAT32 disk image that can be
# written directly to a USB thumbdrive (dd) and boots on real amd64 UEFI
# hardware (e.g. Beelink SER5) as well as under QEMU. This is the "generic