【我所认知的BIOS】->反汇编BIOS之Bootblock(7)
-- Memory initial 之前的一些初始化DMA,8259
By Lightseed
5/20/2010
为什么会有bootblock和非bootblock这么一说呢?其实就是因为有没有真正的内存可以用的区别。这个章节里我们一起来看看经过之前那些章节的讨论后,BIOS在初始化memory之前会做的一些动作。(稍微比较琐碎点,看起来比较枯燥。)
图1 BIOS主流程
从下面的这段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 0E292h
_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, 2
Call 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的基本配置。
还是来看我们反汇编出来的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
图1
多的就不说了,在code我都详细注解了,看不懂的话,再多查查datasheet就知道了。
现在这个小节我们继续讲讲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里去吧。
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就是这样被初始化的呀。
限于篇幅,在内存初始化之前的动作就先告一段落,下一节继续介绍在初始化内存之前,还有些其他的动作。