The Linux boot protocol plays an important role in the initialization of the Linux operating system, emphasizing the importance of system optimization and scalability. This system ensures a seamless transfer of control from the bootloader to the Linux kernel by providing essential information including memory map, command line parameters, and device specifications. By adhering to a uniform boot protocol, Linux achieves a level of versatility across the hardware spectrum of architectures and bootloader functions. Essentially, this protocol is a commitment to a standardized approach that is not only stable but also facilitates bootloader development, improving compatibility and reliability. In particular, the Linux boot protocol greatly contributes to the overall robustness and reliability of the bootstrapping process on Linux-based systems. Almost, if not all, widely available bootloaders that exist on the market are able to speak this protocol and Unikraft, being unable to be detected by these bootloaders as a Linux Boot Protocol compliant system, is hindering the ability to boot on a very large amount of platforms.
I already compiled qemu 9.0.1
using the following flags: --enable-debug --extra-cflags="-g3" --extra-ldflags="-g3" --disable-strip --enable-kvm --enable-avx2 --enable-avx512bw --enable-avx512f
to help me debug.
At the moment, I am looking into creating support/scripts/mklinux_x86.py
using as inspiration the already existing mklinux.py
and the ARM64 PR.
The mklinux_x86.py
script mainly contains functions that help parse and set certain fields of the image header.
The header will look as follows:
Offset/Size | Protocol | Name | Meaning |
---|---|---|---|
01F1/1 | ALL(1) | setup_sects | The size of the setup in sectors |
01F2/2 | ALL | root_flags | If set, the root is mounted readonly |
01F4/4 | 2.04+(2) | syssize | The size of the 32-bit code in 16-byte paras |
01F8/2 | ALL | ram_size | DO NOT USE - for bootsect.S use only |
01FA/2 | ALL | vid_mode | Video mode control |
01FC/2 | ALL | root_dev | Default root device number |
01FE/2 | ALL | boot_flag | 0xAA55 magic number |
0200/2 | 2.00+ | jump | Jump instruction |
0202/4 | 2.00+ | header | Magic signature “HdrS” |
0206/2 | 2.00+ | version | Boot protocol version supported |
0208/4 | 2.00+ | realmode_swtch | Boot loader hook (see below) |
020C/2 | 2.00+ | start_sys_seg | The load-low segment (0x1000) (obsolete) |
020E/2 | 2.00+ | kernel_version | Pointer to kernel version string |
0210/1 | 2.00+ | type_of_loader | Boot loader identifier |
0211/1 | 2.00+ | loadflags | Boot protocol option flags |
0212/2 | 2.00+ | setup_move_size | Move to high memory size (used with hooks) |
0214/4 | 2.00+ | code32_start | Boot loader hook (see below) |
0218/4 | 2.00+ | ramdisk_image | initrd load address (set by boot loader) |
021C/4 | 2.00+ | ramdisk_size | initrd size (set by boot loader) |
0220/4 | 2.00+ | bootsect_kludge | DO NOT USE - for bootsect.S use only |
0224/2 | 2.01+ | heap_end_ptr | Free memory after setup end |
0226/1 | 2.02+(3) | ext_loader_ver | Extended boot loader version |
0227/1 | 2.02+(3) | ext_loader_type | Extended boot loader ID |
0228/4 | 2.02+ | cmd_line_ptr | 32-bit pointer to the kernel command line |
022C/4 | 2.03+ | initrd_addr_max | Highest legal initrd address |
0230/4 | 2.05+ | kernel_alignment | Physical addr alignment required for kernel |
0234/1 | 2.05+ | relocatable_kernel | Whether kernel is relocatable or not |
0235/1 | 2.10+ | min_alignment | Minimum alignment, as a power of two |
0236/2 | 2.12+ | xloadflags | Boot protocol option flags |
0238/4 | 2.06+ | cmdline_size | Maximum size of the kernel command line |
023C/4 | 2.07+ | hardware_subarch | Hardware subarchitecture |
0240/8 | 2.07+ | hardware_subarch_data | Subarchitecture-specific data |
0248/4 | 2.08+ | payload_offset | Offset of kernel payload |
024C/4 | 2.08+ | payload_length | Length of kernel payload |
0250/8 | 2.09+ | setup_data | 64-bit physical pointer to linked list of struct setup_data |
0258/8 | 2.10+ | pref_address | Preferred loading address |
0260/4 | 2.10+ | init_size | Linear memory required during initialization |
0264/4 | 2.11+ | handover_offset | Offset of handover entry point |
For more details about certain fields, read here.
Once everything works for QEMU, I will move onto GRUB2 and look into making lxboot x86 work with it as ISO and as Disk.
Boot loaders have unique reserved identifiers, placed in the type_of_loader
field.
The type_of_loader
field will contain 0xTV, where T is the loader's ID and V is its version.
If a boot loader does not have a ID, use 0xFF.
Assigned boot loader ids (hexadecimal):
Code | Bootloader |
---|---|
0 | LILO (0x00 reserved for pre-2.00 bootloader) |
1 | Loadlin |
2 | bootsect-loader (0x20, all other values reserved) |
3 | Syslinux |
4 | Etherboot/gPXE/iPXE |
5 | ELILO |
7 | GRUB |
8 | U-Boot |
9 | Xen |
A | Gujin |
B | Qemu |
C | Arcturus Networks uCbootloader |
D | kexec-tools |
E | Extended (see ext_loader_type) |
F | Special (0xFF = undefined) |
10 | Reserved |
11 | Minimal Linux Bootloader |
12 | OVMF UEFI virtualization stack |
I am Mihnea Firoiu, a second year Computer Science and Engineering student at University POLITEHNICA of Bucharest. My main interests are operating systems, low-level programming and cyber security.
Feel free to ask questions, report issues, and meet new people.