Linux 启 动 分 析 专 题 第一部分 背景知识简介 几乎所有编写代码的人都有这种体会:如今在计算机这个行业中,许多技术不是你不懂,而是你不知道。所以,在分析之前有些背景知识是必须要知道的。 一. 硬盘结构简介 1. 硬盘参数释疑 到目前为止, 人们常说的硬盘参数还是古老的 CHS (Cylinder/Head/Sector)参数. 那么为什么要使用这些参数, 它们的意义是什么? 它们的取值范围是什么? 很久以前, 硬盘的容量还非常小的时候, 人们采用与软盘类似的结构生产硬盘,也就是硬盘盘片的每一条磁道都具有相同的扇区数,由此产生了所谓的3D参数 (Disk Geometry)。既磁头数(Heads), 柱面数(Cylinders), 扇区数(Sectors),以及相应的寻址方式。 其中: 磁头数(Heads) 表示硬盘总共有几个磁头,也就是有几面盘片, 最大为 255 (用 8 个二进制位存储); 柱面数(Cylinders) 表示硬盘每一面盘片上有几条磁道, 最大为 1023(用 10 个二进制位存储); 扇区数(Sectors) 表示每一条磁道上有几个扇区, 最大为 63 (用 6个二进制位存储); 每个扇区一般是 512个字节(理论上讲这不是必须的, 但好象都取此值)。 据此,磁盘最大容量为: 255 * 1023 * 63 * 512 / 1048576 = 8024 MB ( 1M = 1048576 Bytes ) 或硬盘厂商常用的单位: 255 * 1023 * 63 * 512 / 1000000 = 8414 MB ( 1M = 1000000 Bytes ) 在 CHS 寻址方式中, 磁头, 柱面, 扇区的取值范围分别为 0 到 Heads - 1,0 到 Cylinders - 1, 1 到 Sectors (注意是从 1 开始)。 2. 基本 Int 13H 调用简介 BIOS Int 13H调用是 BIOS 提供的磁盘基本输入输出中断调用, 它可以完成磁盘(包括硬盘和软盘)的复位, 读/写, 校验, 定位, 诊断, 格式化等功能。它使用的就是 CHS 寻址方式, 因此最大只能访问 8 GB 左右的硬盘 ( 本文中如不作特殊说明, 均以 1M = 1048576 字节为单位). 而更不幸的是,标准的IDE接口容许256个扇区/磁道、65536个柱面及16个磁头。它自己本身可以存取 137438953472(128 GB),但是加上BIOS方面63个扇区与1024个柱面的限制后,就只剩528482304(1024*16*63 = 504MB)可以定址得到,这就是所谓标准IDE硬盘只认前504MB问题。 3. 现代硬盘结构简介 在老式硬盘中, 由于每个磁道的扇区数相等 (与软盘一样), 所以外道的记录密度要远低于内道, 因此会浪费很多磁盘空间。为了解决这一问题, 进一步提高硬盘容量, 人们改用等密度结构生产硬盘, 也就是说, 外圈磁道的扇区比内圈磁道多。采用这种结构后, 硬盘不再具有实际的3D参数, 寻址方式也改为线性寻址, 即以扇区为单位进行寻址。 为了与使用3D寻址的老软件兼容 (如使用BIOS Int13H接口的软件), 在硬盘控制器内部安装了一个地址翻译器, 由它负责将老式3D参数翻译成新的线性参数。这也是为什么现在硬盘的3D参数可以有多种选择的原因 (不同的工作模式对应不同的3D参数, 如 LBA, LARGE, NORMAL)。 4. 扩展 Int 13H 简介 虽然现代硬盘都已经采用了线性寻址, 但是由于基本 Int 13H 的制约, 使用 BIOS Int 13H 接口的程序, 如 DOS 等还是只能访问 8 G 以内的硬盘空间。为了打破这一限制, Microsoft 等几家公司制定了扩展 Int 13H 标准(Extended Int13H,详见附录A), 采用线性寻址方式存取硬盘,所以突破了 8 G 的限制,而且还加入了对可拆卸介质 (如活动硬盘) 的支持。 二. Boot Sector 结构简介 1. Boot Sector 的组成 Boot Sector 也就是硬盘的第一个扇区, 它由 MBR (Master Boot Record),DPT (Disk Partition Table) 和 Boot Record ID(Magic Number) 三部分组成。 MBR 又称作主引导记录,占用 Boot Sector 的前 446 个字节 ( 0 to 0x1BD ),包含了硬盘的一系列参数和一段系统主引导程序。引导程序主要是用来在系统硬件自检完后负责从活动分区中装载并运行系统引导程序(引导操作系统)。它的最后一条执行语句是一条JMP指令,跳到操作系统的引导程序去。这里往往是引导型病毒的注入点,也是各种多系统引导程序的注入点。但是由于引导程序本身完成的功能比较简单,所以我们完全可以判断该引导程序的合法性(比如看JMP指令的合法性),因而也易于修复。象命令fdisk/mbr可以修复MBR和KV300这类软件可以查杀任意类型的引导型病毒,就是这个道理。 DPT 即主分区表,占用 64 个字节 (0x1BE to 0x1FD),记录了磁盘的基本分区信息。主分区表分为四个分区项, 每项 16 字节, 分别记录了每个主分区的信息(因此最多可以有四个主分区)。 Boot Record ID 即引导区标记,占用两个字节 (0x1FE and 0x1FF), 对于合法引导区, 它等于 0xAA55, 这是判别引导区是否合法的标志. Boot Sector 的具体结构如下图所示: 2. 主分区表的结构 主分区表由四个分区项构成, 每一项的结构如下: BYTE State : 分区状态, 0 = 未激活, 0x80 = 激活 (注意此项) BYTE StartHead : 分区起始磁头号 WORD StartSC : 分区起始扇区和柱面号, 低字节的低6位为扇区号,高2位为柱面号的第 9,10 位, 高字节 为柱面号的低 8 位 BYTE Type : 分区类型, 如 0x0B = FAT32, 0x83 = Linux 等, 00 表示此项未用 BYTE EndHead : 分区结束磁头号 WORD EndSC : 分区结束扇区和柱面号, 定义同前 DWORD Relative : 在线性寻址方式下的分区相对扇区地址 (对于基本分区即为绝对地址) DWORD Sectors : 分区大小 (总扇区数) 注意:在 DOS / Windows 系统下, 基本分区必须以柱面为单位划分( Sectors * Heads 个扇区), 如对于 CHS 为 764/255/63 的硬盘, 分区的最小尺寸为 255 * 63 * 512 / 1048576 = 7.844 MB。 3. 扩展分区简介 由于主分区表中只能分四个分区, 有时无法满足需求, 因此设计了一种扩展分区格式。 基本上说, 扩展分区的信息是以链表形式存放的, 但也有一些特别的地方。 首先,主分区表中要有一个基本扩展分区项, 所有扩展分区都隶属于它,也就是说其他所有扩展分区的空间都必须包括在这个基本扩展分区中。 对于DOS / Windows 来说, 扩展分区的类型为 0x05。 除基本扩展分区以外的其他所有扩展分区则以链表的形式级联存放, 后一个扩展分区的数据项记录在前一个扩展分区的分区表中, 但两个扩展分区的空间并不重叠。 扩展分区类似于一个完整的硬盘, 必须进一步分区才能使用。但每个扩展分区中只能存在一个其他分区, 此分区在 DOS/Windows 环境中即为逻辑盘。因此每一个扩展分区的分区表 (同样存储在扩展分区的第一个扇区中)中最多只能有两个分区数据项(包括下一个扩展分区的数据项)。 扩展分区和逻辑盘的示意图如下: 三. 系统启动过程简介 系统启动过程主要由一下几步组成(以硬盘启动为例): 1. 开机; 2. BIOS 加电或按reset键后都要进行系统复位,复位后指令地址为 0ffff:fff0,这个地方只有一条JMP指令, 跳转到系统自检 ( Power On Self Test -- POST )程序处; 3. 系统自检完成后,将硬盘的第一个扇区 (0头0道1扇区, 也就是Boot Sector)读入内存地址 0000:7c00 处; 4. 检查 (WORD) 0000:7dfe 是否等于 0xaa55, 若不等于则转去尝试其他启动介质, 如果没有其他启动介质 则显示 "No ROM BASIC" 然后死机; 5. 跳转到 0000:7c00 处执行 MBR 中的程序; 6. MBR程序 首先将自己复制到 0000:0600 处, 然后继续执行; 7. 在主分区表中搜索标志为活动的分区,如果没有发现活动分区或有不止一个活动分区, 则转停止; 8. 将活动分区的第一个扇区读入内存地址 0000:7c00 处; 9. 检查 (WORD) 0000:7dfe 是否等于 0xaa55, 若不等于则 显示 "Missing Operating System" 然后停止, 或尝 试软盘启动或; 10. 跳转到 0000:7c00 处继续执行特定系统的启动程序; 11. 启动系统... 以上步骤中 2,3,4,5 步是由 BIOS 的引导程序完成. 6,7,8,9,10步由MBR中的引导程序完成. 一般多系统引导程序 (如 SmartFDISK, BootStar, PQBoot 等)都是将标准主引导记录替换成自己的引导程序, 在运行系统启动程序之前让用户选择要启动的分区。 而某些系统自带的多系统引导程序 (如 lilo, NT Loader 等)则可以将自己的引导程序放在系统所处分区的第一个扇区中, 在 Linux中即为 SuperBlock (其实 SuperBlock 是两个扇区)。 注:以上各步骤中使用的是标准 MBR, 其他多系统引导程序的引导过程可能与此不同。 下面简要说明一下系统复位后的指令地址0ffff:fff0(物理地址0x0fffffff0): 在实地址模式下,内存有两个保留区域:系统初始化区和中断向量表区。地址0x00000~0x003ff 是为中断向量保留的,256个可能的中断,每一个保留4字节的跳转向量;地址0xfffffff0~0xffffffff是为系 统初始化保留的,此处一般只有一条JMP指令,跳到系统初始引导程序。 系统复位后,cs = 0x0f000、eip = 0x0000fff0,而系统初始引导程序安排在 0x0ffff0000~0x0ffffffff, 一般为ROM固件,使初始引导程序工作于内存实际地址空间以外的另一存储段中。此区域的16~31位都 应为1,cs及eip的初值已保证地址线的16~19位为1,而20~31位,即地址线的高12位,则须由硬件强制置 1,这由一个标志触发器在系统每次复位时置位实现触发。而由于段间转移指令要重新装入cs寄存器, 因此,每当执行段间转移指令时,此标志触发器复位,以后,再次访问时,不再向高12位地址线提供“1”信号,程序从此正常地工作于前1MB的地址空间。 第二部分 硬盘MBR主引导代码分析 一.程序流程 (引导扇区是指硬盘相应分区的第一个扇区,是和操作系统有关的,操作系统的引导是由它来完成的;而MBR主引导程序并不负责引导操作系统,MBR是和操作系统无关的,他的任务是把控制权转交给操作系统的引导程序.) 1 将程序代码由0:7C00H移动到0:0600H(注,BIOS把MBR放在0:7C00H处) 2 搜索可引导分区,即80H标志 成功:goto 3 失败:跳入ROM BASIC 无效分区表:goto 5 3 读引导扇区 失败:goto 5 成功:goto 4 4 验证引导扇区最后是否为55AAH 失败:goto 5 成功:goto 6 5 打印错误进入无穷循环 6 跳到0:7C00H进行下一步启动工作 二.代码注释 下面将用汇编语言写出这一段代码,并进行说明。 ;MBR.ASM ; MASM MBR ; LINK MBR ; EXE2BIN MBR .MODEL tiny .CODE ;设置寄存器及堆栈值 org 0 Head: Start: cli xor ax,ax mov ss,ax mov sp,7C00H ;ss:sp=0:7C00H mov si,sp push ax pop es push ax pop ds ;es=ds=0 sti ;将程序代码由0:7C00H移动到0:0600H处 cld mov di,600H mov cx,100H ;100H Words=512 Bytes,即一个扇区大小 repne movsw db 0EAH ;这个是FAR JUMP的机器码 dw offset Continue+600H, 0000H ;这个是跳转目的地址,即0:061DH ;搜索可引导分区 Continue: mov si,600H+1BEH ;si指向分区表 mov bl,4 ;四个分区 FindBoot: cmp byte ptr[si],80H je SaveRec ;读扇区位置 cmp byte ptr[si],0 jne Invaild ;无效分区 add si,10H dec bl jnz FindBoot int 18H ;进入ROM BASIC ;读取引导分区的扇区,柱面号 SaveRec: mov dx,[si] mov cx,[si+2] mov bp,si ;检查其余分区表 FindNext: add si,10H dec bl jz SetRead cmp byte ptr[si],0 ;是否存在非法分区 je FindNext Invaild: mov si,offset ErrMsg1+600H ;字符串输出子程序 PrintStr: lodsb cmp al,0 je DeadLock push si mov bx,7 mov ah,0EH ;输出字符 int 10H pop si jmp short PrintStr ;下一字符 DeadLock: jmp short DeadLock ;无穷循环,也可以写成jmp $ ;读引导扇区 SetRead: mov di,5 ;读取次数 ReadBoot: mov bx,7C00H mov ax,201H push di int 13H ;cx,dx已经在SaveRec处得到 pop di jnc GoBoot ;成功则启动 xor ax,ax int 13H ;reset驱动器,然后再读取 dec di jnz ReadBoot mov si,offset ErrMsg2+600H jmp short PrintStr 失败输出信息,并进入无穷循环 ;检查读入的引导扇区 GoBoot: mov si,offsetErrMsg3+600H mov di,7C00H+1FEH cmp word ptr[di],0AA55H jne PrintStr ;非AA55标志则输出错误信息 mov si,bp ;si指向可启动分区 db 0EAH,0,7CH,0,0 ;跳转至0:7C00H ErrMsg1 db 'Invaild partition table',0 ErrMsg2 db 'Error loading operating system',0 ErrMsg3 db 'Missing operating system',0 Tail: FillNum equ 1BEH-(Tail-Head) ;计算填0数目 db FillNum dup(0) ;四个分区表项数据,跟分区情况有关,详细含义另解 PartTable db 80H,1,1,0,4,4,0D1H,2,11H,0,0,0,0FEH,0FFH,0,0 db 0,0,0C1H,3,5,4,0D1H,0FEH,0FFH,0FFH,0,0,0ACH,53H,0,0 db 20H dup(0) ID dw 0AA55H end start ;如果开始试用org 600H,那么访问数据时就不必加上600H,如mov si,offset ErrMsg2+600H ;可写为mov si,offset ErrMsg2,这时就不能用exe2bin得到数据,必须试用debug ;debug mbr.exe ;-nmbr.bin ;-rcx 200 ;-wcs:600 ;-q 在硬盘的第一个扇区上保存着分区信息,即主分区表,共有四项,读取分区表必须使用bios的int 13h,一般使用debug就可以了: debug -a xxxx:0100 mov ax,201 mov bx,200 mov cx,1 mov dx,80 ;如果是第二个硬盘则是81... int 13 int 20 xxxx:???? -g=100 这时xxxx:0200开始的512字节就是分区表所在的扇区,前面一部分为MBR,在debug中用-d3be l40就可以看到64字节的分区表信息,16个字节为一项,用-e命令就可以修改,改完后可以重新写回去,只要把前面代码中的mov ax,201改为mov ax,301即可,或者直接把102处的2改成3,比如: -e 102 xxxx:0102 02.3 -g=100 这样就写回去了,不过修改硬盘的第一个扇区须非常谨慎。 下面说一下分区表项的具体意义,取其中一项举个例子: 80 01 01 00 0B 3F FF 00 3F 00-00 00 81 4F 2F 00 1 (80)引导标志,80代表可引导,00代表不可引导,一般必须且只能有一个分区表项的引导标志为 80,除非你自己修改MBR 2 (01)分区开始磁头 3,4 (01 00)=(0,1)分区开始柱面和扇区(后面后详解) 5 (0B)分区类型(后面有详解) 6 (3F)=(63)分区结束磁头 7,8 (FF 00)=(768,63)分区结束柱面和扇区(同上) 9-12 (3F 00 00 00)=(63)此分区前扇区总数,即相对扇区数 13-16 (81 4F 2F 00)=(002F4F81H=3100545)此分区扇区总数 柱面和扇区共用两个字节表示,而柱面号为10位,最大1023,扇区号为6位,最大63,具体各位分布如下图: 扇区号 _____|____ | | ( 7 6 5 4 3 2 1 0 ) ( 7 6 5 4 3 2 1 0 ) |__| |___________| |___________________| | 柱面号 关于分区类型,常见的有: 00 未用,Unused 01 DOS-12(FAT 12) 02 XENIX 04 DOS-16(FAT 16)(分区<32M的,应该已没有了) 05 EXTEND(DOS扩展分区) 06 BIGDOS(>32M)(这个才是现在常说的FAT 16) 07 HPFS(OS/2)(NTFS也是这个标记,好像是) 0B FAT 32 0F 这个一时不确定 50 DM 63 386/ix(unix) 64 NET286(Novell) 65 NET386(Novell) 82 Linux swap 83 Linux native FF BBT(UNIX Bad Block Table) 下面有几个算式用来计算分区参数: 1)第一分区参数 扇区总数=(结束柱面+1)*磁头数*每柱面扇区数-相对扇区数,例如:3100545=(768+1)*64*63-63 2)其它分区参数 扇区总数=(结束柱面-起始柱面+1)*磁头数*每柱面扇区数,如下例: 00 00 C1 01 05 3F FF FD C0 4F-2F 00 C0 90 0F 00 000F90C0H=1020096,(FF FD)=(1021,63),(C1 01)=(769,1),1020096=(1021-769+1)*64*63 3)第一分区相对扇区=每柱面扇区数 其它分区相对扇区=上一分区相对扇区+上一分区扇区总数 扩展分区信息是一个链状结构,在删除分区时,把前面的分区删掉会导致后面的分区也找不到,原因就在于此,我们从主分区表中取出扩展分区项进行一下分析,如下: 00 00 01 C0 05 FE BF 6E C0 10-2F 00 EF A6 69 00 由此我们可以得到数据: 开始磁头:00 开始柱面扇区:01 C0=(192,1) 用debug debug -a100 xxxx:0100 mov ax,201 mov bx,200 mov cx,c001 ;开始柱面扇区号 mov dx,80 ;dh中为开始磁头号,这里为0 int 13 int 20 xxxx:???? -g=100 -d3be l10 读出的扇区中有两个16字节的分区表项和最后的一个55AA标志,这两个分区表项为: 00 01 01 C0 06 FE 7F 97 3F 00-00 00 99 F2 34 00 00 00 41 98 05 FE BF 6E D8 F2-34 00 17 B4 34 00 第一个分区类型为6,其实这是第一个逻辑分区,含义和主分区表项相同 第二个分区类型为5,这其实是指向下一个扩展分区表的 从这里我们可以得到: 开始磁头:0 开始柱面扇区:41 98=(408,1) 继续用debug读出(mov cx,9841)得到 00 01 41 98 06 FE BF 6E 3F 00-00 00 D8 B3 34 00 只有一个表项,是第二个逻辑盘,而且是逻辑盘链的最后一个。 可以看到,主分区表是非常重要的,所以除了小心操作外,还应当进行备份,最安全的备份方式就是用笔抄下来,当然,每次重新进行分区后还应当及时更新。从前面可以看出,分区表里最重要的还是柱面号,其它比如磁头号都是0或者1或者最大值,扇区号都是1或63(最大值),扇区总数什么的也都能算出来,所以分区时最好把各分区的柱面号记下来,这样一旦分区信息被破坏就可以进行恢复了。 如果主分区表不幸丢失或者逻辑分区链被破坏,那么只要从硬盘上找出还存在的分区信息,就有可能部分恢复分区信息,甚至全部可以恢复,不过这样的麻烦大家还是应尽量避免。 在Linux里有一种方法可以恢复主引导扇区(包括主分区表),用如下的命令: dd if=/boot/boot.NNNN of=/dev/hda bs=512 count=1 其中:boot.NNNN 是我们在安装Linux之前整个主引导扇区的备份,NNNN是分区的主次设备号;bs(buffer size)是指重写的字节数。如只是为了修复主引导记录MBR(比如,想把LILO卸载掉),而不是恢复整个主引导扇区,则用如下的命令: dd if=/boot/boot.NNNN of=/dev/hda bs=446 count=1 只把主引导扇区的备份文件boot.NNNN的前446个字节重写入主引导扇区。 LILO 详解 一台电脑从加电到进入操作界面是经过了一系列复杂的操作的。基本的工作是由BIOS完成的。当POST(自检)结束后,BIOS尝试读入BIOS设定的第一个启动设备的第一个扇区,把它看作引导扇区(原先的BIOS总是先尝试软盘的),然后读入里面的信息来引导系统。 我们先来看看DOS的系统引导区: OFFSET 0x000 JMP xx ; 近距离跳转到xx代码段 0x003 ; 磁盘参数 0x03E ; 载入DOS系统核心的代码段 0x1FE 0xAA55 ; 这是BIOS的幻数 DOS的引导区总是从0开始,以BIOS的magic number 结束,总共512字节。从软盘启动比较简单,因为只有一个引导扇区:第一个扇区。而硬盘虽然有很多分区,但是,BIOS根本不去查看分区信息,它象对待软盘一样对待硬盘,仍读入第一个分区:master boot record (MBR). 所以MBR也应该从0开始,以BIOS的magic number 结束。在MBR的最后部分保存了分区表。 每个分区信息占16字节,定义了硬盘可以有4个Primary Partition。如果这些不够用,可以设置所谓的扩展分区。扩展分区包含至少一个逻辑分区。扩展分区的第一个扇区结构类似MBR,它的分区表的第一表项对应第一个逻辑分区。如果存在第二个逻辑分区,那么分区表的第二个表项就包含了一个指针。这个指针指向第一个逻辑分区后面的一个地址。这个地址包含一个分区表。该分区表的第一表项对应第二个逻辑分区。这样就组成一个链表,从而扩展分区可以有任意多的逻辑分区。 每一个主分区和扩展区都包含一个引导扇区。系统只能从这几个地方之一启动。BOOT标志决定哪个分区的引导扇区被引导。 MS-DOS的fdisk和大多数同类工具只能激活主分区。 MBR的代码要作以下的操作: 1:确定活动分区(Active Partition) 2:使用BIOS,将活跃分区的启动扇区读入 3:跳到启动扇区的0位置。 MBR的空间足够容纳一个引导程序来动态的决定活动分区。LILO就是这样一个引导程序。 LILO(LInux LOader) LILO引导扇区包括一个分区表的空间,所以,LILO即可以安装在MBR中,也可以安装在某个分区的引导扇区。 1.LILO可以占据MBR,但是会将老的MBR冲去,出于安全起见,最好在在安装LILO前,将老的MBR(包括分区表)做一个备份。可以通过键入 # dd if=/dev/hda of=/backup/MBR bs=512 count=1 来备份原来的MBR信息, 如果要将MBR写回,可以键入: # dd if=/backup/MBR of=/dev/hda bs=446 count=1 这样,原来的MBR就被写回但不包括分区表。如果分区表也要恢复,那么设置bs=512。 2.通过MS-DOS MBR被引导 LILO就可以安装在这些分区中的一个。当 LILO对应分区被激活后,引导过程如下: BIOS 读入 MBR MBR 读入 活跃主分区:LILO所在的分区; LILO 引导Linux或另外的操作系统。 要引导其它OS且不用LILO很简单,激活那个分区。Linux分区不会有任何变化。 3.LILO也可以被其他的系统引导程序(Boot Manager)引导 1. 假如boot manager可以引导扩展区,Linux可以装在扩展区上; 2. 假如 boot manager 可以引导第二硬盘分区,linux可以装在第二硬盘上; 3. 有些 boot manager 甚至可以引导逻辑分区,那LILO就可以装在逻辑分区上。 但是对于系统引导程序要特别注意的是:某些操作系统直接改写MBR,这会将原来的boot manager破坏。 配置LILO 与LILO有关,即有关系统引导的文件通常放在/boot/下,配置文件是/etc/lilo.conf下。合理的配置lilo. conf对于系统的正常高效运行有着非常重大的意义,可以通过man lilo.conf来查看配置的注意事项 下面是一些重要常用的选项: "boot=" 指明包含引导扇区的设备名(如:/dev/had),若此项忽略,则从当前的根分区中读取引导扇区。 "root=" 告诉内核启动时以哪个设备作为根文件系统使用,其设定值为构造内核时根文件系统的设备名,可用的设备名有: (1)/dev/hdaN~/dev/hddN:ST-506兼容硬盘,a到d上的N个分区 (2)/dev/sdaN~/dev/sdeN:SCSI兼容硬盘,a到e上的N个分区 (3)/dev/xdaN~/dev/xdbN:XT兼容硬盘,a到b上的N个分区 (4)/dev/fdN:软盘,A:(N=0)或B:(N=1) (5)/dev/nfs:由网络取得根文件系统的标志 "nfsroot=" 若需通过NFS提供根文件系统来引导无盘工作站,此参数为内核指定了网络根文件系统所在的机程序、目录及NFS,其格式为:nfsroot=(〈server_ip〉:)〈root_dir〉(,nfs_options)) "nfsaddrs=" 设定网络通讯所需的各种网络界面地址,如无此参数,则内核会试图用反向地址解析协定(RARP)或启动协定(BOOTP)找出这些参数,其格式为: nfsaddrs=〈客户端IP〉:〈服务端IP〉:〈网关IP〉:〈子网屏蔽〉: 〈客户端名称〉:〈网络设备名 〉:〈auto〉 "image=" 指定Linux的内核文件。 "delay=" 以10毫秒为单位,设定引导第一个映像前的等待时间。 "disk=" 某一特殊的硬盘定义非标准参数。 "append=" 为内核传递一个可选的参数行,其典型的应用是为不能完全由系统自动识别的硬盘指定参数,如:append = "hd=64,32,202",还有为一些无法自动识别大内存的低版本内核传递参数,方法是append="mem=128M".mem后边是数字+单位,这个单位可以是byte/M等等 "label=" 为每个映像指定一个名字,以供引导时选择。 "read-only" 设定以只读方式挂入根文件系统,用于文件系统一致性检查(fsck) "install=" 安装一个指定文件作为新的引导扇区,缺省为/boot/boot.b。 "loader=" 说明所使用的链加载程序(chain loader),缺省为/boot/chain.b,如果不是从首硬盘或软盘启动,那么,此选项必须说明。 "table=" 说明包含分区表的设备名,如果此参数忽略,引导加载程序将不能传递分区信息到已引导的操作系统。当此参数指向的分区表被修改时,必须重新运行/sbin/lilo。 "init=" 内核初始化时执行的程序,通常过程为init、getty、rc和sh,版本1.3.43以来的Linux内核能够执行/sbin/init说明的命令行,若在引导过程中出现问题,则可设置init=/bin/sh直接跳到Shell。 "ramdisk_start=" 由于内核不能放在压缩的内存文件系统映像内,为使内核映像能够和压缩的内存映像放在一张软盘内,加入"ramdisk_start=〈offset〉",这样内核才开始执行。 "vga=" 设置显示模式,如80×50、132×44等。 "compact" 激活一种模式,在此模式下,LILO一次向BIOS请求读入相邻的几个分区。这极大的缩短了装载时间,特别是从软盘启动。 "Linear" 使LILO生成线性地址,而不使用通常的Sector/Head/Cylinder机制。Linux地址机制可以不依赖磁盘的物理结构。 "install = boot sector" 使用指定的boot sector写入引导扇区,缺省用/boot/boot.b "map=" 说明映射文件的路径。 "message=[File]" 指定一个文件,该文件的内容将会在LILO引导是被显示。假如没有说明该文件,那么就只会出现"LILO"。 "verbose=[level]" 说明LILO的调试级别。从0(不显示任何信息)到5(所有的状态信息)。 "backup = [backup file]" 以前引导扇区内容的备份文件。缺省使用/boot/boot.device number "force-backup=[backup file]" 和backup 相同,当时假如备份文件存在,被覆盖。 "prompt" 指定要用户通过键盘选择要引导的内核。不会缺省选择。 "timeout=" 设置一个超时值,在此时间内必须有键盘输入,否则用第一个配置。类似,假如超时,就不能再输入密码。一般情况下,该取缺省值,无穷大。 "serial=port, bps parity bits" 设置串口参数。如果LILO会从该文件获取串口参数的话。如果其中之一无效,那所有三个参数都无效。Port从四个标准串口选择一个:0对应COM1 或者/dev/ttyS0.。支持的波特率范围为:100-9600。所有校验设置都支持(n:none,e:even,o:odd)bits为7或者8。缺省为serial=0,2400n8. Ignore-table 让LILO忽略被破坏的分区表。 fix-table 允许LILO将每个分区的(sector/head/cylinder)地址转化为线性地址。通常,分区地址从cylinder boudary开始。某些操作系统,会改变这一点。由于LILO只能将它的启动扇区写于两种地址都一致的分区上,不正确的3D地址可以用fix-table来纠正。但是,这种纠正不能被保证是永远的,所以重分区以保证对齐cylinder boudary 是最好的选择。 "password=[password]" 为引导配置设置password restricted 放松对password的限制。只有用户想传附加的启动参数给内核时才需要password optional 允许配置的几个内核有错误的,或者不存在,如果不说明optional,LILO遇到这种情况就会打印一些错误信息然后退出。 LILO引导过程 每个从LILO引导的配置从image行开始。 image = kernel label = name Image包含要引导的内核。Label是给用户选择用的。Image行通常指向一个设备,例如/dev/fd0,可以找到内核的范围用range来注明。 range = range range可以用start sector -end sector 或者 start sector + length 表示。例如: image = /dev/fd0 label = floppy range = 1+512 LILO 启动信息 缺省设置的LILO启动过程中在启动过程中,LILO会显示'LILO',如果LILO出错退出, 可以根据显示来判断系统的出错原因。 没有信息:LILO根本就没有被读入,没安装LILO,或LILO驻留的分区没被激活。 Lnumber : LILO的第一部分被读入并开始执行。但第二部分不能被读入。后面的数字表明出错原因。这可能是由于硬盘的物理错误或不正确的物理结构信息 LI: LILO的第一部分可以读入第二部分,第二部分执行时出错。这可能是不正确的物理结构信息或重装了boot.b而没有运行LILO重新安装。 LIL:LILO的第二部分启动起来了,但是不能从map文件读入descriptor tables.这说明不正确的物理结构信息或物理错误。 LIL?: LILO的第二部分被读到不正确的地址。原因同LI LIL-: descriptor tables有错。这可能是不正确的物理结构信息或重装了map file而没有运行LILO重新安装。 LILO的卸载 LILO装在MBR以后,它会保留一个MBR的备份在系统的/boot/boot.xxyy中,其中xyy是16进制的设备主/次号码(major/minor numbers),利用命令"ls -l /dev/device"就可获得硬盘或分区的主/次号码。如果这些备份文件已经存在,那么,当你重新安装LILO时,它将不再生成此文件,这就保证了此备份文件是最原始的引导扇区。 若要卸载LILO,你只需恢复初始的引导扇区就可以了。例如:LILO安装在/dev/had,对应的备份文件为/boot/boot.0300,使用下面的命令即可: # dd if=/boot/boot.0300 of=/dev/had bs=446 count=1 LILO是现在Redhat Linux、TurboLinux等许多Linux distribution缺省的引导程序,正如上面所介绍的,拥有很强大的功能,更详细的内容可以在lilo安装的README文件中发现。最重要的是在良好的备份意识指导下,多多实践,这样才能得到最佳的效果。