2015年5月22日 星期五

uefi program 真實機器篇

uefi 真是難搞, 光是如何切割 esp partition 就難倒我, 尤其是在 windows 8 中, 做什麼都有權限不夠的問題。好不容易終於可以用 debian jessie 安裝到 usb hd 上, 可以用熟悉的環境了。

另外一個好方法是使用 Universal-USB-Installer-1.9.6.3 來安裝 linux cd iso, 他會把對應的 esp partition 以及對應的開機檔案 *.efi 準備好, 並裝在 usb 隨身碟上, 方便多了。

edk2 的開發流程在《uefi with qemu》說過了, 並在 qemu 模擬器執行編譯過的 hello efi (32bit) 程式, 這次想要在真實機器上測試, 所以我得先搞定一個 uefi shell, 然後再來執行編譯過的 hello efi 程式。

在真實機器上執行就把《uefi with qemu》的東西複製到開機 usb 隨身碟即可, 然後就在 uefi shell 執行他。

在 nb uefi 選單找了老半天都沒看到怎麼讓 uefi shell 跑出來, 後來找到這篇:
如何製作 UEFI 開機隨身碟並更新 BIOS? (pdf 格式)
照著文件中下載相關 efi 執行檔案並解壓縮到適當的目錄, 將 uefi security 關閉, 並選擇從 usb hd 開機就可以看到 uefi shell。



在我的 acer aspire v5 可以按下 F12, 會有開機選單可以選擇從哪裡開機, 也可以從這邊選 usb hd 開機。不過我不知道怎麼讓 uefi 找到我那個 uefi_hello 程式, 所以還是只能從 uefi shell 執行它。




fs0: 就是我 usb hd 的內容, 可以看到其中的目錄結構。這個 partition 就是 esp parititon。
EFI\BOOT\*.efi
hello.efi 執行後可以看到印出了 HelloWorld。

說實在的, 比起 legacy bios 開機程式, uefi 複雜不少, 但這已經成為主流, 不得不學, 要不然我那個好不容易開發好的 simple os kernel, 豈不是不能在 uefi 上的 pc boot 起來, 我最討厭努力很久的東西白費了, 讓 simple os 只活在模擬器上, 那可沒有任何意思。不過目前我大概沒機會繼續搞下去了, 下次要有所突破可能要進魯蛇模式了。

有個業界朋友說, 業界開發 uefi 沒人在用 gcc 的, 所以如果編出來的程式有點問題, 可以用 ms vc 試試。

來談談 edk2 如何編譯出 m.efi, 他沒有什麼特別神祕的地方, 一樣是呼叫 gcc 來編譯, 只是我們不知道該下哪些編譯參數, uefi program compiling process 是我抓出來的編譯指令。

list 1. L2 的參數真的很多吧!
list 1. L8 GccBase.lds 是 linker script, 產生的檔案竟然是 dll, edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/m.dll
list 1. L20 GenFw 會把 m.dll 轉成 m.efi

list 1. uefi program compiling process
 1 Building ... /media/work/git/uefi/edk2/AppPkg/Applications/Main/m.inf [X64]
 2 "gcc" -g -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-array-bounds -ffunction-sections -fdata-sections -c -include AutoGen.h -fno-common -DSTRING_ARRAY_NAME=mStrings -m64 -fno-stack-protector "-DEFIAPI=__attribute__((ms_abi))" -DNO_BUILTIN_VA_FUNCS -mno-red-zone -Wno-address -mcmodel=large -fno-asynchronous-unwind-tables -Wno-address -Wno-unused-but-set-variable -nostdinc -nostdlib -DUEFI_C_SOURCE -o /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/OUTPUT/./m.obj -I/media/work/git/uefi/edk2/AppPkg/Applications/Main -I/media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG -I/media/work/git/uefi/edk2/StdLib -I/media/work/git/uefi/edk2/StdLib/Include -I/media/work/git/uefi/edk2/StdLib/Include/X64 -I/media/work/git/uefi/edk2/MdePkg -I/media/work/git/uefi/edk2/MdePkg/Include -I/media/work/git/uefi/edk2/MdePkg/Include/X64 -I/media/work/git/uefi/edk2/ShellPkg -I/media/work/git/uefi/edk2/ShellPkg/Include /media/work/git/uefi/edk2/AppPkg/Applications/Main/m.cpp
 3 org_fn: /media/work/git/uefi/edk2/AppPkg/Applications/Main/m.cpp
 4 g++
 5 
 6 "ar" -cr /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/OUTPUT/m.lib  @/media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/OUTPUT/object_files.lst
 7 
 8 "ld" -o /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/m.dll -nostdlib -n -q --gc-sections -z common-page-size=0x40 --entry _ModuleEntryPoint -u _ModuleEntryPoint -Map /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/m.map -melf_x86_64 --oformat=elf64-x86-64 --start-group  @/media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/OUTPUT/static_library_files.lst --end-group --defsym=PECOFF_HEADER_SIZE=0x228 --script=/media/work/git/uefi/edk2/BaseTools/Scripts/GccBase.lds
 9 
10 "objcopy"  /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/m.dll
11 
12 cp -f /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/m.dll /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/m.debug
13 
14 objcopy --strip-unneeded -R .eh_frame /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/m.dll
15 
16 objcopy --add-gnu-debuglink=/media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/m.debug /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/m.dll
17 
18 cp -f /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/m.debug /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/m.debug
19 
20 "GenFw" -e UEFI_APPLICATION -o /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/m.efi /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/m.dll
21 
22 cp -f /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/m.efi /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/OUTPUT
23 
24 cp -f /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/m.efi /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/m.efi
25 
26 cp -f /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/*.map /media/work/git/uefi/edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/OUTPUT

descent@debian64:edk2$ file edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/m.dll
edk2/Build/AppPkg/DEBUG_GCC49/X64/AppPkg/Applications/Main/m/DEBUG/m.dll: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

這裡我搞不懂, efi 需要的是 pe 格式的檔案, 不知道為什麼 elf 也可以正常執行。

書中範例: https://code.google.com/p/uefi-programming-guider/wiki/Download

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。