Linux Kernel 2.6.37 启动过程笔记 :Header.S

http://blog.chinaunix.net/uid-1701789-id-127294.html

写这篇东西的目的是对于这些天看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的指引下进行编译链接在内存中。
  1. 第一个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)。这些属性也是为了兼容性而保留的。
      1. # Kernel attributes; used by setup. This is part 1 of the
      2. # header, from the old boot sector.
      3. .section ".header", "a"
      4. .globl hdr
      5. hdr:
      6. setup_sects: .byte 0 /* Filled in by build.c 告诉bootloader应该加载多少扇区作为kernel的初步启动代码*/
      7. root_flags: .word ROOT_RDONLY
      8. syssize: .long 0 /* Filled in by build.c 告诉bootloader应该加载多少个16字节的数据作为保护模式的代码*/
      9. ram_size: .word 0 /* Obsolete */
      10. vid_mode: .word SVGA_MODE
      11. root_dev: .word 0 /* Filled in by build.c */
      12. boot_flag: .word 0xAA55 /*这是boot Sector的签名,bootloader应该检查这个字以检查启动代码是否合法*/
  2. 真正的kernel入口从第二个512字节开始,当今的bootloader把控制权交到这个入口。
    • 入口就是一个jmp。作用是跳转到start_of_setup
    • 之后的63个字节是Header字段们。具体的定义可以参见Documentation/x86/boot.txt
  3. start_of_setup的主要目的就是设置堆栈,初始化BSS,最终将控制权交给main.c中的main().
下面是Kernel在内存中的分布情况,基本可以解释Header.S的内容

Linux Kernel 2.6.37 启动过程笔记 :Header.S_第1张图片

此后的过程,网上介绍的都很多,我就不重复了。

有很多大神都写了很多文章,让我受益匪浅。
参考的文章有以下:
1. Linux内核启动过程(2.6.23) bootloader部分
2. Linux启动过程综述
3. The Kernel Boot Process

你可能感兴趣的:(linux,kernel)