1.BIOS阶段
有关BIOS就不在这里进行叙述,BIOS用于将启动设备中第一个扇区拷贝到RAM中,而这个扇区可能是存放MBR,后者直接是GRUB等引导程序。引导程序存放在RAM中的0x7C00地址上,
2.引导程序执行阶段
在BIOS阶段中引导程序已经被拷贝到0x00007C00地址上,现在PC指针跳转到该地址上,即执行引导程序指令。这里假设引导程序是GRUB,在linux旧的版本中,GRUB将内核镜像bzImage中setup部分拷贝到0x00009000地址上,将其余部分拷贝到0x000010000上。而对于Linux新版本中,GRUB将内核镜像bzImage中setup部分拷贝到0x10000 以下的某个地址X,而将其余部分拷贝到0x000100000地址上。注意,这里setup部分指的是实模式有关代码,即/arch/XX/boot/。有关内存分布可参考 /Documentation/x86/boot.txt中内容。
3.setup实模式阶段
实模式主要用于检测内存,键盘等设备,基本初始化,最后切换到保护模式下工作,这里通常跳转到0x100000执行保护模式代码。
copy_boot_params(); 复制 boot header 到 "zeropage"
validate_cpu(); 确保支持当前运行的CPU
set_bios_mode(); 告诉BIOS什么CPU我们将要去运行
detect_memory(); 检测Memory
keyboard_set_repeat(); 设置键盘 repeat rate (Why ?)
set_video(); 设置 Video mode
query_mca(); 获得 MCA 信息
query_voyager(); Voyager ?
query_ist(); 获得 Query Intel SpeedStep (IST) 信息
query_apm_bios(); 获得APM 信息
query_edd(); 获得EDD信息
protected_mode_jump(boot_params.hdr.code32_start,
(u32)&boot_params + (ds() << 4));
code32_start参数在header.s中(arch/i386/boot/header.s) 设置如下 :
code32_start: # here loaders can put a different
# start address for 32-bit code.
.long 0x100000 # 0x100000 = default for big kernel
4.保护模式阶段
通常0x100000地址上存放vmlinux.bin,但是为了防止内核过大,采用压缩内核的方式减少内核大小,因此vmlinux.bin一般是压缩后的内核,vmlinux.bin包括/boot/compressed/中代码,压缩内核piggy,及解压缩代码,而vmlinux.bin中的入口函数是startup_32(arch/x86//boot/compress/head_32.S),因此跳转到startup_32中执行,这里包括内核解压缩,最终跳转到真正的内核入口的startup_32函数(arch/x86/kernel/head_32.S)中执行。