編寫UEFI標準應用程式工程模組小結

2021-07-05 05:16:04 字數 4447 閱讀 7314

在edk2根目錄下,有很多以*pkg命名的資料夾,每乙個這樣的資料夾稱為乙個package。「包」是一組模組及平台描述檔案(.dsc檔案)、包宣告檔案(.dec檔案)組成的集合。模組是uefi系統的乙個特色。模組(可執行檔案,即.efi檔案)像外掛程式一樣可以動態地載入到uefi核心中。對應到原始檔,edk2中的每個工程模組由元資料檔案(.inf檔案)和原始檔(有些情況下也可以包含.efi檔案)組成。

在linux下程式設計,除了編寫源**之外,還要編寫makefile檔案。在windows下使用vs(visual studio)時通常要建立工程檔案和原始檔。與之相似,在edk2環境下,我們除了要編寫原始檔外,還要為工程編寫元資料檔案(.inf)。.inf檔案與vs的工程檔案及linux下的makefile檔案功能相似,用於自動編譯源**。包相當於vs中的專案,.dsc檔案則相當於vs專案的.sln檔案;模組相當於vs專案中的工程,.inf檔案則相當於vs工程的.proj檔案。

也就是說我們不但要編寫乙個

c程式的原始檔,還要編寫乙個.inf的工程檔案。

下面是乙個

簡單模組的源程式,它僅有乙個函式uefimain。uefimain就是這個模組的入口函式,

實現功能是向標準輸出裝置輸出字串「helloworld」。

原始碼如下:

一般來說,標準應用程式至少要包含以下兩個部分。

1)標頭檔案:所有的uefi程式都要包含標頭檔案uef?i.h。uef?i.h定義了uefi基本資料型別及核心資料結構。

2)入口函式:uefi標準應用程式的入口函式通常是uef?imain。之所以說通常是uef?imain而不是說必須是uef?imain,是因為入口函式可有開發者指定。uefimain只是乙個約定俗成的函式名。入口函式由工程檔案uef?imain.inf指定。雖然入口函式的函式名可以變化,但其函式簽名(即返回值型別和引數列表型別)不能變化。

①入口函式的返回值型別是efi_status。

在uefi程式中基本所有的返回值型別都是efi_status。它本質上是無符號長整數。

最高位為1時其值為錯誤**,為0時表示非錯誤值。通過巨集efi_error(status)可以判斷返回值status是否為錯誤碼。若status為錯誤碼,efi_error(status)返回真,否則返回假。

efi_success為預定義常量,其值為0,表示沒有錯誤的狀態值或返回值。

②入口函式的引數imagehandle和systemtable。

.efi檔案(uefi應用程式或uefi驅動程式)載入到記憶體後生成的物件稱為image(映像)。imagehandle是image物件的控制代碼,作為模組入口函式引數,它表示模組自身載入到記憶體後生成的image物件。

systemtable是程式同uefi核心互動的橋梁,通過它可以獲得uefi提供的各種服務,如啟動(bt)服務和執行時(rt)服務。systemtable是uefi核心中的乙個全域性結構體。

向標準輸出裝置列印字串是通過systemtable的conout提供的服務完成的。conout是efi_******_text_output_protocol的乙個例項。而efi_******_text_output_protocol的主要功能是控制字元輸出裝置。向輸出裝置列印字串是通過conout提供的outputstring服務完成的。該服務(函式)的第乙個引數是this指標,指向efi_******_text_output_protocol例項(此處為conout)本身;第二個引數是unicode字串。關於protocol和this指標將在第4章詳細介紹。簡而言之,這條列印語句的意義就是通過systemtable→conout→outputstring服務將字串l「helloworld」列印到systemtable→conout所控制的字元輸出裝置

要想編譯main.c,還需要編寫.inf(module information file)檔案。.inf檔案是模組的工程檔案,其作用相當於makefile檔案或visual studio的.proj檔案,用於指導edk2編譯工具自動編譯模組。

工程檔案中,字元

#後面的內容表示注釋。

工程檔案分為很多個塊,每個塊以「[塊名]」開頭,「[塊名]」必須單獨佔一行。有些塊是所有工程檔案都必需的塊,這些塊包括[defines]、[sources]、[packages]和[libraryclasses]

等。還有一些非必須的塊,如

protocol,guids,buildoptions,pcd等模組。

下面是程式的.inf檔案

檔案模組的說明:

1.[defines]塊

[defines]塊用於定義模組的屬性和其他變數,塊內定義的變數可被其他塊引用。

(1)屬性定義語法

屬性名=屬性值

(2)屬性

塊內必須定義的屬性包括:

inf_version:inf標準的版本號。edk2的build會檢查inf_version的值並根據這個值解釋.inf檔案。最新的inf標準版本號為0x00010016,前半部分為主版本號,後半部分為次版本號。通常將inf_version設定為0x00010005即可。

base_name:模組名字字串,不能包含空格。它通常也是輸出檔案的名字。例如,base_name為uefimain,則最終生成的檔案為uefimain.efi。

file_guid:每個工程檔案必須有乙個8-4-4-4-12格式的guid,用於生成韌體。例如,file_guid = 6987936e-ed34-ffdb-ae97-1fa5e4ed2117。

version_string:模組的版本號字串。例如,可以設定為version_string= 1.0。

entry_point:定義模組的入口函式。在上文中我們提到uefimain是模組的入口函式,就是在此處通過設定entry_point的值為uefimain得到的。

2.[sources]塊

[sources]用於列出模組的所有原始檔和資源檔案。

(1)語法

塊內每一行表示乙個檔案,檔案使用相對路徑,根路徑是工程檔案所在的目錄。作為示例的標準應用程式工程模組僅含有乙個原始檔

(2)體系結構相關塊

.$(arch)是可選項,可以是ia32、x64、ipf、ebc、arm中的乙個,表示本塊適用的體系結構。[sources]塊適用於任何體系結構。例如,編譯32位模組時(即在build命令選項中使用了-a ia32選項),工程將包含[sources]和[sources.ia32]中的原始檔;編譯64位模組時,工程將包含[sources]和[sources.x64]中的原始檔。

3.[packages]塊

[packages]列出本模組引用到的所有包的包宣告檔案(.dec檔案)。

(1)語法

[packages]塊內每一行列出乙個檔案,檔案使用相對路徑,相對路徑的根路徑為edk2的根目錄。若[sources]塊內列出了原始檔,則在[packages]塊必須列出mdepkg/mdepkg.dec,並將其放在本塊的首行。

4.[libraryclasses]

[libraryclasses]塊列出本模組要鏈結的庫模組。

塊內每一行宣告乙個需要鏈結的庫(庫定義在包的

.dsc檔案中

)。常用庫有:

5.[protocols]塊

[protocols]列出模組中使用的protocol,嚴格來說,列出的是protocol對應的guid。如果模組未使用任何protocol,則此塊為空。

這裡需要列出所有用到的

guid。

6.[buildoptions]塊

[buildoptions]指定本模組的編譯和連線選項。

編譯器家族可以是msft(visual studio編譯器家族)、intel(intel編譯器家族)、gcc(gcc編譯器家族)和rvct(arm編譯器家族)中的乙個。target是debug、release和*中的乙個,*為萬用字元,表示對debug和release都有效。tool_chain_tag是編譯器名字。編譯器名字定義在conf\tools_def.txt檔案中,預定義的編譯器名字有vs2003、vs2005、vs2008、vs2010、gcc44、gcc45、gcc46、cyggcc、icc等,*表示對指定編譯器家族內的所有編譯器都有效。arch是體系結構,可以是ia32、x64、ipf、 ebc或 arm,*表示對所有體系結構都有效。cc表示編譯選項。dlink表示連線選項。

= 表示選項附加到預設選項後面。 == 表示僅使用所定義的選項,棄用預設選項。

=或==號後面是編譯選項或連線選項。

當原始檔和工程檔案編寫好之後,就可以進行編譯和執行了。

編譯:將該工程檔案的配置到相應的包裡面,在包裡面的

.dsc檔案中的[compontents]部分裡面新增應用程式模組的工程檔案,也就是.inf檔案。然後,執行編譯指令。

執行:執行相應的執行指令。

最後的最後,你就可以看到那個熟悉的「hello word」了。oh ,哈哈哈

UEFI 應用程式開發之使用C標準庫

如何在uefi應用程式開發中使用c標準庫?以下是我一開始寫uefi應用程式時使用的乙個c標準庫的demo。第一次寫部落格。如有誤,請多多指教。蟹蟹 include int main int argc,char argv defines inf version 0x00010006 base name...

Sphinx應用程式編寫

pocketsphinx api核心理念 pocketsphinx api 被設計是為了減輕編寫語音識別功能應用程式。由於使用抽象類,所以在源 和二進位制檔案相容方面,更能保持穩定。因為它完全可重入,所以在同一程序中擁有多個編碼器也不會出現問題。在執行時,新的語言模型的介面 在sphinxbase ...

如何編寫應用程式

每次要編寫嵌入式應用程式的時候總是不知道該如何入手,於是簡單的研究了下現在普遍的掃碼支付模組的sdk開發結構。拿到乙個專案需求時,我們需要看下該專案分為幾個模組,每個模組之間又是以什麼形式連線的。模組化會使程式結構清晰,維護也會方便很多。比如說掃碼支付模組就分為三個部分,底層core部分,mqtt功...