您的位置:首页 > 移动开发 > IOS开发

简单OS开发前奏(二)BIOS启动过程-硬件检测及初始化浅析

2013-09-28 19:28 435 查看
转自:http://blog.csdn.net/otishiono/article/details/5899592

评论中包含许多扩展知识,一并转了。

BIOS就是基本输入输出系统,它是一组固化到计算机内主板上一个ROM芯片上的程序,保存着计算机最重要的基本输入输出的程序、系统设置信息、开机后自检程序和系统自启动程序。 其主要功能是为x86架构的计算机提供最底层的、最直接的硬件初始化设置和控制。一般来说没安装任何操作系统的计算机成为裸机,但是裸机并不裸,因为有BIOS,所以各种硬件仍然可以在你按下启动按钮之后有序的工作,只是这些工作是不为用户提供服务的。

BIOS的基本工作任务:

● POST:开机自检

● 初始化阶段:对DRAM、芯片组,外围设备等设置

● 保存相应数据:在COMS RAM 及 BIOS 数据区保存相应的数据

● 驻入服务例程:写入中断向量表及BIOS的中断服务例程等

 

现在来我们从按下开机按钮开始分析x86硬件系统执行的程序。

按下开机按钮

 

POST - Cold Boot / Power On Self Test Activities 

POST - 冷启动、开机自检 

- power supply starts Clock Generator (8284) with Power 

通电后8284时序发生器开始工作 

Good signal on BUS 

总线产生正常信号 

- CPU reset line is pulsed resetting CPU 

CPU的复位引脚被触发,CPU复位 

- DS, ES, and SS are cleared to zero 

DS,ES,SS初始值为0(CPU处于实模式下)

 

-Cold and Warm Boot both execute the following sequence 

冷启动和热启动都会执行一下序列 

- CS:IP are set to FFFF:0000 (address of ROM POST code) 

CS:IP初始值为FFFF:0000(该地址为BIOS的ROM POST代码) 

- jump to CS:IP (execute POST, Power On Self test)

CPU工作,开始取第一条指令(执行POST,开机自检)

 

看一下Intel的specification中的CPU上电后各个寄存器的初始化值。

 



1、CR0.PE = 0  处理器处于实模式 此位决定了BIOS程序执行时的寻址方式
2、RIP = FFF0h  
3、CS.Base = FFFF_0000h
4、由于在实模式下,第一条指令的物理地址就在:CS.Base + RIP = FFFF_FFF0h。

这里就得到了CPU要执行的第一条指令的物理地址PA:FFFF_FFF0h,这个地址还要经过MCH和ICH的映射处理,最终找到BIOS中被映射到内存中的代码  far jmp F000:xxxxh,根据BIOS的厂商不同跳转地址不同,而这个地址就是BIOS程序的入口地址。

该条指令执行后,CS.Selector和EIP都会被重置。自习想想,处理器处于实模式下那么其最大寻址空间是1M但是第一条指令的地址是FFFF_0000h,超出了1M的范围,所以要经过MCH和ICH的映射。这条指令执行之后就会跳转到1M以内的空间开始按照实模式的寻址方式执行代码。

 

 

 

下面就是BIOS内的固化程序执行过程了,

 

- interrupts are disabled 

关中断 

- CPU flags are set, read/write/read test of CPU registers
4000
 

设置CPU标志位,用读、写、读来测试CPU寄存器 

- checksum test of ROM BIOS 

检测ROM BIOS的校验和 

- Initialize DMA (verify/init 8237 timer, begin DMA RAM refresh) 

初始化DMA(校验、初始化 8237时钟控制器,开始DMA 内存刷新) 

- save reset flag then read/write test the first 32K of memory 

保存复位标志,然后对内存的前32K字节进行读写测试 

- Initialize the Programmable Interrupt Controller (8259) 

and set 8 major BIOS ~interrupt~ vectors (interrupts 10h-17h) 

初始化8259可编程中断控制器,设置好8个主要的BIOS中断向量(INT 10h-17H) 

- determine and set configuration information 

检测并设置好CMOS配置信息 

- initialize/test CRT controller & test video memory (unless 1234h 

found in reset word) 

初始化/测试CRT控制器,测试显存(除非在复位字的位置找到1234h) 

- test ~8259~ Programmable Interrupt Controller 

测试8259可编程中断控制器 

- test Programmable Interrupt Timer (~8253~) 

测试8253可编程时钟中断控制器 

- reset/enable keyboard, verify scan code (AAh), clear keyboard, 

check for stuck keys, setup interrupt vector lookup table 

复位、激活键盘,校验扫描码,清除键盘缓冲区,检查是否有卡住的键,设置中断查找表 

- hardware interrupt vectors are set 

设置硬件中断向量

- test for expansion box, test additional RAM 

测试扩展设备,测试扩充内存 

- read/write memory above 32K (unless 1234h found in reset word) 

读写测试32K字节以上的内存(除非在复位字的位置找到1234h) 

- addresses C800:0 through F400:0 are scanned in 2Kb blocks in 

search of valid ROM. If found, a far call to byte 3 of the ROM 

is executed. 

以2K字节大小的块为单位,从c800:0到f400:0扫描,查找有效映射的ROM。找到后,对ROM的第3个字节进行远程调用。 

- test ROM cassette BASIC (checksum test) 

检测ROM BASIC(校验和测试,现在的BIOS已取消ROM BASIC了……) 

- test for installed diskette drives & ~FDC~ recalibration & seek 

检测安装了的硬盘驱动器、软盘控制器。

 

在这里寻找一个启动设备,这些设备包括Floppy Disk(A:),或者Hard Disk(C:),还可以包括CD-ROM Driver或者其它设备。
 

- test printer and RS-232 ports. store printer port addresses 

at 400h and RS-232 port addresses at 408h. store printer 

time-out values at 478h and Serial time-out values at 47Ch.
检测打印机口和RS-232串口。把打印口地址保存在内存的400h,串口地址保存在408h。打印机超时值保存在478h,串口超时值保存在47Ch。 

- NMI interrupts are enabled 

激活NMI中断 

- perform ~INT 19~ (bootstrap loader), pass control to boot record 

or cassette BASIC if no bootable disk found 

执行INT 19h(引导装载程序),把控制权转交给引导程序
 

当找到响应的启动设备之后,BIOS将会查找Boot信息时能后续开始OS的启动过程。如果它找到了一个Hard Disk,它将会查找一个位于Cylinder 0, Head 0, Sector 1的Master Boot Record(硬盘的第一个扇区),如果它找到的是Floppy Disk,它也会读区软盘的第一个扇区。 如果找不到任何启动设备,系统将会显示一条错误信息,然后冻结系统。如果找到了响应的启动设备,BIOS会将读到的扇区放在内存7C00h的位置,并跳转到那里执行它。从此以后,就有硬件启动阶段进入了OS启动阶段。

- ~WARM BOOT~ procedure is now executed

 

开始执行热启动

到这里基本的硬件启动和初始化都已经完成了,剩下的就是OS的bootloader工作了。

BIOS的开发其实不比操作系统简单多少,以后有机会再深入分析BIOS,下一步就是写bootloader。

待续……

 

 

查看评论

1楼 随心随意随缘 2011-12-20 22:20发表 [回复]

lz有个疑问:

看一下Intel的specification中的CPU上电后各个寄存器的初始化值。

操作系统自举期间使用实模式寻址存储器,这个时候在cs段寄存器中存放的不是段选择子,所以不会用到8字节的段描述符。寻址的存储空间应该在cs寄存器最右边增加一个0h从而形成小段,用以寻址整个1MB空间中的每个段。在ip寄存器中则存放段内偏移从而寻址每条指令。而你说的cs.base实际应该是在保护模式下进行寻址的所用的,lz可以耐心解答一下吗?呵呵,这边不是很明白
Re: Tishion 2011-12-20 23:46发表 [回复]

回复jn1158359135:是这样的,你对CS寄存的理解优点误解,CS寄存器由两部分组成,一部分是程序员可见的 段选择子(Selector)[16bit],一部分是程序员不可见的基址(Base)[32bit],在实模式下的寻址的确如你所说,把Selector的值左移4bit形成20位的段基址放入Base中,然后把这个值加到EIP的值中,就找到了下一条指令的地址。可是硬件初始化的时候值已经固定好了,

RIP = FFF0h 

CS.Base = FFFF_0000h

在开机的第一次寻址中是不需要用到Selctor而直接使用现有的Base的值

CS.Base + IP = FFFF_FFF0h 

这个地址的确超过了1M的地址空间,反而是在4GByte-16Byte的这个地址。

不要有一个惯性思维,实模式不能寻址1M以上的地址,如果我通过改变硬件的话,实模式可以访问任何地址,寻址能力是由硬件和硬件里的内容决定的,这里硬件里的内容已经被设定好了,直接交给CPU去寻址。CPU把地址交给MCH(南桥芯片-相当于一个分配器,根据不同的地址映射分配给不同的设备去处理),MCH会决定这个地址要分配给ICH(北桥芯片-解码器),最终这个地址被解析到BIOS的ROM里面的地址,而在BIOS ROM里面取出计算机的第一条指令,一般都是一个Far Jmp(通常都是jmp far ptr 0F000h:0E05Bh),然后就执行了这条指令。这是一个Far
Jmp所以执行这条语句会改变CS的Selector和Base的和IP的值,Selector=F000h,Base清零,从此以后寻址方式就是Selector左移4bit放入Base;然后Base+IP取指令,可以看到在这之后无论如何,Selector的值都不会超过FFFF,左移以后[FFFF0h]加上最大IP[FFh]的值最多为1000EF,超过了1M,按照算法算出的实模式的最大寻址范围使这个,但是实模式下只有20根地址线可以使用,20个地址线可以表示的最大值就是FFFFFh,再加上一个0地址,总共100000h[1M]个地址,所以实模式下的寻址空间就是从这里来的。可以去看下
Intel 64 and IA32 manual 3A 8.1.4 First Instruction Executed
Re: 随心随意随缘 2011-12-21 13:43发表 [回复]

回复OtishionO:原来在cs寄存器中还存在一部分不可见的32位基址,的确和我原先的想法存在误差。我以为上面那张图中的cs.base是通过实模式下的段选择子在SDT(segment descriptor table)中索引出的表项中的值,那么接下来的一个疑问是:该不可见寄存器除了在开机自举期间使用之外,在整个OS运行期间是否还会用到该寄存器呢?或者该寄存器还有其他什么用途?

另外,我对你对实模式的寻址方式是比较赞同的。可以寻址的存储器实际是取决于地址总线的,如果当前寄存器的位数低于地址总线,那么我可以通过构造额外的位进行寻址,典型的例子就是PAE物理地址扩展,如果当前寄存器的位数高于地址总线,那么再多的位数实际也无法寻址更多的内存空间,典型的例子是在64位下,即便我的寄存器位数达到64位,但实际的地址总线也才40,所以可寻址的地址空间自然最多只能达到1TB。这其实是一个线性地址到物理地址转换的问题,而转换的过程是通过硬件来实现的,而OS只需进行相关设置即可,所以通过改变硬件,无论实模式或是保护模式自然可以访问任何存在一定限制的地址。另外关于那段cpu把地址交给MCH,再决定是否分配给ICH,最终地址被解析到BIOS的ROM里面,这一部分知识确实之前没有了解过,谢谢楼主的传授,呵呵。

另外,楼主的文章很给力,希望多多更新才是,好让大家多多学习呀。如果可以的话,也希望lz可以讲解/翻译一些intel处理器的知识,我看到【译读】系列才写了两篇,可以说看的极其不过瘾,不过我这么说还希望楼主不要见怪才好。
Re: Tishion 2012-02-03 15:15发表 [回复]

回复jn1158359135:没有看到你的再次提问。

现在才看到。段寄存的硬件结构已经存在了,在实模式和保护模式下永远都是一样的。不一样的是这些硬件结构被怎么使用。是模式下的使用方式是:Selector左移4位放入Base

保护模式下我直接引用资料了。。“从80286开始每个段寄存器都配有一个高速缓冲寄存器,称之为段描述符高速缓冲寄存器或描述符投影寄存器,对程序员而言它是不可见的。每当把一个选择子装入到某个段寄存器时,处理器自动从描述符表中取出相应的描述符,把描述符中的信息保存到对应的高速缓冲寄存器中。此后对该段访问时,处理器都使用对应高速缓冲寄存器中的描述符信息,而不用再从描述符表中取描述符。 

各段描述符高速缓冲寄存器之内容如下表所示。其中,32位段基地址直接取自描述符, 32位的段界限取自描述符中20位的段界限,并根据描述符属性中的粒度位转换成以字节为单位。”

80x86保护模式系列教程-作者:李彦昌
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  OS