【我所认知的BIOS】->反汇编BIOS之Bootblock(9)

【我所认知的BIOS->反汇编BIOSBootblock(9)

-- Memory initial 函数

By Lightseed

06/24/2010

1BIOS的主流程

为什么会有bootblock和非bootblock这么一说呢?其实就是因为有没有真正的内存可以用的区别。这个章节里我们一起来看看经过之前那些章节的讨论后,BIOS在初始化memory之前会做的一些动作。(稍微比较琐碎点,看起来比较枯燥。)Memory initial这个函数里面,会再做一些前期的准备工作。比如8259的中断控制器的初始化,PCIE的初始化,等等然后进入到intel提供的MRC里面去。那么这节就讲讲这个函数里面具体接触的东西。

【我所认知的BIOS】->反汇编BIOS之Bootblock(9)

1 BIOS主流程

2CT_Memory_Init整个函数的架构

_F000:36E0 CT_Memory_Init: ; CODE XREF: _F000:E377j

Call Power_Managment_init;伪代码

_F000:370C Power_Managment_init_Exit: ; CODE XREF: _F000:8850j

Call PCIExpressInit ;伪代码

Call Memory_INIT ; There are too many registers which intel do not release, so I have not plan to comment it.

; We usually call these code "MRC", it means memory refrence code. As I know, Award and AMI

; MRC are the same.

;中间省略N

Call IGDDetect ; 伪代码

Ret

上面是memory initial的整个函数反汇编出来的代码。架构也很清晰,正如之前说的那些,8259初始化好了后,继续Power management的初始化,然后再是PCIE的初始化,然后是真正进入到intelMRCdetect和初始化内存。一条线,比较简单。

3、关于南桥那面Power management的初始化

_F000:3709这行中可以看出,在8259初始化好了以后,程序就会进入到初始化power management的函数里去。那我们来看看这个函数里面具体都做了什么。

_F000:8834 Power_Managment_init: ; CODE XREF: _F000:3709j

_F000:8834 mov si, 880Ch

_F000:8837 mov dh, 40h ; '@' ; PM IO

_F000:8839

_F000:8839 Power_Managment_init_loop: ; CODE XREF: _F000:884Ej

_F000:8839 mov dl, cs:[si] ; offset

_F000:883C mov al, cs:[si+1] ; get the value to store

_F000:8840 out dx, al ; set

_F000:8841 out 0EBh, al

_F000:8843 out 0EBh, al

_F000:8845 out 0EBh, al

_F000:8847 add si, 2

_F000:884A cmp si, 8834h ; Table end?

_F000:884E jnz Power_Managment_init_loop

看到上面的函数是不是大家都有比较熟悉的感觉呀?一开始进来就是给SI找到一个tableoffset,然后就是按照结构体的元素来初始化各个寄存器。而这个结构体就比较简单了,总共两个byte。第一个byte是在Power management base address(还记得么?在前面的文章里有讲,PM IO base address4000H)上的偏移。关于table里面的东西,我就不多收了,我觉得我写的挺详细的,只要你对照ICHdatasheet一切都能查到对应的描述。

_F000:880C ;[]--------------------------------------------[]

_F000:880C This table is very easy, so I will not comment them one by one.

_F000:880C I choose the important register to comment. :)

_F000:880C ;[]--------------------------------------------[]

_F000:880C Power_Managment_init_table db 2 ; ; Power Management 1 Enable Register Low byte

_F000:880D db 0 ; ;

_F000:880D ;

_F000:880E db 3 ; ; Power Management 1 Enable Register High byte

_F000:880F db 0 ; ;

_F000:880F ;

_F000:8810 db 0 ; ; Power Management 1 Status Register low byte

_F000:8811 db 0FFh ; ; clear all status

_F000:8811 ;

_F000:8812 db 1 ;

_F000:8813 db 0FFh ; ; Power Management 1 Status Register high byte

_F000:8813 ;

_F000:8814 db 11h ; ; Processor Control Register

_F000:8815 db 0 ; ; No forced throttling, No clock throttling is occurring (maximum processor performance).

_F000:8815 ;

_F000:8816 db 28h ; ( ; General Purpose Event 0 Status Register low byte

_F000:8817 db 0FFh ; ;

_F000:8817 ;

_F000:8818 db 29h ; ) ; General Purpose Event 0 Status Register high byte

_F000:8819 db 0FFh ; ;

_F000:8819 ;

_F000:881A db 2Ah ; *

_F000:881B db 0FFh ; ;

_F000:881B ;

_F000:881C db 2Bh ; +

_F000:881D db 0FFh ; ; clear all GPE0 status

_F000:881D ;

_F000:881E db 2Ch ; , ; General Purpose Event 0 Enables Register the 1st byte

_F000:881F db 0 ; ;

_F000:881F ;

_F000:8820 db 2Dh ; -

_F000:8821 db 0 ; ;

_F000:8821 ;

_F000:8822 db 2Eh ; .

_F000:8823 db 0 ; ;

_F000:8823 ;

_F000:8824 db 2Fh ; /

_F000:8825 db 0 ; ; all GPE0 disable

_F000:8825 ;

_F000:8826 db 30h ; 0 ; SMI Control and Enable Register 1st byte

_F000:8827 db 20h ; ; Enables writes to the APM_CNT register to cause an SMI#.

_F000:8827 ;

_F000:8828 db 31h ; 1

_F000:8829 db 0 ; ; Other function disable

_F000:8829 ;

_F000:882A db 34h ; 4 ; SMI Status Register 1st byte

_F000:882B db 0FFh ; ;

_F000:882B ;

_F000:882C db 35h ; 5 ; SMI Status Register 2nd byte

_F000:882D db 0FFh ; ; clear all SMI status

_F000:882D ;

_F000:882E db 41h ; A ; I can not find the remark of this register in datasheet...:(

_F000:882F db 30h ; 0 ;

_F000:882F ;

_F000:8830 db 44h ; D ; Device Activity Status Register low byte

_F000:8831 db 0FFh ; ;

_F000:8831 ;

_F000:8832 db 45h ; E ; Device Activity Status Register high byte

_F000:8833 db 0FFh ; ; clear all status

4PCIE的初始化

关于这部分的说明,我觉得很惭愧,据我所了解,这部分的代码绝对多数是为了解决一些bug才放在这里的。而且这些bug应该还都是北桥那面的一些东西,intel也没公布相关的说明,所以我也不知道究竟这里面的寄存器是有啥用。这下这段代码就是PCIE初始化的函数被反汇编出来的源码。不过我把这个函数的地址贴出来,而且这里的基本上BIOS是不会动的,所以平时我也没有深入进去研究。

_F000:394A ;[]----------------------------------------[]

_F000:394A PCIExpressInit:

_F000:394A The function of this subrutine is to initial Northbridge

_F000:394A I think you can check with the datasheet by yourself.

_F000:394A Because some of the register, I do not research before .

_F000:394A What's more, we do not touch these code. If you are

_F000:394A interest into it, you can dig into.

_F000:394A ;[]----------------------------------------[]

_F000:394A

_F000:394A PCIExpressInit: ; CODE XREF: _F000:3745j

_F000:394A mov cx, 54h ; 'T' ; bus 0# dev 0# func 0# Reg 54h

_F000:3A90 jmp di ; PCIExpressInit return

PCIE初始化后面,还有关于北桥那面的寄存器操作,比如:MMIO base address的初始化(后面要用到的哦,尤其是intelMRC也会频繁使用的。),MCHBAR的打开呀什么的,都比较简单啦。不过要提的一下是PCIE的访问方法:(我想网上应该有不少的说明,怎么去访问PCIE的配置空间。)

Register Location = PCI Express Base Address + Bus number* 100000h + device

number * 8000h + function * 1000h + Address Offset

5、进入到MRC

BIOS就真正进入到intelMRC,有两点需要说明一下:

第一,我们再看看_F000:37A8之前有三个byte的数据是没有用到的(如果你反汇编了BIOS,如果没有,直接跳过具体的地址)。也许有人会很纳闷,为什么会这样呀?答案是在BIOS中,写code的时候用了aglin 4的动作。从而代指有三个byte是无意义的。所以我们应该跳过去看。

第二,正如我上面的注释里有说,Memory_INIT这个函数里面有太多的寄存器是intel没有release的了,所以我也不想挨着挨着深入。如果您有兴趣可以看看intel的一本橘皮书,好像是ICH BIOS spec吧。具体我不记得了。里面有详细的描述。

6Memory初始化完了后

内存初始化完了以后,在awardbios里面还会继续detect IGD。代码很简单:

主要是操作北桥的相关寄存器(52H,详细的说明查一下北桥的datasheet)来做的。

都挺简单的,对照着北桥的datasheet就可以查清楚了。(你们查不到的寄存器,我也查不到了。。。。所以有些东西,我其实也不清楚,究竟某些寄存器有啥用。)

8、小结

至此关于BIOSbootblock部分最最重要的目的就算是完成了。因为BIOSrom里面跑而且还没有堆栈,真的很费事,而且速度还慢。所以才要尽快地把内存初始化好,然后把放在ROM里面的BIOS源码都copy到内存中来执行。这样的话不仅提高了BIOS初始化主板的速度,还显得让程序更好写。大致的过程可以看看图1所示。

【我所认知的BIOS】->反汇编BIOS之Bootblock(9)

1 BIOS在不同时期的运行过程图

我要简单描述一下图1的意思。左边其实就是BIOS一直在ROM里面跑的过程。(由于北桥开关的原因,FFFF_0000会被映射到F_0000上去,之前有讲在这里再提一下。)所以在图上仍然以F000段开说明,不要混淆哦。然后到内存初始化好了以后,bootblock的解压缩函数就会把BIOS解压缩到内存中去,然后继续执行(这个时候的BIOS就是真的在实模式下执行的了哦,北桥的开关也就是真的把内存和实际的CPU低端寻址对应了。)。

Bootblock的这部分,我们基本就要结束了,后续我们会看到BIOScopy呀什么的操作。让我们拭目以待吧!!