/* StarForth — Steady-State Virtual Machine Runtime Copyright (c) 2023–2025 Robert A. James All rights reserved. Licensed under the StarForth License, Version 1.0 */ /** * capsule_wirebind.h - WIREBIND: the real thumbdrive-attach call site * (FABRIC-3.md §F.5/§F.23). Assembles pieces already built and * individually verified this session -- CERTVERIFY (vm_identity.h's * vm_identity_from_cert()), RUNCAP (capsule_runcap.h), the console-VM + * user-VM pair (capsule_console.h, sk_repl_dispatch_line() in repl.c) -- * into one automatic sequence, replacing the RUNCAP-TEST/PAIR-TEST * diagnostic words that exercised each piece by hand. */ #ifndef STARKERNEL_CAPSULE_WIREBIND_H #define STARKERNEL_CAPSULE_WIREBIND_H #ifdef __STARKERNEL__ #include "starkernel/homeblocks_sig.h" #include "starkernel/vm_identity.h" #include "vm.h" struct blkio_dev; /** * capsule_wirebind_verify_cert - Read the cert region off dev and verify * it against mama_vm's own Zuse identity. Shared by both * capsule_wirebind_try_attach() (the original attach) and BINDSTEP * (mama_word_use(), mama_forth_words.c -- re-verifies live on every USE * of an identity-locked VM, per FABRIC-3.md §F.9 decision 1) so both * call sites check the exact same thing the exact same way. * * No-op-and-fail (-1) if sig->cert_offset is 0 (no cert region -- a * genesis-mode Zuse drive, or simply not a regular identity drive) or * mama_vm has no installed Zuse cert yet. * * @param dev Already-open block device to read the cert from. * @param sig Its already-checked homeblocks_sig_t. * @param mama_vm Hera's own VM -- the trust root (zuse_cert_pubkey). * @param out Filled with the verified identity on success. * @return 0 on success, -1 on any failure (read, verify, or precondition). */ int capsule_wirebind_verify_cert(struct blkio_dev *dev, const homeblocks_sig_t *sig, VM *mama_vm, VMIdentity *out); /** * capsule_wirebind_try_attach - Try to verify and bind a just-attached * regular (non-Zuse) identity drive. * * No-op if sig->cert_offset is 0 (a genesis-mode Zuse drive has no cert * region -- that's capsule_zuse_boot_try_attach()'s own job, not this * one's) or if mama_vm has no installed Zuse cert yet (nothing to verify * the attached cert against). Otherwise: reads the cert devblock(s), * calls vm_identity_from_cert() against mama_vm's own zuse_cert_pubkey * and sig->drive_uuid. On success, reads the drive's own * user_identity_seed_t for its username and births a console VM + * RUNCAP-born user VM pair (idempotent -- no-ops if that username is * already live this session), installs the verified VMIdentity onto the * user VM, and registers the "~user" pairing * (sk_repl_dispatch_line(), repl.c, looks for this). Does NOT USE the * new console automatically -- that stays an explicit, later, * ACL-gated step (BINDSTEP, §F.9), not something a bare attach should * trigger silently. * * @param dev The just-attached, already-open block device. * @param sig Its already-checked homeblocks_sig_t. * @param mama_vm Hera's own VM (the verifier -- her zuse_cert_pubkey is * the trust root regular user certs are checked against). */ void capsule_wirebind_try_attach(struct blkio_dev *dev, const homeblocks_sig_t *sig, VM *mama_vm); /** * capsule_wirebind_eject - Graceful detach of whatever VM is currently * attached via the home-blocks USB path (FABRIC-3.md §F.10, decision 1). * The drive is still physically present when this runs. * * Sequence: resolve the tracked attached-VM id to a live registry entry * (no-op, returns -1, if nothing is tracked or the entry is already * dead/gone -- capsule_vm_kill()'s own idempotency covers a VM already * killed by some other path); blk_vm_flush_all() while the VM is still * alive; if the console's active VM is this same VM, reset it to Hera * (sk_repl_set_active_vm(NULL)) *before* teardown -- required, not * optional, to avoid a dangling console pointer; capsule_vm_kill() by * name; clear the tracked state. * * Single-USB-device constraint (§F.8) means there is never more than one * candidate, so this always targets "whatever's currently attached" -- * no name argument. * * @return 0 on success, -1 if nothing was attached to eject. */ int capsule_wirebind_eject(void); /** * capsule_wirebind_unclean_detach - Abrupt-path counterpart to * capsule_wirebind_eject() (FABRIC-3.md §F.10, decision 2 -- the UNCLEAN * node, closed alongside EJECT). Called from the existing * bot_msc_detach_pending hot-unplug signal (repl.c) -- the device is * already gone by the time this runs, so no flush is attempted; data * since the last flush is lost, which is correct unclean-removal * semantics. Otherwise identical to capsule_wirebind_eject(): same * active-VM reset-before-kill step, same tracked-state clear. */ void capsule_wirebind_unclean_detach(void); #endif /* __STARKERNEL__ */ #endif /* STARKERNEL_CAPSULE_WIREBIND_H */