EDK2でUEFI Application開発環境整備とQEMU Virtual FAT
もうちょっと応用的な内容にトライしようと思ったら久々の開発環境整備で手間取ったので、まずどうやって試すのか、について書いてお茶を濁す。
開発環境はFedora 20 + gcc-4.9 from rawhideという変則な環境だが、新しめのパッケージが使われているディストリならこれと状況は大きく変わらない。
なおアーキテクチャはX64とする。32bit環境については取り扱わない。
まずはEDK2のお決まりのビルド作業について。
git clone https://github.com/tianocore/edk2.git cd edk2 make -C edk2/BaseTools . edksetup.sh
Conf/target.txtを開いて以下のように変更する。
ACTIVE_PLATFORM = AppPkg/AppPkg.dsc TOOL_CHAIN_TAG = GCC49 TARGET_ARCH = X64
edksetup.shが用意したbuildコマンドにより、AppPkg.dscで指定された*.infで列挙されているプログラムがビルドされる。
この独特のビルドシステムはLinux標準のやり方と全く違うので覚える必要がある。
build
ビルド終了するとBuildディレクトリにバイナリが出力される。
$ ls Build/AppPkg/DEBUG_GCC49/X64/ AppPkg GetNetByAddr.debug OrderedCollectionTest.efi ArithChk.debug GetNetByAddr.efi RawIp4Rx.debug ArithChk.efi GetNetByName.debug RawIp4Rx.efi DataSink.debug GetNetByName.efi RawIp4Tx.debug DataSink.efi GetServByName.debug RawIp4Tx.efi DataSource.debug GetServByName.efi RecvDgram.debug DataSource.efi GetServByPort.debug RecvDgram.efi Enquire.debug GetServByPort.efi SetHostName.debug Enquire.efi Hello.debug SetHostName.efi GetAddrInfo.debug Hello.efi SetSockOpt.debug GetAddrInfo.efi Main.debug SetSockOpt.efi GetHostByAddr.debug Main.efi ShellPkg GetHostByAddr.efi MdeModulePkg SocketDxe.debug GetHostByDns.debug MdePkg SocketDxe.efi GetHostByDns.efi OobRx.debug StdLib GetHostByName.debug OobRx.efi TOOLS_DEF.X64 GetHostByName.efi OobTx.debug UefiCpuPkg GetNameInfo.debug OobTx.efi WebServer.debug GetNameInfo.efi OrderedCollectionTest.debug WebServer.efi
次に、UEFI Applicationを実行するためQEMUでUEFIを実行出来るようにする。
OVMFのページから「X64 (zip)」を選択してダウンロードする。
unzipコマンドで解凍してOVMF.fdを取り出す。
mkdir ovmf cd ovmf unzip -x ~/OVMF-X64-*.zip $ ls BUILD_INFO LICENSE OVMF.fd README
ここに、先ほどビルドしたUEFI Applicationをコピーしてくる。
cp ~/edk2/Build/AppPkg/DEBUG_GCC49/X64/*.efi .
これで全ての準備が整ったのでQEMUを実行する。
このとき、VGAは無効にしてシリアルコンソールで立ち上げ、ファームウェアにはOVMF(UEFIファームウェア)を指定、ハードディスクイメージにVirtual FATを指定する。Virtual FATのパスには.(カレントディレクトリ)を指定。
qemu-system-x86_64 -nographic -bios OVMF.fd -hda fat:.
ネットワークブートがタイムアウトするのに暫く時間がかかるがじっと待つ。
UEFI Shellが起動したらFS0:を参照するとカレントディレクトリがみえるはず。
UEFI Interactive Shell v2.0 EDK II UEFI v2.40 (EDK II, 0x00010000) Mapping table FS0: Alias(s):HD7a1:;BLK3: PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1) BLK2: Alias(s): PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0) BLK4: Alias(s): PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0) BLK0: Alias(s): PciRoot(0x0)/Pci(0x1,0x0)/Floppy(0x0) BLK1: Alias(s): PciRoot(0x0)/Pci(0x1,0x0)/Floppy(0x1) Press ESC in 1 seconds to skip startup.nsh or any other key to continue. Shell> fs0: FS0:\> dir Directory of: FS0:\ 12/03/2014 04:21 186,144 GetServByName.efi 12/03/2014 04:21 311,392 OobTx.efi 12/03/2014 04:21 301,952 RawIp4Tx.efi 12/03/2014 04:21 180,832 OrderedCollectionTest.efi 02/10/2014 12:42 4,210 LICENSE 12/03/2014 04:21 293,792 GetAddrInfo.efi 12/03/2014 04:21 243,968 SetHostName.efi 12/03/2014 04:21 327,648 OobRx.efi 12/03/2014 04:21 226,016 GetServByPort.efi 02/10/2014 12:30 10,573 README 12/03/2014 04:21 144,192 ArithChk.efi 12/03/2014 04:21 450,720 GetNameInfo.efi 12/03/2014 04:21 384,320 DataSource.efi 12/03/2014 04:21 368,128 GetHostByDns.efi 12/03/2014 04:21 345,888 DataSink.efi 02/10/2014 12:42 1,048,576 OVMF.fd 12/03/2014 04:21 399,008 GetNetByAddr.efi 12/03/2014 04:21 270,208 Enquire.efi 12/03/2014 04:21 326,848 RawIp4Rx.efi 12/03/2014 04:21 127,232 SocketDxe.efi 12/03/2014 04:21 362,432 GetNetByName.efi 12/03/2014 04:21 411,552 GetHostByAddr.efi 02/10/2014 12:42 130 BUILD_INFO 12/03/2014 04:21 375,456 GetHostByName.efi 12/03/2014 04:21 450,720 SetSockOpt.efi 12/03/2014 04:21 341,056 RecvDgram.efi 12/03/2014 04:21 18,496 Hello.efi 12/03/2014 04:21 341,952 WebServer.efi 12/03/2014 04:21 142,880 Main.efi 12/02/2014 19:33 1,540 NvVars 30 File(s) 8,397,861 bytes 0 Dir(s)
ビルドしてきたサンプルプログラムを実行してみる。
FS0:\> Hello Hello there fellow Programmer. Welcome to the world of EDK II.
なお、このVirtual FATはQEMU起動時の時点で構築されるので、ビルドしては新しいプログラムを試すという使い方をすべきではない。毎回QEMUを再起動すべきである。