feat(v4): the screen and the keyboards

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>
This commit is contained in:
rajames
2026-10-26 18:02:27 -04:00
co-authored by Claude Opus 5.5
parent 0dbc98c049
commit cab0ffb487
76 changed files with 40541 additions and 26 deletions
+25 -9
View File
@@ -465,6 +465,21 @@ void kernel_main(BootInfo *boot_info) {
}
#ifdef STARFORTH_ENABLE_VM
/* The framebuffer the firmware handed over, as the console's screen, in
* the pixel format GOP reported. Both systems' boots call it. */
static void sk_console_fb_from_boot(const BootInfo *boot_info)
{
if (boot_info->framebuffer.base != NULL && boot_info->framebuffer.size > 0) {
FbPixelFormat fb_fmt;
switch (boot_info->framebuffer.pixel_format) {
case (UINT32)PixelRedGreenBlueReserved8BitPerColor: fb_fmt = FB_PIXEL_RGBX32; break;
case (UINT32)PixelBlueGreenRedReserved8BitPerColor: fb_fmt = FB_PIXEL_BGRX32; break;
default: fb_fmt = FB_PIXEL_BGRX32; break;
}
console_fb_init(&boot_info->framebuffer, fb_fmt);
}
}
/* The logger after POST: whatever --log-level asked for (default: LOG_WARN).
* Both systems' boots call it once POST is done. */
static void sk_log_level_after_post(const BootInfo *boot_info)
@@ -523,6 +538,15 @@ static void sk_v4_block_chain(void)
} 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
* Zuse logs in (docs/v4.0.0/STICK.md 2 and 5.3; sk_v4_identity.c turns
* it on). The virtio keyboard is the riscv64/aarch64 machines'; a
* no-op where there is none. */
console_fb_mirror(0);
sk_console_fb_from_boot(sk_v4_boot_info);
(void)virtio_input_find_keyboard();
}
#endif
@@ -842,15 +866,7 @@ static void kernel_main_deep(BootInfo *boot_info) {
* see 4.5f) in exchange for the fuller on-screen record; Captain Bob's
* call, made after 4.5f's -O2 experiment showed the earlier indefinite
* -O0 stall was a compiler-optimization problem, not a correctness one. */
if (boot_info->framebuffer.base != NULL && boot_info->framebuffer.size > 0) {
FbPixelFormat fb_fmt;
switch (boot_info->framebuffer.pixel_format) {
case (UINT32)PixelRedGreenBlueReserved8BitPerColor: fb_fmt = FB_PIXEL_RGBX32; break;
case (UINT32)PixelBlueGreenRedReserved8BitPerColor: fb_fmt = FB_PIXEL_BGRX32; break;
default: fb_fmt = FB_PIXEL_BGRX32; break;
}
console_fb_init(&boot_info->framebuffer, fb_fmt);
}
sk_console_fb_from_boot(boot_info);
/* Copy capsule directory header to heap (has pointer field needing update) */
CapsuleDirHeader *live_dir = (CapsuleDirHeader *)kmalloc(sizeof(CapsuleDirHeader));