EDK2の始め方

内容

  1. EDK2のHelloサンプルを動かす。
  2. EDK2でエコープログラムを作成。

開発環境

  • Ubuntu18.04 (Archlinuxでも動いた)
  • edk2

開発環境構築

edk2をダウンロードする。

git clone https://github.com/tianocore/edk2.git
cd ~/edk2
source edksetup.sh

サンプルを動かす

Helloを表示するサンプルがあるのでまずそれを動かす。

~/edk2/Conf/target.txtの中身のACTIVE_PLATFORMTARGET_ARCHTOOL_CHAIN_TAGを以下のように変更する。

#target.txt
ACTIVE_PLATFORM = AppPkg/AppPkg.dsc
TARGET_ARCH = X64
TOOL_CHAIN_TAG = GCC5

変更したらコンパイルする。

cd ~/edk2
build

初めての場合、エラーが出ると思うが、エラーメッセージに従ってmakeしたあと再度コンパイルすれば通った。うまく行けば、~/edk2/Build/AppPkg/DEBUG_GCC5/X64の中にHello.efiができる。

次に、qemuUEFIを動作させるためのOVMFをビルドする。 ~/edk2/Conf/target.txtACTIVE_PLATFORMOvmfPkg/OvmfPkgX64.dscに変更してbuildコマンドを実行する。 この時にエラーが出たので以下の2つを実行し、再度ビルドした。

cd ~/edk2
git submodule update --init --recursive

sudo apt install acpica-tools

無事ビルドに成功したらqemuで実行する。

mkdir -p ~/run-ovmf/hda-contents
cd ~/run-ovmf
cp ~/edk2/Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd .
cp ~/edk2/Build/AppPkg/DEBUG_GCC5/X64/Hello.efi ./hda-contents/Hello.efi

qemu-system-x86_64 --bios OVMF.fd -hda fat:rw:./hda-contents -net none

f:id:DeadBlue:20190311231408p:plain
qemu

実行後画像のようにするとefiファイルを実行できる。

また、実行したいefiファイルをhda-contents/EFI/BOOT/BOOTX64.EFIとすればqemuを立ち上げたときに実行される。

エコープログラム

次に実際にエコーさせるプログラムを書く。 UEFIプログラムはフルスクラッチで作る!UEFI ベアメタルプログラミング を参考にし、それをEDK2で動くようにした。

~/edk2/AppPkg/Applications/Echoを作り、そこにEcho.cEcho.infを書く。

mkdir ~/edk2/AppPkg/Applications/Echo
cd ~/edk2/AppPkg/Applications/Echo

FILE_GUIDの値はuuidgenコマンドの結果をコピペする。

#Echo.inf
[Defines]
  INF_VERSION       = 0x00010006
  BASE_NAME     = Echo
  FILE_GUID     = 9fa4079c-3c1c-44fd-b776-ff16fee37396
  MODULE_TYPE       = UEFI_APPLICATION
  VERSION_STRING    = 0.1
  ENTRY_POINT       = UefiMain

[Sources]
  Echo.c

[Packages]
  MdePkg/MdePkg.dec

[LibraryClasses]
  UefiLib
  UefiApplicationEntryPoint
#Echo.c
#include <Uefi.h>
#include <Library/UefiLib.h>


EFI_STATUS
EFIAPI
UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable){
  SystemTable->ConOut->OutputString(SystemTable->ConOut,L"Hello EFI\n\r");
  EFI_INPUT_KEY key;
  CHAR16 str[3];
  UINTN waitIndex;
  
  while(1){
    SystemTable->BootServices->WaitForEvent(1,&(SystemTable->ConIn->WaitForKey),&waitIndex);//入力があるまで待機
    SystemTable->ConIn->ReadKeyStroke(SystemTable->ConIn,&key);
    if(key.UnicodeChar != '\r'){
      str[0] = key.UnicodeChar;
      str[1] = L'\0';
    }else{
      str[0] = L'\n';
      str[1] = L'\r';
      str[2] = L'\0';
    }
    SystemTable->ConOut->OutputString(SystemTable->ConOut,str);
  }
  return 0;
}

次に~/edk2/AppPkg/AppPkg.dsc[Components]のところに AppPkg/Applications/Echo/Echo.infを追加する。

#AppPkg.dsc

#### Sample Applications.
  AppPkg/Applications/Hello/Hello.inf        # No LibC includes or functions.
  AppPkg/Applications/Main/Main.inf          # Simple invocation. No other LibC functions.
  AppPkg/Applications/Enquire/Enquire.inf    #
  AppPkg/Applications/ArithChk/ArithChk.inf  #
  AppPkg/Applications/Echo/Echo.inf #追加

その後~/edk2/Conf/target.txtACTIVE_PLATFORMAppPkg/AppPkg.dscに変更しbuildコマンドを実行する。

その後、以下のようにしてqemuで実行する。

cd ~/edk2
cp Build/AppPkg/DEBUG_GCC5/X64/Echo.efi ~/run-ovmf/hda-contents/
cd ~/run-ovmf
qemu-system-x86_64 --bios OVMF.fd -hda fat:rw:hda-contents/ -net none

References