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を実行するためQEMUUEFIを実行出来るようにする。
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を再起動すべきである。