【我所认知的BIOS】->反汇编BIOS之Bootblock(7)-- Memory initial之前的一些初始化DMA,8259By Lightseed5/20/20101、BIOS的主流程为什么会有bootblock和非bootblock这么一说呢?其实就是因为有没有真正的内存可以用的区别。这个章节里我们一起来看看经过之前那些章节的讨论后,BIOS在初始化memory之前会做的一些动作。(稍微比较琐碎点,看起来比较枯燥。)图1 BIOS主流程2、确实是Normal后的第一个JMP从下面的这段code中我们来研究一下,_F000:E1FC这里是的SP指向E200H地址,且我们看看在E200H这里这里存储的数据是E292H,注意了,这里可不是E202H哦。执行retn后,那么CPU的IP寄存器就变成了E292H了,那么CPU就会从此处取code来执行。(可不要犯了ROM_CALL的定势思维。)_F000:E1F8 Not_Resume_From_Sx: ; CODE XREF: _F000:E1D3j_F000:E1F8 ; _F000:E1EDj ..._F000:E1F8 mov al, 0C0h ; '?_F000:E1FA out 80h, al ; manufacture's diagnostic checkpoint_F000:E1FC mov sp, 0E200h_F000:E1FF retn_F000:E1FF ;哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?_F000:E200 dw 0E292h3、CPU Fast string的detect以及CMOS的初始化_F000:E292 Go_on_bios:。。。。。。。。。。。。。_F000:E29D jmp Fast_string_If_open_F000:E29D ;哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?_F000:E2A0 dw 0E2A2h_F000:E2A2 ;哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?_F000:E2A2 mov al, 8Bh ; '? ; CMOS REGISTER 0B: Default is all interrupts(AIE,PIE) turned off,_F000:E2A2 ; date is in BCD format, time is in 24-hour mode, daylight savings_F000:E2A2 ; time is disabled._F000:E2A4 mov ah, 2Call Set_CMOS ;伪代码_F000:E2AE mov al, 8Ah ; '? ; CMOS REGISTER 0A: Default is stage divider at 32.768 kHz, divider_F000:E2AE ; output at 1.024 Khz, interrupting every 976.562 microseconds_F000:E2B0 mov ah, 26h ; '&'Call Set_CMOS ;伪代码上面这段code主要做了两件事情,一个是检测CPU的fast string是否支持。另外一个是初始化CMOS的基本配置。3.1 CPU的fast string还是来看我们反汇编出来的code吧。_F000:E6AB ;------------------------------------------------------------------------------------_F000:E6AB ;FUNC: Fast_string_If_open_F000:E6AB ;_F000:E6AB ;DESC: If CPU support Fast_string then enable it._F000:E6AB ;_F000:E6AB ;IN: NONE_F000:E6AB ;OUT: NONE_F000:E6AB ;------------------------------------------------------------------------------------_F000:E6AB_F000:E6AB ;圹圹圹圹圹圹圹?S U B R O U T I N E圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹?_F000:E6AB_F000:E6AB_F000:E6AB Fast_string_If_open proc near ; CODE XREF: _F000:E29Dj_F000:E6AB mov eax, 0_F000:E6B1 cpuid_F000:E6B3 cmp ebx, 'iryC'_F000:E6BA jz locret_FE6D9_F000:E6BC mov eax, 1_F000:E6C2 cpuid_F000:E6C4 cmp ax, 611h_F000:E6C7 jnz locret_FE6D9_F000:E6C9 mov ecx, 1E0h_F000:E6CF rdmsr_F000:E6D1 and eax, 6_F000:E6D5 or al, 4 ; disable fast string_F000:E6D7 wrmsr_F000:E6D9_F000:E6D9 locret_FE6D9: ; CODE XREF: Fast_string_If_open+Fj_F000:E6D9 ; Fast_string_If_open+1Cj_F000:E6D9 retn_F000:E6D9 Fast_string_If_open endp上面函数的大致的意思是,用CPUID来读取CPU的属性,判断是否支持Fast string,如果不支持的话,那么就disabled掉它。(也许有人会问,上面是fast string,您可以在3A里面查到^.^。)如图1 图13.2 CMOS的基本配置多的就不说了,在code我都详细注解了,看不懂的话,再多查查datasheet就知道了。4、DMA和8259的初始化4.1算法现在这个小节我们继续讲讲memory之前的另外一些动作,这些动作沿用了之前初始化superio的方法,先列一个table,table以结构体的形式存在,用指针指向这个table,用一个循环依次逐个地把table里面列的寄存器都初始化。(算法很简单如下)_F000:E2BF mov si, 0E6DAh ; data source pointor_F000:E2C2 mov cx, 24h ; '$' ; loop counter_F000:E2C5 cld_F000:E2C6_F000:E2C6 loc_FE2C6: ; CODE XREF: _F000:E2CFj_F000:E2C6 lodsw ; Get the port_F000:E2C7 mov dx, ax_F000:E2C9 lodsb ; Get the value will be stored_F000:E2CA out dx, al_F000:E2CB jmp short $+2_F000:E2CD jmp short $+2_F000:E2CF loop loc_FE2C6 ; Get the port算法的话,也就上面这个样子,简单地不能再见到了。BIOS里面,这些都不是难点。难点在于,怎么去理解这个table里面都初始化了些什么,我想这也是大家最care的东西。好吧,那么我们来深入到table里去吧。4.2详细初始化内容table里面的structure如下:Struc { Word ;存放的是将要填值的port address Byte ;存放的是将要填到port address里面的value}_F000:E6DA ;[]-----------------------------------------------------[]_F000:E6DA one word and one byte are made of a set._F000:E6DA The word is port address, the byte is the value will be store_F000:E6DA ;[]-----------------------------------------------------[]_F000:E6DA System_INIT_table dw 3B8h ; 3B8H is the IO for VGA controller, but I can not find out its description. So I don't know its mean_F000:E6DC db 1 ; ;_F000:E6DC ;_F000:E6DD dw 61h ; NMI Status and Control Register_F000:E6DF db 0FCh ; ? ; Turn speaker off_F000:E6DF ;_F000:E6E0 dw 8 ; Channel 0~3 DMA Command Register_F000:E6E2 db 4 ; ; Disable DMA Channel Group_F000:E6E2 ;_F000:E6E3 dw 0D0h ; Channel 4~7 DMA Command Register_F000:E6E5 db 4 ; ; Disable DMA Channel Group_F000:E6E5 ;_F000:E6E6 dw 0F1h ; math coprocessor port_F000:E6E8 db 0 ; ; reset it_F000:E6E8 ;_F000:E6E9 dw 43h ; Choose TIMER 1_F000:E6EB db 54h ; T ;_F000:E6EB ;_F000:E6EC dw 41h ; Initial it_F000:E6EE db 0 ; ;_F000:E6EE ;_F000:E6EF dw 0Dh ; About DMA controller, but intel do not release_F000:E6F1 db 7 ; ;_F000:E6F1 ;_F000:E6F2 dw 0DAh ; About DMA controller, but intel do not release_F000:E6F4 db 7 ; ;_F000:E6F4 ;_F000:E6F5 dw 43h_F000:E6F7 db 40h ; @ ; Timer 1 latch command_F000:E6F7 ;_F000:E6F8 dw 41h_F000:E6FA db 12h ; ;_F000:E6FA ;_F000:E6FB dw 8 ; Channel 0~3 DMA Command Register_F000:E6FD db 0 ; ; enable it_F000:E6FD ;_F000:E6FE dw 0D0h ; Channel 4~7 DMA Command Register_F000:E700 db 0 ; ; enable it_F000:E700 ;_F000:E701 dw 0Bh ; About DMA controller, but intel do not release_F000:E703 db 40h ; @ ;_F000:E703 ;_F000:E704 dw 0D6h ; About DMA controller, but intel do not release_F000:E706 db 0C0h ; ? ;_F000:E706 ;_F000:E707 dw 0D6h_F000:E709 db 41h ; A ;_F000:E709 ;_F000:E70A dw 0Bh_F000:E70C db 41h ; A ;_F000:E70C ;_F000:E70D dw 0D6h_F000:E70F db 42h ; B ;_F000:E70F ;_F000:E710 dw 0Bh_F000:E712 db 42h ; B ;_F000:E712 ;_F000:E713 dw 0D6h_F000:E715 db 43h ; C ;_F000:E715 ;_F000:E716 dw 0Bh_F000:E718 db 43h ; C ;_F000:E718 ;_F000:E719 dw 0D2h_F000:E71B db 0 ; ;_F000:E71B ;_F000:E71C dw 0D4h_F000:E71E db 0 ; ;_F000:E71E ;_F000:E71F dw 20h ; Initial Master 8259_F000:E721 db 11h ; ;级联,边沿触发,需要写ICW4_F000:E721 ;_F000:E722 dw 21h ; Write ICW2_F000:E724 db 8 ; ;中断类型号8H_F000:E724 ;_F000:E725 dw 21h ; Write ICW3_F000:E727 db 4 ; ;主片的IR2引脚接从片_F000:E727 ;_F000:E728 dw 21h ; Write ICW4_F000:E72A db 1 ; ;非特殊完全嵌套,非缓冲,非自动结束,80x86模式_F000:E72A ;_F000:E72B dw 21h ; IMR interrupt mask register_F000:E72D db 0FFh ; ; mask IRQ0~7_F000:E72D ;_F000:E72E dw 0A0h ; Initial Slave 8259_F000:E730 db 11h ; ;级联,边沿触发,需要写ICW4_F000:E730 ;_F000:E731 dw 0A1h ; ICW 2_F000:E733 db 70h ; p ;中断类型号70H_F000:E733 ;_F000:E734 dw 0A1h ; ICW 3_F000:E736 db 2 ; ;接主片的IR2引脚_F000:E736 ;_F000:E737 dw 0A1h ; ICW 4_F000:E739 db 1 ; ;非特殊完全嵌套,非缓冲,非自动结束,80x86模式_F000:E739 ;_F000:E73A dw 0A1h ; IMR interrupt mask register_F000:E73C db 0FFh ; ; mask IRQ8~15_F000:E73C ;_F000:E73D dw 43h_F000:E73F db 36h ; 6 ; initial TIMER 0_F000:E73F ;_F000:E740 dw 40h_F000:E742 db 0 ; ;_F000:E742 ;_F000:E743 dw 40h_F000:E745 db 0 ; _F000:E746关于上面的初始化过程,我想要说明两点:①DMA controller的一些资料intel没有公布,所以我也只能注释到这么多。②8259部分的初始化,在http://blog.csdn.net/lightseed/archive/2009/06/08/4250623.aspx这一节里有详细的描述,我们可以对比这BIOS初始化8259的流程看看,两者是完全相同的。会不会有成就感?起码我当时看到这里的时候是很激动的,原来PIC就是这样被初始化的呀。 限于篇幅,在内存初始化之前的动作就先告一段落,下一节继续介绍在初始化内存之前,还有些其他的动作。