1
0
Fork
You've already forked multistub
0
No description
  • C 57.1%
  • Python 28.3%
  • Assembly 10.7%
  • Meson 2.4%
  • Shell 1.5%
2026年03月17日 00:32:27 +01:00
cross Add empty project copied from stem 2026年03月17日 00:23:33 +01:00
src Rename stub2 to multistub 2026年03月17日 00:32:27 +01:00
test Rename stub2 to multistub 2026年03月17日 00:32:27 +01:00
tools Rename stub2 to multistub 2026年03月17日 00:32:27 +01:00
.gitignore Rename stub2 to multistub 2026年03月17日 00:32:27 +01:00
meson.build Rename stub2 to multistub 2026年03月17日 00:32:27 +01:00
meson.options Rename stub2 to multistub 2026年03月17日 00:32:27 +01:00
README.md Add support for multiboot1 2026年03月17日 00:24:00 +01:00

stub2

A UEFI stub that boots Multiboot2 kernel images. The kernel and optional modules are embedded into PE sections of the stub binary, creating a single self-contained .efi executable that can be placed on an EFI System Partition and booted by firmware without any external bootloader.

Building

Requires: GCC, meson (>= 1.1.0), python3.

meson setup build --cross-file cross/x86_64.txt
meson compile -C build

Produces build/stub2x64.efi.

Embedding a kernel

Use tools/mkstub.py to produce a ready-to-boot EFI binary:

python3 tools/mkstub.py kernel.elf -o my-stub.efi

With a command line and modules:

python3 tools/mkstub.py kernel.elf -o my-stub.efi \
 --cmdline "console=ttyS0 root=/dev/sda1" \
 --module initramfs.img:initrd \
 --module config.cfg

Module syntax is PATH or PATH:CMDLINE. Up to 10 modules are supported.

By default the script looks for build/stub2x64.efi; override with --stub.

Place the resulting my-stub.efi on an ESP (e.g. as EFI/BOOT/BOOTX64.EFI) and boot it from UEFI firmware.

Manual embedding

Sections can also be added individually with objcopy. Use tools/pesvma.py to compute the correct PE section VMA (must be called after each addition):

cp build/stub2x64.efi my-stub.efi
VMA=$(python3 tools/pesvma.py my-stub.efi)
objcopy \
 --add-section .kernel=kernel.elf \
 --change-section-vma ".kernel=$VMA" \
 --set-section-flags .kernel=alloc,load,readonly,data \
 my-stub.efi

Each call to pesvma.py returns the next available VMA for the PE as it currently is, so call it again before adding another section.

Kernel requirements

The embedded kernel must contain a valid Multiboot2 header within the first 32768 bytes, declaring architecture = 0 (i386).

ELF kernels

ELF kernels (32-bit or 64-bit) are loaded by their PT_LOAD segments to the p_paddr physical addresses. All segments must fit in the first 4GB.

The entry point defaults to the ELF e_entry, but can be overridden with MB2 header tags:

  • ENTRY_ADDRESS (type 3): overrides e_entry
  • ENTRY_ADDRESS_EFI64 (type 9): preferred when present (since we boot from UEFI64)

The entry point virtual address is converted to a physical address via the PT_LOAD segment mapping.

Flat binary kernels

Non-ELF kernels are loaded using the ADDRESS header tag (type 2), which must be present along with ENTRY_ADDRESS (type 3) or ENTRY_ADDRESS_EFI64 (type 9). The ADDRESS tag fields specify where and how much to load:

  • header_addr: address corresponding to the MB2 header in memory
  • load_addr: start of the load region
  • load_end_addr: end of file data (0 = load entire file)
  • bss_end_addr: end of BSS region (0 = no BSS)

The stub calculates the file offset to load from: load_file_offset = header_file_offset - (header_addr - load_addr)

python3 tools/mkstub.py kernel.bin -o my-stub.efi

Machine state at kernel entry

  • 32-bit protected mode, paging disabled
  • EAX = 0x36d76289 (Multiboot2 magic)
  • EBX = physical address of the Multiboot2 Information structure
  • CS = 32-bit code segment (base 0, limit 4GB)
  • DS/ES/FS/GS/SS = 32-bit data segment (base 0, limit 4GB)
  • ESP = 0 (kernel must set up its own stack before using call/push)
  • All other general-purpose registers = 0
  • Interrupts disabled

Kernel command line

Pass --cmdline to mkstub.py. The string is passed to the kernel as the CMDLINE MBI tag (type 1). If omitted, an empty string is used.

Modules

Pass --module (up to 10 times) to mkstub.py. Each module is a raw binary blob loaded to a page-aligned physical address below 4GB and passed as a MODULE MBI tag (type 3). Use PATH:CMDLINE syntax to set per-module command lines.

MBI tags provided

The Multiboot2 Information structure passed to the kernel contains these tags (in order):

Tag Type Description
CMDLINE 1 Kernel command line from .cmdline section (empty string if absent)
BOOT_LOADER_NAME 2 "stub2"
MODULE 3 One per embedded .moduleN section, with cmdline from .modcfg
LOAD_BASE_ADDR 21 Physical base address of the lowest loaded ELF segment
ELF_SECTIONS 9 ELF section headers (ELF only, when requested via information request tag)
FRAMEBUFFER 8 GOP framebuffer info (if GOP is available)
ACPI_OLD 14 RSDP v1 (if present in EFI configuration tables)
ACPI_NEW 15 RSDP v2 (if present in EFI configuration tables)
EFI64 12 EFI system table pointer
BASIC_MEMINFO 4 Conventional memory below 640K and above 1MB
MMAP 6 Memory map (EFI memory map converted to MB2 types)
EFI_MMAP 17 Raw EFI memory map
END 0 Terminator