Operating Systems : simple Operating System from scratch (2) — boot from uefi

吳建興
8 min readApr 15, 2021

--

Hello !

雖然之前學了怎麼從 BIOS 開機,照著範例編譯好了 Boot & Loader , 結果想要用我的老舊的筆電來實機試試看這個小小作業系統核心的時候,發覺這台老舊的筆電已經不是從 BIOS 開機了,而是要使用 UEFI 來開機。。。

幸好 " 一個64位操作系統的設計與實現 " 的作者也寫了怎麼使用 UEFI 開機的範例。

這邊簡單紀錄下過程,而沒有原理 ( 因為我也還沒深入的理解 QQ ),方便我之後忘記的話,可以來這邊查閱一下。

我使用的環境是 :
Ubuntu 18.04
gcc --> 4.8
太新的 Ubuntu 沒辦法很簡單地用 apt-get 拿到 gcc-4.8,所以我選擇用比較舊的 Ubuntu 18.04 , 幸好有不太使用的舊筆電,可以隨意把舊有的系統砍掉。

準備 edk2 環境

edk2 是開發 uefi 的環境,我也不知道有沒有其他環境就是了。

(shell) git clone https://github.com/tianocore/edk2.git # 把 edk2 給 clone 下來(shell) cd edk2(shell) git checkout UDK2018 # 切換到 UDK2018 這個 branch(shell) make -C /home/tommy/newedk/edk2/BaseTools/Source/C # 編譯一些基礎的工具(shell) . ./edksetup.sh # 設定下環境變數

使用 edk2 來編譯 uefi shell

修改 ./Conf/target.txt

ACTIVE_PLATFORM = ShellPkg/ShellPkg.dsc  
// 選擇要 build 哪一個 workspace
TARGET_ARCH = X64
// 選擇要 build 哪一種 architecture
TOOL_CHAIN_TAG = GCC48
// 想使用哪一種 tool chain

改好 ./Conf/target.txt 後,就可以開始下 build 的指令了

(shell) . ./edksetup.sh
Loading previous configuration from /home/tommy/newedk/edk2/Conf/BuildEnv.sh
WORKSPACE: /home/tommy/newedk/edk2
EDK_TOOLS_PATH: /home/tommy/newedk/edk2/BaseTools
CONF_PATH: /home/tommy/newedk/edk2/Conf
(shell) build
.
.
.
.
make: Nothing to be done for 'tbuild'.
Building ... /home/tommy/newedk/edk2/ShellPkg/Application/Shell/Shell.inf [X64]
Building ... /home/tommy/newedk/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf [X64]
Building ... /home/tommy/newedk/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.inf [X64]
Building ... /home/tommy/newedk/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf [X64]
make: Nothing to be done for 'tbuild'.
Building ... /home/tommy/newedk/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.inf [X64]
make: Nothing to be done for 'tbuild'.
make: Nothing to be done for 'tbuild'.
make: Nothing to be done for 'tbuild'.
make: Nothing to be done for 'tbuild'.
- Done -
Build end time: 00:11:12, Apr.15 2021
Build total time: 00:00:05

最後可以在 ./Build/Shell/DEBUG_GCC48/X64 拿到 Shell.efi

將 uefi shell 放進 USB,並在開機的時候進入 Shell

找一個 usb,將它格式化成 FAT32,在 Ubuntu 上有很方便的指令。

(shell) lsblk -f 
//先用 lsblk 查一下剛剛插進去的 USB 是哪一個
sdb
├─sdb1 vfat 723A-9988
└─sdb2 exfat aaa 5EA8-363E 14.4G 0% /media/tommy/aaa
(shell) sudo mkfs -t vfat -F 32 /dev/sdb1
// 可以將 /dev/sdb1 格式化成 FAT 32
(shell) sudo mount /dev/sdb1 /mnt
// 把這個 usb 的這個分區掛載在某一個節點
(shell) sudo mkdir -p /mnt/EFI/BOOT
// 建立一些資料夾,名稱一定要相同,因為 uefi 會在這邊找檔案
(shell) sudo cp ./Build/Shell/DEBUG_GCC48/X64/Shell.efi /mnt/EFI/BOOT/BOOTx64.EFI

接著重開機,將 USB 開機的優先順序調成最高,結果會如下圖所示。

用手機來做螢幕節圖,導致畫質不是很好,抱歉ㄌ QQ。

到此為止,我們成功運行了第一個 uefi 的應用程式,接下來可以開始使用 uefi 來做一個簡單的 Hello World 範例。

uefi 的 Hello World!

edk2 本身就有一個 Hello World 的範例了,所以就不用另外再寫了。範例在 ./AppPkg/Application/Hello/Hello.c ,有興趣的話可以進去看下程式碼。

修改 ./Conf/target.txt

ACTIVE_PLATFORM       = AppPkg/AppPkg.dsc
// 選擇要 build 哪一個 workspace
TARGET_ARCH = X64
// 選擇要 build 哪一種 architecture
TOOL_CHAIN_TAG = GCC48
// 想使用哪一種 tool chain,

然後就可以下指令去 build 了

(shell) . ./edksetup.sh
(shell) build
.
.
.
cp -f /home/tommy/newedk/edk2/Build/AppPkg/DEBUG_GCC48/X64/AppPkg/Applications/Sockets/WebServer/WebServer/DEBUG/*.map /home/tommy/newedk/edk2/Build/AppPkg/DEBUG_GCC48/X64/AppPkg/Applications/Sockets/WebServer/WebServer/OUTPUT
- Done -
Build end time: 23:01:08, Apr.15 2021
Build total time: 00:00:36
# 看到 Done 就表示成功 build 好了

接下來一樣掛載磁碟,並把編譯好的執行檔放進去。

(shell) sudo mount /dev/sdb1 /mnt
(shell) sudo cp ./Build/AppPkg/DEBUG_GCC48/X64/Hello.efi /mnt

之後可以再用 USB 開機,進入 Shell 畫面。

(uefi shell)fs0:
(uefi shell)Hello.efi

成功出現 Hello World 的訊息了!接下來就是照這個節奏來寫個 BootLoader。

--

--

吳建興
吳建興

Written by 吳建興

I want to be a good programmer.(´・ω・`)

No responses yet