在刚接触Linux的时候,就想把自己编译好的linux内核放在虚拟机中启动,刚开始时一筹莫展,后来在IBM的linux文档库中发现了一种制作linux iso的方法(《BIOS和 EFI 介绍及其启动光盘制作》),它主要是通过ISOLINUX制作BIOS 的启动程序,详情可以参考以下文章。
http://www.linuxidc.com/Linux/2012-07/66939.htm
http://www.syslinux.org/wiki/index.php/ISOLINUX#What_is_ISOLINUX.3F
言归正传,下面将介绍如何生成一个可被Legacy BIOS引导的Linux最小系统的iso镜像文件。
一、Legacy BIOS boot 介绍
首先了解一下 Legacy BIOS 如何启动或引导。当系统首次引导时,或系统被重置时,处理器会执行一个位于已知位置处的代码。这个位置在基本输入 / 输出系统(BIOS) 中,它保存在主板上的闪存中。CPU 会调用这个重置向量来启动一个位于闪存 /ROM 中的已知地址处的程序。通常,它执行一个启动自测(POST)来检查机器。最后,它从引导驱动器上的主引导记录(MBR)加载第一个扇区。
这时第一阶段的引导加载程序开始了。引导程序 boot loader 就位于 MBR 第一个扇区里面。此时 boot loader 就被装入 RAM 并执行。这个引导加载程序在大小上小于 512 字节(一个扇区),其作用是加载第二阶段的引导加载程序。
当第二阶段的引导加载程序被装入 RAM 并执行时,通常会显示一个动画屏幕,并将 Linux 和一个可选的初始 RAM 磁盘(临时根文件系统)加载到内存中。在加载映像时,第二阶段的引导加载程序就会将控制权交给内核映像,然后内核就可以进行解压和初始化了。在这个阶段中,第二阶段的引导加载程序会检测系统硬件、枚举系统链接的硬件设备、挂载根设备,然后加载必要的内核模块。完成这些操作之后启动第一个用户空间程序(init),并执行高级系统初始化工作。
此处,简单介绍用户空间程序init,它位于/sbin下,是初始化的简称。init程序的工作是读取/etc/inittab文件中描述的指令,对系统的各种软硬件环境做最初化设定.最后运行mingetty等待用户输入用户名登录系统.所有的工作就这么简单,虽然linux启动的时候有很多内容,看上去十分高深,但是都不过是对这个过程的扩充.明白了这个道理,你可以写一些脚本程序让他在系统启动的特定时间运行完成任务.事实上系统内核并不关心/sbin下的init是不是真的init,只要是放在/sbin下名叫init的可执行程序他都可以执行.可以做以下实验:
编写一个非常简单的C程序:
main()
{
printf(“hello,world!\n”);
}
保存后以init.c保存他,并用gcc编译.
#gcc –-static -o init init.c
这里的–static 参数告诉gcc把这个程序静态联接,这样这个程序不倚赖任何库就能运行.把编译好的init程序拷贝到/sbin下,备份好原来的那个.重新启动系统最后系统的输出结果是: hello,world!
然后停在那里。【Linux公社 http://www.linuxidc.com 】 做这个实验以前先确定你知道如何把系统恢复到原来的状态,有一个简单的方法,在内核启动前给他加上init=参数,比如你原先的init被你改成了init.bak 只要在启动的时候给内核加上init=/sbin/init.bak就可以用原来的init程序启动系统。
图 1. 开机过程示意图
制作支持 Legacy BIOS 启动光盘的步骤
2.1 step1 准备 isolinux.bin 和工作目录
在准备制作 ISO 的目录里添加一个子目录,比如 isolinux/ ,然后放入 isolinux.cfg 和一个对所有光盘都一样的 isolinux 提供的引导介质 isolinux.bin。isolinux.bin 可以这样得到,访问syslinux 的官方网站(如下),下载它所提供的syslinux-4.04.tar.bz2 文件,目前最新版为4.04。
http://www.syslinux.org/wiki/index.php/ISOLINUX#What_is_ISOLINUX.3F
当然还要放入相应的 kernel, initrd 等等,目录结构如下:
清单 1. CD_root 目录结构
|—isolinux | |—isolinux.bin | |—isolinux.cfg |—kernel (OS 内核) |—initrd (文件系统) |—readme |
Kernel为需要引导的操作系统内核,此处选择Linux内核,内核的获取可以通过编译适当的Linux内核版本得到,本文采用的是2.6.30.59版。内核可以根据自己的需要进行适当的裁剪,在此不累述。记住,在编译的时候一定要选择x86的体系结构,因为本文是基于x86体系结构镜像讲解的,如果您不知道怎么选择CPU体系结构,可以参考下面的写法:
# make ARCH=x86 menuconfig
编译完成后在arch/x86/boot中会生成内核镜像bzImage。将其拷贝到CD_root(制作iso的根目录)中,当然您也可以专门建立相关的文件夹来存放内核和文件系统,区别只是在配置isolinux.cfg时的路径问题(可参考下一小节)。
除了内核镜像外,还需要文件系统。本节采用busybox制作文件系统,并生成ramdisk镜像文件ramdisk.img。关于ramdisk文件的制作方法见章节:文件系统,其中有一小节专门讲解了如何制作根文件系统。 【Linux公社 http://www.linuxidc.com 】
2.2 step2 配置 isolinux.cfg
prompt 1 timeout 100 default myBIOSiso label myBIOSiso kernel /bzImage append initrd=/ramdisk.img load_ramdisk=1 prompt_ramdisk=0 ramdisk_size=60000 rw root=/dev/ram |
配置 isolinux.cfg
这里只做了简单的配置。注意,这里的文件系统是ramdisk.img,经过笔者试验,发现使用压缩镜像ramdisk.img.gz时,会出现找不到该文件的错误,当笔者将压缩文件重命名为ramdisk.gz后,问题得以解决。所以,此处笔者推荐使用append initrd=/ramdisk.gz load_ramdisk=1 prompt_ramdisk=0 ramdisk_size=60000 rw root=/dev/ram。这样做出来的引导盘会很小。笔者本次制作出来的iso镜像大小为5M,当然,如果需要,您还可以做得更小。
除此之外,利用isolinux还可以添加诸如菜单等内容。更多使用方法可以参考syslinux中的说明文档,同时笔者将在下一小节泛讲菜单的相关内容。
2.3 step3 制作 BIOS 平台可启动光盘
#mkisofs -o output.iso -b isolinux/isolinux.bin -c \ isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-tableCD_root |
制作 BIOS 平台可启动光盘的命令
制作 iso 的时候要使用 -b 参数,用来指定 isolinux.bin 所在的路径,-c 参数的那个文件(boot.cat)是自动生成的,不用关心,其余参数都是固定的。这里的路径都是相对于光盘的根目录而言,和制作光盘时的工作目录没有关系。
完成后,会在当前目录(也可以指定)生成iso镜像光盘文件,文件名为output.iso。
接下来可以在虚拟机中验证生成的iso文件是否可以启动linux。首先安装VMware6.0,然后新建一个虚拟机,内存和硬盘都不必选得很大,要知道我们的内核是非常小的,选择256M的内存,硬盘1G(可以更小,因为这样的操作不需要硬盘,只要内存足够就可以了),完成后,将生成的iso加载到虚拟机的光驱中,启动虚拟机,成功会出现如下图的相似信息。
值得注意的是,我们的根文件系统存在于内存之中,所以您会看到在加载ramdisk1.img时需要一定的时间。在此,简单梳理一下整个启动过程。首先,BIOS完成第一阶段的引导,虚拟机从光驱启动,isolinux会加载内核镜像到虚拟机内存中,然后加载文件系统(ramdisk)到内存中,将执行权限交给Linux内核,内核启动然后加载文件系统。
至此,就可以利用虚拟机验证自己修改的内核和根文件了。当然,这只是一个极为简略和粗糙的启动光盘,用于学习Linux内核和文件系统是相当有益的,你不用担心这会损害您的电脑的目前的状态,因为所有的东西都在内存之中。
在后面的章节中,笔者会介绍更加丰富的启动功能,以及如何从硬盘启动我们制作的Linux系统。
丰富的isolinux 应用
本小节讲述如何完美的应用isolinux进行启动光盘的优化。上节我们已经成功的制作好了一个可启动的光盘,但是那仅是一个功能简单的启动盘,如何制作像系统安装盘一样的,功能丰富,画面优美的linux系统盘就是本节的主要内容。
3.1 添加背景图片
首先来看一下带背景图片的启动菜单示例,如下:
上图是一个简单的示例,如果您有兴趣可以做得更加精致,当然,这不是本节的重点。下面笔者将详细的描述背景图片的添加方式。
要为启动菜单添加背景图片,首先需要准备一张640×480的PNG, JPEG 或 LSS16 格式的图片,笔者尝试过更大的图片,结果是不能将图片正常的加载,所以建议使用640*480的图片。然后照下修改isolinux.cfg文件。
display info.txt PROMPT 0 timeout 200 default vesamenu.c32 MENU BACKGROUND /PIC2.jpg MENU WIDTH 60 MENU MARGIN 0 MENU ROWS 11 MENU HELPMSGROW 15 MENU TIMEOUTROW 22 MENU TABMSGROW 24 MENU CMDLINEROW 24 MENU HSHIFT 10 MENU VSHIFT 2 menu color screen 37;40 #ffffffff #00000000 none menu color border 30;44 #00000000 #00000000 none menu color title 1;36;44 #f01291a9 #00000000 std menu color unsel 37;44 #e01291a9 #00000000 none menu color hotkey 1;37;44 #e060CA00 #00000000 none menu color sel 7;37;40 #e0712704 #20ff8000 all menu color hotsel 1;7;37;40 #e0400000 #20ff8000 all menu color disabled 1;30;44 #60cccccc #00000000 none menu color scrollbar 30;44 #40000000 #00000000 std menu color tabmsg 31;40 #9060CA00 #00000000 none menu color cmdmark 1;36;40 #c000ffff #00000000 std menu color cmdline 37;40 #c0ffffff #00000000 none menu color pwdborder 30;47 #80ffffff #20ffffff std menu color pwdheader 31;47 #80ff8080 #20ffffff std menu color pwdentry 30;47 #c0ffffff #20ffffff std menu color timeout_msg 37;40 #e060CA00 #00000000 none menu color timeout 1;37;40 #f060CA00 #00000000 none menu color help 37;40 #c0ffffff #00000000 none menu color msg07 37;40 #90ffffff #00000000 none MENU AUTOBOOT Automatic boot in # seconds… MENU TABMSG press [TAB] Edit Option MENU TITLE Linux kernel Test LABEL Test Linux MENU LABEL Start My Linux Kernel MENU INDENT 4 KERNEL /bzImage append initrd=/ramdisk.img load_ramdisk=1 prompt_ramdisk=0 ramdisk_size=600000 rw root=/dev/ram |
注意红色标注的部分,PROMPT 0 不会提示用户输入,在制作菜单的过程中,建议将其设为1 ,这样,您可以方便的观察当前配置是否有错误的地方,并且容易查找配置文件中的错误。提示完成后,记得输入回车启动后面的内容。MENU BACKGROUND /PIC2.jpg,这是本节的主要配置选项,PIC2.jpg就是笔者加入的菜单背景。可能您已经注意到上述配置文件中除了对背景的配置外,还有其他的配置信息,如 MENU WIDTH 之类的诸多配置选项,这将在下一小节进行介绍。
要应用isolinux的菜单功能,必须包含vesamenu.c32文件,该文件可以在syslinux-4.04文件中的com32\menu中找到。您可以把该文件复制到要制作的iso镜像文件夹中,笔者将其放在isolinux.cfg的目录下。
3.2 添加各类菜单选项
Isolinux支持丰富的菜单功能,可以参考syslinux-4.04中doc文件夹中的menu.txt文件,该文件作了更为详细的描述,笔者只针对一部分菜单做介绍。
DEFAULT label
设置全局默认,如果“label”指向一个子菜单,那么这个菜单将成为开始菜单;换句话说,这个指令同MENU DEFAULT和MENU START具有相同的作用。
布局选项
上面的选项控制屏幕上菜单的布局。上面的值为默认值。负数值是相对屏幕的计算长度(25用于文本模式,28用于VESA图形模式)。
MENU COLOR element ansi foreground background shadow
设置元素颜色。您可以按如下序列进行设定颜色值:
上图中有英文的简要注释,如screen元素表示重置的屏幕。Title表示标题的工具条,这里的所有元素均有默认值,如下:
您可以根据自己的需求进行修改。这里,讲解一下最后一个元素msgXX,在默认值中,最后一项为msg07,这是什么意思呢?这里XX是两个16进制数,07表示“纯文本”。
整个条目中有一个字段为ansi,从默认值中也可以看出它的取值相当丰富,下面将详细的介绍该字段的含义,取值最小为0, 最大49,各值对应的含义如下:
0 重置所有属性为默认值
1 设置黑体
4 设置下划线 (simulated with color on a color display)
5 set blink
7 set reverse video
22 set normal intensity
24 underline off
25 blink off
27 reverse video off
30 set black foreground
31 set red foreground
32 set green foreground
33 set brown foreground
34 set blue foreground
35 set magenta foreground
36 set cyan foreground
37 set white foreground
38 set underscore on, set default foreground color
39 set underscore off, set default foreground color
40 set black background
41 set red background
42 set green background
43 set brown background
44 set blue background
45 set magenta background
46 set cyan background
47 set white background
49 set default background color
“foreground” 和 “background” 是#AARRGGBB符号的颜色编码,AA RR GG BB 是alpha(不透明度)的十六进制数字,分别为红,绿和蓝。#00000000代表全透明,#ffffffff代表不透明的白色。
“shadow” 控制处理图形化控制台文本阴影,允许值为“none”(无阴影),“std”或”standard”(标准阴影-前景像素凸起), “all” (背景色和前景色都凸起), 和”rev” 或 “reverse” (b背景色凸起)。
F1 textfile [background]
…
F12 textfile [background]
显示全屏帮助(命令行时也有效)。此外,选项的第二个参数允许不同的背景图像(参考MENU BACKGROUND 支持的格式)被显示。注意,textfile文件名。
MENU AUTOBOOT message
替换消息“Automatic boot in # second{,s}…”。#号 替换剩下的秒数,语法”{singular,[dual,]plural}”可以恰当的结合使用。
MENU TABMSG message
替换消息”Press [Tab] to edit options”。
MENU HELP textfile [background]
创建一个菜单条目,其中,被选中时,显示全屏帮助像F-key一样的帮助。