--- name: schos-boot-split description: boot/ is split into bios/ and uefi/; the hand-off contract is what makes a second loader cheap metadata: node_type: project --- **`boot/bios/`** holds the MBR (`bootasm.S`), the El Torito CD stub (`cdboot.S`) and the real-mode stage 2 (`stage2.S`, `stage2main.c`). **`boot/uefi/`** is empty and documented. Separate directories rather than `#ifdef`s, agreed with Nexoniarz 2026-08-09, because the two share almost nothing: a BIOS loader lives in 16-bit real mode, reaches the firmware through software interrupts, and walks itself into long mode; a UEFI loader is a 64-bit PE 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, written down in `boot/README.md`** — ELF segments placed, long mode with interrupts off, a memory map of 24-byte entries at `E820_MAP_ADDR`, framebuffer geometry at `VBE_INFO_ADDR`, verbose flag at `BOOT_VERBOSE_FLAG_ADDR`. A second loader is correct exactly when it satisfies that. **The trap for the UEFI work:** `GetMemoryMap` returns `EFI_MEMORY_DESCRIPTOR`s, which are not E820 entries. Translate them into what `kernel/arch/x86_64/e820.c` already parses rather than teaching the kernel a second format. clang can emit PE/COFF directly (`--target=x86_64-unknown-windows`, `-fuse-ld=lld-link`), so UEFI needs **no new toolchain** — the same LLVM install already builds every other target here. Write the handful of UEFI structures from the specification rather than importing gnu-efi or EDK II: that is both a licensing question ([[schunix-licensing]]) and a large dependency for something small. Build output paths under `$(BUILD)/boot/` were deliberately left unchanged when the sources moved; only source paths differ.