boot/bios/ now holds the MBR, the El Torito stub and the real-mode stage 2; boot/uefi/ is empty and documented. Separate directories rather than #ifdefs, because the two share almost nothing. A BIOS loader lives in 16-bit real mode, reaches the firmware through software interrupts, and walks itself up into long mode. A UEFI loader is a 64-bit PE that the firmware has already placed in long mode with paging on, calling services through a table of function pointers. What they do share is the hand-off contract, which boot/README.md now writes down: ELF segments placed, long mode, a 24-byte-entry memory map at E820_MAP_ADDR, framebuffer geometry at VBE_INFO_ADDR. That contract is the point of documenting it now. UEFI's GetMemoryMap returns EFI_MEMORY_DESCRIPTORs, and the right move is to translate them into the entries kernel/arch/x86_64/e820.c already parses rather than teach the kernel a second format. Build output paths under $(BUILD)/boot are unchanged; only sources moved.
61 lines
3.6 KiB
Markdown
61 lines
3.6 KiB
Markdown
---
|
|
name: schunix-boot-splash-logo
|
|
description: "The boot logo pipeline, why the loader draws it rather than the kernel, and the STAGE2_SECTORS trap that consolidating it exposed."
|
|
metadata:
|
|
node_type: memory
|
|
type: project
|
|
originSessionId: 9d8a2aef-bcf0-47a0-96c6-f706efab4a95
|
|
modified: 2026-08-08T12:04:49.027Z
|
|
---
|
|
|
|
The boot splash shows the `Assets/Schunix Small Logo.png` mark (an SX monogram in
|
|
a ring) above the `S C H U N I X` wordmark and its accent rule, all centred as
|
|
one group. Verified rendering correctly on 2026-08-08.
|
|
|
|
**The logo is drawn by the bootloader, not the kernel.** This is the
|
|
counter-intuitive part and it is a timing fact, not a preference: the kernel does
|
|
not reach `vga_init()` until roughly the last 300ms of a ~2.8s boot, so a
|
|
kernel-drawn logo appeared for about one frame before `console_takeover()` wiped
|
|
it. Drawn from `splash()` in `boot/bios/stage2main.c` it is up for the whole boot.
|
|
`kernel/dev/vga.c` keeps the same drawing code against the same mask
|
|
(`vga_draw_logo`, `vga_logo_centered`) for things that want the mark *after*
|
|
boot — the crash screen, eventually `schinit`. Don't "fix" the duplication by
|
|
deleting the loader's copy.
|
|
|
|
**Pipeline:** `tools/mklogo.py` (host Python, has its own PNG inflate +
|
|
un-filter) crops to the mark, box-downscales, normalises to full strength, packs
|
|
to a 4-bit coverage mask, and writes `include/logo.h`. Run `make logo` — it is
|
|
*not* a build dependency, and `include/logo.h` is committed, on the same
|
|
reasoning as `include/font.h`. The mask is coverage, not colour, so the palette
|
|
stays in [[schunix-console-tty]]'s `include/theme.h`; the loader composites it in
|
|
`SCH_FG` because the source art is a silver gradient and the accent is reserved
|
|
for the one rule. 4 bits rather than 8 because the header is included by the
|
|
*bootloader*, where size is a boot constraint.
|
|
|
|
**`STAGE2_SECTORS` was encoded in five places, not the three `docs/layout.md`
|
|
claimed.** Raising it 24 → 48 to fit the 8 KiB mask proved it: the `dd seek=25`
|
|
offset stayed behind and the kernel got written straight over stage2's tail.
|
|
The five were `boot/bios/bootasm.S`, `boot/bios/stage2main.c`, the `dd seek=`, and *twice*
|
|
inside `tools/mkiso.sh` (its size assertion and `-boot-load-size`). It now lives
|
|
only in the root Makefile, which passes `-DSTAGE2_SECTORS` and exports it to
|
|
mkiso; the `#define`s left in the boot sources are `#ifndef` fallbacks. Hard
|
|
ceiling is 65 sectors — stage2 loads at `0x7E00` and must not reach the
|
|
multiboot kernel-search buffer at `0x10000` — and `stage2main.c` now
|
|
static-asserts that. See also [[schunix-iso-boot]].
|
|
|
|
**`tools/splashshot.ps1`** captures a burst of QEMU screendumps across early
|
|
boot and reports each frame's distinct-colour count, because the splash window
|
|
is too short to hit with a single guessed delay. It uses `-snapshot` plus
|
|
`file.locking=off` so it runs while an interactive QEMU has the images open —
|
|
booting from copies also works but means duplicating all 153 MB of
|
|
`build/fs.img` per run. Colour counts are the
|
|
assertion: ~2 means text console or blank, 18 means the 4bpp logo is up. If it
|
|
ever reads 156 again, something is drawing an 8-bit mask.
|
|
|
|
**Two traps, both hit while doing this:**
|
|
- `$(shell expr $(N) \* 512)` in a Makefile does not work — make passes the
|
|
backslash through, sh globs the `*`, and expr receives a directory listing.
|
|
Make silently carries on with nonsense. Use `$$(( ))` in the recipe.
|
|
- `make iso` was failing when this was written, for unrelated reasons since
|
|
fixed — see [[schunix-ramdisk-root-sizing]]. `-boot-load-size 49` is now
|
|
verified: the ISO boots from optical media only.
|