http://blog.sina.com.cn/s/blog_70dd169101013gcw.html
4 制作带grub启动的磁盘映像
在开始之前,我们简单介绍一下grub:总体上我们可以把GRUB看成一个微型的操作系统,它有Shell、支持配置文件、有文件系统,我 们可以把Stage1和Stage1.5看成一个引导程序,而Stage2则是一个操作系统,只不过这个操作系统是专门用来引导其他操作系统的操作系统, 为此,Stage2支持像kernel, initrd,chainloader等等为此目的而设置的内部“命令”。
GRUB引导操作系统的两种方式:
一.直接引导方式
GRUB同时支持 Linux, FreeBSD, NetBSD 和OpenBSD。如果想要启动其他的操作系统,你必须使用链式启动方式来启动他们。
通常,GRUB直接引导操作系统的步骤如下:
(1) 通过'root'命令指定了/boot目录所在的分区;
(2) 通过'kernel'命令来载入该操作系统的核心映像;
(3) 如果需要模块,通过'module'命令来加载模块;
(4) 运行命令'boot'。
Linux, FreeBSD, NetBSD 和 OpenBSD使用相同的方式启动。你可以通过'kernel'命令来装载核心映像,然后运行'boot'命令。如果核心需要一些参数的话,只要在'kernal'命令以后追加就可以了。
二.链式引导方式
如果要启动一个不被GRUB直接支持的操作系统(例如: Windows 95),可以通过链式引导启动一个操作系统。通常来说,那个引导程序和所要启动的操作系统是安装在一个分区中的。
主要步骤如下:
(1)通过'rootnoverify'命令设置GRUB的主设备指向一个扇区:
grub> rootnoverify (hd0,0)
(2) 通过'makeactive'命令来设置在扇区上的'active’标志位:
grub> makeactive
(3) 通过'chainloader'命令来加载引导程序:
grub> chainloader +1 '+1'表明GRUB需要从起始分区读一个扇区
(4) 运行命令'boot'。
GRUB引导操作系统的简要流程分析:
从计算机启动到GRUB启动操作系统
(1) BIOS执行INT 0x19,加载MBR至0x7c00并跳转执行,如果要安装GRUB到MBR,GRUB的安装程序会把Stage1(512B)拷贝到MBR。视 stage2的大小,安装程序会在Stage1中嵌入Stage1_5或者Stage2的磁盘位置信息。
(2) Stage1开始执行,它在进行直接加载Stage1_5或者Stage2并跳转执行。不论是哪种情况,这一步的结果都是Stage2开始运行了。
(3) Stage2这个小型的操作系统终于开始正式运行了!它会把系统切入保护模式,设置好C运行环境(主要是BSS)。他会先找Config文件(就是我们的 menu.lst),如果没有的话就执行一个Shell等待我们输入命令;然后Grub的工作就是输入命令-解析命令-执行命令的循环,当然 Stage2本身是为加载其他操作系统而存在的,所以如果情况允许,在他执行Boot命令以后就会把控制权转交出去。
三.GRUB的主要启动模块
GRUB 包含一个叫"Stage 1.5"的可选的场景文件以及2个启动映像文件,首先对它们有一个大致的了解。
Stage1 :
这是一个基本必须的用来启动GRUB的映像文件。通常,这个文件是被装载到MBR或者启动扇区所在的分区。由于PC的启动扇区的大小为512字节,所以这个映像文件编译以后也必须为512字节。
Stage1的全部的工作是从本地磁盘把Stage 2或者Stage 1.5装载进来。由于对stage1大小的限制,它通过分程序表的形式来编码Stage 2或者Stage 1.5的位置,所以在stage1是不能识别任何文件系统的。
Stage2 :
这是GRUB的核心映像。它几乎做了除启动它本身以外的所有事情,通常它被存放为某一种文件系统下,但并非一定要放在文件系统下。例如我们在下面做引导软盘boot_a.img时,stage2就是直接写在从软盘第二扇区开始的区域,但该软盘是没有安装文件系统的。
e2fs_stage1_5
fat_stage1_5
ffs_stage1_5
jfs_stage1_5
minix_stage1_5
reiserfs_stage1_5
vstafs_stage
1_5xfs_stage1_5
上述这些文件被称为stage 1.5,它存在的目的是做为stage1与stage2之间的桥梁,也就是说stage1载入stage1.5,然后stage1.5载入stage2。
备注:
stage1与stage1.5之间的区别是,前者是不识别任何文件系统的但后者识别文件系统(例如 'e2fs_stage1_5' 识别 ext2fs)。所以你可以安全的移动stage2的位置,即使是在GRUB安装完以后。
在3的基础上,我们再进一步:制作带grub启动的磁盘映像。
我们可以下载grub-0.97-i386-pc.tar.gz软件包:
这个软件包中放置的是已经编译好的elf格式的执行文件,这里我们用现成的软件包O(∩_∩)O~。
我们也可以下载grub-0.97.tar.gz源码自己编译。
下载网址:
首先建立软盘映像:
$ dd if=/dev/zero of=boot_a.img bs=512 count=2880
在boot_a.img中安装grub:
$ sudo losetup /dev/loop0 boot_a.img
$sudo dd if=./grub-0.97-i386-pc/boot/grub/stage1 of=/dev/loop0 bs=512 count=1
$sudo dd if=./grub-0.97-i386-pc/boot/grub/stage2 of=/dev/loop0 bs=512 seek=1
$ sudo losetup -d /dev/loop0
在qemu中测试是否可以进入grub:
$ qemu -fda boot_a.img
示意图如下:
接着建立磁盘映像:
第一步:创建一个32M的磁盘镜像文件
$ dd if=/dev/zero of=hda_32M.img bs=4096 count=8192
第二步:给磁盘映像分区
$ fdisk -C 16065 -H 255 -S 63 32M.img
解释:设置hda_32M.img的磁头数为255、磁道数为16065、扇区数为63,同时给磁盘分区。
这里我们只分一个区,并设置该分区为引导分区。示意图如下:
第三步:格式化分区
$ sudo losetup -o 1048576 /dev/loop0 hda_32M.img
我们把前面的2048个扇区(0~2047)作为引导扇区使用,格式化分区从第2048个扇区开始。
所以1048576=2048*512
$sudo mkfs.ext3 -m 0 /dev/loop0
这里我们把分区初始化为ext3格式。
第四步:把前面制作的bzImage和initrd4M.img拷贝到rootfs目录中。
$ sudo mount /dev/loop0 rootfs/
$ sudo cp linux-2.6.38/arch/x86/boot/bzImage ./rootfs
$ sudo cp initrd4M.img rootfs/
第五步:为在硬盘空间里面安装grub准备目录和文件
备注:
我们可以下载grub-0.97-i386-pc.tar.gz软件包:
这个软件包中放置的是已经编译好的elf格式的执行文件,这里我们用现成的软件包O(∩_∩)O~。
我们也可以下载grub-0.97.tar.gz源码自己编译。
下载网址:
在Fedora14下编译grub-0.97.tar.gz会出现:
configure: error: GRUB requires a working absolute objcopy; upgrade your binutils的错误
解放方法:
gru-0.97中的configure文件的line 3906:
if { ac_try='${OBJCOPY-objcopy} -O binary conftest.exec conftest'
修改为:
if { ac_try='${OBJCOPY-objcopy} -R .note.gnu.build-id -O binary conftest.exec conftest'
这样编译grub-0.97就没有问题了。
编译命令如下:
$cd image_dir
$tar xvf grub-0.97.tar.gz
$./configure
$make
我们接着在磁盘映像hda_32M.img中创建目录来存放grub
$sudo mkdir rootfs/boot
$sudo mkdir rootfs/boot/grub
$sudo cp ./grub-0.97-i386-pc/boot/grub/* rootfs/boot/grub
第六步:在rootfs/boot/grub中编写menu.lst
内容如下:
default 0
timeout 30
title linux on 32M.img
root (hd0,0)
kernel (hd0,0)/bzImage root=/dev/ram init=/bin/ash
initrd (hd0,0)/initrd4M.img
备注:shell用 root=/dev/ram init=/bin/sh也是可以的。
第七步:卸载磁盘映像
$sudo umount rootfs
$sudo losetup –d /dev/loop0
第八步:利用grub启动软盘,在硬盘映像上添加grub功能
$qemu -boot a -fda boot_a.img -hda hda_32M.img
进入grub界面后:
$root (hd0,0)
$setup (hd0)
示意图如下:
这里我们就制作了一个完整的带有grub引导的磁盘映像文件hda_32M.img文件。
测试从磁盘启动grub引导linux系统:
$qemu -hda hda_32M.img
执行效果如下:
至此一个带有grub启动linux-2.6.38系统的磁盘映像文件已经顺利制作完成,O(∩_∩)O~。
参考资料:
[1]陈香兰老师.Linux操作系统分析: build and run linux-2.6.26.ppt