[Linux] arm と arm64

64bit ARMプロセッサ

携帯機器のほぼ標準となっている ARM プロセッサは、32-bit の v7 アーキテクチャから 64-bit の v8 アーキテクチャに移行しつつあります。とはいえまだソフトウェアは v7 アーキテクチャ向けに書かれたものばかりですので、いきなり移行することはできません。そのため、32-bit と 64-bit を保護レベルの切り替え時にモード切替することができるようになっていて、互換性を保つように設計されています。x86 プロセッサも全く新しい IA-64 アーキテクチャを発表したものの、後で AMD が amd64 アーキテクチャで 32-bit と互換性を保つ技術を導入し、Intel が同調した経緯があります。

boot 時は 64-bit(AArch64) で起動した場合、EL1(OSレベル)やEL0(userレベル) に切り替える際に 32-bit(AArch32) モードを選択することができます。

Linux の互換性

Linux では ARMv7 までのアーキテクチャを「arm」、ARMv8 アーキテクチャを「arm64」と別々のアーキテクチャで扱っています。一方 gcc ではARMの呼び名に合わせてそれぞれ「AArch32」「AArch64」と区別しているので注意が必要です。

arm64 kernel  では、CONFIG_COMPAT を有効にすることで  userland で AArch32 ELF バイナリを起動したときに AArch32 モードに切り替えて実行できるようになっています。arch/arm64/Kconfig には以下のように説明書きがあり、モードの切り替えだけでなく syscall や VFP サポートなどの基本的な機能もアーキテクチャの差異をを超えてサポートされています。

config COMPAT
	bool "Kernel support for 32-bit EL0"
	depends on ARM64_4K_PAGES || EXPERT
	select COMPAT_BINFMT_ELF
	select HAVE_UID16
	select OLD_SIGSUSPEND3
	select COMPAT_OLD_SIGACTION
	help
	  This option enables support for a 32-bit EL0 running under a 64-bit
	  kernel at EL1. AArch32-specific components such as system calls,
	  the user helper functions, VFP support and the ptrace interface are
	  handled appropriately by the kernel.

	  If you use a page size other than 4KB (i.e, 16KB or 64KB), please be aware
	  that you will only be able to execute AArch32 binaries that were compiled
	  with page size aligned segments.

	  If you want to execute 32-bit userspace applications, say Y.

AArch32 ELF バイナリを arm64 kernel で動かすには、次に示すようにいろいろ準備や注意が必要になってきます。

shared library の対応

単純に AArch32 ELF だけの root filesystem であれば何もする必要はないのですが、AArch64 ELF と共存する環境を作る場合は両方の shared library を用意する必要があります。debian などの distro であれば設定で解決できますが、ここでは構成を知るためにとりあえず手動で作る場合を考えてみます。

まず AArch64 ELF の sysroot (sysroot64/) を基準に sysroot をコピーし、AArch32 ELF の sysroot (sysroot32/) からライブラリをコピーします。

$ cp -pr sysroot64         sysroot
$ cp -pr sysroot32/lib     sysroot/lib32
$ cp -pr sysroot32/usr/lib sysroot/usr/lib32

kernel からプロセスとして ELF バイナリを起動する際に、依存関係のあるライブラリは共有ライブラリをリンクします。
その際に動的リンカ(ld.so)が呼び出されますが、このリンカを ELF のアーキテクチャごとに用意しておくことで、マルチアーキテクチャに対応できます。上記の例の場合、AArch32 ELF のローダを /lib に置きます。/lib にはもちろん AArch64 ELF ローダもあります。

$ cp sysroot32/lib/ld-linux-armhf.so.3 sysroot/lib
$ ls -1 sysroot/lib/ld*
ld-2.23.so
ld-linux-armhf.so.3
ld-linux-aarch64.so.1

ターゲット環境ではライブラリの検索パスを指定します。AArch64 ELF と AArch32 ELF の両方のパスを指定しておけば、実行時に自動的に判別して検索します。

# export LD_LIBRARY_PATH=/lib:/usr/lib:/lib32:/usr/lib32

これで arm64 kernel で AArch32 ELF バイナリを起動することができます。

 

device driver の対応

ioctl() は通常 struct file_operations の .unlocked_ioctl メンバに登録した関数を呼び出しますが、異なるアーキテクチャの場合は .compat_ioctl に登録した関数が呼ばれます。この時、引数が 32bit 定義でやってくるので .compat_ioctl 登録関数にて引数や戻り値を変換する必要があります。struct file_operations は linux/fs.h に定義されています。

struct file_operations {
        :
        long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
        long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
        :
};

また、ARM Linux が ILP32 (int/long/pointerが32bit) である一方、arm64 Linux は LP64 (long/pointerが64bit、intが32bit) を採用しています。そのため、sizeof で得られる型のサイズがアーキテクチャによって変化します。これを引数に使うと意味が変わってきます。
特に 第二引数の cmd は マクロ _IOC() を使って定義しますが、定義内に sizeof() を使うためそのままでは 値が変わってしまうことになります。

#define _IOC(dir,type,nr,size) \
        (((dir)  << _IOC_DIRSHIFT) | \
         ((type) << _IOC_TYPESHIFT) | \
         ((nr)   << _IOC_NRSHIFT) | \
         ((size) << _IOC_SIZESHIFT))

#define _IOC_TYPECHECK(t) (sizeof(t))

例えば以下の定義を kernel/user で共有した場合、

#define HOGE_IOC_TEST    _IOC(_IOC_WRITE, 'H', 0x00, long) 

アプリ側からみた HOGE_IOC_TEST は 0x40044800 で ドライバ側から見た HOGE_IOC_TEST は 0x40084800 になり、cmd を正しく判別できなくなるため、型サイズが変わる引数を避けるか .compat_ioctl で cmd をマスクして判別する必要があります。

また、第三引数を構造体へのポインタとする場合にも注意が必要になります。構造体のメンバのメモリ位置やサイズもアプリとドライバで変わってしまう上、packed struct 属性を付けたりすると変換が複雑になってしまうため、避ける必要があります。

[Linux] device tree について

2.6.32 から 4.4 へ

Linux driver の参考書は kernel 2.6.32 辺りの知識で書かれていて,組込みの世界ではあまり新しい kernel を積極的に取り込まないこともあって,私がいる部門でも長い間内部で保持されてきた kernel を使って driver を書いていたのですが,独自の分岐で進化した kernel を maintainance する人材もいなくなり,昨年からいろいろ一新する上で kernel も vanilla kernel に追従することになりました.

昨今では自社向けソースをすべて内部で抱え続けるのも難しく,外に公開していける部分は OpenSource に貢献して協力関係を築いていくのも至極当然の流れでしょう.何故今までそうして来なかったのか不思議なくらいですが…という前置きはおいといて,そんな 2.6 時代の知識から突然最新 LTS の v4.4 の開発手法や kernel API に刷新する必要が出てきたわけです.

device tree とは

最もインパクトがあったのは device tree の導入でした.eLinuxの解説に記載がありますが,OpenFirmware の ePAPR 仕様で規定されているものを元にしたデバイス固有情報を記述するフォーマットです.Linux 以外にも FreeBSD や U-boot でも採用されていて,標準化の動きがあります.
(OpenFirmware とか PAPR と聞くと Mac 互換機の CHRP や BeOS を思い出してしまうのですが…)

実際の記述方法は devicetree.org の文法解説や Linux source の Documentation/devicetree/bindings/ に記載されていますが,実際の arch/arm/boot/dts/ 以下の各 SoC 向けソースが参考になります.

device tree の driver への取り込み方

device tree を導入すると,driver 側の記述の仕方も変わってきます.元々 module_init() や module_exit() で最初と最後を書くだけだったのが,device tree から情報を取り込む操作が必要になるわけですが,その操作は platform driver の framework がベースになります.

例えば,以下のように device tree に foo driver の記述を行うとします.識別文字列の他に,使いたいレジスタアドレスとサイズが書かれています.

/ {
    foo {
        compatible = "hoge,foo";
        reg = <0x12340000 0x200>;
    };
}; 

platform driver は,起動関数・終了関数・識別テーブルを定義します.

static struct platform_driver foo_driver = { 
    .probe  = foo_probe,
    .remove = foo_remove,
    .driver = { 
        .name = "foodriver",
        .of_match_table = foo_of_match,
    },
};
module_platform_driver(foo_driver);

識別テーブルの方は compatible で device tree に適合する識別文字列を定義します.

static const struct of_device_id foo_of_match[] = { 
    { .compatible = "hoge,foo",},
    {},
};
MODULE_DEVICE_TABLE(of, foo_of_match);

このように定義しておいて,起動関数 foo_probe() では device tree の情報を取り込んで,実際の動作に反映させていきます.

static void __init foo_probe(struct platform_device *pdev)
{
    sturce resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    void __iomem *vptr = devm_ioremap_resource(res);
    :
}

この他にも device tree 情報を取り込む platform 関数や of 関数はたくさんあり,方法もさまざまです.
一つサンプルを作って自分なりに確立しておくのが良いかと思います.

[Linux] process と CPU割り当て

CPU migration

Linux では SMP 構成をとる場合,できるだけ CPU を公平に使うようにスケジューリングされます.そのため,各プロセスの CPU 使用率を元に再スケジューリングのタイミングでプロセスの CPU migration (CPU 間の移動)が発生します.

migration で CPU 間をプロセスが移動するためには,一度動作を止めてコンテキスト(レジスタや状態情報など)を移動させて再開,という処理が行われますが,キャッシュ共有する「CPUコア間」に比べて共有しない「CPUクラスタ間」は移動にかかる時間が掛かるため,移動に重みづけしてスケジューラが次の CPU を判断します.

migration 動作を見る

ではプロセッサの migration でどうやって動いてるんだろう,と*手っ取り早く*調べたいと思ってたところ,
busybox の ps では CPU 割り付けが扱われないため,procps パッケージの ps を使うと確認できました.

$ ps -eo pid,psr,comm

ということで,下記のような shell script で回しておけば,出力ログを加工してグラフ化することで遷移の可視化もできます(かなり古典的手法ですが).

#!/bin/sh
(
    while :; do
        ps -eo pid,psr,comm | grep $PROG;
    done
) | awk '{print $1,",",$2}'

CPUやスケジューリングポリシーを指定

プログラムで直接 sched_setaffinity() や sched_setscheduler() を呼び出せばいいのですが,常にプログラムを書き換えられるわけではないので,できれば shell で指定できる方が都合がいいです.util-linux パッケージを使うと可能になります.

taskset で起動プロセスの CPU を固定することができます.例えば CPU1 でプロセスを起動したい場合は
以下のように指定します.

$ taskset -c 1 PROG

chrt で起動プロセスのポリシーを指定することができます.例えば SCHED_FIFO の priority=50 で
起動したいなら次のようにします.

$ chrt -f 50 PROG

また,kernel の起動オプションで ‘isolcpus’ を付けてCPUを指定すると,そのCPUはプロセスのCPU割り付け対象から外されます.全ての CPU を指定すると全て CPU0 でプロセスを起動するようになります.SMP 構成ながら Asymmetric に CPU を使うこともできそうです.

isolcpus=0-3

余談ですが…

SMP 構成の組込みシステムの場合,応答速度や処理量で破綻する可能性があるのであまり CPU を移動するのはうれしくないですが,特定の CPU に処理が集中するのも不利になるため適度に分散させたいため,スケジュールポリシーの選択は重要になってきます.

SCHED_FIFO,RR や CPU 割り付けを固定で行うこれまでのリアルタイム設計は複雑なシステムになるほど不都合になるため,SCHED_DEADLINE (EDF) や新たに提案されている Energy-Aware などの heuristic スケジューリングにも期待したいところです.

VMware Player 環境の再構築

システムの置き換え

これまで HDD 2台でそれぞれ Windows, Ubuntu を置いて、Windows から VMware で Ubuntu を起動していました。システムドライブを SSD に置き換えるにあたり、Windows も Ubuntu も SSD に置くことにしたのですが、ここでハマってしまったので記録しておきます。

Windows7 のインストールの際に SSD(250GB) を NTFS と ext4 に分けることを想定してパーティションを設定し、Windows7 のインストール、Windows10への upgrade、VMware Player のインストールまでは特にハマるところはなく進みました。

仮想環境の構築に失敗

VMware Player で仮想マシンを作成し、以前と同じように設定した後、HDD は IDE 物理ディスクの「PhysicalDrive0 のパーティション3(ext4想定の空き)」を指定して Ubuntu Desktop のインストールを開始。

後半で Grub のインストール先を指定しますが、上記インストールパーティションを指定すると失敗します。Grub は MBR にインストールするものですが、VMware は物理ディスクの場合もブート時に MBR を見に行くためそのままでは失敗します。

Grub は基本パーティションの Linux FileSystem にある /boot/grub/ を見に行くため、最初に Linux をインストールしてから Windows をインストールすれば解決しそうですが、Grub から Windows を起動すると、VMware Player の Grub からホスト OS のWindows が選択できてしまうためこれは惨事になるのが予想できます。

もう一つのシステムディスク登場

結局、SSD の MBR に Grub をインストールせずに VMware Player から論理パーティション上の Ubuntu が起動するには、もう一つディスクを用意して MBR を Grub にすればよいわけですが、仮想環境なので仮想ディスクを使えばよいわけです。

VMware Player で「仮想マシンの設定の編集」→「(ハードウェアタブ)追加」→「ハード ディスク」で通常のディスクを作成し、Grub が起動できればいいので “とりあえず” Ubuntu Server をインストールしました。Grub はこの仮想ディスクである /dev/sdb の MBR にインストールします。

物理パーティションOSの起動

この時点で VMware Player から Grub 経由で Ubuntu Server が起動しますし、物理パーティションの Ubuntu Desktop も認識しているので、メニューから選択すれば起動できます。しかしこちらがメインなので timeout してすぐに起動するように設定します。Grub の設定を行う Ubuntu Server 側で以下の設定値を変更します。

$ sudo vi /etc/default/grub
-GRUB_DEFAULT=0
+GRUB_DEFAULT=4
-GRUB_TIMEOUT=10
+GRUB_TIMEOUT=3
$ sudo update-grub

GRUB_DEFAULT はメニューのデフォルトの選択値です。私の環境では4つ目に Ubuntu Desktop があったので “4” を指定しています。また、GRUB_TIMEOUT は自動選択までの待ち時間で 3秒に設定し直しています。最後に update-grub で /boot/grub/grub.cfg を更新します。

これでめでたく SSD の Ubuntu Desktop が起動できました。これまで使っていた HDD も「IDE 物理ディスク」として設定してマウントすることでそのまま使うことができます。

 

Firefox Developers Conference 2015 in Tokyo

去年に引き続き Firefox の開発者向けカンファレンスに参加してきました。当初doorkeeperで申し込んだ時には300の枠が350に増員された状態で30人待ちだったので,先週に続いての東京遠征だったこともあって諦めてたのですが,まさかの増枠で参加登録が有効になったのでこれは行くしかない,というわけで懇親会込みで日帰り参加となりました.

IMG_9368

午前はキーノートスピーチ,会場は赤と青の光の演出とBGMで盛り上がりました.今回は物議を醸してなかなか実現されなかった iOS版Firefox のリリース直後とあってまずはその話題から.さらに TV のリリースや IoT 機器などへフィールドを広げつつある Firefox OS,全プロダクトで重視されるセキュリティ機能の強化,Android への FxOS Preview のリリースなど,Mozila v1.0 から11年の成果が紹介されました.

独り言: ふと思い返すと,初めて Sun4 で使って衝撃を受けた Netscape Navigator v1.0 が 1994 年だから,あれから21年か…

昼にはiOS版Firefox 宣伝カー”MozBus”がお目見えしてました. 運転席にはフォクすけくんもいます.IMG_9371

午後の Breakout session はテーマに沿って最新技術や動向の紹介を実際のデモなどを交えながらの講演で,バリエーション豊かな話をたくさん聞けました.以下,聴講セッションの感想など.

  • 「鉄腕アニメーション」
    • CSSによる動きの付け方やアニメの考え方を元にMainThreadとCompositor の役割を解説.Compositor の役割は非常に分かりにくいけど,それをセル画のイメージで分かりやすく表現されていた
  • 「Inspection & tweak: Firefox を使ったフロント開発」
    • JavaScript の動作をリアルタイムに覗いたり変えてみたりするデバッグツールの紹介.Web開発も動作の脳内シミュレーションでは限界なので,見える化・変更の効果・ネットワーク状況が分かるツールはありがたい
  • 「Porting C/C++ code to Web」
    • LLVM経由でJavaScript に変換するemscriptenの紹介とWebAssemblyの動向.JavaScriptを書くだけではユーザも限られ速度も厳しいのでnativeに走りがちだが,如何にC/C++のアプリをWebに持ってくるかという興味深いテーマ
  • 「The Web for Everyone – Let’s fix it」
    • Firefox で正しく表示されないサイトを CSS の記述事例を交えて紹介.行儀の悪いサイトをバッサリ切っていったのは面白かった.CSS の見た目チェッカー的サイトも運用される模様
  • 「Embedded Web で加速する Web of Things」
    • TV・サイネージ・車載でのWeb技術の標準化動向や車のデータ取得の応用など.後半は発表者の方の趣味満載だったが,車ですらも hack 対象にできるのは衝撃的だった.時間が足りなかったがもう少し活動の話は聞きたかったかも

IMG_9377

写真撮影の後に懇親会に参加.mozillaスタッフの方々やcommunityの方々ともいろいろ話ができて(フォクすけくん争奪戦は今回も残念でしたが),参加して楽しいお祭りでした.

 

ALL ABOUT マイコンBASICマガジン

かなり更新が滞っていましたが,久しぶりの更新ということで少し毛色の違う話を.

先日,秋葉原の「アーツ秋葉原」にて「ALL ABOUT マイコンBASICマガジン」トークイベントに参加してきました.30数年前に創刊され当時のマイコン少年・パソコン少年の愛読書だったマイコンBASICマガジン.ものづくりやプログラミングの原点になった雑誌である存在で,今活躍している技術者やクリエーターの中にも少なからずプログラムリストを打ち込んでいた人やゲーム攻略をしていた人も多いと思います.

とはいえこのイベント,30分かそこらで450枚完売という大変な人気ぶりでした.会場は小学校を改装したイベントスペースでその講堂が使われ,雰囲気からしてなんだか同窓会的な気分にも.IMG_9319

構成は第一部が編集部の方々のトーク,第二部がスタープログラマーの方々のトーク,第三部がゲームライターの方々のトークで,5時間を超える長丁場でした.内容についてはネタばれ自粛ということなので感想に留めるとして,参加した方々のコメントなどは twitter の 「#ベーマガ」辺りを追跡してください.

IMG_9327

  • 第一部の編集部トーク.私も PROFILE にある通り投稿者の一人でいろいろ掲載していただいたこともあって,寸評である”CHECKER FLAG”欄でコメントされるのがうれしかったのですが,それを書いていた編さんや影さんの話が聞けたのは感動ものでした.
  • 第二部のスタープログラマートーク.BASICマガジンの読者なら必ず知っている方々で,作っていた方々の思い出話は同じ時代を同じように過ごしていたこともあって,機種や分野は違っても通じるものがありました.
  • 第三部のゲームライタートーク.BASICマガジンといえば当時のゲームセンターのゲームやパソコンAVG(アドベンチャー)のレビューは類を見ないものがありました.あの影響でnamcoのゲームをひたすら追いかけた時代もありました.

帰り際,ほぼ最後尾で出演者の方とご挨拶の場もあり少し話しさせていただいたのですが,当時の雑誌に掲載されていた「あの」人たちに会えたのは感無量でした.

掲載された号は今でも大切に保存しています.当時の話やその後の話を書き始めるといつまで続きそうな気もするので,ひとまずこの辺で.

IMG_9341IMG_5804

 

 

au Firefox OS Event

Fx0 発表会

12/23 にベルサール渋谷ファーストにて KDDI Fx0 発表会 に参加してきました.会の内容については各ニュースサイトで詳しく紹介されていますし,ニコ生で中継・録画放送されてますのでそちらをどうぞ.

image001image002image003image004

 

田中社長の発表はもったいぶらせながらも期待させる面白いものでした.他の発表会は見たことがないのですが,非常に楽しませていただきました.

舞台の裏では発表会に続いて行われるハッカソンの発表がありました.実はFirefoxOSでハッカソンってどんな形のものができるんだろうかとかなり興味がありました.各チームとも,UI やサーバ,デバイスとのブリッジとしての開発のしやすさや応用のしやすさを十分活用していました.ただ,会場の Wi-Fi の channel が専用に確保できなかったために,パケットが飛ばずに期待通りの動きが見られなかったのはちょっと残念でした.大きな会場でデモ機をシナリオ通り動かす難しさは痛いほどよく分かりますが,報道や一般の方々に面白い試みがいろいろ詰まってたことは伝わりましたかね?

懇親会では…

イベント終了でゲスト参加者として懇親会にも参加させていただきました.会場にはハッカソンの機材展示や Fx0・OpenWebBoard の実機紹介などもあって,アイデアを気軽に具現化する手段や機材が揃いつつある感じでした.ハッカソンのシマダイチームの方々と歓談して発表の苦労なども聞かせていただきました.

そして最後にBINGO大会もありました.1等が Fx0 本体,2等がフォクすけくん,3等がモバイルセットで各3つずつと,なかなかの大盤振る舞い.まぁこの手の BINGO で揃ったことはないんですが,今日はなかなか調子よく開いていって,リーチからすぐBINGO!

抽選くじを引いて見事に 1等 Fx0 本体が当たってしまいました(^^)

Mozilla CTO の Gal さんから直接手渡され,Congratulation! の言葉をいただきました.発表会の雰囲気を味わえただけでなく,Christmas Present までいただいてわざわざ遠出して来た甲斐がありました.KDDI さん Mozilla さんありがとうございました (_o_)

FirefoxOS Advent Calendar 2014 (18日目)

今日は Firefox OS Advent Calendar 18日目です.

初参戦ですが登録したからには何か記事になることをしないと,ということで,メインストリームで進めていた「FirefoxOS on AndroidStick」を軽くまとめつつ今年の活動を振り返りたいと思います.

久しぶりの「動かしてみる」

元々異なるプラットフォームで何か動かしてみる活動はかなり古くからやっていたのですが,去年の後半に何気なく安価だったので入手した「Android Stick」 と,Simulator で軽く遊ぶだけだった「Firefox OS」の組み合わせを思いついて,久しぶりの「動かしてみる」活動でした.

動かしてみるためにはまずどういう構造なのか・仕組みなのかを知るためにソースを読むわけですが,Gecko-Gonk層の境界を中心に断片的ながらそこそこ読んだものの,各デバイスの機能を UI から理解するために  C++ と JavaScript の境界を越えて(XPCOMやjs-ctypesなど)読むのは非常に苦労しました.

Gonk 層が AOSP ライブラリをベースにしているおかげで,Android が動いていれば取っ掛かりはスムーズ,しかしドライバやベンダ提供ライブラリは公開されず binary だったりするので,Android の想定で作られた前提がことごとく崩れてややこしい問題が現れてくるのです.これを日々叩くために Gecko を試しにいじって反応を見る作業を続け,不安定ながらなんとか動いてるのが現状です.

動かしてみた結果は 関西勉強会と Developers Conference 懇親会 で LT にて報告させていただきました.結構関心を持ってもらえたものの,結局まだ動いてる機体はどこにも公開してないんですね…未だに起動するだけでも console 操作が必要でそこそこ手間だったり,HDMI 出力先が必須なのが今の課題です.

今の活動成果についてはこの Advent Calendar に間に合わせるべく(event駆動型開発!),強引に GitHub に登録してビルド編としてなんとか公開してみました.かなりの長文ですが興味のある方はどうぞ.

仕事でも FirefoxOS?

組込み機器の仕事をしてるので,ボードやチップを扱ってるおかげで目の前の試作機材でも時間があるときに FirefoxOS を動かしたりしてました.割と独自仕様なのでいろいろ苦労したのですが,タッチパネルと Wi-Fi, 動画再生, WebGL 辺りまではなんとかなったのでデモ機レベルまで持っていったものの,軌道に乗せる前に公開することもなくお蔵入りになってしまいました.とはいえ成果の一部は某六本木方面に持ち込んだとか何とか;-)

Flame 端末も購入

やはりちゃんと動く例も見ておきたいので Flame 端末は買いました.普通は update を待たないとなかなか進化しないのですが,build 手順が分かっててすんなり build ROM が入るのはいいですね.適当に作ってた HTML5 を試すデモアプリも簡単に想定通りに動くのはなかなかいい環境です.下回りのドライバやカーネル開発ではこうも行きませんから…

さて次のtargetは…

今年後半はほとんど時間が取れず,来年はさらに環境がすっかり変わってしまってしまうのですが…そんなことはともかく(仕事と同じで)下回りばかりやってても進歩がないので,FirefoxOS の活動にもう一歩踏み込んで,前からやろうと思ってた HTML5 からのデバイス制御辺りは試していきたいと思う次第であります.

 

FirefoxOS on Android Stick (ビルド編)

はじめに(言い訳)

ここのところなかなかネタを書く時間が取れなくて久々の更新です.今回は今年公開して FirefoxOS をいろいろいじる契機になった FirefoxOS on Android Stick のビルド話を書きたいと思います.

前に書いた記事のころはまだ試行錯誤を繰り返して動かしていてビルド手順はかなり難しく再現も難しかったので,最新の Stick を手に入れてそちらに移行してからにしようと思っていました.しかし新機種(MK802IV)は Kernel config に手を入れないと FirefoxOS では使えなかったため kernel のビルドからやり直してたのですが,これが全然思い通りに起動せず,結局いじる時間もなく放置してしまうことになり,さらに悪いことに FxOS 2.x の tablet 未対応が直らず,結果として旧機種(MK808B)の更新も停まっていたのでした.

ということで,年末のこの機会に一度ビルド手順を見直して,なんとか共有できるところまで持っていこうとした顛末です.Stick の個体とか開発環境の差とか面倒なところは無視してるので,この手順を見ても全然動かないかもしれません.まぁこんな風にやってるんだなという雰囲気でお願いします.

ちなみにこれを機会に GitHub の放置アカウントにようやく手を入れました:-)

まずは開発環境の準備

MDN:Firefox OS ビルドの必要条件 を準備してください.これはどの機種のビルドも同じです.

ソースの入手

当然ながら B2G 本体は Stick を選ぶことができませんから,自前で用意した repogitory から取ってきます.config.sh を実行すると,機種依存部分以外は全て他プロジェクトから取って来る形です.今取ってこれるのは v1.4 だけにしています.

% git clone https://github.com/kuni6800/B2G.git
% cd B2G
% git checkout --track remotes/origin/rkand
% GITREPO=https://github.com/kuni6800/b2g-manifest BRANCH=rkand-v1.4 ./config.sh rkand

Android ライブラリの入手

Gonk 層に当たる HW 依存部分はベンダーからリリースされる Android 向けライブラリを使います.SoC提供会社からバイナリ提供されるのが基本ですが,MK808B は ROM image でしか公開されておらず再配布条件が確認しづらいので,本体から持ってくることにします(調べてみると github のいくつかで普通に上がってるけど…公開できるのだろうか?).

Android ライブラリをツリーに用意します.adb などを駆使して Android 本体の system/ 以下を device/rockchip/rk30board/proprietary/system/ 以下に持ってきます. 全部持ってくる必要はなく,実際に必要なファイルは device/rockchip/rk30board/proprietary/release.mk に記載しています.または Finless ROM などにある system.img を mount -o loop で直接マウントする手もあります(お勧めしませんが).

パッチ当てとビルド

build.sh でそのままビルドできればいいんですが,以下のような厄介な問題

があって手動で作業する必要があります.これら差分は github で fork して作業したものを公開してもいいのですが,バージョンに依存するかなり暫定なものなのでとりあえずパッチの形にしています.

まず「xdelta」を apt-get などでインストールしてください.その後,スクリプトを実行してパッチを当てます.

% pushd device/rockchip/rk30board/patches
% ./patch.sh
% popd

なんだか失敗してしまったようなら,patch-rev.sh で戻してから原因を追ってください.

あとは失敗しないことを祈りつつ build.sh を実行して暫く待ちます.

% ./build.sh

アーカイブを作成

めでたくエラーなしでビルドが完了したら,アーカイブを作ります(ROM を作らないのは PicUntu(Linux) を使うため).archive.sh を実行すると「b2g-rkand-(日付8桁).tar.gz」 のファイルが出来上がります.

% ./archive.sh

 PicUntu kernel の Recovery への書き込み

PicUntu のインストールはすでに紹介していますので,こちらを参照ください.MK808B の PicUntu は元の Android を壊さずに recovery 領域に kernel をインストールするのでいろいろ面倒ですが,ファイルシステムは SD カードなのでPCでファイル変更できるという融通が利きます.

ファイルシステムの micro SD カードへのインストール

micro SD カードを用意して PC に挿して,Linux 上でファイルシステムを作ります.予め dmesg などで SD カードのデバイス名(以下 sdX) を確認しておきます.

microSD カードへのパーティション作成とフォーマットを行います.この例では全ての領域を1つのパーティションで設定しています.くれぐれも microSD カードの中身はバックアップしてから実施してください.

% sudo fdisk /dev/sdX
コマンド: p<CR>    # 情報確認
コマンド: d<CR>    # パーティション(全)削除
コマンド: n<CR>    # パーティション作成
Select: p<CR>     # プライマリ
パーティション番号: 1<CR> # →パーティション1
先頭セクタ: <CR>   # →先頭から
Last セクタ: <CR> # →末尾まで
コマンド: w<CR>   # 書き込み
% sudo mkfs.ext4 -L linuxroot /dev/sdX1

microSD カードのフォーマットができたら,マウントしてアーカイブを展開します.先ほどの FxOS のアーカイブもここで展開します.

% mkdir linuxroot
% sudo mount -t ext4 /dev/sdX1 linuxroot
% sudo tar -C linuxroot -zxvf picuntu-linuxroot-0.9-RC3.tgz
% sudo tar -C linuxroot/root -zxvf b2g-rkand-xxxxxxxx.tar.gz

PicUntu 起動してから FxOS を起動するため,その起動用スクリプトを作成します.スクリプトの2行目はConsoleの停止,3行目は画面サイズの変更,4行目は FxOS への切替です.

% sudo cat > linuxroot/root/start_b2g.sh
#!/bin/sh
echo 0 > /sys/class/vtconsole/vtcon1/bind
fbset 1280x720-60-32 -a
chroot /root/root /init
<Ctrl-D>
% sudo chmod +x linuxroot/root/start_b2g.sh

最後にアンマウントして microSD カードを取り出します.取り出したカードは MK808B 本体に挿しておきます.

% sync
% sudo umount linuxroot

Recovery モードでの起動

ようやく本体の起動です.ただ,Android を残していたためそのままでは Android が起動しますので,Recovery モードで起動しなければなりません.困ったことに MK808B には外部操作で Recovery モード起動する方法がなく,以下の方法を取らざるを得ないのが現状です.

  • ターミナルアプリをインストール,ターミナルから「adb reboot recovery」を実行
  • Reboot.apk を導入して「Reboot Recovery」を選択
  • 設定でIPアドレスを調べて「adb connect <ipaddress>」で接続,「adb reboot recovery」を実行

FirefoxOS の起動

PicUntu kernel が起動すると,暫くして Console に login prompt が出ます.アカウントは root,default password は「12qwaszx」 です(公式情報).

ログインできたら,先ほどのスクリプトを起動します.

% ./start_b2g.sh

初回にかなり時間が掛かります.不安定なので Crash Report が出るかもしれませんが,画面が出れば成功です.

最後に

まだまだよく分からない作業が途中にたくさん入っていて,「すぐにやってみる」には程遠いですね.せめて PicUntu や Recovery を使わないで ROM 焼きだけで直接起動したいものです.

また,Android ライブラリ(gralloc.so)の使い方が FirefoxOS では違うのか,エラーが出てメモリリークしてすぐに固まってしまうようです.メッセージからソースがあればすぐ分かる感じなのですが,バイナリ部分なのでもどかしいところです.

これから他のいろんな端末で FirefoxOS の起動に挑戦する方が居られると思いますが,その何かの助けになればいいなと思います.

FirefoxOS v2.1 と tablet 指定

以前、v2.0 を試した際に「アイコンがでかい」という残念な結果を見たわけですが、先日の勉強会でネタ話にしていたところ、「確か tablet ビルドがあったような」ということで確認してみました。

Gaia のデバイス指定

gaia の Makefile を見ると、デバイス種別を指定するところがありました。phone が指定されていたからアイコンが3列、というのは何となく納得。

GAIA_DEVICE_TYPE := phone

Bugzilla にもBug 1010128 にて tablet が追加されているようです。これは試してみないと。

v2.1 へのアップグレード

tablet ビルドを試す前に、v2.0 から v2.1 に上がったこともあって(phoneのまま)そちらを先に試してみました。すると

マウスカーソルが動かない

という事態に。これは phone だからなのか、修正で何かトラブルなのかは追跡できてないですが、動きを見てると「マウス押す」→「マウス移動」→「マウス放す」という動作でしかカーソルが動かないので、もしかしたらタッチスクリーンの動作に引っ張られてそうな感じです。

v2.1 では新クラス GeckoTouchDispatcher が出来て nsAppShell にあった MouseEvent 処理がそちらに移動したので、その影響でマウス処理が正常にできていないのではないか? と思われます。マウス使う人が増えないとこれは当分直らないか…

tablet ビルドを試す

v2.0 で GAIA_DEVICE_TYPE=tablet のビルドを試したところ、まだ用意しただけで何もできないようで、アイコンも何もない画面で、Notification の Setting すら起動できない状態でした。
No Icon on v2.0 tablet

v2.1 で GAIA_DEVICE_TYPE=tablet のビルドではようやく v1.4 で見たアイコンが出現し、横スクロールができるようになっています。ただし、上記のようにマウスがまともに動かないので先に進むことすら困難な状態です。
appear icon on v2.1, but freeze cursor

ところで、tablet ビルドは以前通り横スクロール、phone ビルドは縦スクロールなので、端末の形態により UI のポリシーは変わっていくようです(今のところ)。ちなみにTVデバイス向けの tv ビルドも用意されているようです。