From 1963a0a6d7398a426d0701f90a5bc796e32899ae Mon Sep 17 00:00:00 2001 From: salmonik Date: Fri, 31 Jul 2026 02:55:10 +0200 Subject: feat(rsboot): initial commit — UEFI bootloader extracted from RNG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 AGENTS.md (limited to 'AGENTS.md') diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..a39c192 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,82 @@ +# AGENTS.md — rsboot (RaiserSoft Bootloader) + +## Identity + +rsboot is a custom **UEFI** bootloader (PE32+, x64) that loads a Linux kernel + +initramfs from an ext2 partition using UEFI file system protocols, then +launches the kernel via `LoadImage`/`StartImage`. Single-stage design — +no MBR, no real mode, no stage1/stage2 split. + +This is a standalone submodule of the [RNG](https://git.2137697.xyz/RaiserSoft/rng) project. + +## Code + +- **Language:** C (freestanding, `-m64`, `-ffreestanding`, `-fPIE`, `-mabi=ms`). +- **Assembler:** none currently (no `.asm` files needed). +- **Linker:** `ld` with `-Ttext=0x1000 -e efi_main`, producing an ELF64 + intermediate (`main.elf`). +- **PE conversion:** `objcopy -O pei-x86-64 --subsystem=10` converts the ELF + to a PE32+ image, then Python scripts fix up headers and pad for + firmware compatibility. +- **Dependencies:** none. No libc, no CRT — just raw UEFI protocol calls. +- **Debug:** UEFI console output (`con_out->OutputString()` via serial + + framebuffer as configured by the firmware). +- **UEFI types:** `uefi.h` provides minimal stand-alone type definitions, + GUIDs, and protocol structs (system table, boot services, file system + protocol, loaded image protocol, etc.). + +## Source Layout + +``` +main.c — EFI entry point, loads kernel + initrd, starts image +uefi.h — UEFI types, GUIDs, protocol structs +Makefile — builds BOOTX64.EFI +fix_pe_simple.py — PE header fixup (ImageBase, DllChar, strip relocs) +pad_for_optiplex.py — PE padding for Optiplex 7010 firmware +``` + +## Build + +```sh +make # produces ../build/bootloader/BOOTX64.EFI +``` + +The build pipeline: + +1. **main.o** — compiled with `-fPIE -fshort-wchar -mno-red-zone -mabi=ms` +2. **main.elf** — linked as position-independent ELF64 starting at text 0x1000 +3. **BOOTX64.EFI** — objcopy to `pei-x86-64`, subsystem=10 (EFI application) +4. **fix_pe_simple.py** — sets ImageBase, marks RELOCS_STRIPPED (PIE code + uses only PC-relative addressing, so no fixups needed), sets NX | + DYNAMIC_BASE | HIGH_ENTROPY_VA, clears .reloc data directory and + checksum +5. **pad_for_optiplex.py** — if the PE is smaller than ~160KB, pad to match + the size systemd-boot uses (some AMI Aptio firmware versions on + Optiplex 7010 reject smaller PE files) + +## Kernel Loading Flow + +1. Get our own `LoadedImage` protocol via `handle_protocol` +2. Get `SimpleFileSystem` from the device handle +3. `OpenVolume` → root directory +4. Open `\bzImage`, read into allocated pages +5. Open `\initramfs.cpio.gz`, read into allocated pages +6. `LoadImage` (from memory, not device path) → kernel handle +7. Set kernel's `load_options` (command line) on its `LoadedImage` protocol +8. `StartImage` → kernel takes over + +## Key Conventions + +- **GUIDs:** EFI_LOADED_IMAGE_GUID, EFI_SIMPLE_FILE_SYSTEM_GUID (defined + in `uefi.h` matching the UEFI 2.10 spec). +- **Boot device:** The device we were loaded from (our `LoadedImage.device_handle`). +- **File paths:** `\bzImage`, `\initramfs.cpio.gz` (backslash prefix for + UEFI device paths). +- **Cmdline:** `console=ttyS0,115200 console=tty0 earlyprintk=serial,ttyS0,115200 loglevel=3 rng_tty=ttyS0 initrd=\initramfs.cpio.gz` +- **Memory allocation:** UEFI boot services `AllocatePages` (type 6 = + EfiLoaderData) for kernel/initrd buffers; `AllocatePool` for cmdline copy. +- **Compilation quirks:** `-mabi=ms` is required so UEFI calling convention + (Microsoft x64 ABI) is used; `-fshort-wchar` makes `wchar_t` 16-bit to + match UEFI's CHAR16; `-mno-red-zone` because the red-zone can be clobbered + by UEFI firmware handlers. +- **Commits:** `feat(rsboot):` prefix. -- cgit v1.2.3