loader: the F8 menu on the serial line

The three F8 screens painted into the framebuffer and nowhere else. That is
right on a machine with a screen and useless on one driven over a serial cable
-- which is how this loader is usually driven, and which f8_window() already
went out of its way to support: it accepts 'o' as well as F8 because, in its
own words, "a serial console sends no scan codes at all".

So the prompt invited a serial user in, drew them a menu they could not see,
and then blocked for ever on a key they had no way to choose. The whole visible
behaviour was:

    Press F8 for boot options...
    <nothing, for ever>

Each screen echoes itself to COM1 now -- the boot menu, the resolution list and
System Information. The whole thing once on entry, then one line per *move*;
not on every keypress, because a serial terminal has no cursor to paint over
and an unrecognised key would scroll the selection past again for nothing.

Straight to COM1 rather than through print(): print() goes to ConOut until the
splash is up, and ConOut on a machine with graphics draws its text across the
menu that was just painted there.

Two details found by actually driving it, neither cosmetic:

  - **The item number is shown only where it is a key you can press.** The boot
    menu takes 1-5. The resolution list takes only W/S and Enter and is longer
    than nine entries, so numbering it printed ':', ';', '<' past the ninth --
    a character nobody can type, offering to select something.

  - **Q goes back as well as Esc.** A lone ESC byte on a serial line is
    indistinguishable from the start of an escape sequence, so the terminal
    driver holds it back waiting for the rest and it never arrives as a key.
    Esc is the obvious thing to press on a screen and unreachable on a cable --
    the same shape of problem as F8, and the same answer.

Driven end to end over serial: open the menu, walk it with W/S, open System
Information and come back, open Resolution and come back with Q, then boot.
The graphical menu is unchanged apart from the hint now naming Q.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Nexoniarz 2026-09-22 12:10:37 +02:00
commit 3f2c0bdf05
2 changed files with 135 additions and 2 deletions

View file

@ -79,6 +79,36 @@ Dropping back to protected mode to re-enter through the 32-bit multiboot path
is a mode switch whose failure mode is a triple fault with no console. The
32-bit entry is still present in `entry.S` and now has no caller.
### The menu is on the serial line too
The three F8 screens paint into the framebuffer, which is the right place for
them on a machine with a screen and nowhere at all on one driven over a serial
cable — which is how this loader is usually driven. `f8_window()` already went
out of its way to support that, accepting `o` as well as F8 because *"a serial
console sends no scan codes at all"*. So the prompt invited a serial user in,
drew them a menu they could not see, and blocked for ever on a key they had no
way to choose.
Each screen now echoes itself to COM1: the whole menu once, then one line per
*move*. Not on every keypress — a serial terminal has no cursor to paint over,
so an unrecognised key would scroll the selection past again for nothing.
Straight to COM1 rather than through `print()`, because `print()` goes to
`ConOut` until the splash is up, and `ConOut` on a machine with graphics draws
its text across the menu that was just painted there.
Two details that are not cosmetic:
- **The item number is shown only where it is a key you can press.** The boot
menu takes 1–5. The resolution list takes only W/S and Enter and is longer
than nine entries, so numbering it printed `:`, `;`, `<` past the ninth — a
character nobody can type, offering to select something.
- **Q goes back as well as Esc.** On a serial line a lone `ESC` byte is
indistinguishable from the start of an escape sequence, so the terminal
driver holds it back waiting for the rest and it never arrives as a key. Esc
is the obvious thing to press on a screen and unreachable on a cable — the
same shape of problem, and the same answer, as `o` for F8.
## 3. `kmain()`
`kernel/core/main.c`. The ordering here is not arbitrary and several steps are