[轉] 【我所認知的BIOS】—>PCI SCAN

出處:http://blog.csdn.net/lightseed/article/details/4219244

1、PCI梗概

Study到現在已經快一年了,目前我自己理解,覺得PCI device在整個計算機的應用中是很重要,及其重要的一個東東。整由於它重要,所以可能一節我還講不完,分幾次把我所理解的PCI相關東東都總結一下。PCI是外設元件互連標準(Peripheral Component Interconnect)那麼我們平時說的PCI device就是符合這個標準的設備。(^.^廢話)這個標準由英代爾Intel)公司1991年推出的用於定義局部匯流排的標準。此標準允許在電腦內安裝多達10個遵從PCI標準的擴展卡。最早提出的PCI匯流排工作在33MHz頻率之下,傳輸帶寬達到133MB/s(33MHz * 32bit/s),基本上滿足了當時處理器的發展需要。隨著對更高性能的要求,1993年又提出了64bit的PCI匯流排,後來又提出把PCI 匯流排的頻率提升到66MHz。目前廣泛採用的是32-bit、33MHz的PCI 匯流排,64bit的PCI插槽更多是應用於伺服器產品。從結構上看,PCI是在CPU和原來的系統匯流排之間插入的一級匯流排,具體由一個橋接電路實現對這一層的管理,並實現上下之間的介面以協調資料的傳送。

2、現實中的PCI

平時我們說XX買了一個不錯的PCI顯卡,YY買了一個PCI to USB的適配器,那麼它們都爲什麽會有個PCI三個字呢?是因為他們都是插在PCI插槽上,普通主板上的PCI插槽如圖1.1
圖1.1 普通的PCI插槽

3、PCI設備要運作,我們應該怎麼做?

PCI設備要運作,那麼就需要PCI SCAN。
******************引用 start**********************
[Why need PCI SCAN]現在的computer system泰半由許多PCI devices所組成,因此,BIOS POST中另一個重要的 task is : PCI_SCAN !!!它代表的是: BIOS會掃瞄 whole system,找出所有的PCI devices; initial them and build a linked list of PCI devices.在此list中的每一個node都代表一個PCI device,且含有其 characteristics !

Ex. Vendor ID,Device ID, PFA,Option ROM exist or NOT,…etc.一旦建好此表,以後的 tasks 隨時都可以參考 !!!所以, after PCI_SCAN,有兩件事完成了:
1. PCI device initialization;device config registers(Part A) are correctly set …
2. One data structure is built to describe the PCI devices in whole system(建在memory中)這也是屬於kernel code part ^_^ ( system 一般很少 hang at this stage…)

******************引用 end***********************
以上引用自<小華的部落格>
到這裡可能多半的人都會想到那麼怎麼去scan這些PCI device呢?

4、PCI device scan

4.1PCI設備的configuration space是什麽

顧名思義,PCI設備的configuration space是用來配置PCI device的。我們平時在BIOS修改的某些寄存器就是修改這個裏面的東東。這個space是嚴格按照PCI spec來做的,查看詳細的說,請參見PCI spec2.3的chapter 6 page 195。圖4.1是配置空間的位置說明,截于PCI spec。
 
圖4.1 PCI配置空間的map

4.2怎麼判斷PCI device存在

掃描PCI device一般都是這樣,讀取PCI設備的configuration space中vendor ID 和device ID,判斷他們是否為0xFFFF。若是,則說明該PCI device是不存在的。(因為每個PCI device的製造商都會把他們的ID填入這個位置,而且是read only的。)

4.3怎麼訪問PCI設備的configuration space

用CF8和CFC兩個端口來訪問,爲了能夠不失真我引用了spec里的原文來說明。“Two DWORD I/O locations are used to generate configuration transactions for PC-ATcompatible systems. The first DWORD location (CF8h) references a read/write registerthat is named CONFIG_ADDRESS. The second DWORD address (CFCh) references a read/write register named CONFIG_DATA”從CONFIG_ADDRESS和 CONFIG_DATA其實就很容易看出了,當我們向CF8端口(CONFIG_ADDRESS)寫入規定的格式地址時,便可以從CFC端口(CONFIG_DATA)讀回相應的數據。

4.4 PCI scan的技巧

這裡兩個小技巧:
①    在讀回的端口,你可以取其中的任何一個byte或者word甚至整個double word
②    爲了提高掃描的效率,其實可以先查看header type這個寄存器中的bit7。Bit7的0與1表示該PCI設備是否是single function的,若single function device那麼這個時候就可以直接scan下一個PCI 設備啦。

4.5 訪問舉例

圖4.1是向CF8端口寫入的地址格式,截圖于spec page 32
圖4.1
以下是一段訪問配置空間的code。
mov eax, 80020500h    ;bus 2, device 0, function 5(这里原本我写错了,是网友goldencrest帮我纠正了过来,谢谢!)
mov dx, 0cf8h
out dx, eax
mov dx, 0cfch
in eax, dx
以此類推,變可以把PCI device的整個configuration space都讀取出來。效果圖見圖4.2
圖4.2 用ADU顯示出來的PCI configuration space數據截圖
以上是我對PCI scan的理解。不足之處還望各位指正。

=====================================================================

[我所知道的BIOS]->[PCI SCAN] 9

這次要提的是: PCI ! 


[About PCI device]
1. 每一個PCI device都有其 unique PFA(PCI Function Address). PFA由 bus number,device number & function number所組成.


Ex. USB device PFA is (0,6,0) <- USB is a PCI device and its bus/dev/function is 0/6/0




2. 有了PFA,就可以存取其 PCI configuration registers.


Ex. write USB PCI register 43h bit1 = 1
=>
mov eax, 80003040h
mov dx, 0cf8h
out dx, eax


mov dx, 0cffh
in al, dx
or al, 00000010b
out dx, al


* IO port 0cf8/0cfc 為 PCI config address port & data port,意即:將 address(80003040h)送到config port(0cf8h),然後從 data port(0cfch + 3)來存取 data(al)


* 注意: 32-bit address(80003040h) 中 bit[1:0] = 00b(固定的),所以雖然存取的是 43h,但還是寫成40h ! 而要存取到 43h,則從 0cfch+3來達成 (因為: 0cfch<-> 40h,0cfdh<->41h,0cfeh<->42h, 0cffh<->43h) 


3. 基本的PCI device的 config registers可分成 2 parts:


A. header region(offset 00h~3Fh)
B. device specific region(40h~FFh)


在BIOS’s PCI_SCAN stage中,會touch到 part A. Ex. command byte, BARs, Interrupt line, latency timer,…etc. 而Part B是製作 or design這個device的廠商所附加的 function/feature.


4. 每個PCI device都可以 request 之前所提的 4 resources:
A. memory resource:透過 Base Address Register(BAR)
B. IO resource:透過 Base Address Register(BAR)
C. Interrupt: 透過 interrupt pin
D. DMA: 這需要 device本身即具有 bus master function(status byte會indicate)




[Why need PCI SCAN]
現在的computer system泰半由許多PCI devices所組成,因此,BIOS POST中另一個重要的 task is : PCI_SCAN !!! 


它代表的是: BIOS會掃瞄 whole system,找出所有的PCI devices; initial them and build a linked list of PCI devices.在此list中的每一個node都代表一個PCI device,且含有其 characteristics ! 


Ex. Vendor ID,Device ID, PFA,Option ROM exist or NOT,…etc. 


一旦建好此表,以後的 tasks 隨時都可以參考 !!! 


所以, after PCI_SCAN,有兩件事完成了:
1. PCI device initialization;device config registers(Part A) are correctly set …
2. One data structure is built to describe the PCI devices in whole system(建在memory中) 


這也是屬於kernel code part ^_^ ( system 一般很少 hang at this stage…)





符合PCI spec的device即稱為……..PCI device ^_^

[補充] PCIe device

PCIe device => 符合PCIe spec的device(…廢話…)

對軟體而言,它仍是PCI device. 因此,基本的 header region and device specific region也有. 不過,PCIe新定義了 extended config space,即 offset 100h(含)以上,直到 FFFh( 所以, 最大可以至 4096 bytes )

存取 PCI config space的方式,用原來 0cf8/0cfc的方式依然可行,但只能 access offset 00h~FFh. 要 access 100h(含)以上的 extended config space,則必須用 memory transaction的方式 !

Ex. mov ax, [50400000h] <- read device (4,0,0)’s register 0;2 bytes

here 50000000h: PCIe extended base address. 可以從 chipset register得知
bit[27:20]: Bus information
[19:15]: Device information
[14:12]: Function information
[11: 8]: Extended Register
[7:2]: DW number
[1:0]: Byte enable

因此,只要知道 PCIe extended base address,就可以像以前一樣,可以任意存取 PCIe config registers, even > 0FFh !

除此之外, PCIe device可以由其 Capability pointer(points to a linked list of capabilities)辨認出來. 因為,在眾多的 capabilities中,會有一個 PCIe capability;其 ID value = 10h.

Note: PCIe extended base address 要 reserve and report to OS. Size is 256MByte. 這是BIOS需要做的. (當然,BIOS也要將此 base address寫入 chipset register,讓 chipset 知道:有這樣的 cycle時,是給PCIe device的 ! )

[補充] For P2P bridge

P2P bridge = PCI-to-PCI bridge. 其存在可以 introduce 另一 new PCI bus,可以容納更多的 PCI device.

P2P bridge亦有其 PCI config space,但是 lauout 與 PCI device有點不同,大家可以參閱P2P spec並與PCI device’s config space比較一下.

在 P2P config space中,我常遇到的 issue是和下列 register有關的:
– Primary bus register: offset 18h
– Secondary bus register: offset 19h
– Subordinate bus register: offset 1Ah

—————————————-
Notes:
這三個 registers是BIOS在 PCI_SCAN時會決定的;所代表的意義是:這個 P2P bridge的上面 PCI bus number is ? 下面的PCI bus number is ? 及包含此 P2P bridge的 “branch” 最深的 PCI bus number is ?

Ex. 18/19/1Ah of one P2P bridge is 0/2/3
=> 此 P2P bridge 是 “bridge” PCI bus 0 and 2的(橋接在 PCI bus 0 and 2之間);而包含此P2P bridge的 PCI branch(想像成 tree structure) 最大(深)的PCI bus number is 3
—————————————-

– memory base/limit
– IO base/limit

—————————————-
Notes:
這兩個是 BIOS 在 PCI_SCAN時所 assign的. 所代表的是: resource “window” for devices behind this bridge.意即:若P2P bridge下面(就上例言:是 Bus 2上)有 PCI devices,則他們的 BARs 必須被包含在此 window 之內 !!!
—————————————-

[Practice]
[Q]假設有一個 P2P bridge ,下面有一PCI device;現在必須要去 accessPCI device’s Device ID/Vendor ID(that is, PCI config read). 但是,問題是:做這事的”點”要在 PCI_SCAN之”前”….那要如何做到呢 ^_^ ?

Ans:假如要在很早前(Ex. PCI SCAN之前)去 access P2P bridge後面的 device,照理是做不到的,因為: P2P bridge沒有被正確的 configed…

在此例中,P2P bridge的 primary/secondary/subordinate bus要被 set,後面的device才能被 accessed到 !

所以,假如要在 PCI SCAN前就 access,則BIOS必須手動去 set 此 3 bytes;然後,PCI config access才能被 forward to 其後的 PCI devices…

[Q] 如何 disable memory or IO resource window ?
Ans: 只要將 base設成比 limit “大” 即可 !!!

—————
– 相關討論 Part1 –
—————

前輩已經提到P2P Bridge我就直接問我的問題了

[Q1] Bridge 是用來擴充PCI Bus,在PCI Bus Spec與PCI-PCI Bridge Spec中定義,PCI Device是透過IDSEL來決定他的身分,其中PCI Bus Spec定義AD[31:11],而PCI Bridge Spec定義AD[31:16] 當做IDSEL,這中間差異為何? 為什麼一個要從Bit 11開始當作是Dev 0 ,而另一個由Bit 16 才當作是 Dev 0 ?

Ans: 1. IDSEL對PCI device而言是 input,是用來當作 device’s “chip-select”訊號. 而且,IDSEL “如何連接” 是 H/W決定的,BIOS無法決定.

假如將板子上某個device’s IDSEL “割斷”,則此 device將無法接受 PCI configuration read/write(以 ru.exe來說,就是按F6後,是看不到它的…)

那要如何決定 device’s IDSEL ? 一般而言, board designer會將 “unused AD lines”拿來做 IDSEL,以連接至 PCI device.

在 configuration access時,所下的 Ex. “o cf8 80001020″(看起來是 I/O transaction)會被 host bridge轉成 configuration transaction;此時, host bridge即可判斷此 transaction 要 access的 device是否在該 PCI bus上;if YES 轉成 Type 0 transaction;If NO 轉成 Type 1 transaction,並往下發送…(host bridge只要 check latched “bus information”即可完成此判斷 !)

以 Type 0言,AD bus上的 format as follows:
bit[1:0] = 00 ( indicates “Type 0” )
bit[7:2] indicates register number
bit[10:8] indicates function number

那 Bus number ? Device number ?
=> Bus number不必知道 ! 因為:Type 0產生即代表 bus number = 現在的 bus #
=> Device number呢 ? 因為,此時(Config transaction && address phase) AD bus bit[31:11]沒人用 !!! 因此, board designer會把此 21 bits拿來做 IDSEL用 !

因此, AD bus bit11 <-> device 0
12 <-> device 1
…….

當然,不可能 21 bits都拿來接 PCI devices;因為電路上的現實考量…

……………..以上為:我所知為何從 bit11開始來當作 IDSEL…………….

以 Type 1言,PCI-PCI bridge收到後,會將其 bus information與自己的 secondary bus number比較;若是 addressed device是在 secondary bus上,則將 Type 1 -> Type 0;若否,繼續包成Type 1往下一層送…

在P2P spec v1.1 page 22 有一張表,說明 IDSEL generation(from primary address -> secondary address),其中有提到: if primary address bit[15:11] =0,則 secondary address AD [31:16] = 0000 0000 0000 0001;以此類推.

所以,我覺得為什麼 for P2P bridge 其 IDSEL可由 bit[31:16] 來決定的原因在此 !!!(表的關係…)

……………..以上為:我推論為何從 bit16開始來當作 IDSEL…………….
[補充]
PCI config index register裡面的資料其實和硬體解出configuration cycle是相關的.
一.轉換出來是type 0 cycle的話. 硬體只要做以下兩件事.
1. mask 掉bus number(bit 16 ~ 31)以上的部份.
2.解碼 device number的部份即可到對應的 AD bit. 所以其最低可以使用的就是AD11.也就是說一個bus上最多只能有 21個 devices(只是由於推動力問題, 往往是做不到的).
Note:其實也可以設計成其他大於AD 11開始, 這要看chip設計者決定了.
二. 轉換出來是type 1 cycle的話. 只要做
1. mask 掉reserved以上的部份(bit 24 ~31)
2. bit 0 = 1
由於P2P跟其他device不同的地方就是, 除了type 0 clcye以外, 還必須處理 type 1 cycle. 這也是分成兩部份
一. type 1 -> type 0. 當 bus number 等於 secondary bus number 時候出現.
1. 解碼 device number 到對應的 AD. spec中有提到轉換的表. dev 0 = AD16….etc
2. 把 bit 0 由1 變成 0
二. type 1-> type 1. 當 bus number 介於 secondary bus number和 subordinate bus number
1. 直接往下一層送即可.交給其他的P2P 處理.

[Q2] 在IA32下,CONFIG_ADDRESS 會被轉成Configuration Cycles,當Bus Number <>0 時,NB會轉成Type 1 然後往 DMI送到SB,當P2P Bridge收到後,然後定址到Slot上面的PCI Device,這樣說法對嗎?

Ans: 總而言之, 是自己local bus上的,就會轉成 Type 0,然後打在AD bus上,等待認領;若否就轉成 Type 1,往下一個bridge送,繼續尋找…對的人…for each bridge,都是一樣…
[補充]
對 PCI spec是, 如果以Intel PCI express架構來說. 那個已經被封裝成 pci express的 package了.沒有所謂的 type 0, type 1 cycle了.

[Q3]PCI Device透過IDSEL來決定身分,那PCIE Device呢? 我查過資料,好像PCIE不需要IDSEL那他是如何決定Device Number ?

Ans: 我所遇的 PCIe device也是由 AD bit[31:11]中找線拉至 device’s IDSEL決定的.不知其他家 chipset是如何 implement.
[補充]
PCI express 是internal routing. PCI express是個跟PCI 完全不同的架構. 只是為了軟體相容性的關係, 把software架構做的跟PCI bus一樣. PCI express是point-to-point架構, 一個link 只會連接一個device. 跟PCI 這種可以多個device在同一bus上是不一樣的. 所以 device number對PCI express是完全不重要的.
Note. AMD的Hyper transport 也是基於一樣的心態來設計軟體架構的.

※ PCIe 的device是 internal routing. 以規格來看,下一層的 device number都是為0.

——————
– 相關討論 Part 2 –
——————

DMI指的是 Intel 南北橋中間的通道 ! 之前也是不知P2P bridge部份關於IDSEL的配置,查了表才知道原來有這樣的 mapping(primary address<->secondary address). 其實,可以說 “unused AD bus 會被拿來當 IDSEL用”就是了吧 ^_^
[補充]
是的, 只要軟體能夠知道routing 關係.怎麼接都可以. 只要bus controller控好實際的IDSEL即可. P2P之所以會有嚴格規定(兩項, 1. IDSEL&device number表, 2. secondary bus IRQ routing)是因為P2P 不一定是在板子上. 包含卡都可以有P2P bridge. 在板子上的P2P 可以靠BIOS來建立正確的 routing, 但是插卡不行. 所以必須把這些定義好. 這樣 PnP software(BIOS or OS)才能正確的完成IRQ 分配.讓卡正常工作. 所以如果觀察某些板廠. 就算是真的p2p 沒有存在在板子上, 很多PCI slot的IRQ routing都是依據p2p spec裡面的規定做(因為SB的PCI bus還是落在P2P之後).

在 PCI scan時,BIOS會掃描整個系統的PCI architecture(包含 device & bridge);其掃描方式由BIOS’s PCI kernel來決定 !
[補充]
其實了解PCI spec. 要寫PCI scan其實可以效率好又正確. 常見的新進工程師寫法大概就是 3個 loop來處理. bus:0~255, device:0~31, function:0~7. 掃個 256*32*8次, 反正都是程式做, 結果往往也看來正確.這種寫法其實是不對的. (其實,若是多了解硬體的架構,就可以寫出有效率的code了 ! 這也是F/W工程師的價值…)

Ex. Assume 系統架構是這樣的: NB,P2Px3, PCIe bridge x2;其中:
A. 3 P2Ps的配置 is: P2P0下面接P2P1;P2P下面接P2P2
B. PCIe x 2 & P2P0都在 bus 0;其PFA為
NB(0,0,0)
P2P0(0,1,0)
PCIE0(0,4,0)
PCIE1(0,5,0)

=> 最後的 PCI achitecture is:

Bus 0———————-
NB(0,0,0),P2P0(0,1,0),PCIE0(0,5,0),PCIE1(0,6,0)

*下面 Bus 1/2/3由 P2P0/1/2所 introduce:
Bus 1———————-
P2P1(1,0,0)
Bus 2———————-
P2P2(2,0,0)
Bus 3———————-

*下面 Bus 4由 PCIE0所 introduce:
Bus 4———————-

*下面 Bus 5由 PCIE1所 introduce:
Bus 5———————-

所以,Bus number 是由BIOS’s scanning “algorithm”所決定的;假如採用 depth-first,則會產生上述的結果 ! 決定後的值會填到 bridge的 Primary/secondary/subordinate bus number registers !

[Q]順便問個問題好了. 其實function number不應該是永遠需要scan的, 為什麼?什麼時候才需要scan function number?
Ans: 我想,對於 function number的問題,應該是: PCI header region offset 0Eh bit7代表: milti-function or NOT ! 因此,可以先 check此bit,再決定要不要往下掃了…這樣又少做了許多虛工…^_^

Ex. PFA (0,3,0) 有回應(that is, Vendor ID/Device ID != 0xFFFFFFFF),則先check (0,3,0)’s PCI Reg0Eh bit7; if “1” then 此device為 multi-function device,還要再往下找 Ex. (0,3,1~7) 有無回應;if “0” then try next device number…!

[補充,加快速的的方式]
檢查multi function bit是正確的, 但是不只是因為效率問題. 而是PCI 規格中, single function裝置可以不解碼 config cycle type 0 bit[8~10], 也就是說 一個 single function裝置, 會對 所有的function number回應, 也就是會出現 8 個相同的device.

順便說一下我的scan加速法. 其實我不是使用 vandor ID & device ID來判斷裝置存在與否. 我是用 class/subclass/interfae ID來作判斷. default 只scan bus 0, 遇到 P2P bridge才會把taget bus number+1, 如果遇到multi host(host bridge 數量> 1)的板子才會完整掃描 255個 bus. ^_^

———————————————————————————
———————————————————————————
———————————————————————————

~轉貼自艾克索夫實驗室~
Rootkit in PCI Option ROM

「Rootkit」一字來自 UNIX 界;但目前通常用於描述 Windows 木馬程式作者所運用的隱形技術。
起初,Rootkit指的是一組程式,可讓駭客躲過偵測。 為達成此目的,可執行的系統檔案 (如 login、ps、ls、netstat 等) 或系統程式庫 (libproc.a) 會遭到更換,或安裝核心模組。 這兩種動作只有一個相同目的;防止使用者收到正確資訊,知道電腦上發生了什麼事。

首先介紹PCI的基本常識, PCI Bus是在約1990年由Intel發展出來, 用來連接主機板上的各項裝置的匯流排標準, 後來成為業界的標準之一, Spec可以在PCI-SIG註冊會員之後下載, 架構上簡單的說, 就是一個Host bridge, 在一般的PC上通常指的就是North Brdige, 這個brdige後面就是bus#0(當然也有Multi Host-Bridge的狀況, 這邊舉例的是最單純的情況), 然後接到South Bridge, South Bridge之後可能接的是ISA Bus, IDE Controller, USB, IDE, DMA Controller等等, 如果bus#0上還有別的PCI Bridge, 這個Bridge後面就是bus#1, 如果有多個Bridge存在(PCI最多可以有256個bus), bus#就不一定是固定的了, 一個PCI Bus上可以有32個device, 每個device可以有8個function, 每個function都有屬於自己的256個register. 在PCI的規範裡, 256個register中的前0×40個是公定的功能, 從0×40到0xff則由各家廠商自行實作, 存取這些register的方法, 一般的PC上是透過IO port 0xCF8~0xCFF, 如果是新的PCI-Express則是直接透過Memory Mapped IO, 以存取記憶體的方式直接進行存取, 例如我們想要讀取一個在bus#0 dev#1 func#0的register#40~43, 透過IO的方式如下:

mov eax, (0x01 << 31 ) // Type-1 PCI Configuration
+ (0x00 << 16 ) // Bus#0
+ (0x01 << 11 ) // Device#1
+ (0x00 << 8 ) // Function#0
+ 0x40 // Register#40
mov dx, 0xCF8 // Index Port 0xCF8 ~ 0xCFB
out dx, eax
mov dx, 0xCFC // Data Port 0xCFC ~ 0xCFF
in eax, dx // Get Data in EAX

如果是透過MMIO的方式則簡單多了:

mov esi, (MMIO_BASE) + (0x00 << 20) + (0x01 << 15) + (0x00 << 12) + 0x40
mov eax, [esi]

今天我們比較有興趣的是位在0×30~0×33的register, 在PCI Spec定義中, 這裡的值存放的就是expansion rom在physical memory中被decode到IO的位址, 比如說這個位址是0xFE000000, 如果你在0×30把bit0設為0×1(io->mem decode), Command Register(0×04~0×05)的Memory Space Bit打開, 在0xFE000000的地方你就可以找到這個rom, 開頭是0×55AA(這當然也是規範之一, 用來辨視是否為一個PCI rom), BIOS在POST過程中, 會逐一掃描位於主機板上所有的PCI Device, 假如device上有rom, 就會把它給拷貝到memory中, 然後用jmp指令跳到ROM開頭offset 0×02(別忘了開頭offset 0×00是0×55AA)的地方開始執行PCI ROM, 執行完後ROM會再把控制權交回到BIOS手上, 一般而言, 在傳統記體空間中, 0xC0000~0xCFFFF是給VGA ROM用的, 0xD0000~0xEFFFF則是留給一般的PCI ROM使用, 當然各種情況下還是會有些許差異, 例如有些BIOS會保留0xE0000~0xFFFFF給自己使用, 像是BIOS的interrupt service, DMI data….等等雜七雜八的東西, 執行完的ROM仍然會保留在記憶體中, 因為有些ROM會修改IVT(Interrupt Vector Table), 將某些interrupt service導向自己的code, 像是VGA ROM可能就會hook int 0×10, 這是很合理的, 因為int 0×10是BIOS所提供用來控制螢幕的service, 聰明的你看到這裡應該就知道前面所提的那篇文章想說什麼了, 如果有個”惡意”的程式被埋在PCI ROM裡面, 只要一開機就會自動被執行, 它的運作並不是一時的, 它可以hook某個OS一定會用到的BIOS Interrupt Service, 然後在這個interrupt service被呼叫的時候動作就可以了, 而且麻煩的是即使你format你的HDD也沒用, 除非你把有問題的PCI Device從你的主機板上移除, 嗯….聽起來蠻炫的, 但是, 有可能嗎?

要回答這個問題之前, 需要知道一些基本的常識, 在保護模式下, 因為IO動作受到限制的關係, 要存取IO並不像在DOS那樣容易, 但如果想嘗試Re-flash一顆PCI ROM, 勢必得進行IO動作, 所幸在Windows下這並不是不可能的事, 有些人可能知道利用SeTcbPrivilege和使用ProcessUserModeIOPL structure呼叫undocumented Native API NtSetInformationProcess()就可以達成目的. 一旦攻擊者有辦法修改PCI ROM, 他就可以利用文章中所提到的例子: int 0×10(Windows在開機過程中會透過Ke386CallBios()呼叫int x010), 作他想作的任何事了.

可惜不論哪種攻擊方式, 最終都是要對OS kernel動手腳, 利用各種偵測工具(如: Archon Scanner), 一定可以找到有問題的地方, 如果最後的箭頭指向PCI ROM, 我們可以透過上文所述, 將存在PCI Device和memory中的ROM給dump出來, 需要dump兩邊的rom, 是因為PCI Spec規範中允許實際上所需要配置的記憶體不一定要等於原本rom的大小, 藉以節省保貴的記憶體(別忘了PCI ROM只能被配置到幾個64KB的segment裡而已), 然後向PCI Device的製造商索取正常版本的rom進行比對, 藉以得知是否為被修改的版本. 假如發現有不一樣的地方, 接下來可以朝幾個方向繼續分析是否為有問題的ROM, 我們可以檢查一下它是否修改了不必要的IVT, 像PXE ROM就不太可能hook int 0×10, 或是有保護模式相關的程式碼, 因為一般的ROM應該都是在real mode下執行, 所以應該不會切到protected mode, 如果有相關的程式碼那就非常可疑, 還有rom裡面是否有可疑的字串, 或是位在Windows Kernel位址空間裡的32-bit address, 另外ROM裡面也不太可能出現編碼過的code, 如果rom裡的code很難被disassemble, 或是充滿了一堆obfuscated code, 那也是很有問題.

除了軟體的方式, 最近興起的新技術TPM也能克制這種攻擊手法

未經允許不得轉載:GoMCU » [轉] 【我所認知的BIOS】—>PCI SCAN