Raspberry Pi のカーネルビルド

あちこちで先達の方が記事にされていますが、私もまとめてみました。OS は Raspbian (2014-01-07) とします。以下、Raspberry Pi を rpi と略します。
まず最初に、以下のサイトを眺めます。

以下に作業手順をまとめておきます。
1. Raspbian のカーネルソースを Git で入手します。

host$ mkdir ~/work && cd ~/work
host$ git clone git://github.com/raspberrypi/linux.git

2. 3.10 版のカーネルをチェックアウトします。なぜ 3.10 かというと、既存のインストール済カーネルが 3.10.25 だからです。

Linux raspberrypi 3.10.25+ #622 PREEMPT Fri Jan 3 18:41:00 GMT 2014 armv6l

host$ cd linux
host$ git checkout rpi-3.10.y

なぜか tag が打たれていないので、念のためブランチの先頭を調べておきます。チェックアウトの時期によって内容は異なるはずです。

host$ git show-branch --more=-1
* [rpi-3.10.y] config: Add CONFIG_NFS_SWAP
  [rpi-3.12.y] mach-bcm2708: account for FIQ latency in timer interrupt setup
host$ git log -1
commit 1b49b450222df26e4abf7abb6d9302f72b2ed386
Author: popcornmix <popcornmix@gmail.com>
Date:   Sun Apr 27 18:04:54 2014 +0100

    config: Add CONFIG_NFS_SWAP
    
    See: https://github.com/raspberrypi/firmware/issues/266

3. 次に、クロスコンパイラを入手します。今回は、x86 上の Ubuntu でビルドすることにします。

host$ cd ~
host$ git clone git://github.com/raspberrypi/tools.git

環境変数をセットしておきます。コンパイラもいくつかありますが、上記サイトを参考に、hardfp っぽいものを使ってみます。

host$ export MYCC=~/tools/arm-bcm2708/arm-bcm2708hardfp-linux-gnueabi/bin/arm-bcm2708hardfp-linux-gnueabi-

4. 次に、.config を用意します。上記サイトを見ると、rpi の /proc/config.gz を展開して make oldconfig するとありますが、カーネルのバージョンが違いすぎるのか、.config の差分が多すぎるように見えるので、展開したカーネルソースから持ってきます。いくつか候補がありますが、デフォルトっぽいやつを持ってきました。

host$ cd ~/work/linux
host$ cp arch/arm/configs/bcmrpi_defconfig .config

念のため、ARMv6 用になってるか確認します。

host$ fgrep _CPU_V6 .config
CONFIG_CPU_V6=y

必要ならば、menuconfig で確認します。

host$ make ARCH=arm CROSS_COMPILE=$MYCC menuconfig

5. カーネルをビルドします。期待しているコンパイラが、期待しているオプションで動いているか目視したいので、V=1 を追加しています。大丈夫そうなら、途中で Ctrl-C で止めて、V=1 無しで再開しても良いでしょう。

host$ make ARCH=arm CROSS_COMPILE=$MYCC V=1

6. なんか、modules も自動的にビルドしてくれてるように見えますが、念のため明示的に実行します。

host$ make ARCH=arm CROSS_COMPILE=$MYCC modules

でもって、modules を転送するために「固め」ます。

host$ make ARCH=arm CROSS_COMPILE=$MYCC INSTALL_MOD_PATH=~/tmp/rpimod modules_install
host$ cd ~/tmp/rpimod
host$ tar ../rpimod.tar ./lib/modules && gzip ../rpimod.tar

7. rpi に転送します。ここでは sftp を使います。

host$ cd ~ && sftp rpi
Connecting to rpi...
sftp> mkdir tmp
sftp> cd tmp
sftp> mput tmp/rpimod.tar.gz
sftp> mput work/linux/arch/arm/boot/zImage kernel_new.img
sftp> quit

8. rpi 上で展開します。/boot/config.txt はお好みのエディタで編集してください。

rpi$ cd ~/tmp
rpi$ sudo cp kernel_new.img /boot
rpi$ echo 'kernel=kernel_new.img' >> /boot/config.txt
rpi$ zcat rpimod.tar.gz | (cd /; sudo tar xf -; find /lib/modules/ -exec chown root.root {} \;)

9. rpi をリブートします。本当はシリアルコンソールを繋いだほうが良いのですが、エイっとやってみました。無事に立ち上がったら、dmesg を確認します。

rpi$ dmesg | head

完了です。