LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1677|回复: 14

问个grub的stage1_5 stage2的问题,

[复制链接]
发表于 2005-3-21 19:25:35 | 显示全部楼层 |阅读模式
stage1_5是用来load stage2的,但是没有stage1_5会怎样? stage1_5的有无会产生什么样的影响? ^_^

望指点,谢谢!!
发表于 2005-3-21 20:15:14 | 显示全部楼层
Post by nhjidle
stage1_5是用来load stage2的,但是没有stage1_5会怎样? stage1_5的有无会产生什么样的影响? ^_^

望指点,谢谢!!

stage1_5的主要作用是提供"文件系统"支持,没有它,那么读取启动分区中的stage2会显得很困难。第一,stage2的体积很大,不能放在0面0道的63扇区(这是基于最基本的CHS模式,总共31.5KB;当然,目前的硬盘都支持LBA模式,但即使LBA模式也只有256个扇区);第二,如果用blocklist的方式对stage2进行硬编码定位,是不可能的,因为放置stage2的启动分区的文件系统是变化的。所以,stage2只能从文件系统的方式来进行访问加载。

那么,就需要stage1支持文件系统,但stage1鉴于其512字节的限制(PC的MBR标准),不能编写太多的代码,所以就把文件系统放在stage1_5里了,而stage1_5被放置在MBR随后的若干个扇区里(扇区个数视乎stage1_5的大小),以blocklist的方式被加载,然后stage1_5去加载stage2。

更详细的过程,请参阅以下帖子:
http://www.linuxsir.cn/bbs/showt ... mp;page=1&pp=15

当然,GRUB2抛弃了stage1_5机制,而使用了压缩GRUB内核的方式,结合了stage1_5及stage2。更详细的内幕,请参阅以下帖子,我会一直跟进GRUB2的开发进度以及内幕阐释:
http://www.linuxsir.cn/bbs/showthread.php?t=183111
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-22 15:21:57 | 显示全部楼层
说的好详细啊,,谢谢版主 ^_^
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-23 10:29:27 | 显示全部楼层
再问版主几个问题,,^_^
问题有点多,呵呵,麻烦版主了,,


下面是一小段代码
static void
attempt_mount (void)
{
#ifndef STAGE1_5
  for (fsys_type = 0; fsys_type < NUM_FSYS; fsys_type++)
    if ((fsys_table[fsys_type].mount_func) ())
      break;

  if (fsys_type == NUM_FSYS && errnum == ERR_NONE)
    errnum = ERR_FSYS_MOUNT;
#else
  fsys_type = 0;
  if ((*(fsys_table[fsys_type].mount_func)) () != 1)
    {
      fsys_type = NUM_FSYS;
      errnum = ERR_FSYS_MOUNT;
    }
#endif
}

p1.通常在引导中是要用到stage1.5的,所以应该是看#else后面的代码,那它为什么把fsys_type 置为0?
p2.如果是对于linux,那么有关于bsd的不用看吧?
p3.blockfile通常是定义了还是没定义?
p4.安装程序是不是把stage1.S拷贝到了mbr,那么这个512字节中应该是没有分区表的,那么分区表是在  stage1.5中设置?
p5.stage1.S中只是将mbr后面的一个扇区拷贝到了0x8000,这个扇区里面的咚咚就是stage1.5?如果是,那么在stage1.5的cmain中一开始便调用了grub_read ((char *) 0x8000, SECTOR_SIZE * 2);,那不是覆盖了么?、
回复 支持 反对

使用道具 举报

发表于 2005-3-23 11:16:19 | 显示全部楼层
Post by nhjidle
再问版主几个问题,,^_^
问题有点多,呵呵,麻烦版主了,,


下面是一小段代码
static void
attempt_mount (void)
{
#ifndef STAGE1_5
  for (fsys_type = 0; fsys_type < NUM_FSYS; fsys_type++)
    if ((fsys_table[fsys_type].mount_func) ())
      break;

  if (fsys_type == NUM_FSYS && errnum == ERR_NONE)
    errnum = ERR_FSYS_MOUNT;
#else
  fsys_type = 0;
  if ((*(fsys_table[fsys_type].mount_func)) () != 1)
    {
      fsys_type = NUM_FSYS;
      errnum = ERR_FSYS_MOUNT;
    }
#endif
}

p1.通常在引导中是要用到stage1.5的,所以应该是看#else后面的代码,那它为什么把fsys_type 置为0?
p2.如果是对于linux,那么有关于bsd的不用看吧?
p3.blockfile通常是定义了还是没定义?
p4.安装程序是不是把stage1.S拷贝到了mbr,那么这个512字节中应该是没有分区表的,那么分区表是在  stage1.5中设置?
p5.stage1.S中只是将mbr后面的一个扇区拷贝到了0x8000,这个扇区里面的咚咚就是stage1.5?如果是,那么在stage1.5的cmain中一开始便调用了grub_read ((char *) 0x8000, SECTOR_SIZE * 2);,那不是覆盖了么?、


a1: 因为安装grub的时候,grub会检测你的启动分区的文件系统类型,然后将对应的stage1_5安装到0面0道的第2个扇区及后面的扇区中去,所以只有一个文件系统,fsys_type为0。

a2: 嗯。是的。不同的loader算法针对不同的操作系统。

a3: 未清楚。

a4: 错误。stage1.S里面保留了分区表以及其他的一些信息,它的内容排列必须符合x86的PC标准,这样才能具备兼容性。在安装GRUB的时候,GRUB会填充stage1.S编译成的boot.img里面的保留内容,当然包括填充分区表。

a5: 错误。stage1_5的头部的512字节,也就是头扇区,是start.S的代码

ps:其实GRUB已经成为GRUB Legacy了,现在的GRUB2是一个崭新的改革版本,如果兄弟要研究bootloader,请转向GRUB2;另外,我对GRUB2比较熟悉一点。  ;)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-23 11:55:28 | 显示全部楼层
辛苦班班了哈,刚下了个grub2,要是有个grub2的论坛就好了,不用每次都麻烦版主了^_^,//bow
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-23 15:56:18 | 显示全部楼层
刚看了会grub2的源代码,感觉grub2比起grub来更象是一个os ,而且其中没有了stage1.5 stage2概念,代码显得更加简洁:)
但还是有不少问题不太明白 :%
1.boot.S是安装程序拷贝到mbr(sector 0)中的,它读入紧跟mbr的第一个sector(sector 1)到0x8000,然后跳到0x8000处开始执行。sector1中方的是什么?(startup.S?,应该不是,因为grubkernel的读入是在diskboot.s中,要是startup.S那么kernel就读不进来了。)

2.关于diskboot.s,它将grub kernel读到0x8200开始处,然后跳到0x8200开始执行,(grub kernel是从sector2开始的?)
* _start is loaded at 0x2000 and is jumped to with CS:IP 0:0x2000 in kernel.
是在哪里将它load到0x2000的,又是在哪一步开始执行的?而且它对绝对地址的计算却为
#define ABS(x) (x-_start+GRUB_BOOT_MACHINE_KERNEL_ADDR),应该是
#define ABS(x) (x-_start+0x2000)才对啊,??

3.pxeboot.s  0x8200
* _start is loaded at 0x7c00 and is jumped to with CS:IP 0:0x7c00 */
       ljmp    $0, $0x8200
       . = 0x8000 - 0x7C00 -1
       .byte 0
它怎么会被放到0x7c00呢?而且 . = 0x8000 - 0x7C00 -1不好理解,既然是从0x7c00开始的,那么地址怎么会下降到 0x8000-0x7c00??

4.startup.s的作用主要是转入保护模式,开启a20地址线,解压内核(从kernel的1k开始,kernel的前面1k是没压缩的),拷贝模块,清零bss段,,然后跳到main.c的grub_main开始执行,startup.s是放在哪个位置?而且里面的START_SYMBOL一直没找到它的定义 :p


好多问题啊,又得辛苦版主拉,,主要是关于grub2的资料少之又少啊,所以只能向先驱请教了,感觉自己主要是对启动的顺序没理清楚
回复 支持 反对

使用道具 举报

发表于 2005-3-23 18:04:30 | 显示全部楼层
Post by nhjidle
刚看了会grub2的源代码,感觉grub2比起grub来更象是一个os ,而且其中没有了stage1.5 stage2概念,代码显得更加简洁:)
但还是有不少问题不太明白 :%
1.boot.S是安装程序拷贝到mbr(sector 0)中的,它读入紧跟mbr的第一个sector(sector 1)到0x8000,然后跳到0x8000处开始执行。sector1中方的是什么?(startup.S?,应该不是,因为grubkernel的读入是在diskboot.s中,要是startup.S那么kernel就读不进来了。)

执行流程为:
boot.S --> bootdisk.S --> startup.S

Post by nhjidle

2.关于diskboot.s,它将grub kernel读到0x8200开始处,然后跳到0x8200开始执行,(grub kernel是从sector2开始的?)
* _start is loaded at 0x2000 and is jumped to with CS:IP 0:0x2000 in kernel.
是在哪里将它load到0x2000的,又是在哪一步开始执行的?而且它对绝对地址的计算却为
#define ABS(x) (x-_start+GRUB_BOOT_MACHINE_KERNEL_ADDR),应该是
#define ABS(x) (x-_start+0x2000)才对啊,??

这段注释是开发者的错误,应该去掉。
0x2000在GRUB Legacy(0.9x)中装载stage1.5,但GRUB2没有stage1.5,故被弃用。

Post by nhjidle

3.pxeboot.s  0x8200
* _start is loaded at 0x7c00 and is jumped to with CS:IP 0:0x7c00 */
       ljmp    $0, $0x8200
       . = 0x8000 - 0x7C00 -1
       .byte 0
它怎么会被放到0x7c00呢?而且 . = 0x8000 - 0x7C00 -1不好理解,既然是从0x7c00开始的,那么地址怎么会下降到 0x8000-0x7c00??

pxeboot.S的作用和boot.S类似,但用于网络启动。


Post by nhjidle

4.startup.s的作用主要是转入保护模式,开启a20地址线,解压内核(从kernel的1k开始,kernel的前面1k是没压缩的),拷贝模块,清零bss段,,然后跳到main.c的grub_main开始执行,startup.s是放在哪个位置?而且里面的START_SYMBOL一直没找到它的定义 :p

startup.S被bootdisk.S加载至0x8200。

其实startup.S有两种作用,一是负责后续内核的环境初始化,也就是你所提及的流程;二是为后续内核提供设备驱动层,这些设备驱动层的底层是BIOS例程,封装INT13H以提供磁盘读取驱动,封装INT15H以提供内存信息访问,封装INT10H以及INT16H以提供键盘输出、屏幕显示驱动。后者和前者的代码是分开的。前者的体积为512B,再加上bootdisk.S的512B,就是1KB。而这1KB,正如你所言,没有被压缩。

START_SYMBOL由GRUB2的源码目录里的conf目录中的文件指定,其实就是_start。
回复 支持 反对

使用道具 举报

发表于 2005-3-25 20:59:54 | 显示全部楼层
grub-0.94属于1还是2?
回复 支持 反对

使用道具 举报

发表于 2005-3-25 21:48:56 | 显示全部楼层
Post by netjune
grub-0.94属于1还是2?

版本号小于等于0.9的都属于GRUB Legacy,之后的版本从1.90开始,属于GRUB2。
版本跳跃的现象很常见,例如Linux内核。
回复 支持 反对

使用道具 举报

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

本版积分规则

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