##目的
Raspberry Pi2のカーネルコンフィグの変更、デバイスドライバの作成などを予定しているため、
備忘録として記載します。
私は2箇所ぐらいハマりましたが、以下の手順に従えばハマらずに済むと思います。
##使用機器および知識
・OS X El Capitan 10.11.4(Mac)
・VirtualBox(5.0.16)
・Ubuntu14.04(32bit、isoファイル)
・Raspberry Pi2 Model B
・microSD(既にRASPBIAN JESSIEがインストールされている状態)
・Disk Arbitrator(Mac上のmicroSDオートマウントを阻止するツール)
・ターミナル上のコマンド操作
##前提知識:クロスコンパイルの必要性
クロスコンパイルを行う理由は、Linuxカーネルのビルド時間を短縮するためです。
貧弱な環境(Raspberry Pi2)でLinuxカーネルをビルドする場合は終了までに何時間もかかりますが、
Mac(Windows)のような高性能なCPUを搭載した環境でビルドする場合は数十分で終了します。
しかし、単純にMacでビルドしたカーネルは、Raspberry Pi上で動作しません。
その理由は、Macの環境(CPU)で動作する事を前提として、ビルドが行われているからです。
そこで、TOOL-CHAINを用いたクロスコンパイルによって、
Mac(Ubuntu)でRaspberry Pi2環境(CPU)向けのカーネルを作成します。
##仮想環境の準備
クロスコンパイルには、bash(シェル)が必要です。
Macにはbashが存在しますが、私の環境ではクロスコンパイル中にエラーが発生しました。
そのため、代用としてUbuntu(14.04、32bit)を仮想環境上に導入します。
1)Mac版のVirtualBoxをダウンロード
2)VitualBoxをインストール
3)Ubuntu14.04(32bit)のisoファイルをダウンロード
4)VirtualBoxを利用して、UbunutuをMacに導入(参考サイト)
5)Ubuntuの画面サイズ設定を変更(変更しない場合、解像度640×480で固定。参考サイト)
6)UbuntuとMacの間で、ファイル交換が可能な状態に変更(参考サイト)
7)以下のコマンドを入力し、/home/username以下のファイル名を日本語から英語に変更
例)デスクトップ(日本語) > Desktop(英語)
$ $ LANG=C xdg-user-dirs-gtk-update
最後の7)は、単純にパス指定中に英語・日本語の入力切替を行うのが面倒なだけでなく、
ビルドに失敗しないようにするためです。
以前、私は2byte文字(日本語)のせいで、ビルドにコケた事がありました(別のボードですが)。
##クロスコンパイル環境の作成、クロスコンパイルの実行
この節の操作は、全てUbuntu(仮想環境)で行います。
まず、vim(エディタ)とgit(バージョン管理システム)をインストールします。
vimは必須ではありませんが、viより操作しやすいため、このタイミングで導入します。
余談ですが、gitは「Linus Torvalds(Linuxの産みの親)が約2週間で作成」したらしい。素晴らしい。
$ sudo apt-get install vim
$ sudo apt-get install git
続いて、TOOL-CHAINをgitからインストールします。
一連のファイルは、ユーザのホームディレクトリ以下のtools(/home/username/tools)に格納されます。
$ cd ~/
$ git clone https://github.com/raspberrypi/tools
TOOL-CHAINを使用する際に長いパスを記述するのは面倒なため、環境変数を設定します。
以下のコマンドを入力し、.bashrc(bashの設定ファイル)の末尾に2つのPATHを追加します。
$ vi ~/.bashrc
追加するPATH
PATH="$PATH":~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian
PATH="$PATH":~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin
続いて、gitからLinuxカーネルのソースを取得します。
Desktop直下にLinuxコードをクローンします。
$ cd ~/Desktop
$ git clone --depth=1 https://github.com/raspberrypi/linux
linuxディレクトリに移動し、Raspberry Pi2用のkernel7.imgを指定します。
その後、Raspberry Pi2用のコンフィグファイル(.config)を作成します。
ここでのBCM2709は正しいSOC(System on a Chip)を指定していませんが、
公式サイト通りなので、気にしない事にします(Raspberry Pi2のSOCは、BCM2836)。
$ cd /home/username/Desktop/linux
$ KERNEL=kernel7
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig
自分好みにカーネルコンフィグを設定します(画像はコンフィグ画面)。
今回、私は"Power Management options > Suspend to RAM and standby"を有効化しました。
(私は変えたいコンフィグ設定が見つけられない事が多いです。恐らく、探し方があるのでしょうね)
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
最後に、以下のコマンドでクロスコンパイルを行います。
30分以上はかかりますので、技術書や漫画を読むなり、ゲームするなり、掃除するなり、暇を潰しましょう。
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs
ちなみに、64bit版Ubuntuを使用した方は、このタイミングでビルド失敗します(使用するgccが異なるため)。
PATHを以下のように変更すれば、ビルドが通る筈(私は未検証。公式と別の方の報告では成功してます)。
PATH="$PATH":~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64
PATH="$PATH":~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
##microSDに作成したファイル(zImageやモジュール)をインストール
既にmicroSDにはRASPBIAN JESSIEがインストールされている状態と仮定します。
まず、Macに差し込んだmicroSDをUbuntu(仮想環境)に認識させます。
microSDのマウント情報が欲しいので、mount
をMacのターミナル上で入力します。
今回は、各パーティションが以下のように割り当てられている事が分かりました。
/dev/disk2s6 on /Volumes/boot (msdos, local, nodev, nosuid, noowners)
/dev/disk2s1 on /Volumes/RECOVERY (msdos, local, nodev, nosuid, noowners)
この2つのパーティションをアンマウントします。
$ sudo umount /dev/disk2s6
$ sudo umount /dev/disk2s1
//もしくは
$ sudo diskutil umountDisk /dev/disk2
次に、VirtualBox vmdkファイル(./sd-card.vmdk)を作成します。
コマンド末尾の"/dev/disk2"は、環境に合わせて変更します。
例えば、マウント情報が"/dev/disk1s1"ならば、"/dev/disk1"と変更します。
$ sudo VBoxManage internalcommands createrawvmdk -filename ./sd-card.vmdk -rawdisk /dev/disk2
"./sd-card.vmdk"と"/dev/disk2"のパーミッション(権限)を
書き込み、読み込み、実行可能状態に変更します。念のため、所有者情報も変更します。
(このパーミッション変更、Macを再起動する度に必要です。面倒)
$ sudo chmod 777 /dev/disk2
$ sudo chmod 777 ./sd-card.vmdk
$ sudo chown username /dev/disk2
$ sudo chown username ./sd-card.vmdk
// usernameは適宜、置き換えなければなりません。
Ubuntuの電源を落として、Oracle VM Virtualマネージャ(VirtualBoxを起動した直後の画面)を
開いた状態にします。
そこから、「設定(①) > ストレージ(②) > ハードディスクの追加(③)」を選択し、
「既存のディスクの選択」を選択します。その後"sd-card.vmdk"を「コントローラ:SATA」に追加します。
私はこのタイミングで「Resource busy」というエラーが出ましたが、
原因はmicroSDが再びマウントされていたからでした。アンマウントすれば、追加できる筈です。
Ubuntuを起動し、Ubuntuターミナル上でlsblk
コマンドを入力すると、microSD情報が確認できます。
ここで、Ubuntuが起動できなければ、Mac側でmicroSDのマウント状況を確認してください。
アンマウントをしてからUbuntuを起動しても失敗する場合(再びマウントされてしまう場合)、
Disk Arbitratorによって再マウントをブロックします。
Disk Arbitratorの右下にあるModeを"Block mounts"に設定した状態で、
disk2s1(Device欄)を選択した後、unmountボタンをクリックします。disk2s6にも同じ操作をします。
(/etc/fstabを編集してオートマウントを防ぐ事は、El Capitanではできません)
Ubunutuが無事に起動できれば、Ubuntuターミナル上でmicroSDをマウントします。
mkdir mnt/fat32
mkdir mnt/ext4
sudo mount /dev/sdb1 mnt/fat32
sudo mount /dev/sdb2 mnt/ext4
モジュールをインストールします。
sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=mnt/ext4 modules_install
Device Treeをインストールし、古いカーネルの情報をバックアップします。
最後にmicroSDをアンマウントしたら、実機で動作確認を行います。
sudo cp mnt/fat32/$KERNEL.img mnt/fat32/$KERNEL-backup.img
sudo scripts/mkknlimg arch/arm/boot/zImage mnt/fat32/$KERNEL.img
sudo cp arch/arm/boot/dts/*.dtb mnt/fat32/
sudo cp arch/arm/boot/dts/overlays/*.dtb* mnt/fat32/overlays/
sudo cp arch/arm/boot/dts/overlays/README mnt/fat32/overlays/
sudo umount mnt/fat32
sudo umount mnt/ext4
以上で、作業は終了です。