# UEFI BIOS tutorial 這篇文章主要用來記錄學習 UEFI EDKII 的心路歷程,由於非該領域的專業,因此難免會有錯誤。 以下介紹提供在windows環境或是Linux環境中的安裝與操作方式 ==如有發現錯誤,還請大家踴躍指正== ## Try EDK2 on Fedora 41 (Linux) ### 需要的安裝套件: ```clike= # 這會安裝開發C/C++工具所需的套件集合 dnf group install -y development-tools # 以下是執行edkII 所需要的套件 dnf install nasm libXext-devel \ libX11-devel uuid-devel \ gcc-c++ libuuid-devel acpica-tools ``` ### 下載官方鏡像原始程式碼: ```shell= $ mkdir UEFI; cd UEFI UEFI$ git clone https://github.com/tianocore/edk2.git UEFI$ cd edk2 UEFI/edk2$ git submodule update --init ``` ### 編譯EDKII工具鍊: ```shell= UEFI/edk2$ make -C BaseTools UEFI/edk2$ source edksetup.sh ``` 第一次執行 source edksetup.sh 會在 Conf目錄生成 tools_def.txt、target.txt、build_rule.txt 檔案,這是之後 build 指令會預設讀取的資訊 build 指令也是 edk2 用來編譯 package 的命令腳本,路徑會在剛剛編譯的 BaseTools 下: ```clike edk2/BaseTools/BinWrappers/PosixLike/build ``` ## Try EDK2 on Windows 11 Windows 環境下比較常使用的toolchain是visual studio C/C++。 ### 需要的安裝套件: 與Linux不同,Linux通常根據不同的發行版提供不同的安裝管理工具 (ex: Fedora use dnf/yum, Debian use apt, OpenSUSE use zypper/YasT)。 Windows通常是可以下載一個執行檔案,並透過執行該執行檔案來安裝環境。 - 下載 Visual Studio,並勾選C/C++開發環境 ![image](https://hackmd.io/_uploads/H1g2HMRYyg.png) - 下載 Python,並將其添加進PATH中 - 下載 Nasm(組譯器),IASL(ACPI 元件體系結構下載),同樣須將其添加至PATH中 - 與Linux環境預設會安裝git不同,Windows一般需要自行安裝git for windows ### 下載官方鏡像原始程式碼: 開啟PowerShell,並在其輸入以下命令 ``` PS> git clone https://github.com/tianocore/edk2.git PS> cd edk2 PS> git submodule update --init PS> .\edksetup.bat Rebuild # 這邊可以看到,命令以反斜線形式表示路徑 ``` ![image](https://hackmd.io/_uploads/r1eCDfRYyg.png) 其中會輸出重要的環境路徑,以及如下的編譯過程 ![image](https://hackmd.io/_uploads/rkJ-OfRFkg.png) build 命令有幾個常用的選項可供配置: - -a TARGETARCH or --arch=TARGETARCH: 該選項用於指定目標的指令及架構,常見的有 IA32(X86)、X64(AMD64, X86_64)、ARM、RISCV64 - -p PLATFORMFILE or --platform=PLATFORMFILE: 建構由 DSC 檔案名稱參數指定的平台,覆蓋 target.txt 的 ACTIVE_PLATFORM 定義 - -m MODULEFILE or --module=MODULEFILE: 建構由 INF 檔案名稱參數指定的模組,如果未提供該選項,預設會編譯 package 中的所有 Module - -t TOOLCHAIN or --tagname=TOOLCHAIN: 使用工具鏈標記名建構平台,覆蓋 target.txt 的 TOOL_CHAIN_TAG 定義,在 windows 環境中通常是 VS2015,Linux 中則使用 GCC - -b BUILDTARGET or --buildtarget=BUILDTARGET: 使用 TARGET 建置平台,覆蓋 target.txt 的 TARGET 定義,常用的有 RELEASE 或是 DEBUG 在 edk2 Module 中,模擬器是常用的工具,編譯該工具的方式如下: ```shell= # 在該命令中我們沒有使用 -m 指定要編譯的 Module # 因此會將 EmulatorPkg 中的所有 Module 都編譯 UEFI/edk2$ build -p EmulatorPkg/EmulatorPkg.dsc -t GCC -a X64 ``` 編譯完成之後會在下命令的該目錄之下,出現一個 Build 目錄,這裡面會有以我們編譯的 Package 為名稱的目錄。 以剛剛編譯的模擬器工具為例,如下: ```shell= UEFI/edk2/Build$ ls EmulatorX64/ # 進入 EmulatorX64 目錄後我們可以看到 DEBUG_GCC 目錄 # 雖然我們沒有使用 -b 來指定目標,但預設會是DEBUG ``` 要執行虛擬機只需執行 Host,他會在剛剛編譯的套件路徑之下中,以下是執行後的範例: ![image](https://hackmd.io/_uploads/rkbz2FfUJe.png) 可以看到很多 efi 執行檔,我們隨意執行一個 HelloWorld.efi 後即可得到結果。 ### OVMF 開放虛擬機器韌體 OVMF 是基於 EDKII 的韌體,可以在 qemu x86-64 虛擬機器下運作。這樣可以輕鬆地使用 UEFI 韌體進行調試和實驗 ```shell= # 在該命令中我們沒有使用 -m 指定要編譯的 Module # 因此會將 OvmfPkg 中的所有 Module 都編譯 UEFI/edk2$ build -p OvmfPkg/OvmfPkgX64.dsc -t GCC -a X64 -b RELEASE # 編完的檔案放在 Build/{Platform Name}/{TARGET}_{TOOL_CHAIN_TAG}/FV UEFI/edk2/Build/OvmfX64/RELEASE_GCC/FV$ ls -alh OVMF* -rw-r--r--. 1 alan alan 3.5M Jan 2 17:07 OVMF_CODE.fd -rw-r--r--. 1 alan alan 4.0M Jan 2 17:07 OVMF.fd -rw-r--r--. 1 alan alan 528K Jan 2 17:07 OVMF_VARS.fd ``` - OVMF 韌體(QEMU 的 UEFI 實作)分為兩個檔案: - OVMF_CODE.fd 包含實際的 UEFI 韌體 - OVMF_VARS.fd 是用於模擬持久 NVRAM 儲存的「模板」 有 OVMF 後我們就可以使用 qemu 模擬器來執行。 ```shell= $ qemu-system-x86_64 -s -pflash OVMF.fd -hda fat:rw:<efi_file_loc>\ -net none -debugcon file:debug.log -global -isa-debugcon.iobase=0x402 -nographic ``` 執行之後,debug 的相關訊息會輸出到 debug.log ![image](https://hackmd.io/_uploads/S1xwHT4Lke.png) #### 使用qemu搭配gdb進行除錯 ![image](https://hackmd.io/_uploads/Hy_sEWGf1e.png) ![image](https://hackmd.io/_uploads/SyGOEWffkx.png) ### UEFI Module EDK2 的最重要兩個套件: Module、Package Package 可以簡單的理解為 edk2 目錄中以 Pkg 為後綴的目錄都是一個 Package,Package 是由一組 Module 以及 Platform 檔案(.dsc) 和 Package 聲明檔案(.dec) 所組成。 ### <font color=#008000>DEC</font> EDK II Package Declaration File. 該檔案定義有關 Package 中提供的內容的資訊。 EDK II Package 是類似內容的集合。 ### <font color=#008000>DSC</font> EDK II Platform Description File. 該檔案描述了要建置的 Modules、Libraries和 Components以及如何構建,以及定義連結 EDK II 模組時將使用的程式庫實例。 ### <font color=#008000>FDF</font> EDK II Flash definition file. 此檔案用於定義韌體映像、更新套件和 PCI 選項 ROM 的內容和二進位映像佈局。 ### <font color=#008000>INF</font> EDK II Module Information File. 該文件描述了模組的編寫方式。對於 EDK,此檔案描述了 Components 或 Libraries 的編寫方式以及提供一些基本的建置資訊。 該檔案類似 Makefile - 檔案內容由 Block 來組成,有些Block式必須要提供的,有部分是可選的 - [Defines] - 定義了 Module 的屬性 - 必須要是第一個描述的 section - INF_VERSION: 版本號 - BASE_NAME: 編譯完後的執行檔案的名稱,如果為 test,則編譯完後會叫 test.efi - FILE_GUID: UUID,Linux 中可以使用 uuidgen 來生成 - ENTRY_POINT: 這個為 Module 的 main function,非常重要 - [Sources] - 要編譯的原始程式碼 - 要描述其位置,root 路徑就是 inf 檔案的所在路徑 - [Sources.$(Arch)]: 用來特別說明哪些檔案只能在某個 ISA 中被編譯 - $(Arch): 是可選用的項目,常見的有 X64,IA32,ARM,如果在編譯中使用 -a X64,則代表 [Sources]以及 [Sources.X64] 的內容會被編譯 - Toolchain: 除了 ISA 為可指定選項外,Toolchain也是可以選用的,常見的有 GCC,INTEL,這會用來表示編譯時使用的編譯器要選擇哪一個,ex: test.c | GCC,表示只有編譯器指定為 GCC 時才會編譯該檔案 - [Packages] - 標示引用到的其他 Packages 的 dec - 每一行提供一個檔案,root的路徑為 EDKII 的根目錄 - 一般最常使用的 Uefi.h 檔案,由於其位於 MdePkg 目錄下,因此這邊就需要包含 MdePkg/MdePkg.dec - [LibraryClasses] - 標示要鍊接到的 Module - [BuildOptions] - 指定編譯和鍊接的選項參數 (可選非必須) - 格式與 compiler 中常見的 istarget 非常類似 - [Compiler]: ==Target== _ ==ToolChain== _ ==ARCH== _ ==CFLAGS|LIBFLAGS== _ ==FLAGS== - Compiler 可以是 GCC或INTEL(ICC) - Target 可以是 DEBUG、RELEASE或是 =='*'== - ToolChain 可以是 VS2015,GCC或ICC - Arch 表示使用的ISA, =='*'== 表示所有ISA皆適用 - CFLAGS 編譯選項 LIBFLAGS鍊接選項 ### <font color=#008000>EFI</font> UEFI 的執行程式,載入記憶體後被的行程實例稱為 Image, ### UEFI power on flow ![image](https://hackmd.io/_uploads/S1dIK8RRkl.png) - SEC (Security Phase) - Create CAR (Cache As Ram) - Real address mode to flat mode - PEI (Pre-EFI Initialzation) ### UEFI Package ##### Emulator 介面 ![image](https://hackmd.io/_uploads/S1PryLzPkg.png) ##### UEFI data type UEFI 中可以區分為 Windows 中的 __int64 跟 Linux 中的 long long,均表示為 64位的integer type。 其中常用的 EFI_STATUS 就是該資料型態。 ### 常用工具 [intel udk debugger tool](https://www.intel.com/content/www/us/en/developer/articles/tool/unified-extensible-firmware-interface.html) 這裡存放除錯工具與使用手冊 ### Reference - Unified Extensible Firmware Interface (UEFI) Specification, Release 2.10 - https://book.huihoo.com/pc-architecture/