分类:
2008-05-04 23:17:42
此文与另一篇“保护模式简述”都是转载于文章《一个简单的32位多任务操作系统的实现》。下面这部分内容是我在读《linux内核完全注释》的bootsect.s源代码时所能用到的。它最好的地方在于对启动程序存放于硬盘的加载情况分析的很详细,而《linux内核完全注释》只讲解了启动程序位于软盘时的加载情况。
系统的启动过程:任何一台计算机,在开机后,它要做的第一件事情就是引导(Booting),通过引导,计算机为自身搭建好运行环境,为以后OS的启动与运行做好准备。首先,我们来看看一台计算机是如何引导自身的。在机器加电后,电源供电稳定后,电源会传给8284A时钟生成器一个“Power Good”低电位信号,随后8284A会输出有效的RESET信号,使CPU复位,这时CS:IP = FFFF:0000。CPU在这里执行一条jmp far addr类指令,跳转到实际BIOS映射代码的位置,开始执行BIOS代码。
上述是机器在加电后的启动过程,大家都知道计算机的启动是分为冷启动与热启动的,那么对于热启动,其过程又是怎样的呢?其实热启动只不过是将键盘中断程序置复位标志为1234h,然后再跳转到BIOS处执行,其主要是省去了在自检过程中对存储器的检测。
在跳转到BIOS后,首先会先关闭中断,然后开始自检(POST)工作,这个自检主要检测计算机最基本设备的运转状态。其主要包括对,CPU内部寄存器测试,BIOS芯片字节的检查,8237 DMA控制器测试,基本32K RAM检测等最基本内容。由于被检测设备在系统运行中的重要性,因此在此过程中,BIOS一旦检测到任何异常,都将判为致命性错误,系统将被停机。
通过上面的自检后,BIOS开始初始化8259可编程中断控制器,并设置BIOS的8个主要中断向量(int 10h—int 17h),然后初始化并测试CRT视频接口以及显示内存(对于热启动这一步将跳过),在确认正常后,执行其内部的显示卡标准驱动程序(注意这里的驱动跟安装操作系统下的驱动是不一样的),这段代码会存放在C0000h,其主要目的是初始化显示卡。然后BIOS会打印显卡信息。
接着BIOS开始检查其他设备,其包括对8259中断控制器测试,8253定时器测试,键盘复位和卡键测试,扩展I/O测试,设置硬件中断向量,扩展RAM测试(这里的RAM测试会检测除0—32K以外的整个RAM空间,对于热启动同样也会跳过这一阶段),.然后BIOS会搜索其他设备的ROM,如果找到,则会执行它们。接着测试ROM-BASIC的字节检查,测试磁盘驱动器(如:FDC等),测试打印机端口和RS-232,并设置他们的地址。
然后打开NMI(不可屏蔽中断),最后就是调用Int 19h进行自举。这一阶段的自检如果发生错误,系统会判断其为一般性错误,并显示出相应的提示信息。在此过程中,BIOS会将检测收集到的数据保存在内存低1K--2K的区域,并将BIOS中断向量表,以及BIOS程序运行所需要的stack保存在内存低0K--1K的地方。
下面就是系统自举工作了,系统调用int 19h进行自举,寻找启动设备,如:软驱,硬盘,光驱等等。找到后系统读取启动设备的0号逻辑扇区(如是软盘就读取0面0道1扇区的整个内容),并将读取的内容放到内存地址为0000:7C00的地方。
当然,如果找不到启动设备,BIOS就会调用Int 18h,并给出相应的提示信息,然后进入ROM-BASIC。(有些机器会在等待一段时间后自动进入CMOS。如:很久以前海洋的AMD 386DX/40主板)至此,BIOS的引导程序结束,CPU开始执行0000:7C00处的代码。在这里需要说明一下的是,BIOS的引导程序是与操作系统无关的,但随后CPU开始执行的代码就开始与操作系统存在较大的相关性了,因此对于不同的操作系统,下面这一部分可能会存在着较大的不同。不过,从目的上来讲,它们是相同的,即都是为将要运行OS的内核(Kernel)作准备。
进入这一部分的首要工作就是执行启动设备的引导程序。硬盘与软盘的对于引导程序的存放结构是不同的。硬盘有一个叫做MBR(Master Boot Record)的扇区,系统会首先执行它,以判断那个分区是启动分区,并读入该分 区的第一个扇区,并执行。并且在这个扇区中还存放着硬盘分区表(DPT),这个表的地位相当重要,因为它包含了
各个分区的诸如:分区类型,起始位置,结束位置等重要参数。下面我们来详细介绍一下MBR的结构。MBR的结构分为三部分,首先是可执行代码,占446个字节,然后是4个分区表,每个占16个字节,共64个字节,最后是签字AA55H。
下表列出了分区信息的详细内容:
偏移 |
长度 |
描述 |
0 |
字节 |
分区状态0:非活动分区,80h活动分区(可引导) |
1 |
字节 |
分区起始头 |
2 |
字 |
分区起始扇区和起始柱 |
4 |
字节 |
分区类型 |
5 |
字节 |
分区中止头 |
6 |
字 |
分区中止扇区和中止柱 |
8 |
双字 |
分区起始绝对扇区 |
0Ch |
双字 |
分区扇区数 |
然后我们开始介绍MBR中的可执行代码部分:
首先,程序会检测MBR的签字是否合法,即判断其最后字是否为AA55h.通过后,将自身移动到内存中的其他地方,以备将来在此装入引导分区的Boot扇区.然后,程序检查四个分区的分区状态,找出活动分区,并将该分区的Boot扇区读入到0000:7C00h处,并检查其签字是否合法,在通过后,程序跳转到0000:7C00h处执行,即将控制权交给活动分区的Boot程序;对于软盘则没有那么复杂,软盘的第一个扇区就是它的Boot区,系统自举时将直接将其读入到0000:7C00h处并执行。
从功能上来讲软盘与硬盘的Boot区是相同的,其任务都是将OS的内核(Kernel)读入到内存并执行。但具体来看,由于绝大多数OS的Kernel是以文件形式存放在磁盘上的,要读取它就要涉及到对文件系统的操作,这使得它们在实现上又是很不相同的。因此,对于Boot区的分析我们将放在后面的内容中具体介绍。