2010年03月01日
AndroidのエミュレータをNFSroot化する
おおまかな流れ
- Androidのビルド
- kernelのビルド
- NFSroot化のための変更
Androidのビルド
Ubuntu 9.04 (x86_64)で行いました。
http://source.android.com/download
またはUbuntu 9.04でandroidのビルドを参照して必要なファイルをインストールしてください。
ソースの取得
$ mkdir mydroid $ cd mydroid $ ANDROID_TOP=$PWD $ repo init -u git://android.git.kernel.org/platform/manifest.git $ repo sync
ソースを置いたディレクトリを$ANDROID_TOPとします。
ビルド
$ source build/envsetup.sh $ lunch (そのままリターン入力) $ make -j4 > make.log 2>&1 & $ tail -f make.log
私の環境ではビルドに26分かかりました。(Core 2 Quad Q9550 @ 2.83GHz)
動作確認。
-show-kernelをつけるとkernelのログが見られます。
$ emulator -show-kernel
別の端末で以下を実行するとユーザーランドでのログが見られます。
$ adb logcat
kernelのビルド
Androidのkernelのコンフィグの確認
さて、現在実行中のkernelはNFSrootに必要なコンフィグになっているでしょうか。emulatorを実行中に以下のコマンドでkernelのコンフィグファイルを取得します。
$ adb pull /proc/config.gz $ zcat config.gz |less
NFSのクライアントが無効になっていました。なのでkernelのソースもとってきてリビルドします。
カーネルのリビルド
$ mkdir kernel $ cd kernel/ $ git clone git://android.git.kernel.org/kernel/common.git $ cd common $ git checkout -b android-goldfish-2.6.29 origin/android-goldfish-2.6.29 $ export ARCH=arm $ export CROSS_COMPILE=../../prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi- $ make goldfish_defconfig $ make menuconfig $ make -j4 2>&1 |tee make.log
make menuconfigでは以下の項目を有効にします。
File systems ---> [*] Network File Systems ---> [*] NFS client support [*] NFS client support for NFS version 3 [*] Root file system on NFS
ビルドしたカーネルの動作確認
$ emulator -kernel kernel/common/arch/arm/boot/zImage -show-kernel
NFSroot化のための変更
qemuの変更
emulatorの中からqemuのメイン関数を呼んでいるので、そこに渡される引数を変更します。
-initrd, -nand のオプションをはずして
-append のオプションに以下のパラメータを追加します。
"root=/dev/nfs rw nfsroot=$ANDROID_NFSROOT ip=dhcp init=/init"
このためのソース修正のパッチをこのページの最後に置いておきます。この修正をして$ANDROID_TOPディレクトリでmakeします。
NFS用のルートファイルシステムの作成
NFSサーバの設定はこちらを参照してください。
NFS用のディレクトリを/export/android/rootとします。
ここにファイルを展開するためのスクリプトを作りました。やっていることは
- ramdisk.imgを展開してsystemとdataのディレクトリをコピー。
- init.rcに変更を加えて不要なmount を抑止。
- ファイルのオーナーとグループをrootに変更。
$ANDROID_TOPのディレクトリでこれを実行してください。
$ cd $ANDROID_ROOT $ cat ./make_nfsroot.sh ROOT=/export/android/root [ -e $ROOT ] && sudo rm -rf $ROOT mkdir -p $ROOT cd out/target/product/generic/ zcat ramdisk.img | (cd $ROOT; cpio -i) cp -a system $ROOT cp -a data $ROOT [ -e $ROOT/data/app ] && chmod 771 $ROOT/data/app cp $ROOT/init.rc $ROOT/init.rc.org sed -e 's/mount rootfs/#mount rootfs/' -e 's/mount yaffs2/#mount yaffs2/' $ROOT/init.rc.org > $ROOT/init.rc sudo chown -R root:root $ROOT $ ./make_nfsroot.sh
emulatorの起動
$ export ANDROID_NFSROOT=192.168.xx.xx:/export/android/root $ emulator -kernel kernel/common/arch/arm/boot/zImage -show-kernel
さてうまく起動できたでしょうか。
これでemulatorの動作中かどうかにかかわらずAndroidの中のファイルを読み書きすることができます。
GoldfishならぬGlassfishかな。水族館で見かけた透明で内臓が外から見えちゃう魚。
2010.6.29追記
make_nfsroot.shに以下の行を追加しました。
[ -e $ROOT/data/app ] && chmod 771 $ROOT/data/app
Froyoだとデフォルトでビルドすると何かテストプログラムが /data/appに置かれるようになったのですが、このディレクトリにグループの書き込み権がないとadb installが失敗します。
Eclairではビルド時には/dataは空で実行時にディレクトリが作成されていたので問題がありませんでした。
qemuの変更パッチ
$ANDROID_TOP/external/qemu
diff --git a/android/main.c b/android/main.c index 7b20919..53a1cc9 100644 --- a/android/main.c +++ b/android/main.c @@ -2355,8 +2355,13 @@ int main(int argc, char **argv) } } +/* added by koba */ +#define NFSROOT 1 + +#ifndef NFSROOT args[n++] = "-initrd"; args[n++] = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_RAMDISK); +#endif if (opts->partition_size) { char* end; @@ -2422,6 +2427,7 @@ int main(int argc, char **argv) } } +#ifndef NFSROOT { const char* filetype = "file"; @@ -2466,7 +2472,7 @@ int main(int argc, char **argv) args[n++] = "-nand"; args[n++] = strdup(tmp); } - +#endif if (hw->hw_sdCard != 0) opts->sdcard = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_SDCARD); else if (opts->sdcard) { @@ -2711,6 +2717,17 @@ int main(int argc, char **argv) p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart); } +#ifdef NFSROOT + { + char *nfsroot = getenv("ANDROID_NFSROOT"); + if (!nfsroot) { + fprintf(stderr, "### ERROR: ANDROID_NFSROOT is not set\n"); + exit(1); + } + p = bufprint(p, end, " root=/dev/nfs rw nfsroot=%s ip=dhcp init=/init", nfsroot); + } +#endif + if (p >= end) { fprintf(stderr, "### ERROR: kernel parameters too long\n"); exit(1);
トラックバックURL
トラックバック一覧
コメント一覧
GlassfishはSun(Oracle)のサーバが。。。
http://www.sun.com/software/products/appsrvr/index.jsp
なので、タイトルに使うのは止めて最後にぽろっと呟いてみました。