【BIOS 探索之旅】 (4.21日更新)
写在之前 想写 BIOS 研究系列已久,今天开始以旅程的方式边写边研究 BIOS,这是一个边写边学习的过程,从基本为起点站,何时为终点站不清楚,希望能坚持下去,期间难免会有错误之处,敬请指正。 研究 BIOS 是一项赋挑战的工作,难度好比研究 kernel 代码,BIOS 是极具吸引力的。读懂它对计算机系统将有质的飞越。 为了便于浏览,每写完一篇将会锁贴,批评指正讨论或建议请另起一贴 :) .[ 本帖最后由 mik 于 2008-4-21 01:35 编辑 ] 预备
一、所需材料
1、主要BIOS :ex38dq6.f2 :技嘉主板上Intel X38 MCH + ICH9 平台。
备用 BIOS:ma79xds4.f4 : 技嘉主板上AMD 790X 北桥 + SB600 南桥平台。
2、cbrom:这是一个BIOS编辑工具,这里所用的是cbrom182版本
3、lha2.55:LHA格式的解压工具。
4、awdbedit:award bios 的图形化编辑工具,方便简单。
5、hex workshop:一个十六进制编辑工具,简单小巧。
6、IDA:一个反汇编工具,这里使用的是IDA 5.2版本
二、所需知识
1、汇编语言:这是必备的知识,汇编掌握的程度和理解能力成正比。
2、机器语言:这个不是必需的,但推荐能够读懂机器语言,某些场合下当汇编语言也陷入窘境时,机器语言是唯一的解释手段。
3、x86体系知识:具体可以查看相关的Intel 或 AMD 手册
4、ISA/PCI 总线知识:可以查看相应的 ISA/PCI Specification5、north/south bridge 知识:Intel 现在以MCH代称north bridge,ICH代称south bridge,可以查看相应的 datasheet
[ 本帖最后由 mik 于 2008-4-1 00:41 编辑 ] 起点:几个重要知识
一、地址空间解析
(1) 0 ~ 9_FFFF:属于DOS的基本内存,被MCH控制提交到DRAM。
(2) A_0000 ~ B_FFFF:此区域能提交到Device 2(集成显示设备)、Device 1(PCI Express接口设备)以及提交到ICH进行处理。按Dev2/Dev1/ICH优先顺序进行映射。
当处理器在SMM模式下,此区域供SMM 使用,此时,此区域将被MCH提交到DRAM相同的位置上。
(3) C_0000 ~ F_FFFF:共256KB的区域被称为PAE(Programed Attribute Memory)区域,可定义4种类型属性:Disable、Read/Write、Read-Only以及Write-Only。根据这些操作类型可以提交到DRAM和ICH处理。这些区域的初始状态是Disable属性,也就是说,缺省时将得交到ICH处理。可由BIOS BOOTLOCK进行对类型的属性设置,从而达到shadow memory效果。。
(4) E_0000 ~ E_FFFF:典型地被用作BIOS使用。俗称E_Segment。
(5) F_0000 ~ F_FFFF:被提交到LPC总线上的BIOS,它是High BIOS的别名,初始属性是disable,将被MCH控制直接提交到ICH处理。俗称F_Segment。
(6) F0_0000 ~ FF_FFFF:这1M的空间可以选择保留给ISA使用,这段空间将不提交至DRAM,转交ICH处理。
(7) TOLUD(Top Of Low Usable DRAM)由Host Bridge Registers设置,在地址空间最低DRAM memory区域的顶端,在TOLUD下的TSEG区域可设置为1M、2M或8M,processor在SMM模式下将被提交至DRAM相同地址上。
(8 ) IGD区域:可供MCH内部集成的Graphics Device使用,MCH内被定义为Device 2。大小由1M ~ 64M。
(9) E000_0000 ~ EFFF_FFFF:这段空间典型地被用作为PCI Express 配置空间,由Host Bridge(Dev0)的PCIEXBAR寄存器设置。缺省的Pci Express Base Address设置为0_E000_0000,共256M大小。每个Device的每个Functon大小为4K(包括PCI的256 Byte和PCI Express增强的空间共4K)
★ PCI Express Bus 定义了256条Bus:Bus0 ~ Bus255,每条Bus下可挂32个设备:Device0 ~ Device 31,每个设备下又可执行8个Function:Function 0 ~ Function 7。
★ PCI Express空间大小可得:256 × 32 × 8 × 4096 = 256M
(10)FEC0_0000 ~ FEC7_FFFF:这段区域固定分配IOAPIC中断控制器使用,访问这段区域将被提交到ICH处理。
(11) FEC8_0000 ~ FECF_FFFF:附加的APIC增加区域提交至 PCI Express 端口,当不设此区域时,整个APIC 配置区域(FEC0_0000 ~ FECF_FFFF)将提交至 ICH。
(12) FEDA_0000 ~ FEDB_FFFF:可选为HSEG区域以供SMM模式下使用。被重新映射至A_0000 ~ B_FFFF区域。
(13) FEE0_0000 ~ FEEF_FFFF:这段区域保留给FSB中断信号使用。当PCI Express 或 ICH上的设备往这段区域写数据时,将以中断信号形式提交至FSB上,不会提交到DRAM。
(14) FFE0_0000 ~ FFFF_FFFF:此区域固定分配给BIOS 使用。共2M空间,将直接提交至ICH处理。
二、关于PCI Bus
1、PCI Bus是一种原生32位,通过Dual Address Cycle形式来实现64位寻址的数据总线。
2、PCI的配置寄存器集成在MCH(North Bridge)内部:CONFIG_ADDRESS寄存器和CONFING_DATA寄存器,通过端口 CF8H ~ CFBH 来实现32位数据访问 CONFIG_ADDRESS寄存器;通过端口 CFCH ~ CFFH 来实现32位数据访问 CONFIG_DATA 寄存器。
3、PCI 设备访问地址如下:
31
30 ~ 24
23 ~ 16
15 ~ 11
10 ~ 8
7 ~ 0
1
保留
Bus
Device
Function
Offset
4、访问的形式:
mov eax,80000090h
mov dx, CF8h
out dx, eax
mov dx, CFCh
in eax,dx
… …
起点:几个重要知识(续)三、I/O 空间
1、系统提供的64K IO寻址空间(0 ~ FFFF)划分几种情况:★分为MCH(hostbridge) 使用和 ICH 使用,大部分供ICH外部设备使用。例如:CF8h ~ CFFh 这些端口固定分配供MCH用来访问PCI Configuration Space。
★分为系统固定分配及按情况进行分配。如:0 ~ 1Fh 端口固定分配给ICH的DMA 控制器使用。
★一些端口被保留未用。
2、一般PCI设备都可选用memory空间和IO空间进行设备访问。在PCI设备的configuration Register可对PCICMD寄存器的IOSE位设为IO空间访问,根据IOBASE及IOLIMIT寄存器设置IO端口地址。
http://blogimg.chinaunix.net/blog/upfile2/080402011020.jpg四、MCH(hostbridge)提交到ICH后的转发处理
ICH包括PCI-to-PCI bridge 、PCI-to-ISA bridge、USB Controller、PCI Express Ports等等。ICH收到经MCH提交来的地址,相当多都分派到PCI-to-ISA bridge(LPC Controller)中的Firmware Hub及LPC bus。
第一站:剖析First Instruction Executed
一、Processor 寄存器初始状态
http://blogimg.chinaunix.net/blog/upfile2/080401013630.jpg
1、CR0.PE = 0,处理器处于实模式
2、RIP = FFF0h
3、CS.Base = FFFF_0000h
4、由于在实模式下,第一条指令的物理地址就在:CS.Base + RIP = FFFF_FFF0h。
二、MCH(NorthBridge)的处理
FFFF_FFF0h地址由Processor送到MCH进行解析,这个地址落在MCH固定为High BIOS 分配的区域中,MCH直接通过DMI接口送到ICH进行处理。
MCH相当于一个派发者角色,根据定义的地址映射分派到不同的接口。
三、ICH(SouthBridge)的处理
1、ICH对MCH提交过来的地址进行解码。
2、ICH的地址映射机制中:FFFF_FFF0地址落 FFF8_0000 ~ FFFF_FFFFh这个范围中,这个范围的地址将直接分派到LPC接口的Frimware Hub进行处理,LPC 接口相当于一个PCI-to-ISA 桥,BIOS寄居在LPC bus上,从而访问BIOS区域。
3、在物理器件上,ICH Firmware Hub的IDSEL选择固定地址设为FFF8_0000 ~ FFFF_FFFF范围,LPC接口寄存器(B#0, D#30,F#0)中的,Firmware Hub Decode Enable寄存器的bit15固定为1,允许FFF8_0000 ~ FFFF_FFFF地址提交到Firmware Hub。这样确保FFFF_FFF0提交到LPC bus。
ICH相当于一个解码器角色,解码后分配任务给设备执行。
四、第一条指令执行
经典地在FFFF_FFF0绝大多数是一条far jmp指令:jmp far ptr 0F000h:0E05Bh,不同的BIOS跳转的地址或许不同。这条指令跳转到FE05B这个地址上执行。同时刷新CS.Selector、CS.Base以及EIP寄存器。引一段 Intel 的话:
The first instruction that is fetched and executed following a hardware reset is
located at physical address FFFFFFF0H. This address is 16 bytes below the
processor’s uppermost physical address. The EPROM containing the software initialization
code must be located at this address.
The address FFFFFFF0H is beyond the 1-MByte addressable range of the processor
while in real-address mode. The processor is initialized to this starting address as
follows. The CS register has two parts: the visible segment selector part and the
hidden base address part. In real-address mode, the base address is normally
formed by shifting the 16-bit segment selector value 4 bits to the left to produce a
20-bit base address. However, during a hardware reset, the segment selector in the
CS register is loaded with F000H and the base address is loaded with FFFF0000H. The
starting address is thus formed by adding the base address to the value in the EIP
register (that is, FFFF0000 + FFF0H = FFFFFFF0H).
以上这段文字表明,Intel从架构上规定了,processor复位后,FFFFFFF0H地址上必须包含一些初始化程序,BIOS必须在定位在这段地址区域上。
MCH与ICH的配合从物理上通过地址映射机制保证了这一点的实施。
五、验证一下FFFF_FFF0地址上是否是一条far jmp指令,可以简单地打开cmd窗口执行debug命令。
C:>debug
-d F000:FFF0
F000:FFF0 EA 5B E0 00 F0 30 32 2F 32 37 2F 30 38 00 FC
EA 5B E0 00 F0 就是 jmp far ptr F000:E05B 指令,这条指令跳转到FE05B的物理地址上,这将是 BIOS 的 BOOTBLOCK。
[ 本帖最后由 mik 于 2008-4-3 02:21 编辑 ] 第一站:剖析First Instruction Executed(续)
六、BIOS地址空间高端与低端的别名机制
1、在整个地址空间中 FFE0_0000 ~ FFFF_FFFF 这段2M 区域真正地被固定分配给 BIOS 使用,包括基本的 BIOS 区以及一些设备扩展的 BIOS 区。这段空间是不能提交至 DRAM 的。
2、实际上,BIOS的低端地址C_0000 ~ F_FFFF 属于PAM区 (即:Programmed Attibute Memory) ,这段区域可被赋为4个访问属性:disable,read-only,write-only 以及 read/write。根据访问属性的不同可被提交到ICH,也可以提交DRAM,但初始化的属性是Disable,为DRAM不可用,初始状态是通过DMI提交到ICH处理的,但是可以在 BIOS 代码修改的,从而提交至DRAM。
3、C_0000 ~ F_FFFF 与 FFFC_0000 ~ FFFF_FFFF 指向同一个区域,被冠以别名称呼,即C_0000 ~ F_FFFF 被映射到 FFFC_0000 ~ FFFF_FFFF。
AMD 如是说:
Accesses to BIOS space in the low megabyte (between 000C_0000h and 000F_FFFFh) are mapped to the top megabyte (between FFFC_0000h and FFFF_FFFFh) on the LPC bus; the OAR locks for these apply to these accesses based on the remapped address at the top megabyte.
http://blogimg.chinaunix.net/blog/upfile2/080404004348.jpg
无论是C_0000 ~ F_FFFF,还是 FFFC_0000 ~ FFFF_FFFF 最终结果都将送到LPC bus上的FFFC_0000 ~ FFFF_FFFF 地址上。
http://blogimg.chinaunix.net/blog/upfile2/080404004400.jpg
类似地,Intel 如是说,这里列出一小部分:
http://blogimg.chinaunix.net/blog/upfile2/080404004331.jpg
AMD 与 Intel 在物理上,确保了这一别名机制。
第二站:分解BIOS
注意:本站点讨论的部分内容不详,还没了解透,定义为:不清昕,可能有错误的。
这里主要以Intel平台的BIOS文件讨论,辅助参考AMD平台的BIOS文件。要分解的BIOS文件选了当下较新的X38芯片组平台的ex38dq6.f2 这个BIOS文件,而BIOS的文件是ma79xds4.f4,这是AMD的最新的7系芯片组其中的790X芯片组平台。
好,下面开始进行分解ex38dq6.f2这个BIOS文件。
一、工具的使用
1、Ex38dq6.f2是Award Bios,有一个图形化的BIOS编辑软件awdbedit,可以很方便的将BIOS的组件分解出来。
2、通用的BIOS编辑软件cbrom,这里使用的是cbrom182版本。下面是使用cbrom182显示BIOS组件的清单,命令行下使用:Cbrom182 ex38dq6.f2 /D,结果如下(部分):
******** ex38dq6.f2 BIOS component ********
No. Item-Name Original-Size Compressed-Size Original-File-Name
================================================================================
0. System BIOS 20000h(128.00K)15478h(85.12K)ex38dq6.BIN
1. XGROUP CODE 0FC40h(63.06K)0B0ECh(44.23K)awardext.rom
2. ACPI table 04E16h(19.52K)0193Ch(6.31K)ACPITBL.BIN
3. EPA LOGO 0168Ch(5.64K)0030Dh(0.76K)AwardBmp.bmp
4. GROUP ROM 031D0h(12.45K)0225Ah(8.59K)ggroup.bin
5. YGROUP ROM 0C180h(48.38K)066E4h(25.72K)awardeyt.rom
6. GROUP ROM[ 0] 08210h(32.52K)0303Dh(12.06K)_EN_CODE.BIN
7. PCI ROM 10000h(64.00K)09DBEh(39.44K)ICH9RAID.BIN
8. PCI ROM 03600h(13.50K)02553h(9.33K)ICH8AHCI.BIN
9. PCI ROM 07A00h(30.50K)04479h(17.12K)JMB59.BIN
10. MINIT 08220h(32.53K)0824Fh(32.58K)DDR2_MRC.X38
11. PCI ROM 0C800h(50.00K)079FDh(30.50K)rtegrom.lom
12. LOGO1 ROM 00B64h(2.85K)00520h(1.28K)dbios.bmp
13. LOGO BitMap 4B30Ch(300.76K)07EEEh(31.73K)x48dq6.bmp
14. GV3 01EFDh(7.75K)00B66h(2.85K)PPMINIT.ROM
15. OEM0 CODE 028ABh(10.17K)01E1Bh(7.53K)SBF.BIN
(SP) NCPUCODE 1D000h(116.00K)1D000h(116.00K)NCPUCODE.BIN
Total compress code space= E5000h(916.00K)
Total compressed code size = 75C8Dh(471.14K)
Remain compress code space = 6F373h(444.86K)
清单: 2.1
整个ex38dq6.f2 文件1M大小,包含了16个组件,最后的NCPUCODE.BIN组件,是虚拟的或者说物理上不存在,用awdbedit软件分解不包括这个组件,实际上只有15个真实组件,这些组件全都是经过压缩的。
第2列是组件的名字,第3列是组件真实的大小,第4列是组件中部分压缩的数据在ex38dq6.f2文件中的大小,最后1列是分解后组件存在磁盘上的物理文件名,以ex38dq6.bin为例,这个组件真实的大小为128K,其中85.12K是压缩部分,其余的以纯代码形式分布在FE000 ~ FFFFF区域,典型地:第一条far jmp就分布在这个区域。
ex38dq6.BIN 是BIOS的主体组件。
awardext.rom、awardeyt.rom 是BIOS的扩展部分。
ACPITBL.BIN 是供ACPI所使用的低级部件,可供操作系统使用。
PCI ROM 是 PCI 设备的一些组件。
还有一些显示的BMP图片
其余组件不详,有待了解:)
3、使用cbrom182来分解组件的方法:
Cbrom182 ex38dq6.f2 /XGROUP extract 分解出 awardext.rom
Cbrom182 ex38dq6.f2 /ACPI extract 分解出 ACPITBL.BIN
如此类推,可以逐步分解出各个组件,但是,SYSTEM BIOS组件,也即是 ex38dq6.bin 这个组件,我怎么试也没分解出来,所以用以下推荐的方法分解。
4、推荐分解BIOS组件的方法
使用图形化的BIOS编辑软件awdbedit可以很方便简单分解全部的组件。运行awdbedit软件,打开ex38dq6.f2,忽略掉一些警告信息,进入后,选择 –> 就可以分解出全部的组件。
二、BIOS组件位置分析
1、ex38dq6.f2文件共1M大小,除了包含各个BIOS组件外,还充斥着大量的“填充码”,这些“填充码”是FF字节以及00字节,主要用来分隔各个组件,以及填充文件。
2、压缩组件是以LZH形式压缩,每个压缩组件以“-lh5-”开头,十六进制码形式为 2D 6C 68 35 2D,这是压缩组件的戳记,因此,在BIOS文件中只要寻找到这个戳记就可以区分开每个组件。
seg000:000024 F7 2D 6C 68 35 2D 5054 01 00 00 00 02 00 00$?lh5-PT.....
seg000:001000 00 50 20 01 0B 65 7833 38 64 71 36 2E 42 49..P ex38dq6.BI
seg000:00204E 24 D3 20 00 00 2D 208F 77 BF 74 89 29 BB AAN$?..- 弚縯?华
seg000:00307F 33 33 37 37 4D 07 7355 45 55 78 35 91 D5 663377MsUEUx5懻f
seg000:004085 B7 54 49 34 52 21 0E9B A5 10 91 11 BC 1D 28叿TI4R!洢??(
seg000:0050B1 2A 66 A0 DD 5B BB BA9C 0D 51 0C C5 17 AA F2?f犦[缓?Q??
seg000:0060FB DD BC AC AD 34 F1 55DB 53 CC 03 DD A6 86 30?棘?馯跾?荭?
seg000:00702A CF 42 B5 DC 53 52 2243 F0 75 84 66 40 00 77*螧弟SR"C饀刦@.w
seg000:00807F FE 66 83 37 77 79 E79E BC F6 FF BD 7A FD EE??wy鐬荐 途中小憩:了解几个数据结构
在继续之前,先了解几个知识点
一、BIOS的简短介绍。
1、IBM推出个人计算机,简称:IBM PC。定义了BIOS规范。最初的BIOS由IBM工程师独立完成。后来为了普及IBM PC,IBM 公开了PC内部结构以及BIOS的编程规范,接口并鼓励协助各厂商开发BIOS
2、各BIOS厂商迅速崛起,代表厂商有:AMI、Award、Phoenix等。逐渐发展成为一个小厂商被大厂商吞并的时代。
3、BIOS的基于工作任务:
● POST:开机自检
● 初始化阶段:对DRAM、芯片组,外围设备等设置
● 保存相应数据:在COMS RAM 及 BIOS 数据区保存相应的数据
● 驻入服务例程:写入中断向量表及BIOS的中断服务例程等
二、中断向量表
1、BIOS启动初期的一个重要工作就是在内存最低端设置相应的BIOS中断向量表,若启动了DOS系统,DOS的系统还负责设置相应的DOS中断向量表,典型的代表是INT 21h服务。
2、中断服务程序获取的算法:
● Interrupt Handler = IDTR.base + vector × vector size
● X86 支持 256(FF)中断。
● 处理器RESET 后处于 16 位real mode,IDTR.base 初化为 0,
因此:整个BIOS 及 DOS 系统的中断向量表位于:0 + 0 × 4~0 +FF × 16,也就是 0 ~3FFh 的物理地址。
3、BIOS及DOS的整个中断向量表布局如下(0 ~ 3FF):
中断号 地址 说明
00 0000 除0错
01 0004 单步执行
02 0008 不可屏蔽中断
03 000C 断点调试
04 0010 溢出中断
05 0014 BIOS打印屏幕中断
06 0018 无效指令错
07 001C 无效浮点指令
08 0020 IRQ0 定时器中断
09 0024 IRQ1 键盘中断
0A 0028 IRQ2 串联次中断控制器
0B 002C IRQ3 COM2
0C 0030 IRQ4 COM1
0D 0034 IRQ5 LPT2
0E 0038 IRQ6 软盘控制器
0F 003C IRQ7 LPT1
10 0040 BIOS 视频服务例程
11 0044 BIOS 外围设备检查
12 0048 BIOS 检测内存大小
13 004C BIOS 磁盘例程
14 0050 BIOS 通信服务例程
15 0054 BIOS 扩展系统例程
16 0058 BIOS 键盘服务例程
17 005C BIOS 打印服务例程
18 0060 ROM BASIC 例程
19 0064 引导系统
1A 0068 BIOS 时间/RTC
1B 006C BIOS Ctrl-Break处理程序
1C 0070 Int 8h调用的计时子例程
1D 0074 视频参数表
1E 0078 软盘驱动器参数表
1F 007C 字符点阵表
20 0080 DOS 程序终止
21 0084 DOS 系统服务例程
22 0088 DOS 程序结束地址
23 008C DOS Ctrl-Break处理程序
24 0090 DOS 程序严重错误处理
25 0094 DOS 读磁盘例程
26 0098 DOS 写磁盘例程
27 009C DOS TSR
28 00A0 DOS 空闲中断
29 00A4 DOS 字符输出
2A 00A8 网络接口
2B ~ 2D 00AC ~ 00B4 保留
2E 00B8 DOS Shell传递参数
2F 00BC DOS 多重功能中断
30 00C0 保留
31 00C4 DOS 保护模式接口
32 00C8 保留
33 00CC 鼠标服务例程
34 ~ 3E 00D0 ~ 00F8 浮点仿真运算拦截码入口
3F 00FC 覆盖管理
40 0100 软盘中断服务
41 0104 硬盘1参数表
42 0108 视频中断(用于EGA)
43 010C EGA 参数表
44 0110 EGA 点阵字符表
45 0114 保留
46 0118 硬盘2参数表
47 ~ 49 011C ~ 0124 保留
4A 0128 CMOS/RTC 报警中断
4B ~ 66 012C ~ 0198 保留
67 019C 扩展内存管理程序
68 ~ 6F 01A0 ~ 01BC 保留
70 01C0 IRQ8 CMOS/RTC 中断
71 01C4 IRQ9 重定向到 Int 0A
72 01C8 IRQ10 PnP设备
73 01CC IRQ11 PnP 设备
74 01D0 IRQ12PS/2、USB 设备使用
75 01D4 IRQ13 数字协处理器
76 01D8 IRQ14 IDE设备
77 01DC IRQ15 IDE 设备
78 ~ FF 01E0 ~ 03FC 保留
4、关于中断向量表的后续话题
1)中断向量表的重定位
Interrupt Vector Table 的基地址存储在 IDTR寄存器。Processor 复位后,IDTR.base = 0。也即中断向量表在物理位置0地址上。中断向量表的基地址可以通过 LIDT 指令更改。但实模式的DOS系统不作出任何改变。
2)中断向量表的变迁
保护模式的现代操作系统重新对中断向量表进行了定位。Interrupt Vector Table 被 Interrupt Descriptor Table 取代了。前者是存放真实的中断服务程序的入口地址。后者是存放的称为门符的描述符结构。描述符定义了相应的属性及权限。真实的中断服务程序被门符间接索引。
3)中断向表的变迁
时至今日,中断体系的变迁,保护模式下的中断向量的含义大部分发生了改变。如:13号向量是 #GP(General Protection)异常。发生了如系统数据结构产生违例访问或越权访问等就产生保护异常。
4)旧的中断向量表结构
旧的中断向量表以及中断服务程序依然位于内存的低位。这份由BIOS维护的中断向量表结构只在系统启动初期产生一些作用。成功引导操作系统后,将被操作系统所抛弃,操作系统将建立属于自己的一套中断向量表以及中断服务程序。典型的是Linux 系统定义了 80h 号向量作为system call 门符。
三、CMOS 数据区域
CMOS 数据区存放一些基本系统数据,如RTC(真实的时间戳),它是一个主板上的一个RAM,为了使CMOS RAM里面的数据不丢失,主板上提供了一个电池供电。
1、CMOS RAM 的访问方式
访问 CMOS RAM 是过I/O 端口在IO Space进行的,CMOS RAM 大小为128 字节,地址范围从0 ~ 7Fh。
● 70h 端口:这个端口是个索引地址端口,通过向这个端口输送一个地址值,这个地址值位于 CMOS RAM里。
地址索引值的结构如下:
Bit7:最高位为 NMI Disable 位。置1则 Disable NMI
Bit6 ~ 0:CMOS RAM 地址索引,范围从 0 ~ 7Fh
● 71h 端口:这个端口是数据端口。从这个端口获取71h端口输送索引地址的内容。
● 72h 端口:这个端口如同71h端口一样,但这个端口可以访问整个256字节空间。也就是它的Bit7是有效索引值。
● 73h 端口:这个端口如同72h 端口一样,获取从72端口输送索引地址的内容。
错误:此处有误,谢谢 zx_wing 指出.
正确为:
● 72h 端口:这个端口如同70h端口一样,但这个端口可以访问整个256字节空间。也就是它的Bit7是有效索引值。
● 73h 端口:这个端口如同71h 端口一样,获取从72端口输送索引地址的内容。
2、CMOS RAM 数据内容
地址索引 含义
00 ~ 09h 相应的系统时间域
0A Bit7:0-时间可读 1-等待更新再读
Bit6 ~ 4:除法器频率
Bit3 ~ 0:时间中断频率
0B Bit7:0-设定时间,但仍在计时状态 1-设定时间,但在停止计时状态
Bit6:同期性中断,0-Disable 1- Enable
Bit5:时间警报中断,0 – Disable 1-Enable
Bit4:1-允许中断在更新时间时0-Disable
Bit3:方波设定 0 – Disable1-Enable
Bit2:日期/时间格式0 – BCD格式 1- Binary格式
Bit1:时间制式0- 12时制 1- 24时制
Bit0:日光节约时间 0-Disable 1-Enable
0C Bit7:IRQ标志
Bit6:周期性中断标志
Bit5:警报中断标志
Bit4:更新中断标志
Bit3~0:保留
0D Bit7:CMOS RAM内容正常性,0正常 1-异常
Bit6~0:保留,为0
0E Bit7:CMOS/RTC 芯片电源,0正常 1异常
Bit6:CMOS RAM CheckSum0 正常1 异常
Bit5:CMOS RAM 配置状态,0配置与检测的一致 1不一致
Bit4:CMOS RAM 内存状态,0记录的内存与检测一致 1不一致
Bit3:硬盘C启动状态 0启动通过可Boot 1失败,无法Boot
Bit2:时间记录0 正常无误 1记录异常
Bit1~0:保留,为0
0F 00: 软件复位
01:实模式/保护模式下发生RESET或实模下芯片组初始化时发生RESET
02:实模式/保护模式下内存检查通过后RESET
03:实模式/保护模式下内存检查失败后RESET
04:通过INT 19h 重新开机(Boot)
05:清除键盘中断(EOI),跳到40:67记录的位置
06:保护模式下测试成功后RESET跳到40:67记录的位置
07:保护模式下测试失败后RESET
08:由POST切到保护模式下进行内存检测
09:BIOS INT1使用
0A:返回跳到40:67记录的程序入口
0B:IRET回到40:67 记录的程序入口
0C:RET回到40:67记录的程序入口
0D~FF: 上电时初始复位
10h ~ 2Fh ISA系统配置
30h ~ 3Fh BIOS设置
40h ~ 7Fh 芯片组配置
四、BIOS 记录数据区域
1、如下图所示,紧接着中断向量表结构的是BIOS用来记录数据的区域,地址范围:400h ~ 600h 共 512 字节。这个区域被 BIOS 用来检测系统状态而记录使用的区域,以及 BIOS 定义的某些数据结构(例如:键盘缓冲区)。
http://blogimg.chinaunix.net/blog/upfile2/080418005222.jpg
2、在 BIOS 执行初期 BIOS 将检测 BIOS 数据区域的某些数据确定当前机器状态。例如:BIOS 通过检查 的内容是否是 1234H 从而确定机器是热启动还是冷启动。
3、BIOS 定义了键盘缓冲区在 01Eh 开始的 32 个字节的。
.
[ 本帖最后由 mik 于 2008-4-30 19:13 编辑 ] 第三站 跟着流程走(一):
far jmp后发生什么?
接下来用IDA pro打开ex38dq6.BIN观察,这个是BIOS的主体文件,跟着流程走,看看far jmp后BIOS做什么工作。
一、下面是第一张流程图:
http://blogimg.chinaunix.net/blog/upfile2/080421012019.jpg
1、第一条指令 jmp far ptr F000:E05B 经过几个跳转,跳到F000:F46C处
2、以下是F000:F46C的代码:
seg000:FF46C cli
seg000:FF46D cld
seg000:FF46E xchg bx, bx
seg000:FF470 smsw ax
seg000:FF473 test al, 1
seg000:FF475 jz short near ptr 0F480h
seg000:FF477 cli
seg000:FF478 mov al, 0FEh ; '?
seg000:FF47A out 64h, al ; AT Keyboard controller 8042.
seg000:FF47A ; Resend the last transmission
seg000:FF47C cli
seg000:FF47D hlt
--------------------------------------------------------------
取机器状态字,也就是CR0寄存器,测试CR0.PE是否为1,判断CPU是否处于实模式状态,若不是则停机。
若处于实模式转到F000:F480继续处理。
3、转到F000:F480又经过一道跳转,来到F000:E043进行处理
4、下面是F000:E043的代码:
seg000:FE043 mov al, 8Fh ; '? ; disable NMI# and get 0Fh offset register
seg000:FE045 out 70h, al ; CMOS Memory:
seg000:FE045 ;
seg000:FE047 out 0EBh, al
seg000:FE049 in al, 71h ; get OFh offset register data
seg000:FE04B out 0EBh, al
seg000:FE04D or al, al ; is RESET ?
seg000:FE04F jmp near ptr 0F483h
在这里,取 CMOS RAM 中位于0F处1个字节的数据,通过测试这个字节是否为0,判断是否属正常启动。
5、正常启动的话,调用F000:54DE这个子过程进行处理,否则跳到F000:3468。
二、下面看看F000:54DE的处理,以下是第二张流程图:
http://blogimg.chinaunix.net/blog/upfile2/080421012033.jpg
下面proc_F54DE的代码:
seg000:F54DE mov ax, 0
seg000:F54E1 mov es, ax
seg000:F54E3 cmp word ptr es:472h, 1234h
seg000:F54EA jnz short near ptr 54F8h
seg000:F54EC mov al, 8Fh ; '?
seg000:F54EE out 70h, al ; CMOS Memory:
seg000:F54EE ;
seg000:F54F0 out 0EBh, al
seg000:F54F2 mov al, 0AAh ; '?
seg000:F54F4 out 71h, al ; CMOS Memory:
seg000:F54F4 ;
seg000:F54F6 out 0EBh, al
seg000:F54F8 mov dx, 3C4h
seg000:F54FB mov al, 1
seg000:F54FD out dx, al ; EGA: sequencer address reg
seg000:F54FD ; clocking mode. Data bits:
seg000:F54FD ; 0: 1=8 dots/char; 0=9 dots/char
seg000:F54FD ; 1: CRT bandwidth: 1=low; 0=high
seg000:F54FD ; 2: 1=shift every char; 0=every 2nd char
seg000:F54FD ; 3: dot clock: 1=halved
seg000:F54FE inc dl
seg000:F5500 in al, dx ; EGA port: sequencer data register
seg000:F5501 or al, 20h
seg000:F5503 out dx, al ; EGA port: sequencer data register
seg000:F5504 call near ptr 76FBh
seg000:F5507 retn
1、在BIOS数据区的0472处存放着一个复位标志:
seg000:F54E3 cmpword ptr es:472h,1234h
通过比较 是否1234h,标志1234h是一个热启动标志位,机器热启动时,例如:按下CTRL+ALT+DEL 三个键时,由键盘中断处理程序在处写标志1234h。
2、是热启动的话,将写入AA标志到CMOS RAM 的0F处。
3、接着设置EGA相应的工作状态。
4、在proc_F76FB过程里置定时器1的状态。
5、最后调用过程proc_F2941进行芯片组的初始化。
三、下面是本站节的重点,初始化某部分芯片组,下面是流程图:
http://blogimg.chinaunix.net/blog/upfile2/080421012043.jpg
1、下面重点理解 write_pci_byte这个BIOS提供的rontine,代码如下:
seg000:FF798 xchg ax, cx ; write_byte routine
seg000:FF799 shl ecx, 10h
seg000:FF79D xchg ax, cx
seg000:FF79E mov ax, 8000h ; Bus 0
seg000:FF7A1 shl eax, 10h
seg000:FF7A5 mov ax, cx
seg000:FF7A7 and al, 0FCh
seg000:FF7A9 mov dx, 0CF8h ; config_address register
seg000:FF7AC out dx, eax
seg000:FF7AE add dl, 4 ; config_data register
seg000:FF7B1 mov al, cl
seg000:FF7B3 and al, 3
seg000:FF7B5 add dl, al
seg000:FF7B7 mov eax, ecx
seg000:FF7BA shr eax, 10h
seg000:FF7BE out dx, al
seg000:FF7BF retn
将这个routine功能简化为C代码形式来看比较直观:
void wirte_pci_byte(int offset_number, int mask)
{
if (number == -1)
jmp_7666();
do_wirte_pci_byte(offset_number, mask);
}
这段routine固定写PCI的Bus0,Device0,Function0,offset 值放在cx中,由调用者传来,置什么值放在al寄存器,这是1个字节的值。
Bus0,Dev0,Fun0是hostbrige控制器(NorthBridge),也即是DRAM控制器的地址所在。这段代码是典型的写PCI设置的手法。PCI设置地址送入config_address_register中,然后往config_data_register里写数据,这个PCI设备地址将映射到PCI设备的寄存器,如前面介绍的地址空间图所示,PCI设备地址范围是E000_0000 ~ EFFF_FFFF,这段空间提交到相应的PCI设备。
2、现在回过头来看调用者,cx=95,al=33 这个参数传给 write_pci_byte。Offset是95,mask码是33。Offset 95在write_pci_byte将被置为94,这将是DRAM控制器的PAM4寄存器,PAM4寄存器控制D_8000 ~ D_FFFF内存空间的属性。写入33,结果是:将这段空间置为read/write属性,这将是所有访问这段空间的操作会提交到DRAM。而不再是ROM。
3、Offset 96的结果和offset 95一样,在write_pci_byte的掩码中被置为offset 94。
茅塞顿开,若有所得拜读了 谢谢!:lol: