原文转自不点,本人有变更和删减
首先,Grub4DOS 是什么?
Grub4DOS 是服务于 PC BIOS 基于平台开源的引导管理器 GNU GRUB legacy 以 GPL2 发布授权协议。
这种引导管理器的特点是什么?
可用于启动 DOS、Windows、Linux 其他操作系统也可用于启动其他引导管理器。它可以自己经过 MBR、PBR、CDROM、PXE 启动,也可以从 DOS、Win9x、Linux 在操作系统下启动或被其他指导管理器启动 fbinst、NTLDR、BOOTMGR、SYSLINUX、GNU GRUB、LILO 启动。它具有磁盘和光盘模拟功能(基于实际模式) BIOS),可用于启动软盘、硬盘、光盘图像。
grub4dos 介绍核心文件
grub4dos 有两个核心文件,grldr 和 grub.exe,用于不同的场合。
在 grub4dos 早期发展,只有 GRUB.EXE 没有这个核心文件 GRLDR 文件。GRUB.EXE 起初只是 DOS 可执行文件格式由两部分组成:
头部 主体
头是为主体的运行做准备的。“主体” 就是 GNU GRUB 的核心代码 pre_stage2。后来,grub.exe 也可以当作 DOS 使用设备驱动格式 DEVICE=grub.exe 加载,甚至 grub.exe 也是合法的 Linux 其他许多指导工具可以加载核格式。然而,头 主体” 整体结构没有变化。
GRLDR 也差不多,由 “头部 主体” 构成。与 “GRUB.EXE 是为DOS 出生的情况类似,GRLDR 就是为 NTLDR 而生的。它甚至被称为grub for ntldr”。grub4dos 所有的核心文件有如此简单、单一的整体结构,使其易于分析和掌握。
GRLDR 的头部占用 16 风扇区,即 8K,即 8192 或者(用十六进制表示)0字节x2000 字节。GRLDR 的头部会被 NTLDR 加载。遗憾的是,NTLDR 不能够把 GRLDR 完全加载到内存,只能加载 8K 大大小小的头。这就是为什么 GRLDR 头正好是8K” 的原因。这样,当头部得到控制时,它就有了寻找主体的主要任务 部分在哪里,然后将主体部分加载到内存中。实际执行步骤是在每个硬盘和分区的根目录中找到头部的整个目录GRLDR 文件(如果都失败了,最后会尝试在第一软盘 fd0 根目录搜索 GRLDR 找到文件) GRLDR 然后加载完整 GRLDR 文件到内存,并提交控制权。
顺便说一句 grldr.mbr 文件。主要用于安装 MBR 上。它的长度是 18 个扇区(即 9K)。其任务和功能是寻找和加载 GRLDR 文件。这有点类似 GRLDR 头部的作用。但 GRLDR 头部是被 NTLDR 加载,而 grldr.mbr 是被 BIOS 所以,这还是有区别的。grldr.mbr 末尾的两个扇区用于探测和适应 BIOS 磁盘几何参数。所以,grldr.mbr 的长度是 18 个扇区,比 grldr 的头部(16 扇区)多了两个扇区。grldr.mbr 也能被 NTLDR 但是,NTLDR 也只能加载 grldr.mbr 的开头的 16 扇区(8K),末尾不能加载两个扇区。NTLDR 的升级版 —— BOOTMGR —— 但能完全加载 grldr.mbr 因为内存 BOOTMGR 可加载长达 64K 的文件。而 grldr.mbr 只有 9K,因此,它可以被接受 bootmgr 内存完全加载。
从版本 0.4.5 开始,grub.exe 也能够被 ntldr 加载(在 boot.ini 的末尾添加 c:\\grub.exe="grub.exe" 这样的一行完全相似 grldr 的情况)。
grldr 并非只能被 ntldr 其它启动软件也可以加载加载。例如,fbinst、syslinux 都可以加载 grldr。原则上,任何启动软件(改造后)都可以加载 grldr,因为加载起来很容易,只要 grldr 放在 16 可以在字节对齐的内存地址处提交控制权。另外,一切都可以加载 ntldr 还可以加载引导管理器 grldr。这是因为 ntldr 总是在固定地址加载 2000:0000 处,而如果 grldr 这里也加载,当然可以正常运行,因为 2000:0000 是一个 16 字节对齐地址。
当网卡的 PXE BIOS 加载 grldr 时,它把 grldr 加载在 0000:7C00 这也是一个 16 字节对齐地址。所谓 “16 字节对齐 16 意思是整除。
无论 grldr(或 grub.exe)被加载的东西(以及加载在哪里)是什么? grldr(或 grub.exe)附加步骤将自动执行,即主体部分(pre_stage2)放置在固定地址 0000:8200 处。也就是说,当主体部分即将获得控制权时,它总是位于 0000:8200 处。
前面已经解释过了 grldr 和 grub.exe 宏观结构都是 头+主体。但头和主体都有更精细的结构。
GRLDR 固定占用头部 16 扇区(8K)。但是,GRUB.EXE 头很长,长度不固定。所以首先要确定头部的长度。
相对于 GNU GRUB legacy 头是 grub4dos 特有的。头部的唯一功能是将主体加载到内存中。而主体就是 GNU GRUB legacy 的核心代码 pre_stage2。因此,当主体得到控制时,头部就不必存在了。头部就像三级运载火箭中的一个级别。它的目的和功能是把主体送到轨道上,然后放弃自己。当主体得到控制时,找不到头,因为它已经从内存中消失了。
grub4dos 也改造了 GNU GRUB legacy 的核心文件 pre_stage(它成了 grub4dos 主体部分)。grub4dos 在主体的开头安排了许多核心变量,允许用户读取或写入。有些变量不能写入,一旦写入,就会被破坏 grub4dos 工作环境。有些变量可以写入,用户可以通过写入这些变量来控制 grub4dos 行为方式。
内存中主体部分的位置固定,头部加载在物理地址上 0x8200 这里可以看作是主体的固有 “轨道”。所以,很多变量都在 0x8200 之后的小区域。当然,grub4dos 内核中的许多结构属于用户可访问的信息,分散在所有内存空间中。例如,0x800 处的 4K 字节是未压缩的内置菜单;0x110000 处的 256K 内存虚拟盘的图像通常位于内存的顶部。grub4dos 核心似乎对内存的使用有一种破碎的感觉,但它有一个发展过程,我们不希望后续工作 grub4dos 版本会给用户带来麻烦,所以尽量保持兼容性。兼容性要求使 grub4dos 使用内存有点奇怪。
如何使用grub4dos
大多数人没有或很少接触过linux的windows用户刚刚开始使用grub菜单离不开时间。也就是说,使用grub以前,我们要做好准备menu.lst文件。
下面是一个menu.lst的例子。(以#和//开始,表示注释,不执行)
# 默认延迟时间(秒),即启动界面将停留30秒。
timeout 30
# 第一项是默认值,如果是1,则默认执行第二项菜单。
default 0
#设置外部命令的位置
#set例如:--set-path=变量
command --set-path=(bd)/BOOT/GRUB/
# 设置图形背景文件
splashimage (hd0,0)/boot/grub/xp2008.gz
# 设置中文支持的字体文件
fontfile (hd0,0)/boot/grub/fonts
# 现在基本上背景图片和字体都集成了meassgae在文件中。因此,我们可以用一个命令代替上述两个命令。因此,我们可以用一个命令代替上述两个命令。命令如下:
# 设置图形背景文件和字体
gfxmenu (bd)/BOOT/GRUB/MESSAGE
#将指定文件作为配置文件加载执行此命令后,将重新加载内置菜单,进入二级、三级或任何菜单后可返回主菜单。该命令可以解决返回主菜单的问题。
configfile (md)4 8
title 使用map启动本地硬盘上的一键备份还原软盘镜像文件
map (hd0,0)/boot/grub/okdos.ima (fd0)
map --hook
chainloader (fd0) 1
rootnoverify (fd0)
title 使用memdisk启动本地 Win98 软盘镜像文件
kernel (hd0,0)/boot/grub/memdisk.gz
initrd (hd0,0)/boot/grub/win98.img
title 使用memdisk本地硬盘上启动瑞星杀毒软盘压缩镜像文件
root (hd0,0)
kernel /boot/grub/memdisk.gz c=80 h=12 s=36 floppy
initrd /boot/rav.zip
title 启动第一主分区(hd0、0)上的操作系统
rootnoverify (hd0,0)
makeactive
chainloader 1
title 启动第二主分区(hd0、1)操作系统上的操作系统
rootnoverify (hd0,1)
makeactive
chainloader 1
title 启动WinPE 2003 维护系统
//加载外置SRS驱动
F6IMG
///输出指定内容(即启动菜单时显示此行文本)
echo $[1106]Loading TYPE, Please Wait ...
//0x8298是扩展内存的大小,单位是KB,这里也就是192MB用上面的话MAP --MEM(将要模拟的镜像加载到内存中,然后模拟为虚拟软驱)加载WINPE.ISO,否则就以MAP方式加载。
checkrange 0x30001:-1 read 0x8298 > nul && map --mem (ud)/BOOT/WINPE.ISO (0xff) ! run (ud)/BOOT/WINPE.ISO (0xff)
//避免蓝屏参数
map --e820cycles=3
///模拟立即生效
map --hook
///加载风扇链式加载器(虚拟软驱)
chainloader (0xff)
title 启动Win8PE精简全能版(32位)
find --set-root /BOOT/bootmgr
{ x}