x86 boot enhancements, x86 boot protocol 2.04 9/11
PATCH 1/1 x86 boot enhancements, x86 boot protocol 2.04 9/11
Linus please apply,
Update the boot protocol to include:
- A compiled in command line
- A 32bit entry point
- File and memory usage information enabling a 1 to 1 conversion between the bzImage format and the static ELF executable file format.
- In setup.c split the parameters between those that are compiled in or specified by the bootloader and those that are queried from the BIOS.
Eric
Documentation/i386/boot.txt +237 -34
@@ -4,6 +4,9 @@ H. Peter Anvin <[email protected]> Last update 2002-01-01 + Eric Biederman <[email protected]> + Last update 7 April 2002 + On the i386 platform, the Linux kernel uses a rather complicated boot convention. This has evolved partially due to historical aspects, as well as the desire in the early days to have the kernel itself be a
@@ -35,6 +38,14 @@ initrd address available to the bootloader. +Protocol 2.04: (Kernel 2.5.8-pre4) + - Decompression in place (smaller load footprint) + The overhead is now 72KB below 1MB && 8 bytes above 1MB + - 32bit entry point support + - Exported the load time memory usage. + - zImage now has a larger memory footprint than bzImage. + should we just kill zImage? + **** MEMORY LAYOUT The traditional memory map for the kernel loader, used for Image or
@@ -100,34 +111,42 @@ The header looks like: -Offset Proto Name Meaning +Offset Proto Name Meaning /Size -01F1/1 ALL setup_sects The size of the setup in sectors -01F2/2 ALL root_flags If set, the root is mounted readonly -01F4/2 ALL syssize DO NOT USE - for bootsect.S use only -01F6/2 ALL swap_dev DO NOT USE - obsolete -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 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/2 N/A pad1 Unused -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 +01F1/1 ALL setup_sects The size of the setup in sectors +01F2/2 ALL root_flags If set, the root is mounted readonly +01F4/2 ALL syssize DO NOT USE - for bootsect.S use only +01F6/2 ALL swap_dev DO NOT USE - obsolete +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 Magic signature "HdrS" +0206/2 2.00+ protocol_version Boot protocol version supported +0208/4 2.00+ realmode_swtch Boot loader hook (see below) +020C/2 2.00+ start_sys_seg Segment the zImage kernel was loaded at (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+ initrd_start initrd load address (set by boot loader) +021C/4 2.00+ initrd_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/2 N/A pad1 Unused +0228/4 2.02+ cmd_line_ptr 32-bit pointer to the kernel command line +022C/4 2.03+ ramdisk_max Highest legal initrd address +0230/2 2.04+ entry32_off offset of 32bit entry point +0230/2 2.04+ internal_cmdline_off offset of compiled in command line +0234/4 2.04+ real_base Default load address of real mode code +0238/4 2.04+ real_memsz Memory used @ real_base +023C/4 2.04+ real_filesz Amount of data loaded @ real_base +0240/4 2.04+ kern_base Kernel decompressor load address +0244/4 2.04+ kern_memsz Memory used @ kern_base +0248/4 2.04+ kern_filesz Amount of data loaeded @ kern_base For backwards compatibility, if the setup_sects field contains 0, the real value is 4.
@@ -180,8 +199,14 @@ loadflags, heap_end_ptr: If the protocol version is 2.01 or higher, enter the offset limit of the setup heap into heap_end_ptr and set the - 0x80 bit (CAN_USE_HEAP) of loadflags. heap_end_ptr appears to - be relative to the start of setup (offset 0x0200). + 0x80 bit (CAN_USE_HEAP) of loadflags. heap_end_ptr is + relative to the start of setup (offset 0x0200). + + If the protocol version is 2.04 or higher set the 0x40 bit + (STAY_PUT). This explictly tells the real mode code that you + don't expect it to relocate itself to 0x90000. No earlier + protocols versions look at this bit so it is safe to set it + unconditionally. setup_move_size: When using protocol 2.00 or 2.01, if the real mode
@@ -190,15 +215,15 @@ additional data (such as the kernel command line) moved in addition to the real-mode kernel itself. - ramdisk_image, ramdisk_size: + initrd_start, initrd_size: If your boot loader has loaded an initial ramdisk (initrd), - set ramdisk_image to the 32-bit pointer to the ramdisk data - and the ramdisk_size to the size of the ramdisk data. + set initrd_start to the 32-bit pointer to the ramdisk data + and the initrd_size to the size of the ramdisk data. The initrd should typically be located as high in memory as possible, as it may otherwise get overwritten by the early kernel initialization sequence. However, it must never be - located above the address specified in the initrd_addr_max + located above the address specified in the ramdisk_max field. The initrd should be at least 4K page aligned. cmd_line_ptr:
@@ -248,6 +273,11 @@ covered by setup_move_size, so you may need to adjust this field. +If the protocol version is 2.04 or higher a compiled in command line +may be present. If this is the case the passed command line is +appended onto the tail of the compiled command line. Assuming +there is room. + **** SAMPLE BOOT CONFIGURATION
@@ -269,8 +299,8 @@ if ( protocol >= 0x0200 ) { type_of_loader = <type code>; if ( loading_initrd ) { - ramdisk_image = <initrd_address>; - ramdisk_size = <initrd_size>; + initrd_start = <initrd_address>; + initrd_size = <initrd_size>; } if ( protocol >= 0x0201 ) { heap_end_ptr = 0x9000 - 0x200;
@@ -436,3 +466,176 @@ After completing your hook, you should jump to the address that was in this field before your boot loader overwrote it. + + +**** THE COMPRESSED KERNEL HEADER + +As of boot protocol version 2.04 a header has been added to the +compressed data, to reduce information loss. Most bootloaders +should never need to look at these fields. + +Offset Proto Name Meaning +/Size + +0000/4 2.04+ jump Jump Instruction +0004/4 2.04+ input_addr Load address of compressed data +0008/4 2.04+ input_len Length of compressed data +000C/4 2.04+ output_overhang Extra bytes needed for inplace decompression +0010/4 2.04+ kernel_base Kernel load address +0014/4 2.04+ kernel_filesz Memory usage @ kernel_base +0018/4 2.04+ kernel_memsz Data size @ kernel_base +001C/4 2.04+ unzip_filesz Decompressor code/data size +0020/4 2.04+ unzip_memsz Decompressor code memory usage + +**** DETAILED DESCRIPTION OF FIELDS + + entry32_off: + The unsigned offset of the 32bit entry point from the real + mode kernel. For boot protocols 2.03 or earlier, this field is + not present, and there is no 32bit entry point. + + The 32bit entry point is a mechanism for entering the kernel + without doing 16bit PC BIOS calls. Very useful for systems + with alternative firmware implementations. + + A bootloader using the 32bit entry point should verify that + there are real_memsz bytes available at real_base (real_base + remains relocatable in bzImages). And that there kern_memsz + bytes available at kern_base. For zImages you should also + verify that there are kernel_memsz bytes available at + kernel_base. + + Verifing there is enough memory for the kernel to load is + necessary for using the 32bit entry point, and suggested for + the 16bit entry point. In the case of the 32bit entry point + the kernel has no ability to talk to whatever weird firmware you + have until it is fully loaded. + + The 32bit entry point makes the following assumptions. You + are calling it protected mode. Paging is disabled. All + segment registers are loaded with a 32bit segment with a base + of 0, and a limit of 0xFFFFFFFF (limitless). Either %esp == 0 + and you are using the default real_base or %esp points to a + stack large enough to hold at least 12 new bytes of data. + + + internal_cmdline_off: + The offset of the null terminated compiled in command line + from the real mode kernel. For boot protocols 2.03 or + earlier this field is not present, and there is no built in + command line. The memory from internal_cmdline_off to + real_filesz is reserved for the compiled in command_line. An + external utility may modify this command line. + + To change the maximum size of the compiled in command line several + variables need to be modified. real_filesz to indicate the + new maximum size. setup_sects to indicate if the number of + sectors needed for the realmode kernel changes. + + A heap is maintained between real_filesz and real_memsz/heap_end_ptr. + Increasing the size of the heap is not a problem, decreasing + it is. So when changing the real_filesz, real_memsz and + heap_end_ptr should also be changed. + + input_addr/input_len: + The kernel is loaded into memory in compressed form. + input_addr is the location where the compressed data is + loaded, and input_len is the count of how many bytes of + compressed data there are. + + These two variables allow an external program to inspect a + bzImage and find the compressed data. This is mostly of use + to build.c as it computes output_overhang but other programs + may find it useful as well. + + output_overhang: + Most decompression algorithms may transformed into near + in-place algorithms by simply overlapping the compressed data + and the decompressed data buffers. For a particular + decompression algorithm then the question becomes how much + overlap is safe. More practically how much must the + compressed data stick out from the end of the decompressed + data buffer for this technique to work. + + output_overhang is that amount the compressed data buffer + must extend beyond the decompressed data buffer for + decompression in place to work for the linux kernel. + + build.c is responsible for computing this number. For + gzip typically this number is 8 (file length and checksum). + But in pathological cases it may be worse. + + real_base, real_memsz, real_filesz, + kern_base, kern_memsz, kern_filesz, + kernel_base, kernel_memsz, kernel_filesz, + unzip_memsz, unzip_filesz, + + Up to this point building a zImage or a bzImage has been a + very lossy process. The introduction of these variables + attempts to rectify that situation. They document exactly + which pieces of memory, the kernel uses during the boot + process, and they indicate exactly how large the various data + segments of the kernel are. It is now possible to create a + lossless transformation to and from a static ELF executable. + + Program segments are described with 3 variables. The base + address where the segment is loaded in memory. The file size + which records the amount of data in the input file that is + loaded into memory. The memory size which is greater than or + equal to the file size and records how much memory this + program segment consumes. + + base +-----------+ + | code/data | + filesz +-----------+ + | bss | + memsz +-----------+ + + The real program segment (real_base, real_filesz, real_memsz) + describes the memory usage of the real mode code from 4KB to + 640KB. The real code segment and the command line must be + located somewhere in this range. + + The compressed kernel segment (kern_base, kern_filesz, + kern_memsz) describes the memory usage of the compressed + kernel. For a zImage this is memory below 1MB for a bzImage + this is memory starting at 1MB. + + For bzImages it is sufficient to look at the real program + segment, and the compressed kernel segment to get the entire + boottime memory usage of the kernel. real_memsz is increased + to also document the decompressors real memory usage, and the + kern_memsz value is increased to document the decompressed + kernels memory usage. + + You can look at heap_end_ptr to get the actual memory + footprint of the real mode segment. Just the decompressors + memory footprint is kern_base + kernel_filesz + + output_overhang, if unzip_memsz bytes are available of real + memory, and kern_base + kernel_filesz + output_overhang + + unzip_memsz bytes otherwise. + + The decompressed kernel segment (kernel_base, kernel_filesz, + kernel_memsz) describes the memory usage of the decompresed + kernel (essentially vmlinux). + + The decompressor segment (load_address, unzip_filesz, unzip_memsz) + describes the memory usage of the kernel decompressor, + not counting the compressed data. + + The real program segment describes memory in the range + 4KB (0x1000) to 640KB (0xa0000) that the real mode kernel + uses. real_base may be moved lower or higher in memory if + there is a memory conflict with another address. When doing + so the following considerations should apply. + + For a zImage the range [real_base, real_base + + real_memsz) should not overlap the range [ kern_base, + kern_base + kern_memsz]. + + Ensure that the range [real_base, real_base + + real_memsz) is within the range [ 0x1000, 0xa0000). + + With this information it becomes safe to statically relocate + the real mode kernel as well as to dynamically relocate the + real_mode kernel.
arch/i386/Config.help +6 -0
@@ -803,6 +803,12 @@ a work-around for a number of buggy BIOSes. Switch this option on if your computer crashes instead of powering off properly. +CONFIG_CMDLINE + Generally it is best to pass command line parameters via the + bootloader but there are times it is convinient not to do this. + This allows you to hard code a default kernel command line, whatever + the bootloader passes will be appended to it. + CONFIG_X86_MCE Machine Check Exception support allows the processor to notify the kernel if it detects a problem (e.g. overheating, component failure).
arch/i386/boot/realmode.lds +1 -1
@@ -1,5 +1,5 @@ OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") -ENTRY(_start) +ENTRY(entry32) OUTPUT_ARCH(i386) SECTIONS {
arch/i386/boot/setup.S +190 -21
291 lines not on this page · raw message
arch/i386/config.in +1 -0
@@ -284,6 +284,7 @@ bool ' Use real mode APM BIOS call to power off' CONFIG_APM_REAL_MODE_POWER_OFF fi +string 'Initial kernel command line' CONFIG_CMDLINE "" endmenu source drivers/mtd/Config.in
arch/i386/kernel/setup.c +74 -17
143 lines not on this page · raw message
include/asm-i386/boot_param.h +8 -3
@@ -83,15 +83,20 @@__u32 cmd_line_ptr;/* 0x228 */ /* 2.03+ */ __u32 ramdisk_max;/* 0x22c */ -/* Below this point for internal kernel use only */ -__u32 pad2;/* 0x230 */ +/* 2.04+ */ +__u16 entry32_off;/* 0x230 */ +__u16 internal_cmdline_off;/* 0x232 */ __u32 real_base;/* 0x234 */ __u32 real_memsz;/* 0x238 */ __u32 real_filesz;/* 0x23c */ __u32 kern_base;/* 0x240 */ __u32 kern_memsz;/* 0x244 */ __u32 kern_filesz;/* 0x248 */ -__u8 reserved15[0x2d0 -0x24c ];/* 0x24c */ +/* Below this point for internal kernel use only */ +__u32 entry32_used;/* 0x24c */ +__u32 entry32_16_off;/* 0x250 */ +struct initial_regs32 regs;/* 0x254 */ +__u8 reserved15[0x2d0 -0x274 ];/* 0x274 */ struct e820entry e820_map[E820MAX ];/* 0x2d0 */ /* 0x550 */ } __attribute__((packed));