Chinaunix首页 | 论坛 | 博客
  • 博客访问: 332679
  • 博文数量: 125
  • 博客积分: 30
  • 博客等级: 民兵
  • 技术积分: 160
  • 用 户 组: 普通用户
  • 注册时间: 2012-12-06 15:18
文章分类

全部博文(125)

文章存档

2014年(29)

2013年(93)

2012年(3)

分类: LINUX

2013-05-22 20:51:17

写这篇东西的目的是对于这些天看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的内容


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

有很多大神都写了很多文章,让我受益匪浅。
参考的文章有以下:
2.
 

阅读(414) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~