Linuxホストでuefiバイナリのビルドめも

ueifですね。uefiの勉強会に行くのに開発環境を先に整えておくだろjkという気もするのでまずはLinuxホストでビルド環境を作って見ました。
持ち運び用のPCはmbaなのでほんとはmacで腕津環境整えたかったのですがgccのクロス環境を作るのが面倒だったのでまずはLinuxで環境作るという手抜きぷっりです(´・ω・`)

一応こんな感じの開発・実行環境です。
実行環境:MacBook Air(rEFItのシェルで)
開発環境:CentOS 6.3(外からアクセスできる所に作りたかったのでさくらのvpsです)

実行環境のMBAはcpuがCore2 Duo、メモリが2GBというスペックなので仮想環境もちと厳しい今日この頃なためrEFItのシェルを使うことにしました。rEFItはSSDではなくてUSBメモリにインストールしてます。

ueifのバイナリに必要なのはbinutilsとuefiのライブラリです。ueifのライブラリはgnu-efiを使用します。
まずはutif用のbinutilsを作ります。binutilsgnuのftpサイトから最新の2.23.1をダウンロードしました。

これを展開してconfigure -> make -> make installという基本通りの手順でビルド&インストールします。
オプションの--prefixはインストール先ですね。--program-prefixのほうは適当な名称をつければOKです。別につけなくても良いのですがあった方が便利なのでつけています。たとえば、arといったときに/usr/bin/arなのか$PREFIX/bin/arなのかってなると面倒なのでつける幹事ですね。あ、これはgnu-efiのビルドでも使います。
confifureのオプションは以下のようにしました。

./configure --prefix=$PREFIX --disable-nls --enable-64-bit-bfd --enable-targets=i386-efi-pe,x86_64-phoenix-freebsd --program-prefix=efi-x86_64-

binutilsが作れたら次はgnu-efiのビルドです。これもプロジェクトのページからダウンロードします。2013/01/26の時点ではgnu-efi_3.0s.orig.tar.gzがダウンロード出来ました。
ダウンロードして展開したら次はビルドですが、これはconfigureはなくてMake.defautlsでインストール先やgcc、ツールチェインなどの指定を行います。
変更した箇所をさくっとdiffにすると以下の通りです。

--- gnu-efi-3.0.orig/Make.defaults      2012-11-06 03:16:15.000000000 +0900
+++ gnu-efi-3.0.new/Make.defaults       2013-01-26 16:56:30.141546985 +0900
@@ -38,7 +38,7 @@
 # Where to install the package. GNU-EFI will create and access
 # lib and include under the root
 #
-INSTALLROOT=/usr/local
+INSTALLROOT=/home/masami/efi_tools/gnu_efi
 LIBDIR=lib

 TOPDIR    := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
@@ -59,9 +59,9 @@
 ASFLAGS    = $(ARCH3264)
 LDFLAGS           = -nostdlib
 INSTALL           = install
-prefix     = /usr/bin/
+prefix     = efi-x86_64-

-CC            := $(prefix)gcc
+CC            := gcc
 AS            := $(prefix)as
 LD            := $(prefix)ld
 AR            := $(prefix)ar

INSTALLROOTはインストール先なので任意ですね。prefixはbinutilsのコンパイル時に指定した--program-prefixの値を使います。CCですが、今回はgccはCentoOSのデフォルトの物を使ってますのでprefixは外しています。
設定を変更したらビルドします。これはmake -> make installという順番で実行します。
インストールまで成功するとINSTALLROOTの下にincludeとlibという2個のディレクトリが作成されています。
これで開発環境の準備は終わりですオツカレチャ━━━━( ´∀`)━━━━ン!!!!

そうしたらお約束のhello worldから作りましょう。ソースは参考にしたwebページのものを微妙に変えただけの代物です。

//hello.c
#include <efi.h>
#include <efilib.h>

EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
  SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
  InitializeLib(ImageHandle, SystemTable);
  conout = SystemTable->ConOut;

  uefi_call_wrapper(conout->OutputString, 2, conout, (CHAR16 *)L"moi!!!\\n\\r");


  while(1);

  return EFI_SUCCESS;
}

Makefileも同じくなので変更点だけ。
ARCHは64bitなのでx86_64に。EFIROOTはgnu-efiのINSTALLROOTで指定した所です。prefixはbinutilsの--program-prefixで指定した値、ccはprefixを外してCentOSgccを呼ぶようにしてます。ARCH以外はgnu-efiのMake.defaultsと同じ設定ですね。

ARCH     = x86_64
EFIROOT  = /home/masami/efi_tools/gnu_efi
prefix      = efi-x86_64-
CC          = gcc

これでmakeをするとhello.efiができます。fileコマンドで確認するといい感じな表示ですね( ´∀`)bグッ!

$ file hello.efi
hello.efi: PE32+ executable (EFI application)

そうしたらこのhello.elfをmbaの実機で動かすのでrEFItのインストールが必要です。インストールは下のほう参考先としてあげたところの手順でインストールできますのでここでは省略します。

rEFItをUSBメモリにインストールしたらhello.efiを配置しましょう。ファイルの置き場所はrEFItのコマンドがあるところに置いてみました。
パスは/Volumes/<ラベル>/efi/tools/hello.efiとなります。
そして再起動してrEFItのメニュー画面からシェルを選択し、実行します。
f:id:masami256:20130126162610j:plain
写真だとフルパスで指定しますが、ファイルを置いた場所は他のコマンドもある場所なのでhello.efiだけでも大丈夫です。

これでやっとスタート地点に立てましたねε-(;-ω-`A) フゥ…

以下のページを参考にしました。
UEFIのプログラミング

rEFItをUSBメモリにインストール