注:
1、本文档翻译的是Linux内核的源代码中的Documentation\x86\ boot.txt。内核版本为2.6.36.2。
2、该文档的版权依照原文档的版权要求,需要遵循GNU GENERAL PUBLIC LICENSE Version 2。
3、本文所有内容,不保证其正确性。读者请自己辨识。
在x86平台上,Linux内核具有一个颇为复杂的引导协议。在现代计算机系统中,为了运行早已不是主流操作系统的DOS(运行于实模式)而设计了一套复杂的内存管理模式。正式这个历史原因加剧了Linux引导的复杂性。
目前,在X86平台上,Linux的引导协议存在以下的几个版本:
古老内核版本:仅仅支持zImage/Image内核打包类型。另外,早期版本的内核不支持内核命令行参数。
2.00版:(1.3.73版内核制定)添加对bzImage内核打包类型和initrd的支持,开始规定引导加载程序与内核之间的联系。setup.S可以重定位,但是依然假设原来的setup区域是可写的。
2.01版:(1.3.76版内核制定)新增堆越界警告。
2.02版:(2.4.0-test3-pre3版内核制定)新的内核命令行协议。允许在常规内存的任意位置(即1MB以下的任意位置。)不再更改原来的setup区域。这样就可以很安全地从那些使用EBDA或32位BIOS的系统中引导内核(TODO:为什么?)。从该版本开始,不再推荐使用zImage内核打包格式,但是依然支持。
2.03版:(2.4.18- pre1版内核制定)明确加载程序加载initrd到内存时可以使用的最大的内存位置。
2.04版:(2.6.14版内核制定)将syssize字段拓展为4个字节(也就说最大可以表示4GB)。
2.05版:(2.6.20版内核制定)引入relocatable_kernel和kernel_alignment字段 ,使保护模式的内核可以重定位。
2.06版:(2.6.22版内核制定)添加一个字段用来指定内核命令行内容的大小。
2.07版:(2.6.24版内核制定)新增虚拟化引导协议。引入hardware_subarch和hardware_subarch_data字段。并在load_flags中添加KEEP_SEGMENTS标志。
2.08版:(2.6.26版内核制定)新增crc32奇偶检验码和ELF文件格式payload(ELF format payload)。引入payload_offset和payload_length字段以便于payload进行寻址。
2.09版:(2.6.26版内核制定)为单链表结构体setup_data新增一个64位物理指针字段。
2.10版:(2.6.31版内核制定)为了约定内核的边界对齐要求,新增kernel_alignment、init_size和pref_address字段。新增扩展引导加载程序ID。
内存布局
内核加载程序加载Image或zImage格式内核时的“常规内存“布局,如下:0A0000BIOS保留不使用。为BIOS EBDA保留。
09A000命令行
堆栈用于内核的实模式部分。
098000内核 setup内核的实模式部分
090200内核引导扇区内核的逻辑引导扇区
090000内核的保护模式部分除实模式部分外的内核的绝大部分都在这儿。
010000引导加载程序引导扇区的入口点是0000:7C00
001000MBR/BIOS保留
000800通常被用于MBR
000600
000000BIOS使用
当使用bzImage内核打包类型时,内核的保护模式部分被重定位到0x100000(高位内存,1MB处),并且内核的实模式部分(引导扇区、setup和堆栈)也可以是被放置到0x10000到常规内存顶部之间的任意位置。不幸的是,在2.00和2.01版的引导协议中0x90000以上的内存区间还是会被内核使用,从而导致引导程序无法自由使用他们。不过该问题在2.02版的协议中已经解决。
内核加载程序应该尽量使用常规内存的低端部分。因为,一些新版的BIOS会使用常规内存的高端部分做为扩展的BIOS数据区域(Extended BIOS Data Area,缩写为EBDA)。另外,引导加载程序应该调用BIOS的INT 12H中断去获取实模式部分由多少内存可以使用。
不过,有时候INT 12H会告诉你,现在系统中只有很少的内存可以使用,以至于内核加载程序根本无法引导。内核加载程序只好显示错误信息并退出。所以,内核加载程序应该尽量少地使用内存并尽可能有效地使用内存。由于zImage和老版的bzImage类型的内核需要使用实模式的0x90000段,所以,内核加载程序应该确保不会使用0x9A000以上的区域。很多BIOS都会因为这个问题而崩溃。
在>=2.02版本引导协议的bzImage类型的内核中,内存布局如下图所示:内核的保护模式部分
100000I/O memory hole
0A0000BIOS保留
命令行应该尽可能多的不使用
(请参考下面的“X+10000”节)
X+10000堆栈用于内核的实模式部分。
X+08000内核setup
内核引导扇区内核的实模式部分
内核的逻辑引导扇区
X引导加载程序引导扇区的入口点是0000:7C00
001000MBR/BIOS保留
000800通常被用于MBR
000600
000000BIOS使用
注:内核引导程序应该将地址X设计地尽量的低。