2010年03月01日

AndroidのエミュレータをNFSroot化する

AndroidのエミュレータにQEMUが使われているのはご存知のことでしょう。

今回はこれまでの経験をいかして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

トラックバック一覧

1. Android2.2(Froyo)のダウンロードとビルド  [ KMC Staff Blog ]   2010年06月29日 10:27
6/24にAndroid2.2(Froyo)のソースが公開されました。さっそくビルドしてみたので、その方法を簡単に紹介します。

コメント一覧

1. Posted by androidzaurus   2010年03月01日 10:44
5 これだと、systemの下をいじる開発をEmulatorで行うときに、いちいちsystem.imgをリビルドする必要がないので、便利ですね。

GlassfishはSun(Oracle)のサーバが。。。
http://www.sun.com/software/products/appsrvr/index.jsp
2. Posted by koba   2010年03月01日 21:20
Glassfishが元SunのJ2EEのプロジェクト名であることは実は知ってました。
なので、タイトルに使うのは止めて最後にぽろっと呟いてみました。

コメントする

名前
 
  絵文字
 
 
記事検索
最新コメント
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード