Boot manager: Niveus window, keys and wells, Instrument Sans, pointer, other systems, working power entries

The F8 menu is redrawn in the Niveus language: a window with three lights,
bevelled keys with a lit edge, wells for panels, anti-aliased corners and a
soft shadow, set in Instrument Sans rasterised into include/gfx/nvfont.h
(tools/python/mknvfont.py, make nvfont). Scale doubles on screens 1400 px tall
or more. Lists taller than the screen scroll.

The keyboard still drives everything, and a mouse, touchpad or tablet does
too: both UEFI pointer protocols are polled, hover moves the highlight, a
click activates. The cursor stays hidden until the pointer has really done
something, since the firmware installs a pointer protocol with or without a
mouse. The 'keep this resolution?' countdown is one ten-second budget however
many times the pointer moves.

Loaders found at well-known paths on any volume (Windows, Ubuntu, Debian,
Fedora, Arch, openSUSE, systemd-boot, rEFInd, other BOOTX64.EFI) are listed
and chain-loaded with LoadImage/StartImage. 'Reboot to firmware' used to halt;
it now sets OsIndications and restarts, and Restart and Shut Down call
ResetSystem.

Checked under QEMU+OVMF: menu, resolution list (incl. 2560x1600 at double
scale), system information, shut down, firmware setup, chain-loading a copy of
the loader from a second disk, and a full boot of the ISO to the login prompt.
Pointer hover and click were checked only with synthetic events: in this setup
a USB mouse or tablet delivered no event to the loader (one USB I/O handle
appeared but no pointer protocol came from it), and why was not established.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVRhxi9zpdW2uDUN4FVcao
This commit is contained in:
Nexoniarz 2026-10-26 15:31:39 +01:00
commit dee3affa3b
11 changed files with 9304 additions and 208 deletions

View file

@ -330,9 +330,64 @@ 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 boot manager
F8 (or `o` on a serial line) opens the boot manager. It used to be a text list
on a dark plate; it is now drawn in the Niveus language the site is drawn in
(`docs/Website/niveus`): a window with three lights, keys with a lit upper edge
and a shadow beneath, panels cut into the surface as wells, a graphite ground
that darkens towards the bottom, and the mark above the list.
What makes that possible in a loader is that nothing in it is large:
- **Shapes** are rounded rectangles with a vertical gradient. Corners are
anti-aliased by supersampling only the corner pixels, against a colour the
caller names. Nothing reads the framebuffer back, because that memory is
uncached on real hardware and a read per pixel is the difference between a
menu that appears and one that crawls. (The one exception is the pointer,
which saves sixteen by nineteen pixels.)
- **Type** is Instrument Sans, the face Niveus ships. A TrueType rasteriser
does not belong in a loader, so `tools/python/mknvfont.py` renders it once
into `include/gfx/nvfont.h` as 8-bit coverage bitmaps with fractional
advances, at the size for ordinary screens and at twice that for screens 1400
pixels tall or more. Rasterising at the real size is what keeps it crisp;
doubling pixels does not.
- **Layout** is computed from the item list, not drawn from fixed positions: a
list taller than the screen drops the mark, then scrolls with a bar.
An entry is a label, a newline and a line of detail. The entries are:
| Entry | Does |
|---|---|
| Boot SchOS / (verbose) | the two ways of starting this system |
| other systems | one entry per loader found at a well-known path on any volume: Windows Boot Manager, Ubuntu, Debian, Fedora, Arch, openSUSE, systemd-boot, rEFInd, and any other `\EFI\BOOT\BOOTX64.EFI` that is not this one. Chosen, they are started with the firmware's own `LoadImage`/`StartImage`, and if the other loader returns, the menu is still here |
| Resolution | the list of modes the firmware offers, or a typed size, with the "keep this?" confirmation |
| System Information | firmware, UEFI revision, processor, memory, display, ACPI |
| Firmware Setup | sets `OsIndications` and restarts into the firmware's own settings; on firmware that does not support it, says so instead of restarting for nothing |
| Restart, Shut Down | `ResetSystem` |
| Remote debugging | `make DEBUG=1` builds only |
Keyboard, mouse, touchpad and touchscreen all drive it: both UEFI pointer
protocols are polled (a mouse reports movement, a tablet reports position),
hover moves the highlight, a click activates, and the wheel scrolls. All input
goes through one function, `wait_event()`, so every screen behaves the same way.
The cursor stays hidden until the pointer has actually done something, because
the firmware's console layer installs a pointer protocol whether or not a mouse
is attached. USB devices appear some time after their controller is connected
and the menu is already up by then, so the loader connects every controller when
the menu opens and looks for pointers again twice a second for ten seconds.
The "keep this resolution?" confirmation counts ten seconds down once, however
many times the pointer moves over the button: a person with a garbled screen
waving a mouse around must not be able to keep postponing the revert.
**Not verified:** hover and click were exercised with synthetic events. Under
QEMU and OVMF a USB mouse or tablet never delivered an event to the loader, so
the pointer path has not been seen working on a device -- real hardware first.
### The menu is on the serial line too
The three F8 screens paint into the framebuffer, which is the right place for
The 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
@ -351,7 +406,7 @@ 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
menu takes 1–9. 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

View file

@ -29,10 +29,10 @@ asked for one. That is the right default and it has one bad consequence —
to enable it.** A laptop with no serial port that stops before it can draw has
nowhere to say why, and `schinitd enable` needs a prompt that does not exist.
So a build made with `make DEBUG=1` has a sixth entry in the F8 menu:
So a build made with `make DEBUG=1` has one more entry at the end of the F8 menu:
```
> 6. Remote debugging: off
> Remote debugging: off
```
Picking it toggles the entry, booting carries the choice through