SchOS/.claude/memory/schunix-iso-boot.md
Nexoniarz 08a1a9033a boot: separate BIOS from UEFI
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.
2026-08-09 16:00:03 +02:00

2.6 KiB

name description metadata
schunix-iso-boot `make iso` builds a bootable CD; it needs El Torito no-emulation plus ATAPI because the loader never uses INT 13h
node_type type originSessionId modified
memory project a665e14b-86bd-4b41-a228-51377f3e9225 2026-08-04T17:28:16.714Z

make iso produces a bootable schunix.iso (added 2026-08-04). Always a RAMROOT build — a disc that needed a second disk for its root would not be an install medium, and read-only media cannot host a writable root anyway.

Why it is built the way it is. Schunix's loader never calls INT 13h: it drives the IDE registers directly, and stage2 has already switched to protected mode before it reads the kernel. That rules out both El Torito emulation modes (hard-disk emulation exists only through the BIOS) and floppy emulation (2.88 MB cap). So:

  • boot/bios/cdboot.S — a separate stage 1 for optical media. tools/mkiso.sh passes -boot-load-size 25, so the BIOS loads cdboot and all 24 sectors of stage2 before anything of ours runs, putting stage2 at 0x7E00 exactly where bootasm.S would have. cdboot only records the medium and jumps.
  • The medium flag is one byte past the verbose flag, at VBE_INFO_ADDR + 0x101. bootasm.S must clear it or a warm reboot from a disc sends a hard-disk boot looking for an optical drive.
  • stage2main.c gained an ATAPI reader (PACKET + SCSI READ(12), 2048-byte blocks with a one-block cache) and finds where it was loaded from by reading the El Torito boot catalog: LBA 17, pointer at offset 0x47, then Load RBA at catalog offset 40.
  • Do not pass -boot-info-table to xorriso — it patches 56 bytes over offset 8 of the boot image, which is the middle of cdboot's code. That is why the boot catalog is parsed instead.

The trap that cost the most time here: ATAPI's 0x14/0xEB signature is only valid until something issues a command, and the BIOS has just finished reading the disc to load us — so on a CD boot the signature is always stale. atapi_reset() (SRST via the control port at io + 0x206) is what makes the probe work.

Two unbounded waits were hiding behind that, both of which hung with no message on a machine with no ATA disk: waitdisk() in stage2main.c and idewait() in kernel/dev/ide.c. Both are bounded now, ideinit() tolerates an empty channel, and anything that probes a disk must call ide_disk_present() first — iderw() rightly panics on an absent drive.

Check it with pwsh -File tools/bootcheck.ps1 -Iso -Fb, which boots with no hard disk attached at all. See schunix-verify-by-driving-shell.