http://blog.chinaunix.net/uid-1701789-id-127294.html
写这篇东西的目的是对于这些天看bootloader和kernel启动的一点总结。写Linux启动的文章很多,但是写Header.S是怎么被执行到的不多,这也造成了我花了很多时间来寻找为什么入口不在0x7c00。现在终于弄明白了。
在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. Linux启动过程综述
本文详细介绍了Linux内核启动过程,特别是Header.S代码是如何被执行的,包括其组织结构、关键内容及其在启动过程中的角色。通过分析MBR和Header.S之间的交互,解释了为何入口代码不再位于0x7c00,以及如何通过Header.S实现兼容性和初始化任务。
761

被折叠的 条评论
为什么被折叠?



