LinuxSir.cn,穿越时空的Linuxsir!

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

Grub 源代码分析

[复制链接]
发表于 2008-8-4 16:59:40 | 显示全部楼层
牛,,顶支持啊,学习!!!
回复 支持 反对

使用道具 举报

发表于 2008-8-14 15:04:44 | 显示全部楼层
已经花时间看了
回复 支持 反对

使用道具 举报

发表于 2008-10-3 00:24:52 | 显示全部楼层
http://blogimg.chinaunix.net/blog/upfile2/081003000156.pdf
链接是我对各网友发言的合集。
回复 支持 反对

使用道具 举报

发表于 2009-1-31 01:07:11 | 显示全部楼层
Post by home_king;1058253
针对上面,我来修正一下。

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中找到更多的内幕。
复制代码

0面0道第1扇区有问题吧  柱面和磁道都是一样的
应该改为 0柱面0磁头第1扇区
还有第一主分区也应该是 0柱面1磁头第1扇区
回复 支持 反对

使用道具 举报

发表于 2009-4-5 17:06:17 | 显示全部楼层
关于chainloader机制,哪位大侠能给讲解一下?前面好像都没涉及。
回复 支持 反对

使用道具 举报

发表于 2009-4-5 17:08:42 | 显示全部楼层
Post by ty173238;1942466
0面0道第1扇区有问题吧  柱面和磁道都是一样的
应该改为 0柱面0磁头第1扇区
还有第一主分区也应该是 0柱面1磁头第1扇区

嗯,这个更正是对的。原文可能是笔误吧(郁闷,第一帖没发出去,第二帖发现发重了)
回复 支持 反对

使用道具 举报

发表于 2009-9-29 13:36:35 | 显示全部楼层
我选的是grub0.93,假设启动盘是默认的硬盘启动,且支持lba寻址,
问题一:
读stage1时,有这么一句
lba_mode:
/* save the total number of sectors */
movl        0x10(%si), %ecx


则ecx=?,the total numbers of sectors 作何解?,有何用处?


问题二:


stage1把控制权交给了stage2中的start.s后,假设设置了stage1_5,继续往下读,此时start.s已被加载到0x8000处,由此开始执行#ifdef STAGE1_5
# define ABS(x) (x-_start+0x2000)
#else
# define ABS(x) (x-_start+0x8000)
#endif /* STAGE1_5 */
#define MSG(x)  movw $ABS(x), %si; call message
这段等效为define ABS(x) (x-_start+0x2000)

执行到MSG(notification_string),问题出来了,movw$ABS(notification_string),%si;call message;
等效为movw$(notification_string-_start+0x2000),%si;call message;
我们知道此时notification的绝对地址应当是notification_srting-_start+0x8000才对啊?

问题三:读asm.s
发现访问符号地址是并未对其进行绝对地址转换的过程,例如:ifndef SUPPORT_DISKLESS
        /* save boot drive reference */
        ADDR32        movb        %dl, EXT_C(boot_drive)

        /* reset disk system (%ah = 0) */
        int        $0x13
#endif
像这里的boot_drive 为什么呢?这样不需要绝对地址的吗?
回复 支持 反对

使用道具 举报

发表于 2009-9-29 15:23:30 | 显示全部楼层

我的几个疑问

我选的是grub0.93,假设启动盘是默认的硬盘启动,且支持lba寻址,
问题一:
读stage1时,有这么一句
lba_mode:
/* save the total number of sectors */
movl        0x10(%si), %ecx


则ecx=?,the total numbers of sectors 作何解?,有何用处?是bios先在0x10(%si)设置好的吗?


问题二:


stage1把控制权交给了stage2中的start.s后,假设设置了stage1_5,继续往下读,此时start.s已被加载到0x8000处,由此开始执行#ifdef STAGE1_5
# define ABS(x) (x-_start+0x2000)
#else
# define ABS(x) (x-_start+0x8000)
#endif /* STAGE1_5 */
#define MSG(x)  movw $ABS(x), %si; call message
这段等效为define ABS(x) (x-_start+0x2000)

执行到MSG(notification_string),问题出来了,movw$ABS(notification_string),%si;call message;
等效为movw$(notification_string-_start+0x2000),%si;call message;
我们知道此时notification的绝对地址应当是notification_srting-_start+0x8000才对啊?

问题三:读asm.s
发现访问符号地址是并未对其进行绝对地址转换的过程,例如:ifndef SUPPORT_DISKLESS
        /* save boot drive reference */
        ADDR32        movb        %dl, EXT_C(boot_drive)

        /* reset disk system (%ah = 0) */
        int        $0x13
#endif
像这里的boot_drive 为什么呢?这样不需要绝对地址的吗?


问题四:DATA32        ADDR32        lgdt        gdtdesc 这条指令的两个前缀是什么意思啊
回复 支持 反对

使用道具 举报

发表于 2010-2-21 21:49:10 | 显示全部楼层
终于找到一个说得比较明白的帖子了,谢谢!顺便顶一下吧。
回复 支持 反对

使用道具 举报

发表于 2010-4-9 10:09:30 | 显示全部楼层
学习, 学习。
回复 支持 反对

使用道具 举报

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

本版积分规则

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