mruby on EFI Shellのビルド

※この記事では後々mrbgemsを追加していく事などを意図してmrubyをビルドする事に拘っているが、単にmrubyをUEFIで試してみたいだけならば自分でビルドする必要はない。ここのHow to useからリンクされている"download page"をクリックすればダウンロードできる。

前回の記事をベースにmruby on EFI Shellのビルドを行う。

他のmruby on EFI Shellのビルド方法のメモ()は日付が2年前になっておりディストリやgccのバージョン、EDK2のコードがこのときからかなり変わってはいるが、手順に大きな変更は見られなかった。

まず、Conf/tools_def.txtのGCC44_ALL_CC_FLAGSから-Werrorを取り除く。

DEFINE GCC44_ALL_CC_FLAGS            = -g -fshort-wchar -fno-strict-aliasing -Wall -Wno-array-bounds -ffunction-sections 
-fdata-sections -c -include AutoGen.h -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings

AppPkgにmrubyを追加する。

cd AppPkg/Applications
git clone https://github.com/masamitsu-murase/mruby_on_efi_shell.git mruby
cd mruby
git submodule update --init --recursive
cd mruby
rake
cd ..
ruby override/override.rb

AppPkg/AppPkg.dscを開いて[Components]にAppPkg/Applications/mruby/mruby.infを足す。

diff --git a/AppPkg/AppPkg.dsc b/AppPkg/AppPkg.dsc
index 424434c..e34ceb6 100644
--- a/AppPkg/AppPkg.dsc
+++ b/AppPkg/AppPkg.dsc
@@ -112,6 +112,7 @@
   AppPkg/Applications/Main/Main.inf          # Simple invocation. No other LibC
   AppPkg/Applications/Enquire/Enquire.inf    #
   AppPkg/Applications/ArithChk/ArithChk.inf  #
+  AppPkg/Applications/mruby/mruby.inf

 #### A simple fuzzer for OrderedCollectionLib, in particular for
 #### BaseOrderedCollectionRedBlackTreeLib.

LibCにパッチを当てる。

diff --git a/StdLib/LibC/Main/Main.c b/StdLib/LibC/Main/Main.c
index b203d15..f22edcf 100644
--- a/StdLib/LibC/Main/Main.c
+++ b/StdLib/LibC/Main/Main.c
@@ -31,7 +31,7 @@
 #include  <MainData.h>
 #include  <unistd.h>

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

mrubyをビルド。

build

前回と同様の手順でovmfディレクトリにmruby.efiをコピーしてくる。

cd ~/ovmf
cp ~/edk2/Build/AppPkg/DEBUG_GCC49/X64/mruby.efi .

それっぽいサンプルコードを用意する。

sort.rb
[10,2,4,1].sort.each{|i| p i}
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)

QEMUを起動、UEFIから実行してみる。

qemu-system-x86_64 -nographic -bios OVMF.fd -hda fat:.

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:\
02/10/2014  12:42               4,210  LICENSE
12/03/2014  06:27                  96  fib.rb
02/10/2014  12:30              10,573  README
02/10/2014  12:42           1,048,576  OVMF.fd
12/03/2014  06:28                  30  sort.rb
02/10/2014  12:42                 130  BUILD_INFO
12/03/2014  06:47             525,440  mruby.efi
12/02/2014  22:06               1,540  NvVars
          8 File(s)   1,590,595 bytes
          0 Dir(s)
FS0:\> mruby fib.rb
55
FS0:\> mruby sort.rb
1
2
4
10

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を再起動すべきである。

OSvのご紹介 2014年12月版

ご注意:OSvは絶賛開発中のプロダクトであるため、将来のバージョンではここに書いてある通り動かない場合があります。

OSvとは

OSvは、ハイパーバイザやIaaSプラットフォームへアプリケーションをデプロイすることに特化した軽量OSです。
Linuxで動作するいくつかのアプリケーションが動きますが、Linuxを使わずにフルスクラッチで実装されています。

詳しくはOSCの発表スライドを見て下さい。

提供される機能
  • Linux互換 libc API(一部のLinuxアプリケーションとの互換性)
  • position independentでビルドされたLinux/x86_64バイナリのロード&実行
  • ZFS
  • TCP/IP(IPv4 only)、DHCP
  • SMP
  • シングルプロセス/マルチスレッド
  • REST APIによるプログラマブルな管理機構
  • Luaで実装された簡易シェル
  • 簡易デプロイツール「Capstan」による1コマンドデプロイ&実行
対応アプリ
  • openjdk7, 8(特殊な操作を行う物以外殆どのPure Javaアプリケーションが動作)
  • cruby 2.1.5(テストされた一部のRubyアプリが動作)
  • node.js 0.10.31 (テストされた一部のサンプルプログラムが動作)
    • express
    • socket.io
  • mruby
  • lua
  • mysql
  • memcached
  • haproxy
  • redis
実行環境

OSvの使い方

ここではLinux KVMを対象とし、Linux環境で実行する例を示します。
それ以外の環境についてはWikiを参照して下さい。

Capstanのインストー
curl https://raw.githubusercontent.com/cloudius-systems/capstan/master/scripts/download | bash
prebuiltイメージの実行
capstan run -n 'bridge' cloudius/osv # Lua Shellのみのイメージを実行

capstan run -n 'bridge' cloudius/osv-tomcat # Tomcatのみのイメージを実行

capstan run -n 'bridge' cloudius/osv-cassandra # Cassandraのみのイメージを実行

capstan run -n 'bridge' cloudius/osv-memcached-opt # memcachedのみのイメージを実行

capstan run -n 'bridge' cloudius/osv-redis-memonly # Redisのみのイメージを実行

libvirtによってvirbr0がNAT用に準備されていないとコマンドの実行が失敗します。
この場合はネットワークに繋がったブリッジデバイスを準備して-b br0などとして指定して下さい。

Web UIへのアクセス

OSvインスタンス起動時に、

OSv v0.16
eth0: 192.168.122.163

のように割り当てIPアドレスが表示されます。
WebサーバはこのIPアドレスのポート8000に起動しているので、ブラウザでここへアクセスします。
正常にアクセス出来るとこのようなWebページが表示されます。

REST APIへのアクセス

RESTサーバはWeb UIのサーバと共用になっており、同じIP・ポート番号を使用します。
REST APIのドキュメントは http://:8000/dashboard/swagger/ にアクセスする事で得られます。
このWebページはJavaScriptによりREST APIを実際に実行してみることも可能になっています。

curlを用いてシェル上で試す場合、以下のようになります:

# js.jarをアップロードする
curl -X POST http://192.168.122.89:8000/file/js.jar -Fname=@js.jar

# 次回起動時のcmdlineを変更
curl -X POST -d cmdline="java.so -jar js.jar" http://192.168.122.89:8000/os/cmdline

# OSvインスタンスを再起動
curl -X POST http://192.168.122.89:8000/os/reboot

次回予告

REST APIのより詳しい使い方、CLIの解説、アプリケーションのデプロイ方法などについて解説していきます。

Baytrail-M NUC(DN2820FYKH)でFreeBSDが起動しなかった話・その後

http://www.slideshare.net/syuu1228/intel-nuc
の続きの話です。

CURRENTにマージされたbug fixはMFCって言って、stableへマージされて次のRELEASEに含まれる仕組みになってるっぽいんですが、このパッチも無事取り込まれたようで、次のRELEASE(10.1, 9.3かな?)に入るようです。

[base] Revision 267809
[base] Revision 267821

これでFreeBSD起動しねぇ!って騒がなくてすむね!

Macでもmruby-simplehttpserverをcapstanを使ってお手軽簡単にOSv向けにビルド&実行

前回の記事ではLinuxに絞ってcapstanを使ったmruby on OSvのビルド&実行方法を紹介しましたが、アプリケーションのコンパイルが他プラットフォームでは出来ないと説明しました。

代わりに、github上にビルド済みのアプリケーションバイナリを置いて、OS Xでcapstanを使ってOSvのイメージを作成&実行することに成功したので、これを紹介します。

brewで必要になるアプリをインストー

brew install go qemu git

環境変数を設定

echo 'export GOPATH=$HOME/go'    >>  $HOME/.profile
echo 'export PATH=$PATH:$GOPATH/bin'  >> $HOME/.profile
source  $HOME/.profile

capstanをインストー

go get github.com/cloudius-systems/capstan

mruby-simplehttpserver用のcapstanリポジトリをチェックアウト

git clone -b prebuilt https://github.com/syuu1228/capstan-mruby-simplehttpserver.git

リポジトリのビルド

QEMUのウインドウが一時的に表示されることがあるようですが、特に触らなくて問題ありません。

cd capstan-mruby-simplehttpserver
capstan build

VMの実行(VM上のポート番号80をホスト上のポート番号10080へ転送)

ハイパーバイザを指定しない場合VirtualBoxが用いられますが、正常に動作するようです。

capstan run -f 10080:80

http serverへのアクセステスト

curl http://127.0.0.1:10080/html -v

* About to connect() to 127.0.0.1 port 10080 (#0)
*   Trying 127.0.0.1...
* Adding handle: conn: 0xd0d8f0
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0xd0d8f0) send_pipe: 1, recv_pipe: 0
* Connected to 127.0.0.1 (127.0.0.1) port 10080 (#0)
> GET /html HTTP/1.1
> User-Agent: curl/7.32.0
> Host: 127.0.0.1:10080
> Accept: */*
> 
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: my-mruby-simplehttpserver
< Date: Mon, 19 May 2014 17:57:13 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 28
< 
<H1>Hello mruby World.</H1>
* Closing connection 0

matsumotory氏のmruby-simplehttpserverをcapstanを使ってお手軽簡単にOSv向けにビルド&実行する

OSvは最近capstanというビルド・デプロイツールが出来たので、以前のようにOSをビルドしなくてもアプリだけビルドしてVMイメージ作成&実行が簡単にできます。

ここでは、@matsumotory氏がブログで解説されていたmruby-simplehttpserver用のcapstanリポジトリを作成してみたので、インストール&実行方法を紹介します。

バイナリディストリビューションのインストール&実行はWindows・Mac・Linuxに対応していますが、今のところソースコードからアプリをビルドするにはLinuxが必要(公式対応ディストリはFedora 20)なので、以下の手順はFedora 20を使って説明します。

なお、この記事ではcapstan用リポジトリの作り方について詳しい解説をしていませんが、こちらにビルド設定定義ファイル「Capstanfile」のドキュメントがあるので、興味があれば読んでみて下さい。

GoとQEMUとgitをインストー

wget http://go.googlecode.com/files/go1.2.1.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.2.1.linux-amd64.tar.gz
sudo yum install qemu-system-x86 git

.bashrcに環境変数を追加

export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

capstanをインストー

go get github.com/cloudius-systems/capstan

mruby-simplehttpserver用のcapstanリポジトリをチェックアウト

git clone https://github.com/syuu1228/capstan-mruby-simplehttpserver.git

リポジトリのビルド

cd capstan-mruby-simplehttpserver
capstan build

VMの実行(VM上のポート番号80をホスト上のポート番号10080へ転送)

capstan run -f 10080:80

http serverへのアクセステスト

curl http://127.0.0.1:10080/html -v

* About to connect() to 127.0.0.1 port 10080 (#0)
*   Trying 127.0.0.1...
* Adding handle: conn: 0xd0d8f0
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0xd0d8f0) send_pipe: 1, recv_pipe: 0
* Connected to 127.0.0.1 (127.0.0.1) port 10080 (#0)
> GET /html HTTP/1.1
> User-Agent: curl/7.32.0
> Host: 127.0.0.1:10080
> Accept: */*
> 
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: my-mruby-simplehttpserver
< Date: Mon, 19 May 2014 17:57:13 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 28
< 
<H1>Hello mruby World.</H1>
* Closing connection 0

Linux上のmikutterでリンクをクリックしたら別のLinux上のブラウザで表示する方法

Linux上のmikutterでリンクをクリックしたらMac上のブラウザで表示する方法 - かーねる・う゛いえむにっきの続きですが、「いや、おれMacとか使ってねぇし?不自由なOSユーザー氏ね!」みたいな声が聞こえてくる気がする*1ので、Linuxでも出来るかどうか考えてみました。
で、なんか10秒くらい考えた結果、出来そうなのでここに書いておきます。

基本的な設定は前回の記事と全く同じなのでそちらを参照して下さい。
シェルスクリプトだけ違うものを使います。

cat > open <<EOS
#!/bin/sh
ssh teokure.local env DISPLAY=:0.0 xdg-open $*
EOS
chmod +rx open

あんまりしっかり試してないけど多分これで大丈夫

*1:完全な被害妄想