feat(kernel): Artemis and Zuse from one disk -- the stick; virtio Artemis leaves v4
sk_v4_identity.c: a USB drive is this system's stick if its GPT has both StarshipOS partitions and
it is the disk the loader booted from (BootDisk's DiskGUID), or, when the boot was not from a
stick, the first such disk while none is attached. Then: its Artemis partition must carry a good
artemis_sig ('Artemis: the stick's signature is bad -- not used' otherwise), is attached first --
the first disk slot -- ('Artemis: the stick's partition attached'), Zuse's key is read from its
genesis marker, and its identity partition is checked and attached as before. Any other drive,
raw or GPT: 'USB: a drive that is not this system's stick -- not used'. On a pull the identity
partition is detached, then Artemis. sk_v4_identity_boot / sk_v4_run take the loader's BootDisk.
kernel_main.c: no virtio Artemis on the v4 path. kernel/Makefile: ARTDISK= attaches no virtio disk
(every QEMU target); ARTDISK stays for system=v3.
STICK.md 4 amended as ruled (R2): on v4 only this system's stick is used; users' drives minted by
this system's Zuse come with the users design after INSTALL. BRINGUP.md: Secure Boot off on every
PC (ruled 2026-10-28), RDRAND in QEMU, the SER5 smoke-test stick, A4 not on v4.
Tests: new stick_artemis (x3, no virtio disk), stick_zuse, two_sticks (replaces datastick),
artemis_unsigned, raw_ident; changed stick_boot, gpt_zuse, gpt_hotplug, midpull (replug) -- all
failed before, pass after (two test defects found and fixed: the signature's offset, the 63-char
log cut). Regression 20/20. 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 4.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
1b45f5f85f
commit
1e8a6fed34
@@ -500,19 +500,16 @@ static void sk_log_level_after_post(const BootInfo *boot_info)
|
||||
/* THE BLOCK CHAIN, for the v4 node. It asks this kernel for its blocks
|
||||
* (v4/include/v4/blocks.h, docs/v4.0.0/MESH.md 8.3). The chain is set up
|
||||
* with the calls the v3 path makes and in its order -- fast RAM and the
|
||||
* ramdrive, then PCI, then the virtio disk -- and, as there, after POST.
|
||||
* What the v3 path does next with that disk is not done here, because it is
|
||||
* Artemis's and Zuse's and v4 has neither yet: the genesis signature,
|
||||
* Zuse's root key, and the owner's word that the disk may be formatted.
|
||||
* Until an owner gives that word the subsystem reads the disk and will not
|
||||
* write it. */
|
||||
* ramdrive, then PCI -- and, as there, after POST. There is no virtio disk
|
||||
* on the v4 path: Artemis is the stick's Artemis partition, attached when
|
||||
* the stick arrives, before its identity partition (sk_v4_identity.c;
|
||||
* docs/v4.0.0/STICK.md 4, plan 2026-10-27-stick-4-one-disk.md, Task 4). */
|
||||
static BootInfo *sk_v4_boot_info;
|
||||
static void sk_v4_block_chain(void)
|
||||
{
|
||||
const size_t ram_size = (size_t)BLK_RAM_BLOCKS * BLK_FORTH_SIZE, krd_size = 1024u * 1024u;
|
||||
uint8_t *blk_ram = (uint8_t *)kmalloc(ram_size);
|
||||
uint8_t *krd = (uint8_t *)kmalloc(krd_size);
|
||||
static blkio_dev_t artemis_dev;
|
||||
size_t i;
|
||||
|
||||
/* POST is done: the logger drops to --log-level, as on the v3 path
|
||||
@@ -541,13 +538,6 @@ static void sk_v4_block_chain(void)
|
||||
} else {
|
||||
console_println("entropy: not available (continuing without)");
|
||||
}
|
||||
if (virtio_blk_find_artemis(&artemis_dev) != 0) {
|
||||
console_println("Artemis: no virtio-blk disk");
|
||||
} else if (blk_subsys_attach_device(&artemis_dev) == BLK_OK) {
|
||||
console_println("Artemis: virtio-blk attached");
|
||||
} else {
|
||||
console_println("Artemis: virtio-blk found, and could not be attached");
|
||||
}
|
||||
|
||||
/* The screen and the keyboards, as the v3 path has them: the screen is
|
||||
* cleared and stays dark -- console text goes to serial only -- until
|
||||
@@ -641,7 +631,7 @@ static void kernel_main_deep(BootInfo *boot_info) {
|
||||
* engine, in place of the v3 VM and everything below. It does not
|
||||
* return. */
|
||||
sk_v4_boot_info = boot_info;
|
||||
sk_v4_run(sk_v4_block_chain);
|
||||
sk_v4_run(sk_v4_block_chain, &boot_info->boot_disk);
|
||||
}
|
||||
}
|
||||
console_println(boot_info->args.system == KARGS_SYSTEM_V3
|
||||
|
||||
@@ -126,7 +126,7 @@ static int sk_v4_readline(void)
|
||||
}
|
||||
}
|
||||
|
||||
void sk_v4_run(void (*chain)(void))
|
||||
void sk_v4_run(void (*chain)(void), const BootDisk *boot_disk)
|
||||
{
|
||||
v4_boot boot;
|
||||
|
||||
@@ -149,7 +149,7 @@ void sk_v4_run(void (*chain)(void))
|
||||
for (;;) { }
|
||||
}
|
||||
}
|
||||
sk_v4_identity_boot();
|
||||
sk_v4_identity_boot(boot_disk);
|
||||
#if EMERGENCY_CONSOLE_ENABLED
|
||||
/* a console that needs no login has the screen from the start */
|
||||
console_fb_mirror(1);
|
||||
|
||||
@@ -9,9 +9,16 @@
|
||||
* the first node, Hera. The check that the drive is hers is v3's own
|
||||
* (capsule_zuse_boot_check()).
|
||||
*
|
||||
* Artemis and Zuse come from one disk, this system's stick
|
||||
* (docs/v4.0.0/STICK.md 4; plan 2026-10-27-stick-4-one-disk.md, Task 4): its
|
||||
* Artemis partition is attached first -- the first disk slot, where Zuse's
|
||||
* genesis marker is read -- then its identity partition is checked as an
|
||||
* identity drive always has been. No other drive is used on v4; drives of
|
||||
* users minted by this system's Zuse come with the users design after INSTALL.
|
||||
*
|
||||
* Not here (the plan's "not in this gate"): WIREBIND identities, EJECT,
|
||||
* ACL-ZUSE-BOOT, and genesis -- which writes Artemis's disk, and the v4 boot
|
||||
* does not write it yet (Phase 5).
|
||||
* does not write it yet (the stick's increment 5).
|
||||
*/
|
||||
#include "starkernel/v4/sk_v4_identity.h"
|
||||
#include "starkernel/console.h"
|
||||
@@ -22,6 +29,7 @@
|
||||
#include "starkernel/xhci_driver.h"
|
||||
#include "starkernel/blkio_usb.h"
|
||||
#include "starkernel/homeblocks_sig.h"
|
||||
#include "starkernel/artemis_sig.h"
|
||||
#include "starkernel/capsule_zuse_boot.h"
|
||||
#include "starkernel/kbd_input.h"
|
||||
#include "starkernel/gpt.h"
|
||||
@@ -44,15 +52,18 @@ static uint8_t g_zuse_root_pubkey[32];
|
||||
static int g_zuse_root_known;
|
||||
static struct blkio_dev *g_zuse_dev;
|
||||
|
||||
/* A drive in a USB slot: the raw disk; its StarshipOS identity partition as
|
||||
* a device of its own, when it has a GPT with one; and the one of the two
|
||||
* given to the block subsystem, if either was (a GPT disk is never given
|
||||
/* A drive in a USB slot: the raw disk; when it is this system's stick, its
|
||||
* StarshipOS identity and Artemis partitions as devices of their own; and
|
||||
* which of them were given to the block subsystem (a disk is never given
|
||||
* whole: docs/v4.0.0/plans/2026-10-26-stick-2-gpt-reader.md, ruled). */
|
||||
typedef struct {
|
||||
blkio_dev_t raw;
|
||||
blkio_dev_t part;
|
||||
gpt_part_dev_t part_state;
|
||||
blkio_dev_t *used;
|
||||
blkio_dev_t *used; /* the identity partition, once attached */
|
||||
blkio_dev_t art;
|
||||
gpt_part_dev_t art_state;
|
||||
blkio_dev_t *art_used; /* the Artemis partition, once attached */
|
||||
} sk_v4_drive_t;
|
||||
|
||||
/* One per slot, per xHCI controller, as repl.c's g_usb_ctrl. */
|
||||
@@ -66,6 +77,8 @@ static gpt_part_t g_gpt_parts[SK_V4_GPT_PARTS];
|
||||
|
||||
static uint64_t g_last_beat;
|
||||
static int g_said_no_genesis;
|
||||
static const BootDisk *g_boot_disk; /* the loader's: the disk it booted from */
|
||||
static int g_stick_in; /* a stick's Artemis partition is attached */
|
||||
|
||||
static const char *sk_v4_user_prefix(void)
|
||||
{
|
||||
@@ -77,13 +90,14 @@ int sk_v4_identity_present(void)
|
||||
return g_zuse_session;
|
||||
}
|
||||
|
||||
void sk_v4_identity_boot(void)
|
||||
void sk_v4_identity_boot(const BootDisk *boot_disk)
|
||||
{
|
||||
unsigned xi;
|
||||
static xhci_dev_t xhci_devs[XHCI_MAX_CONTROLLERS];
|
||||
|
||||
/* Zuse's public key, from the genesis marker on Artemis's disk */
|
||||
g_zuse_root_known = capsule_zuse_boot_root_pubkey(g_zuse_root_pubkey) == 0;
|
||||
/* Zuse's public key comes later: from the genesis marker on the stick's
|
||||
* Artemis partition, once it is attached (sk_v4_drive_arrived) */
|
||||
g_boot_disk = boot_disk;
|
||||
|
||||
/* every xHCI controller, as kernel_main.c's v3 path: a drive already in
|
||||
* a port is found by the bring-up's own port scan */
|
||||
@@ -106,24 +120,41 @@ void sk_v4_identity_boot(void)
|
||||
g_last_beat = heartbeat_ticks();
|
||||
}
|
||||
|
||||
/* A drive that has arrived: given to the block subsystem (Artemis's, the
|
||||
* kernel's), then, if it is Zuse's, her session begins. */
|
||||
/* Is the disk whose GPT was just read (gpt_read gave GPT_OK) this system's
|
||||
* stick? It has both StarshipOS partitions, and it is the disk the loader
|
||||
* booted from -- the same DiskGUID -- or, when the boot was not from a stick
|
||||
* (an ISO, an ESP image), the first such disk while none is attached. */
|
||||
static int sk_v4_is_this_stick(unsigned nparts)
|
||||
{
|
||||
uint8_t guid[16];
|
||||
|
||||
if (gpt_find(g_gpt_parts, nparts, gpt_type_starship_identity) < 0 ||
|
||||
gpt_find(g_gpt_parts, nparts, gpt_type_starship_artemis) < 0)
|
||||
return 0;
|
||||
if (g_boot_disk && g_boot_disk->is_stick) {
|
||||
gpt_disk_guid(guid);
|
||||
return memcmp(guid, g_boot_disk->disk_guid, 16) == 0;
|
||||
}
|
||||
return !g_stick_in;
|
||||
}
|
||||
|
||||
/* A drive that has arrived. This system's stick: its Artemis partition is
|
||||
* attached (the first disk slot, the block subsystem's), Zuse's public key is
|
||||
* read from its genesis marker, then its identity partition is attached and,
|
||||
* if it is Zuse's, her session begins. Any other drive is not used. */
|
||||
static int sk_v4_drive_arrived(sk_v4_drive_t *d)
|
||||
{
|
||||
blkio_dev_t *dev = &d->raw;
|
||||
blkio_dev_t *dev;
|
||||
homeblocks_sig_t sig;
|
||||
homeblocks_sig_result_t sig_rc;
|
||||
artemis_sig_t asig;
|
||||
uint8_t seed[32], pubkey[32];
|
||||
zuse_drive_t which;
|
||||
unsigned nparts;
|
||||
int gpt_rc, idx;
|
||||
int gpt_rc;
|
||||
|
||||
/* GPT first (docs/v4.0.0/STICK.md 4): a disk with a valid GPT is used
|
||||
* through its StarshipOS identity partition only; one with no such
|
||||
* partition, a damaged table or an unreadable first block is not used at
|
||||
* all; a disk with no GPT is read raw, as an identity drive always has
|
||||
* been. */
|
||||
d->used = (blkio_dev_t *)0;
|
||||
d->art_used = (blkio_dev_t *)0;
|
||||
gpt_rc = gpt_read(&d->raw, g_gpt_parts, SK_V4_GPT_PARTS, &nparts);
|
||||
if (gpt_rc == GPT_BAD) {
|
||||
console_println("GPT: a USB drive has a damaged partition table -- not used");
|
||||
@@ -133,20 +164,40 @@ static int sk_v4_drive_arrived(sk_v4_drive_t *d)
|
||||
console_println("GPT: a USB drive could not be read -- not used");
|
||||
return 1;
|
||||
}
|
||||
if (gpt_rc == GPT_OK) {
|
||||
idx = gpt_find(g_gpt_parts, nparts, gpt_type_starship_identity);
|
||||
if (idx < 0) return 1; /* no StarshipOS partition: not ours to use */
|
||||
if (gpt_part_open(&d->part, &d->part_state, &d->raw, &g_gpt_parts[idx]) != BLKIO_OK) {
|
||||
console_println("GPT: a USB drive's identity partition is not on 1 KiB blocks -- not used");
|
||||
return 1;
|
||||
}
|
||||
dev = &d->part;
|
||||
if (gpt_rc != GPT_OK || !sk_v4_is_this_stick(nparts)) {
|
||||
console_println("USB: a drive that is not this system's stick -- not used");
|
||||
return 1;
|
||||
}
|
||||
if (gpt_part_open(&d->art, &d->art_state, &d->raw,
|
||||
&g_gpt_parts[gpt_find(g_gpt_parts, nparts, gpt_type_starship_artemis)]) != BLKIO_OK ||
|
||||
gpt_part_open(&d->part, &d->part_state, &d->raw,
|
||||
&g_gpt_parts[gpt_find(g_gpt_parts, nparts, gpt_type_starship_identity)]) != BLKIO_OK) {
|
||||
console_println("GPT: the stick's partitions are not on 1 KiB blocks -- not used");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Artemis first: formatted and signed at build (STICK.md 4); a
|
||||
* signature that does not check out is not used, nor is the stick */
|
||||
if (artemis_sig_check(&d->art, &asig) != ARTEMIS_SIG_OK) {
|
||||
console_println("Artemis: the stick's signature is bad -- not used");
|
||||
return 1;
|
||||
}
|
||||
if (blk_subsys_attach_device(&d->art) != BLK_OK) {
|
||||
console_println("Artemis: the stick's partition could not be attached");
|
||||
return 0;
|
||||
}
|
||||
d->art_used = &d->art;
|
||||
g_stick_in = 1;
|
||||
console_println("Artemis: the stick's partition attached");
|
||||
/* Zuse's public key, from the genesis marker on Artemis's fence */
|
||||
g_zuse_root_known = capsule_zuse_boot_root_pubkey(g_zuse_root_pubkey) == 0;
|
||||
|
||||
/* then the identity partition, as an identity drive always has been */
|
||||
dev = &d->part;
|
||||
sig_rc = homeblocks_sig_check(dev, HOMEBLOCKS_SIG_START_FBLOCK, &sig);
|
||||
if (blk_subsys_attach_device(dev) != BLK_OK) {
|
||||
console_println("xhci: USB MSC block-subsystem attach failed");
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
d->used = dev;
|
||||
if (g_zuse_session) return 1;
|
||||
@@ -179,14 +230,23 @@ static int sk_v4_drive_arrived(sk_v4_drive_t *d)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* A drive that has left: its identity partition is let go, then its Artemis
|
||||
* partition -- in that order, because blk_subsys_detach_device() removes
|
||||
* only the chain's tail, and the identity partition was attached last. */
|
||||
static void sk_v4_drive_left(sk_v4_drive_t *d)
|
||||
{
|
||||
blkio_dev_t *dev = d->used;
|
||||
|
||||
if (!dev) return; /* never given to the block subsystem */
|
||||
d->used = (blkio_dev_t *)0;
|
||||
blk_subsys_detach_device(dev);
|
||||
if (dev != g_zuse_dev) return;
|
||||
if (dev) {
|
||||
d->used = (blkio_dev_t *)0;
|
||||
blk_subsys_detach_device(dev);
|
||||
}
|
||||
if (d->art_used) {
|
||||
blk_subsys_detach_device(d->art_used);
|
||||
d->art_used = (blkio_dev_t *)0;
|
||||
g_stick_in = 0;
|
||||
}
|
||||
if (!dev || dev != g_zuse_dev) return;
|
||||
g_zuse_session = 0;
|
||||
g_zuse_dev = (struct blkio_dev *)0;
|
||||
/* nothing of her session is left on the screen; it is dark again --
|
||||
|
||||
Reference in New Issue
Block a user