EDKでmrubyをビルドする

EDKでアプリケーションを作る方法を調べたかったので mruby on EFI Shellを参考に mrubyをビルドしてみました。 書いてあるとおりに進めたら問題なく動きました。ありがとうございます。

edk2_for_mrubyは使わず 前回ビルドしたEDKが '~/src/edk2' に置いてあるのでそれを使って作業します。

$ cd ~/src/edk2
$ . edksetup.sh BaseTools

mruby_efi_shellをダウンロードして '~/src/edk2/AppPkg/Applications/mruby' へ展開します。

edk2_for_mrubyのコミットログを参考に edk2に変更を加えていきます。

コミットログでは 'AppPkg/AppPkg.dsc' を編集しています。 私の環境では 'ACTIVE_PLATFORM=MdeModulePkg/MdeModulePkg.dsc' となっているのでまずはこれを変更します。 'Conf/target.txt' を修正。

ACTIVE_PLATFORM = AppPkg/AppPkg.dsc

'AppPkg/AppPkg.dsc' に 'mruby.inf' について追記。

[Components]
AppPkg/Applications/Hello/Hello.inf
AppPkg/Applications/Main/Main.inf
AppPkg/Applications/Enquire/Enquire.inf
AppPkg/Applications/mruby/mruby.inf

'mruby.inf' には以下のようなカテゴリがあります。

  • [Defines]
  • [Sources]
  • [Packages]
  • [LibraryClasses]
  • [BuildOptions]

EFIアプリケーションとしての基本情報やビルドに関する情報を書くものみたい。

続くコミットログでは 'StdLib/Include/string.h' の仮引数名を修正しています。 なぜこの修正が必要なのか未だにわかっていないのですが修正しないとビルドエラーが出るのは確か。 大文字がいけないのかな?とりあえずmemcpyだけ引用しておきます。

-void     *memcpy(void * __restrict Dest, const void * __restrict Src, size_t N);  
+void     *memcpy(void * __restrict Dest, const void * __restrict Src, size_t n);

続いて 'StdLib/LibC/Main/Main.c' を修正。
(この修正をしなくてもビルドできましたが、できあがったmruby.efiは動きませんでした。)

-extern int main( int, char**);  
+extern int EFIAPI main( int, char**);

ビルド。

$ build

USBメモリに 'mruby.efi' をコピー。今回のビルドで新たにできた 'Hello.efi' もついでに。

$ cp Build/AppPkg/DEBUG_*/X64/mruby.efi /path/to/usb/EFI/edk2/
$ cp Build/AppPkg/DEBUG_*/X64/Hello.efi /path/to/usb/EFI/edk2/

ファイルからも実行してみたいので以下のファイル(fib.rb)もコピー。

# fib.rb
def fib(n)
    return 0 if n == 0
    return 1 if n == 1
    fib(n-2) + fib(n-1)
end

p fib(10)

EFI Shellから実行。

Shell> fs2:
fs2:\> cd EFI\edk2
fs2:\> Hello.efi
Hello there fellow Programmer.
Welcome to the world of EDK II.
fs2:\> mruby.efi -e "[10,2,4,1].sort.each{|i| p i}"
1
2
4
10
fs2:\> mruby.efi fib.rb
55

EFI Shellではキーボードのレイアウトが変わるので記号を打つのが面倒です。

libcを使えることもわかったし、なんとなくの感覚もつかめました。いよいよEFIアプリの実装に着手できそう。

参考ページ