AndroidのKernel Moduleをコンパイルする

Pocket

SoftBankの回線をただ解約するのはもったいないので、WiMaxが付いてて各方面で絶賛投げ売り中のauのHTC EVOたんを入手したよ!(若干ネタが古い感はするーする!)

さてRootも無事取って、Cisco AnyConnect (VPNクライアント)をインストールして接続しようとしたら、”tun.ko”がないからむりぽって言われたので、tun.koをカーネルソースからコンパイルしてみることにした。

もともとOpenVPN用のモジュールなので、インストールするとOpenVPNも使えるようになるはずです。(もちろんカーネルモジュールだけじゃ動かないので他のファイルも必要です!)

最初OSXでやろうとしたんだけど、なんか面倒っぽかったのでLinux上でやってます。僕はたまたま手元にCentOSがあったのでCentOSでやったけど、きっとDebianとかでも動くはずです。

コンパイル済みのtun.koも準備しました。
http://nunnun.jp/evo/tun.ko-2.6.35.10-g04a0907.zip
/system/lib/modulesに入れれば動くはずです。 

用意するもの

手順

  1. ダウンロードしたファイルを展開する
    ホームディレクトリにandroidというフォルダを作ってそこに展開することにします。(別に場所はどこでも平気です)
    $ mkdir android
    $ cd android
    $ wget http://dl.google.com/android/android-sdk_r15-linux.tgz
    $ wget http://dl.google.com/android/ndk/android-ndk-r5c-linux-x86.tar.bz2
    $ wget http://dl4.htc.com/RomCode/Source_and_Binaries/supersonic-2.6.35-gb-MR.tar.gz
    $ tar zxvf android-sdk_r15-linux.tgz
    $ tar xvf android-ndk-r5c-linux-x86.tar.bz2
    $ tar zxvf supersonic-2.6.35-gb-MR.tar.gz

  2. デバイス(HTC EVO WiMAX)からカーネルコンフィグを抜きます
    デバイスがPCに接続された状態で、config.gzを抽出し、展開します。
    $ adb pull /proc/config.gz .
    $ gunzip config.gz
    $ mv config .config

    別のマシンから抜いてくる場合は、config.gzを抜いてそれを作業ディレクトリに転送し、展開します。

  3. Configを書き換える
    デフォルトではコンパイルしないことになっているTUNモジュールをコンパイルするために、展開した.configを書き換えます。vimなりemacsで開いて
    # CONFIG_TUN is not set
    という行を探します。探したらその行の下に、
    CONFIG_TUN=m
    という行を追加し、保存します。保存後、.configファイルをカーネルを展開した supersonic_GB_MR フォルダにコピーします。
    $ cp .config supersonic_GB_MR

  4. Makefileを変更する
    コンパイルして生成されるカーネルモジュールとデバイスで動いているカーネルのバージョンを合わせるために、Makefileを変更します。
    まず、 デバイスを接続したマシン上で、
    $ adb shell uname -a
    Linux localhost 2.6.35.10-g04a0907 #1 PREEMPT Tue Aug 30 13:49:12 CST 2011 armv7l GNU/Linux

    を実行します。実行するとカーネルのバージョンがわかります。この場合2.6.35.10-g04a0907がバージョンです。
    その後、Makefileを変更します。カーネルを展開した  supersonic_GB_MR フォルダにMakefileがあるのでそれをvimなりemacsなりで開いて、
    EXTRAVERSION =
    という行を探して、先ほどのバージョンのマイナーバージョン以下(つまり2.6.35以下)を追加します。この場合、EXTRAVERSIONの行は、
    EXTRAVERSION = .10-g04a0907
    となります。

  5. コンパイルする!
    準備が終わったので、早速コンパイルしてみる。カーネルを展開したディレクトリに移動して、makeする。
    ただ、環境変数をちゃんと設定しないと動かない。こんな感じ
    $ export ARCH=arm
    $ export CROSS_COMPILE=arm-eabi-
    $ export PATH=$PATH:~/android/android-ndk-r5c/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin/

    環境変数を設定したら、makeする。

    $ make modules

    なんかエラーが出た場合は何かが足りない。aptitudeとかyumで探してぶち込む。無事コンパイルが終わると、drivers/net/ ディレクトリに tun.ko というカーネルモジュールが生成されているはず。fileすると、

    $ file drivers/net/tun.ko
    drivers/net/tun.ko: ELF 32-bit LSB relocatable, ARM, version 1 (SYSV), not stripped

    こんな感じに出るはず。

  6. デバイスに転送する
    コンパイルしたカーネルモジュールをデバイスに転送して、/system/lib/modules に配置します。
    デバイスをつないだマシンから、以下のように操作します。
    $ adb push tun.ko /sdcard/tun.ko
    $ adb shell su -c "mount -o rw,remount /system /system"
    $ adb shell su -c "cp /sdcard/tun.ko /system/lib/modules"
    $ adb shell su -c "insmod /system/lib/modules/tun.ko"
    $ adb shell su -c "mount -o ro,remount /system /system"

    いずれもエラーが出ずに処理が終われば正常です。エラーが出る場合はroot権限がとれていてsuがインストールされているか確認してください。

以上。最初NDKを最新のもので試したのだけど、付いてきたクロスコンパイラがarm-linux-androideabi-4.4.3で、これだと

# insmod tun.ko
insmod: init_module 'tun.ko' failed (Exec format error)

と言われてしまってモジュールを読み込めなかった。なんかARMのGCC 4.0特有の問題みたい。

This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

Leave a Reply