【我所认知的BIOS】->反汇编BIOS之Bootblock(3)
--initialize some chipset register
By Lightseed
5/13/2010
在上一篇中,我和大家探讨了下面代码中的BT_CPU_Init这个函数,它主要是一些特殊CPU的micro code的update。那么我们继续往下走,就会发现初始化chipset寄存器的函数,如_F000:E1C3这行所示。这里是用ROM_CALL来调用的。
_F000:E1B8 mov sp, 0E1BEh ; First Use ROM_CALL
_F000:E1BB jmp BT_CPU_Init ; Save esp (Return Address)
_F000:E1BB ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
_F000:E1BE dw 0E1C0h
_F000:E1C0 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
Call Chipset_Reg_Init_Early ;伪代码
Chipset_Reg_Init_Early函数的代码要反汇编也很容易啦,双击或者是点中它回车即可。反汇编并加注如下:
; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
_F000:F600
_F000:F600 Chipset_Reg_Init_Early: ; CODE XREF: _F000:E1C3j
_F000:F604 mov si, 0F6DCh ; Get the chipset register initial table offset
_F000:F607
_F000:F607 Init_Chipset_Ren_loop: ; CODE XREF: _F000:F629j
_F000:F607 mov cx, cs:[si] ; Get the DEV#,FUNC#,REG#
Call Get_Pci_Byte ; ROM_CALL to get byte from chipset.伪代码,取回值存在AL里
_F000:F612 and al, cs:[si+2]
_F000:F616 or al, cs:[si+3]
Call Set_Pci_byte ;伪代码
_F000:F622 add si, 4
_F000:F625 cmp si, 0F740h ; Is init table end?
_F000:F629 jnz Init_Chipset_Ren_loop ; No, go on looping
上面这个函数其实注释已经把90%的内容都说清楚了,不过我还是要再强调一下其中的一点,在_F000:F604中,是为了找到一个table。在这个table中存放着一系列的寄存器的地址以及BIOS需要initialize的值。我详细加注如下:
Chipset_Reg_Init_table dw 0F01Ch ; Bus 0# Dev 30#, Func 0#, Reg 1CH .PCI to PCI bridge register 1ch
_F000:F6DE db 0 ; ; Clear all bit
_F000:F6DF db 10h ; ; Set the IO base is 10h, it means base address is 1000h
_F000:F6DF ;
_F000:F6E0 dw 0F004h ; Bus 0# Dev 30#, Func 0#, Reg 1CH .PCI to PCI bridge register 04h
_F000:F6E2 db 0 ; ; Clear all bits
_F000:F6E3 db 1 ; ; I/O space enable
_F000:F6E3 ;
_F000:F6E4 dw 0FB20h ; Bus 0# Dev 31#, Func 3#, Reg 20H . SMBUS controller register 20h
_F000:F6E6 db 0 ;
_F000:F6E7 db 0 ; ; The low byte of SMBUS controller base address is 0h
_F000:F6E7 ;
_F000:F6E8 dw 0FB21h ; Bus 0# Dev 31#, Func 3#, Reg 21H . SMBUS controller register 21h
_F000:F6EA db 0 ;
_F000:F6EB db 50h ; P ; The high byte of SMBUS controller base address is 50h,
_F000:F6EB ; So we can know the SMBUS base address is 5000h on the platform.
_F000:F6EC dw 0FB40h ; Bus 0# Dev 31#, Func 3#, Reg 40H . SMBUS controller register 40h
_F000:F6EE db 0 ;
_F000:F6EF db 1 ; ; Enable SMBUS host controller
_F000:F6EF ;
_F000:F6F0 dw 0FB04h ; Bus 0# Dev 31#, Func 3#, Reg 4H . SMBUS controller register 4h
_F000:F6F2 db 0 ;
_F000:F6F3 db 3 ; ; SM bus Memory and IO space enable
_F000:F6F3 ;
_F000:F6F4 dw 0F841h ; Bus 0# Dev 31#, Func 0#, Reg 41H . LPC interface bridge register 41h
_F000:F6F4 ; ACPI IO base address reg
_F000:F6F6 db 0 ;
_F000:F6F7 db 40h ; @ ; ACPI io base address is 4000h
_F000:F6F7 ;
_F000:F6F8 dw 0F844h ; Bus 0# Dev 31#, Func 0#, Reg 44H . LPC interface bridge register 44h
_F000:F6FA db 0 ;
_F000:F6FB db 80h ; € ; Decode of the I/O range pointed to by the ACPI base register is enabled, and the ACPI power
_F000:F6FB ; management function is enabled.
_F000:F6FB ;
_F000:F6FC dw 0F848h ; Bus 0# Dev 31#, Func 0#, Reg 48H . LPC interface bridge register 48h
_F000:F6FC ; low byte of GPIO base address
_F000:F6FE db 0 ;
_F000:F6FF db 80h ; € ; The low byte of GPIO base is 80h
_F000:F6FF ;
_F000:F700 dw 0F849h ; Bus 0# Dev 31#, Func 0#, Reg 49H . LPC interface bridge register 49h
_F000:F700 ; High byte of GPIO base address
_F000:F702 db 0 ;
_F000:F703 db 40h ; @ ; High byte of GPIO base address is 40h, So GPIO base add is 4080h
_F000:F703 ;
_F000:F704 dw 0F84Ch ; Bus 0# Dev 31#, Func 0#, Reg 4cH . LPC interface bridge register 4ch
_F000:F704 ; GPIO Control Register
_F000:F706 db 0 ;
_F000:F707 db 10h ; ; Enables decode of the I/O range pointed to by the
_F000:F707 ; GPIO Base Address register (D31:F0:48h) and enables the GPIO function
_F000:F708 dw 0F864h ; Bus 0# Dev 31#, Func 0#, Reg 64H . LPC interface bridge register 64h
_F000:F708 ; Serial IRQ Control Register
_F000:F70A db 0 ;
_F000:F70B db 0C0h ; ? ; Enable serial IRQ and set it in continuous mode
_F000:F70B ;
_F000:F70C dw 0F8D9h ; Bus 0# Dev 31#, Func 0#, Reg D9H . LPC interface bridge registerD9h
_F000:F70C ; Firmware Hub Decode Enable Register
_F000:F70E db 0 ;
_F000:F70F db 0C0h ; ? ; Enable decoding F000
_F000:F70F ;
_F000:F710 dw 0F8DCh ; Bus 0# Dev 31#, Func 0#, Reg DCH . LPC interface bridge registerDCh
_F000:F710 ; bios controller Register
_F000:F712 db 0 ;
_F000:F713 db 0 ; ; Setting the BIOSWE will not cause SMIs
_F000:F713 ; Only read cycles result in Firmware Hub I/F cycles.
_F000:F714 dw 0F8B8h ; Bus 0# Dev 31#, Func 0#, Reg B8H . LPC interface bridge register B8h
_F000:F714 ; GPI Routing control Register
_F000:F716 db 0 ;
_F000:F717 db 55h ; U ; GPI 0 SMI
_F000:F717 ;
_F000:F718 dw 0F8B9h
_F000:F71A db 0 ;
_F000:F71B db 55h ; U ; GPI 1 SMI
_F000:F71B ;
_F000:F71C dw 0F8BAh
_F000:F71E db 0 ;
_F000:F71F db 55h ; U ; GPI 2 SMI
_F000:F71F ;
_F000:F720 dw 0F8BBh
_F000:F722 db 0 ;
_F000:F723 db 55h ; U ; GPI 3 SMI
_F000:F723 ;
_F000:F724 dw 0F885h ; Bus 0# Dev 31#, Func 0#, Reg 85H . LPC interface bridge register 85h
_F000:F724 ; LPC I/F Generic Decode Range 1 Register
_F000:F726 db 0 ;
_F000:F727 db 4 ; ; The high byte of decode range base address
_F000:F727 ;
_F000:F728 dw 0F884h
_F000:F72A db 0 ;
_F000:F72B db 81h ; ? ; The low byte of decode range base address, So decode range is (480h-500h)
_F000:F72B ; bit 0 : Enable the GEN1 I/O range to be forwarded to the LPC I/F
_F000:F72B ;
_F000:F72C dw 0F889h
_F000:F72E db 0 ;
_F000:F72F db 2 ;
_F000:F730 dw 0F888h
_F000:F732 db 0 ;
_F000:F733 db 91h ; ? ; The low byte of decode range base address, So decode range is (290h-3100h)
_F000:F733 ; bit 0 : Enable the GEN1 I/O range to be forwarded to the LPC I/F
_F000:F733 ;
_F000:F734 dw 0F882h ; Bus 0# Dev 31#, Func 0#, Reg 82H . LPC interface bridge register 82h
_F000:F734 ; LPC I/F Enables Register
_F000:F736 db 0 ;
_F000:F737 db 8 ; ; Enable Floppy Drive
_F000:F737 ;
_F000:F738 dw 0F883h ; Bus 0# Dev 31#, Func 0#, Reg 83H . LPC interface bridge register 83h
_F000:F738 ; LPC I/F Enables Register
_F000:F73A db 0 ;
_F000:F73B db 34h ; 4 ; Enable KBC,micro controller2, Super io decode
_F000:F73B ;
_F000:F73C dw 0F881h ; Bus 0# Dev 31#, Func 0#, Reg 81H . LPC interface bridge register 81h
_F000:F73C ; I/O Decode Ranges Register
_F000:F73E db 0EFh ; ? ; FDD use 3F0h
_F000:F73F db 0 ;
_F000:F740 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
我想有了这个table的加注,去理解怎么初始化这些寄存器的话,应该不是难事了。
我们再来看看,其实在这个函数里,逻辑都很简单,只是对HW的操作比较具体,所以需要对照SPEC来看看。着重要说的一个是Get_Pci_Byte这个函数,这个函数我们可以从上面的代码中看出,它的输入参数是CX,而CX里面存的是pci的device No. function No.和register No.但是却没包含BUS No.原因是为什么呢?让我们跟如到里面去看看究竟。
(关于这段反汇编出来的code,其实很简单的。不过考虑到不太方便,所以您自己根据自己反汇编出来的code再研究吧。大致就是不需要输入BUS number就可以访问PCI设备的配置空间了。因为南桥原本就是在bus 0上。)
我们来看看_F000:F76F这行,这是对即将要访问的PCI BUS No.的赋值,很明显是直接给了0,从此我们也可以推测出,Get_Pci_Byte这个函数是且仅仅是访问PCI BUS 0#上的PCI device 设备。(再扩展一下,其实就是North bridge和South bridge两个芯片里的各个PCI device了。)而且还可以知道,CX的bit 0~7是要访问的register number等等,和PCI spec里面的那个map是对应的。
至此关于Chipset的一些些(为什么说一些些呢?因为还有很多寄存器马上还要继续初始化,从
_F000:F6A6 mov bx, 0F6ACh ; There do not use ROM_CALL
_F000:F6A9 jmp Other_Register_Init。
这两行中Other_Register_Init跟进去看。)寄存器初始化就算告一段落了。
呵呵。。。预先提醒一下大家,Other_Register_Init这个函数可以做了很多事情哦。这个函数里面我会分几个章节来介绍它所做的工作。