- 論壇徽章:
- 0
|
第三站 跟著流程走(一):
far jmp后發(fā)生什么?
接下來用IDA pro打開ex38dq6.BIN觀察,這個(gè)是BIOS的主體文件,跟著流程走,看看far jmp后BIOS做什么工作。
一、下面是第一張流程圖:
![]()
1、第一條指令 jmp far ptr F000:E05B 經(jīng)過幾個(gè)跳轉(zhuǎn),跳到F000:F46C處
2、以下是F000:F46C的代碼:
seg000:FF46C cli
seg000:FF46D cld
seg000:FF46E xchg bx, bx
seg000:FF470 smsw ax
seg000:FF473 test al, 1
seg000:FF475 jz short near ptr 0F480h
seg000:FF477 cli
seg000:FF478 mov al, 0FEh ; '?
seg000:FF47A out 64h, al ; AT Keyboard controller 8042.
seg000:FF47A ; Resend the last transmission
seg000:FF47C cli
seg000:FF47D hlt
--------------------------------------------------------------
取機(jī)器狀態(tài)字,也就是CR0寄存器,測(cè)試CR0.PE是否為1,判斷CPU是否處于實(shí)模式狀態(tài),若不是則停機(jī)。
若處于實(shí)模式轉(zhuǎn)到F000:F480繼續(xù)處理。
3、轉(zhuǎn)到F000:F480又經(jīng)過一道跳轉(zhuǎn),來到F000:E043進(jìn)行處理
4、下面是F000:E043的代碼:
seg000:FE043 mov al, 8Fh ; '? ; disable NMI# and get 0Fh offset register
seg000:FE045 out 70h, al ; CMOS Memory:
seg000:FE045 ;
seg000:FE047 out 0EBh, al
seg000:FE049 in al, 71h ; get OFh offset register data
seg000:FE04B out 0EBh, al
seg000:FE04D or al, al ; is RESET ?
seg000:FE04F jmp near ptr 0F483h
在這里,取 CMOS RAM 中位于0F處1個(gè)字節(jié)的數(shù)據(jù),通過測(cè)試這個(gè)字節(jié)是否為0,判斷是否屬正常啟動(dòng)。
5、正常啟動(dòng)的話,調(diào)用F000:54DE這個(gè)子過程進(jìn)行處理,否則跳到F000:3468。
二、下面看看F000:54DE的處理,以下是第二張流程圖:
![]()
下面proc_F54DE的代碼:
seg000:F54DE mov ax, 0
seg000:F54E1 mov es, ax
seg000:F54E3 cmp word ptr es:472h, 1234h
seg000:F54EA jnz short near ptr 54F8h
seg000:F54EC mov al, 8Fh ; '?
seg000:F54EE out 70h, al ; CMOS Memory:
seg000:F54EE ;
seg000:F54F0 out 0EBh, al
seg000:F54F2 mov al, 0AAh ; '?
seg000:F54F4 out 71h, al ; CMOS Memory:
seg000:F54F4 ;
seg000:F54F6 out 0EBh, al
seg000:F54F8 mov dx, 3C4h
seg000:F54FB mov al, 1
seg000:F54FD out dx, al ; EGA: sequencer address reg
seg000:F54FD ; clocking mode. Data bits:
seg000:F54FD ; 0: 1=8 dots/char; 0=9 dots/char
seg000:F54FD ; 1: CRT bandwidth: 1=low; 0=high
seg000:F54FD ; 2: 1=shift every char; 0=every 2nd char
seg000:F54FD ; 3: dot clock: 1=halved
seg000:F54FE inc dl
seg000:F5500 in al, dx ; EGA port: sequencer data register
seg000:F5501 or al, 20h
seg000:F5503 out dx, al ; EGA port: sequencer data register
seg000:F5504 call near ptr 76FBh
seg000:F5507 retn
1、在BIOS數(shù)據(jù)區(qū)的0472處存放著一個(gè)復(fù)位標(biāo)志:
seg000:F54E3 cmp word ptr es:472h, 1234h
通過比較 [0472] 是否1234h,標(biāo)志1234h是一個(gè)熱啟動(dòng)標(biāo)志位,機(jī)器熱啟動(dòng)時(shí),例如:按下CTRL+ALT+DEL 三個(gè)鍵時(shí),由鍵盤中斷處理程序在[0472]處寫標(biāo)志1234h。
2、是熱啟動(dòng)的話,將寫入AA標(biāo)志到CMOS RAM 的0F處。
3、接著設(shè)置EGA相應(yīng)的工作狀態(tài)。
4、在proc_F76FB過程里置定時(shí)器1的狀態(tài)。
5、最后調(diào)用過程proc_F2941進(jìn)行芯片組的初始化。
三、下面是本站節(jié)的重點(diǎn),初始化某部分芯片組,下面是流程圖:
![]()
1、下面重點(diǎn)理解 write_pci_byte這個(gè)BIOS提供的rontine,代碼如下:
seg000:FF798 xchg ax, cx ; write_byte routine
seg000:FF799 shl ecx, 10h
seg000:FF79D xchg ax, cx
seg000:FF79E mov ax, 8000h ; Bus 0
seg000:FF7A1 shl eax, 10h
seg000:FF7A5 mov ax, cx
seg000:FF7A7 and al, 0FCh
seg000:FF7A9 mov dx, 0CF8h ; config_address register
seg000:FF7AC out dx, eax
seg000:FF7AE add dl, 4 ; config_data register
seg000:FF7B1 mov al, cl
seg000:FF7B3 and al, 3
seg000:FF7B5 add dl, al
seg000:FF7B7 mov eax, ecx
seg000:FF7BA shr eax, 10h
seg000:FF7BE out dx, al
seg000:FF7BF retn
將這個(gè)routine功能簡(jiǎn)化為C代碼形式來看比較直觀:
void wirte_pci_byte(int offset_number, int mask)
{
if (number == -1)
jmp_7666();
do_wirte_pci_byte(offset_number, mask);
}
這段routine固定寫PCI的Bus0,Device0,Function0,offset 值放在cx中,由調(diào)用者傳來,置什么值放在al寄存器,這是1個(gè)字節(jié)的值。
Bus0,Dev0,Fun0是hostbrige控制器(NorthBridge),也即是DRAM控制器的地址所在。這段代碼是典型的寫PCI設(shè)置的手法。PCI設(shè)置地址送入config_address_register中,然后往config_data_register里寫數(shù)據(jù),這個(gè)PCI設(shè)備地址將映射到PCI設(shè)備的寄存器,如前面介紹的地址空間圖所示,PCI設(shè)備地址范圍是E000_0000 ~ EFFF_FFFF,這段空間提交到相應(yīng)的PCI設(shè)備。
2、現(xiàn)在回過頭來看調(diào)用者,cx=95,al=33 這個(gè)參數(shù)傳給 write_pci_byte。Offset是95,mask碼是33。Offset 95在write_pci_byte將被置為94,這將是DRAM控制器的PAM4寄存器,PAM4寄存器控制D_8000 ~ D_FFFF內(nèi)存空間的屬性。寫入33,結(jié)果是:將這段空間置為read/write屬性,這將是所有訪問這段空間的操作會(huì)提交到DRAM。而不再是ROM。
3、Offset 96的結(jié)果和offset 95一樣,在write_pci_byte的掩碼中被置為offset 94。
|
|