原文转自不点,本人有改动和删减
首先,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 个字节,或者(用十六进制表示)0x2000 字节。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_stage2(它就成为了 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文件当中了。所以我们可以用一个命令取代上面2个命令。命令如下:
# 设置图形背景文件及字体
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
chainloader /BOOT/bootmgr
title 启动Porteus 3.2 中文版
kernel (bd)/BOOT/vmlinuz
initrd (bd)/BOOT/initrd.xz
title 启动Slitaz迷你系统
kernel (bd)/BOOT/BZIMAGE root=/dev/null vga=normal autologin
initrd (bd)/BOOT/ROOTFS.GZ
title 运行密码破解功能菜单
configfile (bd)/BOOT/GRUB/PJ.LST
title 尝试从硬盘启动电脑
//在所有分区根目录查找文件名为ntldr的文件,忽略光驱,如果找到就立即停止搜索,找到就设该设备为根;在所有分区根目录查找文件名为bootmgr的文件,忽略软驱,如果找到就立即停止搜索,找到就设该设备为根。中间的'||'是逻辑或运算符,二个条件,谁先成立先执行谁。
find --set-root --ignore-floppies --ignore-cd /ntldr || find --set-root --ignore-floppies --ignore-cd /bootmgr
// 映射找到引导文件(ntldr、bootmgr)的设备为第一硬盘(hd0)
map () (hd0)
//映射第一磁盘(hd0) 找到引导文件(ntldr、bootmgr)的设备为当前设备
map (hd0) ()
//仿真生效
map --rehook
//在所有分区根目录查找文件名为(ntldr,bootmgr)的文件,忽略光驱,如果找到就立即停止搜索,找到就设该设备为根
find --set-root --ignore-floppies --ignore-cd /ntldr || find --set-root --ignore-floppies --ignore-cd /bootmgr
//加载当前设备根目录下的 ntldr或bootmgr 文件
chainloader /ntldr || chainloader /bootmgr
title 重启
reboot
title 关机
halt
参考这个例子,我们就可以根据自己需要对菜单进行修改。
比如从网上下载了效率源的镜像文件,文件名为XLY.IMG。我们只需把
title 使用memdisk启动本地 Win98 软盘镜像文件
kernel (hd0,0)/boot/grub/memdisk.gz
initrd (hd0,0)/boot/grub/win98.img
改成
title 硬盘检测修复工具 效率源 (memdisk)
kernel (hd0,0)/boot/grub/memdisk.gz
initrd (hd0,0)/boot/grub/xly.img
或者改成
title 硬盘检测修复工具 效率源 (map)
map (hd0,0)/boot/grub/xly.img (fd0)
map --hook
chainloader (fd0)+1
rootnoverify (fd0)
同时把xly.img文件保存到第一主分区(一般是C:)的boot\grub目录下。
当然也可以保存到其它路径。
比如xly.img文件保存到C:\boot下,则menu.lst文件相应改为:
map (hd0,0)/boot/xly.img (fd0)
又如xly.img文件保存到D:\test下,则menu.lst文件相应改为:
map (hd0,4)/test/xly.img (fd0)
(参看下面的几点提示d)
从上面的例子可以看出,启动软盘镜象,有两种方式,即用memdisk或用map。
用memdisk时,img文件可压缩;在img文件大小为非1.44MB或2.88MB标准镜像时,需要指定CHS参数。img文件的CHS参数可用winimage获得。
【提示:参数H, S是关键参数,必须准确无误;参数C设定错了,也不影响引导。】
另外,菜单文件中的文件路径可用相对路径(如:/boot/rav.zip)或绝对路径(如:(hd0,0)/boot/grub/xly.img)表示。
map方式对软盘映像大小没有限制,但要求必须连续存放。
map --mem则无此限制,但要求有足够的内存(使用超大映像文件时要注意这点)。
此映像将被拷贝到一个内存区域,映像本身可以是非连续的,甚至可以是被压缩的。
比如:
map --mem /boot/xxx.ima (fd0)
map --hook
chainloader (fd0)+1
rootnoverify (fd0)
官方文档“Grub4dos高级功能”中对map和memdisk的区别进行了说明:
map是GRUB4DOS内置的功能,而memdisk是一个外部的程序
map可以直接映射磁盘上的文件,而memdisk必须要把文件装载到内存里。
map可以把影像文件映射为第二只硬盘,而而memdisk只能映射为第一只硬盘。
map有自动生成MBR的功能,而memdisk没有。因此memdisk只能使用磁盘影像,不能使用文件系统影像。
几点提示:
A、菜单文件中所用的memdisk.gz文件,不包括在grub4dos的发行包里,需自行准备。可从SysLinux软件包或从其它基于grub的工具(如本人的GGhost一键恢复)中获得。
B、菜单中所用的其它文件如xp2008.gz(背景文件)、fonts(中文字体文件)及各种镜像文件等,均需拷贝到文件中指定路径。 fontfile命令不可单独使用,需与splashimage一起使用。
C、菜单文件中的命令全部使用小写。
D、初学者使用绝对路径时要注意GRUB对设备的命名方法。系统的第一个硬盘驱动器表示成(hd0),其上的第一个分区表示为(hd0,0),也就是说对于硬盘,采用(hdx,y)的形式来表示,x、y都是从0开始计数的,x表示硬盘号,y表示分区号。
由于主分区只能有四个,所以第一硬盘的四个主分区分别用(hd0,0)~(hd0,3)来表示;逻辑分区则从(hd0,4)开始算,即第一逻辑分区用(hd0,4),第二逻辑分区用(hd0,5)来表示,依次类推。
一般机子的硬盘都是一个主分区,其余是逻辑分区。因此C盘用(hd0,0),D盘用(hd0,4)来表示。 光盘用(cd)表示,第一软驱用(fd0)表示。
grub4dos对于常规设备的命名
grub4dos对于常规设备有两种命名规则,
一种是 (ud) , (pd) , (nd) , (hd) , (cd) , (fd) 六种直观设备命令,可以对 hd 、 cd 、 fd 三种设备进行编号。
ud 为 bean 原创的 fbinst 启动方式制作的隐藏分区
pd 为 pxe device ,即pxe设备
nd 为 network device ,网络驱动器,现已不常用
hd 为 hard device ,磁盘类设备
cd 为 cdrom device ,光驱类设备
fd 为 floppy device ,软驱类设备
同时还有对特殊设备的命名:
() 就是一对空括号,表示当前设备。
(bd) boot device,通用写法,初始启动设备,可以使菜单更具通用性。注:使用configfile命令会改变启动设备。
(md) 内存驱动器,实现了将整个内存作为一个磁盘驱动器来访问。(预留驱动器号 0xffff )。
注意: (md)只工作在支持BIOS中断int15/EAX=E820h的系统上。
(rd) 随机存贮驱动器。(md) 设备访问内存是从物理地址0开始,而 (rd) 可以访问起始于任何基地址的内存。
如果是使用FB制作的启动U盘,(ud)代表隐藏的启动分区,()代表可见区。(bd)=(ud)。
关于G4D的一些“经典”问题的搜罗解答
Q1:
大硬盘(128G以上),无法启动GRLDR,可是在Windows下一切正常。
Answer:
因为BIOS有缺陷,往往无法访问比较靠后的文件(GRUB仰赖BIOS来访问磁盘),但是Windows有自己的磁盘驱动,所以没有问题。
Workaround:
把GRLDR移到磁盘靠前的位置
Q2:
在硬盘上的某某文件(ISO、IMG等)无法直接被map映射,加了--mem参数可以。
Answer:
因为那个文件不是连续存放在磁盘上的。直接map需要文件连续的存放在存储器上,
Workaround:
利用磁盘整理工具整理一下该文件即可(比如说WinContig)。
Q3:
我用--mem的方式来启动PE,可惜在启动时遇到了蓝屏(注:不是7B蓝屏,直接map也不会蓝屏)。
Answer:
因为你的BIOS有问题(或者叫做恶意封杀也行),对GRUB4DOS的map兼容不好。
Workaround:
使用新版的GRUB4DOS启动,在map语句后,map --hook前加一句:map --e820cycles=x(x的值在0-3之间,一般的新机器用3,一些品牌机要用0)
Q4:
我用新版的G4D把font文件放到第一个盘的第一个区上,用fontfile (hd0,0)/fonts这个语句,可惜无法显示中文。
Answer:
fontfile是旧版的命令,新版应该使用VBE模式。
Workaround:
①打开你的菜单
②搜索unifont.hex.gz这个文件并下载,放到某目录(假设是(hd0,0)/boot/grub)
③把fontfile (hd0,0)/fonts这句删掉,换成:
graphicmode -1
font 电脑(hd0,0)/boot/grub/unifont.hex.gz
④用UTF8格式保存你的菜单。
Q5:
我用新版的G4D启动WINPE提示分辨率超出。
Answer:
这个应该是G4D对电脑的图形支持出现了问题。
Workaround:
修改菜单文件,在最上面加一句命令:
graphicsmode 3
或者terminal console。
然后保存菜单即可解决问题。
terminal console 是使用普通 VGA 模式的 BIOS 调用而进入文本模式。
graphicsmode 3 是使用符合 VBE 规范的 BIOS 调用而进入文本模式。
按道理,两者都应该成功才对。但是,由于某些主板存在问题,所以,可能会发生一个能够成功而另一个不能成功的情况。
凭直观感觉,我觉得 graphicsmode 3 的成功率可能要高一些,尤其是当用户已经用 gfxmenu 进入图形模式的时候(其实这个图形模式也属于 VBE 的范畴),通常就应该用 VBE 的 BIOS 调用而回到文本模式(因为 VBE 的文档中就是这么建议的),也就是说,应该用 graphicsmode 3 来返回到文本模式。
电脑