其實我自己著重的部分是在PI, 但是顧及全面性,

且PI確實也涉及到一些UEFI Concepts, 故還是把這一部分也寫出來.

 

不過在參考資料的過程中, 看到某一文章的回應內容 ( http://stenlyho.blogspot.tw/2008/10/efi.html   )

懷疑EFI替換的必要性, 看起來也是有它的道理在.

 

 

總之, 我還是繼續了解一下UEFI這東西 (不過 凡事都要帶些懷疑 ?)

 --------------------------------------------------------------------------------

在UEFI Driver Writer Guide中 的第三章Foundation裡首先提到UEFI 所引進的主要概念.

在這pdf檔裡接著會介紹的基本概念如下:

  1. Basic programming model
  2. Objects managed by UEFI-conformant firmware
  3. UEFI system table
  4. Handle database
  5. Protocols
  6. UEFI images
  7. Events
  8. Task priority levels
  9. Device paths
  10. UEFI driver binding model
  11. Platform initialization
  12. Boot manager and console management
  13. EDK II libraries.

參考另一份pdf檔 - Beyond BIOS中則只提到6種, 即上述標色的幾項(其中database & Protocol是放在同一標題中)

 

畢竟這份DWG是根據寫driver的角度而說明, 故這邊就從標色的六項做了解.

 

 

1. Objects managed by UEFI-conformant firmware

UEFI內的objects, 則透過UEFI提供的services來做管理

這邊提到的objects有很多種types

  UEFI objects

最重要的是前面五項, 而至於後者, EV大多driver不會去做存取, 最後三個更是鮮少用到.

 

 

2. UEFI system table

在UEFI中最重要的資料結構, 

一個UEFI executable image(如UEFI driver)透過這個table可存取系統上的設定資訊, 以及所有services的存取

也提供額外資料結構的存取(如紀錄系統資訊的SMBIOS table, etc)

這邊提到的UEFI services則分成三種,      //services之後會再補充說明

UEFI boot services

UEFI runtime services

從Protocols中提供的services

前兩者提到的services, 則透過各自的table來存取, 即

UEFI boot services透過UEFI boot services table

UEFI runtime services透過UEFI runtime services table     ←感覺有寫等於沒寫, 增加行數用的嗎 

在每一版UEFI Spec中, 這兩個table所提供的services的數量跟種類都是固定的.

 

至於Protocol services則是相關functions與資料欄位組成的群組, 並由GUID命名      //3. Handle database & Protocols會說明.

用來作為與裝置如consoles, mass storage devices, networks的連結, 才能進一步做使用與操作

(這邊英文寫provide software abstractions for devices such as consoles...., 在這邊我想翻成自己理解的意思會比較好)

透過Protocol services可延伸更多常用services來做使用.

 

Protocols做為基礎的building blocks, 也是為什麼UEFI能在之後依然有"延伸"功能的原因

UEFI Spec定義超過30種不同的protocols及應用. 而UEFI driver也能產生額外的protocols來延伸功能

 

//後續回頭再補充UEFI system table

 

 

3. Handle database and protocols

會把protocols也歸在這邊的原因是Handle database是由handles跟protocols這兩個物件所組成的.

而Handles則是一個或多個protocols的集合

這邊再一次提到Protocols由GUID命名, 這個資料結構可含有資料欄位, services, 或同時都有, 或其實都沒有(//即tag GUID, 後續提到)

 

在系統reset的時候, database是空的,

而在PI階段時, system firmware, drivers, UEFI applications會建立handles, 並在handles上附上一個或多個protocols

對於任何一個executable UEFI image, 在database裡的資訊是屬於全域性(global)且可存取.

 

每一個擁有獨特handle number的Handle都由system firmware作維護.

handle type由附在其身上的protocol type來決定.

所以一個UEFI handle可代表以下元件:

  • 如UEFI drivers, UEFI applications的executable images.
  • 如network controllers(網卡), hard drive partitions(磁碟分割)的裝置
  • 如EFI Decompress, EBC Interpreter這類由drivers存取的UEFI services

Handle database  

(Screenshoted from UEFI Driver Writer Guide V1.0.0 p.19)

圖所呈現的是database的一部分, 除了handles跟protocols之外, 每一個protocols也都有objects lists關聯著

database利用這個list來追蹤那些agents使用那些protocols

這個database所提供的資訊對於UEFI drivers的運作非常重要, 之所以不會有資源衝突來作讀取 啟動 停止 卸載都是這個原因

 

#實作Time

在Shell底下相關指令 - devices, devtree, dh, drivers

devices是顯示由UEFI drivers管理的裝置清單.

devtree官方簡介(就是輸入help devtree指令後...)是說顯示UEFI Driver Model相容裝置樹狀圖, 其實就是樹狀圖拉

dh直接執行則是看所有handle清單及其連結object, 或也可指定特定handle看單一資訊, 或指定protocol id, 即GUID來找有哪些handles關聯著(只是會打GUID打到很煩吧)

drivers則是顯示UEFI driver清單

主要我們執行devices跟drivers這兩個指令可以知道,

所有資訊都是透過第一行欄位作升冪排序, 也就是Handle numbers

如上面提到的handle所代表的元件種類, 其中就是drivers / devices

 

回來. 在一個系統裡, 只會有一個Handle database.

前面我們提到handle可能代表的元件, 這邊, 換提到就handle本身而言, 有哪些種類.

Handle types  

(Screenshoted from UEFI Driver Writer Guide V1.0.0 p.20)

 

圖表顯示handle種類, 以及之間的關聯, 其中各types的敘述如下  //其實只是再細部解釋, 對於整體了解沒有太大幫助

Image handle - 讀進memory裡的UEFI Driver image的handle. 支援Loaded Image Protocol

Driver hanlde - 支援所有protocols.最常見的是Driver Binding Protocol, 以及兩個Component Name Protcols跟兩個Driver Diagnostics Protocols

Driver image handle - 擁有兩種屬性的handle

Agent handle - 有些在UEFI Spec裡的UEFI driver model-related services則使用這個詞.

Agent代表的是一個UEFI元件, 可使用在database裡的protocol.

是故能代表上述三項handle.

Controller handle - 代表的是平台裡存在的console或是boot device.

如果代表的是實體裝置, 則必須支援Device Path Protocol.

此外device handle也必須支援一個或多個I/O protocols來用來存取使用其裝置.

(原先table裡有描述那些Protocols分別提供那些services, 這邊就不打上來了)

Device handle - 等同Controller handle的意思

Bus controller handle - 由一bus driver或一hybrid driver(產生child handles)管理的一個Contoroller handle

這邊提到的bus並不是所謂硬體觀點的bus, 在DWG這份文件所提到的是以軟體觀點來看

產生一個child handle, 是唯一區分controller handle跟bus controller handle的方法.

Child handle - 這是一個由bus driver或hybrid driver所產生的controller handle.

區分child handle跟controller handle的方式是看哪個driver在使用.

以bus driver的觀點來看, 這個handle就會是child handle; 同一個handle

以device driver的觀點來看就會是controller handle

//老實說 這算滿容易搞混, 總之還算有意義吸收的東西就是 -

  跟bus controller handle或 child handle會有關聯的就是因為bus/hybrid driver這個主謀

Physical controller handle - 代表一個實體裝置的controller handle, 必須支援Device Path Protocol

Virtual controller handle - 代表一個虛擬裝置的controller handle, 且不支援Device Path Protocol

Service handle - 與特定tasks相關的handle, 像是decompression 或是HII forms display.

可與其他drivers連接, 但並不連接任何硬體或檔案管理.

這類handle並不使用在Loaded Image Protocol, Driver Binding Protocol, Device Path Protocol

而是用在database裡的特定protocol, 其提供的services可被其他UEFI applications或UEFI drivers所使用.

這個service protocols清單定義如下

HII functionality,

Platform Driver Override Protocol

Unicode Collation Protocol

Boot Integrity Services Protocol

Debug Support Protocol

Debug Support Protocols

Decompress Protocol (optional) - 提供開發者更多彈性, EDK II提供幾個演算法

EFI Byte Code (EBC) Protocol

//也就是說這類handle只提供特定services, 並不代表實體的images或devices等

 

 3-1. GUID

透過UEFI Boot Services Table, UEFI Runtime Services Table, 以及裝在handle database裡的Protocols

UEFI環境得以藉此提供software services. 其中Protocols是主要UEFI Spec之所以能有延伸機制的原因.

而Protocols由GUID命名.

 

GUID是一個128-bit, 二進位的globally unique identifier(照翻就是..全域唯一識別元...有時意會就好, 翻了反而不對勁)

(UUID = universally unigue identifier, 通用唯一識別碼, 一種標準, GUID即為UUID的實作)

通常會表示成32個16進位的字串, 如下:

aabbccdd-eeff-gghh-iijj-kkllmmnnoopp

照UEFI Spec附錄說明, 前面4 bytes就是TimeLow的部分 (The low field of the timestamp), 其餘,

eeff - TimeMid

gghh - TimeHighAndVersion (除了TimeHigh還有版本編號)

ii - ClockSeqHighAndReserved (The high field of the clock sequence以及variant)

jj - ClcokSeqLow

kkllmmnnoopp - Node (The spatially unique node identifier - 照翻:空間唯一節點識別...

GUID應用的範圍很廣, Windows OS裡的COM物件的類別和介面, GPT格式, 等等

在這裡則是作為Protocol的命名.

第三組數位gghh裡的高位gg, 代表的是其GUID演算法版本.

早期會使用網卡MAC來計算GUID最後一組數位, 故存在隱私問題, 只要透過GUID便能追溯到當初建立此檔案的電腦.

隨機GUID(或UUID)的重複機率很低, 詳請請見wiki - UUID

 

 3-2. Protocols

在這篇文章中上面也提了兩次以上了, 所謂U"E"FI是因為Protocol的關係,

Protocols可作為個別模組間的溝通管道, 像是drivers.

 

模組(ex, Drivers)建立protocols時分成兩個部分, 其主體是一個C-style的資料結構稱作protocol interface instructure,

或直接稱作interface, 裡面包含相關的function pointers以及資料結構.

另一個就是GUID, 並不在上述的interface裡.

 

Protocols被放在一database裡, 而database並非是平面的, 也就是說Protocols之間可以群組化

每一個群組也就是一個handle(所以這個就是handle database)

系統中可以有很多相同的Protocols, 但在單一handle哩, 一定只能有一個

 

Drivers對於Protocols來說同時是使用者也是製造者.

舉例, 一個在PCI bus上的SCSI Host Controller用的UEFI driver,

使用了PCI I/O Protocol, 也產生了SCSI Host Controller Protocols

 

如何產生? 首先其結構必須先從記憶體配置出來(不管是從程式(program)中或是透過記憶體配置運作)

接著Protocol必須被初始化, 也就是把填入內容.

內容是甚麼? 其實就是function pointers, 將其宣告進去.

也就是說產生Protocols的方式

就是宣告它的功能用處並把它發佈到database裡(其他drivers也才因此能找到並使用其宣告)

 

DWG裡提到, 雖然在protocols裡存放資料是可以的, 但非常不建議,

畢竟動態資料本來就會常作變動; 單純提供functions使用會較安全且有延伸性

Protocols的producer則利用InstallMultipleProtocolInterfaces()      //一種Protocol Handler Services

來把protocols安裝進database並提供使用

 

如要使用Protocols則是相對簡單的工作, 利用GUID來在database搜尋protocols

而就service protocols而言, 在database裡只會有一個個體, 故使用者可利用LocateProtocol() 這個service.

如是存在於很多handles裡的protocols則使用LocateHandleBuffer()這個service來找出支援特定protocols的handles

接著在使用OpenProtocol() service來找到特定handle上的protocols

 

還有一種情況, 在producer建立之前就先呼叫protocol, 在這邊

consumer可使用RegisterProtocolNotify() service, 要求傳送通知, 當protocol的new instances建立好時.

 

在boot time(開機過程)期間任何UEFI image可使用protocols

但是一旦ExitBootServices()呼叫過後, database便不可再使用了      //這邊還需要多作了解, DWG的第五章.

 

● Protocol interface structure.

08 Protocol Construction  

看圖說故事, 一個UEFI driver建立了一個handle以及protocol, 其protocol含有interface跟GUID.

UEFI driver本身通常會有額外的private data fields, 但在interface裡只會有個指向其功能的指向器

其功能主要就是放在UEFI driver裡, 根據其driver複雜度, 可能產生一個或多個protocols

 

也有些沒定義在UEFI Spec裡的protocols, 而是在EDK II這類的發展工具中, 在特定實作中可提供其功能.

沒定義在UEFI Spec裡的原因是, 因為就支援開機進入OS或編寫一個UEFI driver過程中,

並不是一個必要的外部介面.      //Beyond BIOS跟DWG各有列出幾個例子

DWG舉例如下:

Print 2 Protocol - MdeModulePkg/Include/Protocol/Print2.h

Deferred Procedure Call Protocol - MdeModulePkg/Include/Protocol/Dpc.h

VGA Mini Port Protocol - IntelFrameworkModulePkg/Include/Protocol/VgaMiniPort.h

UEFI Driver跟UEFI OS Loaders則不該使用到這些protocols.

 

●Multiple protocol instances

前面有稍微提到, 一個handle可以附著多個protocols, 但每種protocols只能有一個個體

避免後續無法判別該使用哪一個個體

至於driver建立多個特定protocol的個體附到不同的handle上

其例子為PCI I/O Protocol, 每一個PCI device, PCI bus driver都會裝上這個protocol

根據其裝置, 各自protocol個體都會設定成各自的資訊, 如OpROM位址, 大小

 

也因此同個protocol可以有不同的版本(在不同handle的前提下)

舉例, 每個UEFI driver產生了Component Name Protcols到其driver image handle上

當裏頭的GetDrvierName()功能呼叫後, 則每個handle回傳各自driver的唯一名稱

USB bus driver handle回傳"USB bus driver", 而PXE driver handle則回傳"PXE base code driver"

 

●Tag GUID

甚麼都沒有只有一個GUID的protocol稱作tag GUID.

也是有其用吐, 像是標記特定device handle為特別用途,

或是讓其他UEFI images更容易找到該device handle.

 

  

-------------------------------------------------------------------------------

好多內容...

 

參考資料來源:

http://sourceforge.net/apps/mediawiki/tianocore/index.php?title=Driver_Developer

(UEFI Driver Writer's Guide(DWG) for UEFI 2.3.1 03/08/2012, Ver 1.0.1)

http://www.uefi.org/ 

(For downloading UEFI Spec 2.4)

 

http://zh.wikipedia.org/wiki/UUID 

http://en.wikipedia.org/wiki/Globally_Unique_Identifier

 

 

 

創作者介紹
創作者 紀錄, 記東記西 的頭像
H.j. Yao

紀錄, 記東記西

H.j. Yao 發表在 痞客邦 留言(0) 人氣( 5098 )