|
发表于 2006-11-4 18:33:28| 字数 5,274| - 中国–上海–上海 东方有线
|
显示全部楼层
|阅读模式
光盘启动过程探究
本文为51NB首发,欢迎转载,转载请注明出处,原作者,谢谢支持!
==第一部分==
一 说明
最近对可启动光盘的启动原理产生兴趣,花点时间研究了一下,小有收获,了解了如何顺利从光盘boot起来,写出来与大家分享。
大家平时在制作启动光盘的过程中可能会碰到这样那样的问题(如制作的系统安装盘不能启动,用Ezboot、Diskemu等工具制作的多重启动无法多重启动等),如果读完本文能帮你找到解决的办法,那对我来说也将是一种欣慰。
二 需要用到的知识和工具
由于涉及到BIOS以及汇编相关的知识,所以要求读者最好具有微机原理方面的知识(没有也没有关系,多花点时间应该读的懂)。讲解过程中还会用到相关的Spec的阅读,英文不错的话会轻松很多。
工具:WinHex(UltraEdit也可),WinISO(UltraISO也可),XP安装光盘一张
三 全文的结构
首先我会在第二部分讲解Bootable CD-ROM的相关规范,让大家对光盘启动过程有个认识,然后会在第三部分结合工具和图片详细讲解。
==第二部分==
一BIOS Boot Specification / El Torito Specification
BIOS Boot Specification――定义了BIOS支持的启动设备,以及BIOS如何发现并引导这些设备。
El Torito Specification――启动光盘的规范,本文的重点
这两份规范可以从Phonix BIOS的网站上下到,地址:
http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/pc+industry+specifications.htm
还一份规范是ISO9660,普通CD-ROM的规范。想了解光盘信息的存储以及文件结构的可以看一看。
二 启动过程
我们知道PC启动的时候会先由BIOS进行控制,BIOS进行基本的硬件设备的检测以及相关设置过程后会搜索可启动的介质,搜索的设备列表是由BIOS负责的(我们也可以在BIOS里设置不从某些设备启动),而搜索的的顺序一般都是我们自己在BIOS里设置好的。找到可启动的设备后BIOS会加载启动设备中的代码到内存,然后整个系统的控制权就交给启动代码,到此BIOS的作用就结束了(Windows下)。
关于整个BIOS的启动过程,可以参考我之前写过的一篇文章:
http://bbs.cfan.com.cn/viewthread.php?tid=339334&extra=&highlight=%C6%F4%B6%AF%2Brossini23&page=1
我们现在关心的是从CD-ROM启动的情况。
光盘启动过程如下:
1在BIOS中设置光盘启动
2 POST(Power On Self Test,加电自测试)
3光驱检查光盘是否有引导功能:
1)先读取光盘的Sector 17区的引导描述符
2)根据引导描述符提供的地址来载入BCF(Boot Catalog File,启动目录文件)
3)根据启动目录文件来载入BIF(Boot Image File,启动映像文件)
4)运行启动映像文件中的引导程序,开始进入操作系统
见下图中间部分:
三 讲解
依照ISO9660标准,普通CD-ROM有333,000个扇区,0~15为保留值,第16个扇区是主扇区描述符,标志着光盘文件系统的开始。第17个扇区是引导描述符,存放启动标志各启动目录文件地址。启动目录文件包括了光盘的操作系统、启动方式BIF的位置。BIF中则存放了启动程序。
由于我们只关心启动光盘,所以从第十七个扇区开始才是我们的重点。
1 先看引导描述符区:
第0个字节必须为0
第1-5字节必须为CD001,这个是ISO9660的规范
第7-26字节必须为EL TORITO SPECIFICATION
第27-46字节全为0
根据以上信息可以判定该光盘可启动
第47-4A字节为Boot Catalog(启动目录文件)的地址(扇区的编号),这个很重要!
余下的所有字节求用,全为0
现在已经根据47-4A字节内容得到了启动文件的地址,那么我们可以找到启动目录文件,然后看它的内容
启动目录文件又分为两部分:Validation Entry和Initial Entry
2 看Validation Entry:
第0个字节为0
第1个字节标志光盘适用的平台类型,Intel平台的为0
第2-3字节为0
第4-1B字节为制作商信息
第!C-1D字节为校验和,校验和就为0
第1E-1F字节为结束标志,一定是55AA
3 紧接着Validation Entry的是Initial Entry,它主要给出启动文件的地址
第0个字节为标志信息,88为可启动,00为不可启动
第1个字节是启动介质的类型。分别是非模拟方式,模拟1.2M软盘模式,模拟1.44M软盘模式,模拟2.88M软盘模式。
第2-3字节为将启动代码装载到内存的时候用的段地址,学过DOS的都知道,DOS用的是7C00这个地址,这个地方为0的话说明加载到7C00,否则填入其它地址
第4个字节同第5字节
第5个字节保留,为0
第6-7字节为应该拷贝到内存中的扇区数,结合下面的看
第8-0B字节为应该装入内存的扇区的地址,这个就是真正的启动文件的地址
4 现在已经找到启动文件的地址,BIOS将启动文件装入内存后就开始了真正的光盘启动过程,启动文件会加载相关操作系统文件进入操作系统。
==第三部分==
现在我们用WinHex工具看XP安装光盘上的扇区,来验证刚才我们分析的过程
根据第二部分第三节的内容,我们看光盘上第17个扇区的内容:
跟分析的完全一样,我们看到47字节对应的数为13H(十进制为19),转到19扇区去
这个是19扇区的Validation Entry和Initial Entry:
跟分析的一样。我们找到第6-7字节和第8-0B字节,得到的两个数分别为0107H和04H,把十六进制的0107H转换为10进制为263,转到263扇区看:
这个就是XP安装光盘的引导代码了。怎么?看不懂?说实话,这么一大堆数字我也看不懂,幸好已经有“先人”帮我们分析过了,我们看开头的一部分:
NT,2000,XP的CDROM引导扇区代码分析
07C0:0000 FA cli ;禁止中断
07C0:0001 33C0 xor ax, ax
07C0:0003 8ED0 mov ss, ax ;初始化运行堆栈,将 SS:SP 指向运行代码前
07C0:0005 BC007C mov sp, 7C00
07C0:0008 FB sti ;允许中断
07C0:0009 8CC8 mov ax, cs
07C0:000B 8ED8 mov ds, ax ;将 DS 指向 CS 相同地址,此处操作比较浪费,只用了一次
07C0:000D 52 push dx ;引导扇区运行时 DX 保存当前引导磁盘号
;下面几条指令用于取得装入偏移地址,由于不能直接对 IP 进行 mov 指令
;所以使用一条 CALL 指令利用堆栈将 IP 取出
07C0:000E E80000 call 0011 ;执行一条函数调用指令,从而将下一条指令的地址压入堆栈
07C0:0011 5E pop si ;取出刚刚压入的地址
07C0:0012 81EE1100 sub si, 0011 ;减掉偏转地址得到实际的开始偏移
07C0:0016 7412 je 002A ;如果偏移为零跳转
;判断装入地址是否为 0000:7C00 如果是则使用远跳转进行地址转换到 0037
07C0:0018 81FE007C cmp si, 7C00 ;装入偏移是否为 7C00
07C0:001C 7575 jne 0093
07C0:001E 8CC8 mov ax, cs ;取得装入段地址,此句多余,见 0009
07C0:0020 3D0000 cmp ax, 0000 ;装入段地址是否为 0000
07C0:0023 757F jne 00A4
07C0:0025 EA3700C007 jmp 0037 ;使用远跳转指令进行地址转换
;判断装入地址是否为 0000 如果是则直接进行运行到 0037
07C0:002A C606AE0133 mov byte ptr [01AE], 33 ;修改错误代码为 3,意义为装载地址错误
07C0:002F 90 nop
07C0:0030 8CC8 mov ax, cs ;多余,同 001E
07C0:0032 3DC007 cmp ax, 07C0 ;装入段地址是否为 07C0
07C0:0035 757E jne 00B5
;前面这段代码用于解决不同系统装入地址的问题,合法地址为 0000:7C00 或 07C0:0000
;如果地址不正确,则进行错误处理,运行到此处地址应全部转换为 07C0:0037
07C0:0037 8CC8 mov ax, cs ;取什么取,一定是 07C0 了
07C0:0039 8ED8 mov ds, ax ;这次才真的有用,见 000B
07C0:003B C606AE0134 mov byte ptr [01AE], 34 ;修改错误代码为 4,意义为非法引导盘
07C0:0040 90 nop
07C0:0041 80FA80 cmp dl, 80 ;查看当前引导磁盘号是否小于 80 ,即不是硬盘或 CDROM
07C0:0044 726F jb 00B5 ;如果是则转移错误处理
07C0:0046 C606AE0135 mov byte ptr [01AE], 35 ;修改错误代码为 5,意义为引导扇区非法或不完整
07C0:004B 90 nop
07C0:004C BBFE07 mov bx, 07FE ;BX 指向引导扇区结尾标志
07C0:004F 8B07 mov ax, [bx] ;取出标志
07C0:0051 3D55AA cmp ax, AA55 ;是否为 AA55
07C0:0054 755F jne 00B5 ;如果不是,则转移错误处理
;装载 BOOTFIX.BIN 并运行,显示 Press any key to boot from CD
;如果没有此文件则直接跳过
07C0:0056 5A pop dx ;恢复引导磁盘号
07C0:0057 88169904 mov [0499], dl ;保存磁盘号至数据区
07C0:005B 688A04 push 048A ;BOOTFIX.BIN 文件名的地址
07C0:005E 6A0B push 000B ;文件名长度为 11
07C0:0060 680020 push 2000 ;装载起始段地址 2000
07C0:0063 E87603 call 03DC ;调用装载函数
07C0:0066 0F820F00 jb 0079 ;如果不成功则直接跳过
07C0:006A 60 pusha
07C0:006B 1E push ds
07C0:006C 06 push es ;保存当前运行现场
07C0:006D 8A169904 mov dl, [0499] ;取出当前引导磁盘号
07C0:0071 9A00000020 call 2000:0000 ;运行刚刚装载的 BOOTFIX.BIN
07C0:0076 07 pop es
07C0:0077 1F pop ds
07C0:0078 61 popa ;恢复运行现场
;装载 SETUPLDR.BIN 并运行
07C0:0079 687E04 push 047E ;SETUPLDR.BIN 文件名的地址
07C0:007C 6A0C push 000C ;文件名长度为 12
07C0:007E 680020 push 2000 ;装载起始段地址 2000
07C0:0081 E85803 call 03DC ;调用装载函数
07C0:0084 0F823500 jb 00BD ;如果不成功则转错误处理
07C0:0088 8A169904 mov dl, [0499] ;取出当前引导磁盘号
07C0:008C 33C0 xor ax, ax
07C0:008E 680020 push 2000
07C0:0091 50 push ax ;在堆栈中制造 2000:0000 的返回地址
07C0:0092 CB retf ;转移到 2000:0000 运行刚装载的 SETUPLDR.BIN
全部代码可以在这个地址找到:
http://it.13520.org/ArticleView/2005-9-6/Article_View_170710.Htm
粗略看一下,也就是这个启动代码先初始化工作环境,然后找到光盘上I386文件夹下的Fixboot,bin,我们知道这个文件的作用是显示一句话: Press any key to boot from CD,装过XP的对这句话再熟悉不过了。
接下来就是加载Setupldr.bin文件,同样在I386目录下,Setupldr.bin会调用Ntdetect.com来发现机器上安装的硬件(这一步在安装系统的时候也可以看到,屏幕上显示Setup is inspecting your Hardware…),为进一步安装提供硬件支持。好了,就到这了,到这一步上已经不在上面的代码控制下了,这个是XP安装过程的问题了。
==第四部分==
总结:理论结合实际的分析工作已经结束了,希望看完本文你能有所收获,如果你在用Nero等工具制作启动光盘的过程中遇到什么问题你可以用本文提到的一些工具来自己分析一下光盘,应该能解决启动方面的问题。
谢谢你能花时间看完这么一篇文章,祝您愉快!
[ 本帖最后由 rossini23 于 2006-11-5 12:41 编辑 ] |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?注册
x
评分
-
查看全部评分
|