【我所认知的BIOS】->反汇编BIOS之Bootblock(3)--initialize some chipset registerBy Lightseed5/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 theGEN1 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 theGEN1 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这个函数可以做了很多事情哦。这个函数里面我会分几个章节来介绍它所做的工作。