Files
LithosAnanake/include/starkernel/repl.h
T
Robert Allan JamesandClaude Sonnet 5 63b8b3bc29
Build / build-aarch64-iso (push) Waiting to run
Build / build-amd64-iso (push) Waiting to run
Build / build-riscv64-img (push) Waiting to run
Migrate Hera->Artemis storage-attach to a real message round-trip
Hera still polls xHCI and sig-checks attached drives, but the storage
registration step (blk_subsys_attach_device(), now wrapped as the
BLK-ATTACH primitive) moves to Artemis's own dictionary, reached via
HERA-BLK-ATTACH-REQ/BLK-ATTACH-ACK (VM-EXEC, since Hera can't load her
own messaging.4th -- see the doc comment in repl.c). Identity birth
(Zuse genesis / WIREBIND) is deferred until the ack confirms storage
actually succeeded, instead of running synchronously underneath a
storage call that might fail ("wait for ack, safer for identity data").

Caught and fixed a real bug live during acceptance testing: Artemis's
ACK-APPEND-NUM fed a single-cell value into <# #S #> (which expects a
double-cell pair), causing a stack underflow the first time
HERA-BLK-ATTACH-REQ ran. Fixed with the same `0 SWAP` convention every
other numeric-append helper in this codebase already uses.

Verified booting clean to (zuse) ok> with no VM-EXEC errors on all
three architectures (amd64/aarch64/riscv64).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Ec88YKxxhZGG1RNnune78
2026-09-07 21:22:04 -04:00

188 lines
7.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
StarForth — Steady-State Virtual Machine Runtime
Copyright (c) 20232025 Robert A. James
All rights reserved.
Licensed under the StarForth License, Version 1.0
*/
/**
* repl.h - Emergency FORTH REPL for LithosAnanke kernel
*/
#ifndef STARKERNEL_REPL_H
#define STARKERNEL_REPL_H
#include "vm.h"
#include "starkernel/homeblocks_sig.h"
struct blkio_dev;
#ifdef __cplusplus
extern "C" {
#endif
/**
* sk_repl - Run the emergency FORTH REPL on the serial console.
*
* Blocks until vm->halted is set (BYE word) or the VM encounters a halt.
* Runs with interrupts enabled; the APIC heartbeat continues to fire.
*
* @param vm Mama VM instance (must be fully initialised)
*/
void sk_repl(VM *vm);
/**
* sk_repl_run - Bare REPL loop (no banner).
*
* Same as sk_repl but skips the version/welcome banner. Used by START
* to enter a child VM's interpreter loop without reprinting the header.
*
* @param vm Fully initialised VM instance
*/
void sk_repl_run(VM *vm);
/**
* sk_repl_step - Execute one REPL turn on a VM and return.
*
* Prints the VM's prompt, reads one line, interprets it, prints ok/ERROR,
* then returns. Used by the Compudynamics VM-STEP primitive so Hera can
* give a single REPL quantum to a child VM without surrendering control
* for the full sk_repl_run() loop.
*
* @param vm Fully initialised VM instance
* @return 1 if the VM is still running, 0 if it halted during this turn
*/
int sk_repl_step(VM *vm);
/**
* sk_repl_set_active_vm - Redirect REPL input to a different VM (USE word).
*
* Pass NULL to restore default dispatch (Mama's VM).
* The change takes effect on the next REPL iteration.
*
* @param vm Target VM, or NULL for default
*/
void sk_repl_set_active_vm(VM *vm);
/**
* sk_repl_get_active_vm - Return the current USE-redirected VM, or NULL.
*/
VM *sk_repl_get_active_vm(void);
/**
* sk_repl_get_homeblocks_dev / sk_repl_get_homeblocks_sig - The currently
* attached home-blocks USB drive, or NULL if none is attached / the
* attached drive didn't check out as HOMEBLOCKS_SIG_OK (FABRIC-2.md
* §F.6/§F.9/§F.18). Both return NULL together; never one without the
* other.
*/
struct blkio_dev *sk_repl_get_homeblocks_dev(void);
const homeblocks_sig_t *sk_repl_get_homeblocks_sig(void);
/**
* sk_repl_get_attached_blk_dev - The currently attached USB block
* device, regardless of home-blocks recognition (FABRIC-2.md
* §F.8/§F.19) -- MINT's own target, since a blank/unminted drive never
* sets sk_repl_get_homeblocks_dev() above. NULL if nothing is attached.
*/
struct blkio_dev *sk_repl_get_attached_blk_dev(void);
/**
* sk_repl_register_words - Registers repl.c's own FORTH-visible words
* (currently just BLK-ATTACH-ACK, Artemis's storage-attach reply target --
* see sk_word_blk_attach_ack()'s doc comment in repl.c). Call once from
* register_forth79_words() alongside the other __STARKERNEL__-only
* registration calls.
*/
void sk_repl_register_words(VM *vm);
/**
* sk_console_getkey - Real body of the standard dictionary's KEY word
* (called from shim.c's getchar()). Blocks until a key is available from
* either input source (serial console or the PS2/virtio keyboard-event
* bridge), servicing the heartbeat/idle loop while waiting so a KEY call
* from inside any word never stalls the heartbeat. No echo -- that's the
* caller's responsibility, same as any standard KEY.
*
* @param active_vm VM whose idle dispatch runs while waiting (see
* sk_repl_idle()'s own doc comment on why this is a
* parameter rather than read via sk_repl_get_active_vm())
* @return the key read, as an unsigned byte value
*/
int sk_console_getkey(VM *active_vm);
/**
* sk_console_key_available - Real body of the standard dictionary's
* ?TERMINAL word (called from sf_terminal_ready()). Non-blocking peek:
* returns 1 if a key is ready without consuming it (a following
* sk_console_getkey() returns that exact key), 0 otherwise.
*/
int sk_console_key_available(void);
/**
* sk_console_readline - Real body of the standard dictionary's
* QUERY/EXPECT words (called from shim.c's fgets()). Reads one line from
* the console with echo and backspace support, servicing the heartbeat/
* idle loop while waiting -- the same line editor the REPL's own prompt
* uses internally, so a mid-word EXPECT behaves identically to typing at
* "ok>" itself.
*
* @param buf Destination buffer
* @param size Buffer capacity, including the NUL terminator
* @param active_vm VM whose idle dispatch runs while waiting
* @param reanchor_prompt Nonzero to re-print the "ok> " prompt whenever
* an idle bottom half (heartbeat, USB attach/detach) writes
* to the console while this readline blocks at a bare,
* untyped prompt -- keeps the top-level prompt as the last
* thing shown once the chatter dies down. Callers whose
* prompt line is their own (shim.c's fgets(), i.e.
* QUERY/EXPECT/ACCEPT) pass 0 so "ok> " never gets stamped
* onto their mid-word input context.
* @return number of characters placed in buf, not counting the NUL, or -1
* (2026-09-06) when reanchor_prompt is nonzero and the attached
* identity logged out while this call was blocked waiting for
* input with nothing typed yet -- see repl.c's own doc comment
* on this function for what a caller must do with -1.
*/
int sk_console_readline(char* buf, int size, VM* active_vm, int reanchor_prompt);
/**
* sk_repl_headless_wait - Idle-service loop with no interactive surface
* at all: no banner, no prompt, no console_getc()/readline. Runs
* heartbeat_service() and the same SK_IDLE_BEAT_INTERVAL-gated
* sk_repl_idle(mama) cadence sk_console_readline()'s own idle branch
* uses -- so USB/WIREBIND/Zuse-attach detection, the heartbeat, and all
* other idle-tick subsystems keep running -- until a real identity is
* currently attached (Zuse's own session, or a WIREBIND user), at which
* point it returns.
*
* Revised 2026-09-06: originally exited on a one-way sticky "has anyone
* ever logged in this boot" flag (sk_console_mark_login()/sk_console_
* login_occurred(), both retired) -- that let a real gap through, found
* live: once the flag tripped once, it never reset, so a later full
* logout (nobody attached at all) fell through to a bare, unauthenticated
* prompt instead of going silent again. This now checks live attach
* state instead (repl.c's own sk_console_identity_present()), and is
* called from two places: once from kernel_main.c in place of an
* immediate sk_repl(mama) call when EMERGENCY_CONSOLE_ENABLED is off (the
* default, 2026-09-05) -- no thumbdrive, no prompt, at boot -- and again
* from inside sk_repl_run()'s own main loop, every time nobody is
* currently attached, so the same silence re-engages after any later
* logout mid-boot too. When EMERGENCY_CONSOLE_ENABLED is on (the debug/
* recovery escape hatch), neither call site applies -- the console shows
* immediately and stays visible regardless of attach state, exactly as
* before this change.
*
* @param mama Hera's own VM instance -- the idle-dispatch target,
* same as every other sk_repl_idle() caller uses.
*/
void sk_repl_headless_wait(VM *mama);
#ifdef __cplusplus
}
#endif
#endif /* STARKERNEL_REPL_H */