LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: phyma

Grub 源代码分析

[复制链接]
发表于 2005-1-25 10:39:59 | 显示全部楼层
请教一个问题,当grub把内核文件bzlinux装入mem后,grub将跳转到内核哪部分执行了?

感觉应该是setup.S的start,做一些BOIS检测收集硬件参数过程,但grub已将cpu切换到保护模式,而setup.S应该是实模式下执行,这不是有冲突了吗?
是不是grub在装入内核后又转入实模式然后开始执行内核?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-1-28 11:28:24 | 显示全部楼层
Post by redjing
请教一个问题,当grub把内核文件bzlinux装入mem后,grub将跳转到内核哪部分执行了?

感觉应该是setup.S的start,做一些BOIS检测收集硬件参数过程,但grub已将cpu切换到保护模式,而setup.S应该是实模式下执行,这不是有冲突了吗?
是不是grub在装入内核后又转入实模式然后开始执行内核?

对,grub在设置好内核后,然后切换至实模式,具体跳向哪里取决于kernel header里面的一个字段
回复 支持 反对

使用道具 举报

发表于 2005-2-13 19:09:35 | 显示全部楼层
楼主还写不写下去?
回复 支持 反对

使用道具 举报

发表于 2005-3-10 18:47:21 | 显示全部楼层
Post by phyma

     视stage2的大小,安装程序会在stage1中嵌入stage1-5或者stage2的磁盘位置信息。
b,stage1开始执行,它在进行直接加载stage1-5或者stage2并跳转执行(还有些额外的工作,这里忽略先)
     stage1-5很无辜,除了加载stage2以外它没有其他任何作用。


针对上面,我来修正一下。

stage1的代码文件,是源码目录下stage1/stage1.S,汇编后便成了一个512字节的img,被写在硬盘的0面0道第1扇区,作为硬盘的主引导扇区。

注意,硬盘主引导扇区 = 硬盘主引导记录(MBR)+ 硬盘分区表(DPT)

stage1的工作并不是加载什么stage1_5或者stage2,而是加载0面0道第2扇区上的512字节代码至0x8000,然后跳至0x8000执行。这里我们提及的另一个512字节代码,是来自源码目录下stage2/start.S文件的,而start.S的作用是作为stage1_5或者stage2(视乎编译grub时的指定)的总入口,它才是stage1_5或者stage2的真正加载器。

总结起来,那么就是stage1加载start,然后将执行权交给start,由start来加载stage1_5或者stage2。所以,斑竹说的“安装程序会在stage1中嵌入stage1-5或者stage2的磁盘位置信息”这句话是错误的。

大家想验证这些关系,请使用以下命令(这里假设你把grub安装在第一个IDE硬盘):

  1. 1. 倾印stage1.S的机器代码映像
  2. dd if=/dev/hda of=BOOT.img bs=1 count=512
  3. 2. 倾引start.S的机器代码映像
  4. dd if=/dev/hda of=START.img skip=512 bs=1 count=512
  5. 3. 用emacs打开这些映像,并将它们转换为16进制格式来查看
  6. emacs xxx.img
  7. M-x hexlify-buffer

  8. 同时对照一下源码中的内容,尤其是那些"GRUB"、"Loading stage1.5"等静态显示数据,你就会验证了上面我的说法,并且在start.S中找到更多的内幕。
复制代码
回复 支持 反对

使用道具 举报

发表于 2005-3-11 13:29:09 | 显示全部楼层
stage2的内幕并不神奇,正如斑竹所言,是一个mini OS,但我们觉得GRUB神奇的地方在于文件系统的识别功能。这种神奇色彩也就是"鸡蛋与鸡谁先有"的矛盾体。

PC上电后,就会执行BIOS的代码,BIOS将加载硬盘主引导扇区,总共512字节的二进制代码,这些代码就是stage1,然后BIOS将执行stage1。这一点大家都不会感到奇怪,这是很自然的流程。然而,stage2的体积比较大(因为它实现的功能比较全面嘛),所以一般stage2不会被放在固定的磁盘扇区中以供stage1只使用BIOS例程便可对其raw read,那么,stage2就会作为一个文件被放在文件系统里。

大家都知道,stage1_5就是文件系统的支撑代码,在stage1_5没有被加载以前,stage2是不能被stage1找到的,所以我们研究GRUB,关键看看究竟stage1是怎么加载stage1_5的,而stage1_5又被放在哪里。

待续...
回复 支持 反对

使用道具 举报

发表于 2005-3-11 13:30:06 | 显示全部楼层
好帖
期待更新中
回复 支持 反对

使用道具 举报

发表于 2005-3-11 14:02:19 | 显示全部楼层
接着上面的话题。

stage1_5究竟被放在哪呢?很多兄弟可能以为它就是/boot/grub/底下的哪些xxfs_stage1_5文件,但试想一下,要找到boot分区所在的stage1_5文件,那么就必须使得stage1具备文件系统识别功能,而stage1_5本身就是文件系统的支撑代码,它必须加载stage1_5才能具备这种功能。那么,我们又回到了那种矛盾体的悖论──要加载stage1_5来找到stage1_5? 呵呵。

所以用来识别boot分区文件系统的stage1_5不能作为文件来被stage1读取,它只能被存放在固定的扇区中。这里强调"用来识别boot分区文件系统",那是因为并不是所有的stage1_5文件都被放在固定扇区的,只有boot分区的文件系统对应的stage1_5才会被放在固定的扇区中去!比如说,你的boot分区的文件系统是ext2,那么在安装GRUB的stage1的时候,e2fs_stage1_5就会被存放至一个固定的扇区集,而其他的如reiserfs_stage1_5就依然作为文件来存放,以供GRUB使用root()命令来识别其他的boot分区(那时候,stage2已经被加载了,所以这个不成问题)。

那么,如何验证我上面的说法呢?还是使用dd命令。

  1. 1. dd if=/dev/hda of=STAGE1_5.img bs=1k skip=1 count=20
  2. 将STAGE1_5.img用emacs打开,转换为hex格式查看。

  3. 2. 将/boot/grub/e2fs_stage1_5拷贝一份到当前目录,用emacs打开,转换为hex格式查看。
  4. 注意,如果你的boot分区是别的文件系统,应该打开对应的stage1_5文件来查看。我这里的boot分区为ext2文件系统。
复制代码


查找这两个文件中相同的字符串,如"Loading stage1.5","GRUB"等,同时注意到它们交集的行数数量,你会发现,原来e2fs_stage1_5被放在0面0道的第3个扇区开始往后10多K的扇区集里。
回复 支持 反对

使用道具 举报

发表于 2005-3-11 14:04:17 | 显示全部楼层
这里是e2fs_stage1_5文件的hex倾印片断:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

发表于 2005-3-11 14:05:25 | 显示全部楼层
这里是从0面0道的第3个扇区倾印片断:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

发表于 2005-3-11 14:10:40 | 显示全部楼层
从中可见,e2fs_stage1_5的确是被放在了0面0道的第3个扇区开始的扇区集里!

stage1加载了start后,start便加载随后的扇区总共10多K的扇区到内存,随后执行这些stage1_5代码,有了stage1_5,那么识别文件系统中的stage2文件,就不是什么难事了。

关于stage1、start、stage1_5的位置关系,我们从下面的倾印片断中,可得知一二;注意,这个片断处于stage1_5倾引的开头,而它正是start.S的代码(从字符串可得知):

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表