写这篇东西的目的是对于这些天看bootloader和kernel启动的一点总结。写Linux启动的文章很多,但是写Header.S是怎么被执行到的不多,这也造成了我花了很多时间来寻找为什么入口不在0x7c00。现在终于弄明白了。
arch/x86/boot/Header.S是Kernel启动的第一段代码,它使用AT&T的汇编格式编写,和标准的Intel汇编格式有很大的区别。具体对于AT&T汇编的解释可以参照Linux 汇编语言开发指南。在MBR的介绍的时候,曾经说过0x7c00是最简单的MBR的开始代码,并且MBR会把Kernel的Header.S加载进入这个地址并且把执行权交给kernel。但是这是在很久以前的事情了,随着越来越复杂的Bootloader, 例如Grub, 介入和Linux Kernel放弃直接从软驱启动Header.S的代码也进行了改变。
首先我们来看一下Header.S是怎么组织的。Header.S是在Setup.ld的指引下进行编译链接在内存中。
- 第一个512字节的内容是为了兼容软驱时代而存在的。它正好被放在一个磁盘扇区之内。
- 当其作为入口代码被执行的时候会在屏幕上打印出错代码“Direct booting from floppy is no longer supported. Please use a boot loader program instead. Remove disk and press any key to reboot . . .”。
- 512字节中还包含一部分的kernel的属性,称之为hdr(Header)。这些属性也是为了兼容性而保留的。
- # Kernel attributes; used by setup. This is part 1 of the
-
# header, from the old boot sector.
-
.section ".header", "a"
-
.globl hdr
-
hdr:
-
setup_sects: .byte 0 /* Filled in by build.c 告诉bootloader应该加载多少扇区作为kernel的初步启动代码*/
-
root_flags: .word ROOT_RDONLY
-
syssize: .long 0 /* Filled in by build.c 告诉bootloader应该加载多少个16字节的数据作为保护模式的代码*/
-
ram_size: .word 0 /* Obsolete */
-
vid_mode: .word SVGA_MODE
-
root_dev: .word 0 /* Filled in by build.c */
-
boot_flag: .word 0xAA55 /*这是boot Sector的签名,bootloader应该检查这个字以检查启动代码是否合法*/
- 真正的kernel入口从第二个512字节开始,当今的bootloader把控制权交到这个入口。
- 入口就是一个jmp。作用是跳转到start_of_setup
- 之后的63个字节是Header字段们。具体的定义可以参见Documentation/x86/boot.txt
- start_of_setup的主要目的就是设置堆栈,初始化BSS,最终将控制权交给main.c中的main().
下面是Kernel在内存中的分布情况,基本可以解释Header.S的内容
此后的过程,网上介绍的都很多,我就不重复了。
有很多大神都写了很多文章,让我受益匪浅。
参考的文章有以下:
2.
阅读(6710) | 评论(4) | 转发(8) |