Orange Pi 2G-IOT向けLinux Kernelの再構築手順

# はじめに
## 内容について
想定読者はコマンド見て、はいはいそうだよねー、ってくらいにはKernel再構築をやってきた人向け。2G-IOT向けのカーネルがどこにあるのか、ARM向けのbootイメージをどう作り、2G-IOTの場合はどこにインストールすればいいのか、あたりの情報をまとめただけの物です。そう人しか2G-IOTとか買ってない気がしますし、基本は自分用のメモ。

## 目的
2G-IOTは映像出力がLCDインタフェースというのが出てるだけ。しかもこのLCDインタフェースってのが公式ショップ売ってる1種類のLCDモジュールに限られるという……なんかもったいない基板の作りをしています。他のOrange PiシリーズみたくHDMIはないし、Zeroのようなビデオ出力信号も出ていません。なので画像出そうと思ったらGPIO/SPIでLCD直接叩くか、FBTFTあたりのドライバを持ってきて/dev/fb*越しに利用するくらいしかありません。で、FBTFTは残念ながらオフィシャルイメージには含まれておらず、またbuildするにはカーネルごとbuildするしかなさそうです（頑張ってmoduleだけbuildしようとしたけどkernel version変わってしまった。これ、詳しい人なら回避策知ってそう）。それ以外でもドライバ類はかなり絞ってbuildされたカーネルになってるようなので自前でドライバ追加したくなる事は多そう（例えばジョイスティック系のドライバは標準では入っていない）。/dev/ashmemが存在したりと、基本的にはAndroid向けにポートしたカーネルをUbuntu等のほかのLinuxディストリビューションでもそのまま再利用しているようです。

# 前準備
## ツール取得
おそらく配布イメージでいきなりgit cloneしようとするとルート証明書がなくてエラーが出るはず。```apt-get install wget```あたりをしておくと証明書もインストールされて一安心。直接入れるだけならおそらくca-cartificatesっていうパッケージを入れればOK。

```libncurses-dev``` もmenuconfigに必要なのでapt-get installで入れる。

## bc
入ってないとkernel/timeconst.hを作るところで怒られるはず。```apt-get install bc```で入れておく。

## gcc
デフォルトのgccは5.4だが、対応してるKernelはgcc-5.1まででしかコンパイルが通らない。aptのパッケージはgcc-5って一括りでマイナーバージョンで切り替えられなくなっているので、```apt-get install gcc-4.9```で4.9系列を使う事にする

## ソース取得
[ここ](https://github.com/orangepi-xunlong/OrangePiRDA_kernel)にあるやつが公式なソース。バージョンも3.10.62-rel5.0.2でバイナリと一致する。

```shell-session:root
% cd /usr/src
% git clone https://github.com/orangepi-xunlong/OrangePiRDA_kernel.git linux
```

あるいは、公式バイナリは ```/xspace/OpenSource/GitHubLinux/OrangePiRDA/kernel/``` というパスで開発しているようなので、そちらにチェックアウトしてsymlinkを張っておくのもあり。```/lib/modules/``` 以下の未解決symlinkも ```/xspace``` の方を見てる模様。


自分は[fbtft](https://github.com/notro/fbtft)が欲しかったので

```shell-session:root
% cd /usr/src/linux/drivers/video
% git clone https://github.com/notro/fbtft.git
```

とした後、fbtft公式のドキュメントにあるように以下の2ファイルに1行づつ追加。

```:drivers/video/Kconfig
source "drivers/video/fbtft/Kconfig"
```

```:drivers/video/Makefile
obj-y += fbtft/
```

# Build手順（/usr/src/linux以下にて）
## FBTFTの有効化（必要な場合）
```shell-session:root
% make menuconfig CC=gcc-4.9
```

```Device Drivers > Graphics support``` にて
```Support for small TFT LCD display modules``` をmodule、同項目以下に多数のサブモジュールが入っているので全てmoduleに設定。あとはSaveして終了するまでExitしまくる。

## Kernel
```shell-session:root
% make dep zImage CC=gcc-4.9
```

## modules
```shell-session:root
% make modules modules_install CC=gcc-4.9
```

ここでインストールされるモジュールのバージョンシグネチャは3.10.62-rel5.0.2+。なので、既存のカーネルからは読めない。

# インストール
## インストール先
/dev/mmcblk0p1の中にzImageとuInitrdをコピーする必要がある。zImageは ```make zImage``` で作れるからいいけどuInitrdはマニュアルで作る必要がありそう（これも詳しい人はもっと良い方法を知ってそう）。

## uInitrd
ここを読んでいるような人なら知っていると思うけど、これはboot過程でまともなファイルシステムを読めるようになる前に必要となるファイルをまとめたram disk image。通常はinitrdって名前で、U-Bootが読める形式に変換してあるのがuInitrd（で良いはず）。ようは基本的なドライバなどをメモリにペタっと貼り付けて、そのアドレスを渡してカーネルを起動してあげれば、あとはそこから基本的なドライバ読んで、その先のSDカードやらHDDのアクセスやらext4なんかのフィアルシステムの解釈に繋がりますね、という。

内容についてはオリジナルデータを展開して新しいmodulesを追加、再度uInitrdに戻してあげれば良いでしょう。

```shell:root
% mount /dev/mmcblk0p1 /mnt
% cd /mnt
% mkdir initrd
% cd initrd
% tail -c+65 ../uInitrd | gunzip | cpio -id
% cp -rp /lib/modules/3.10.62-rel5.0.2+ lib/modules
% find . | cpio -o -H newc | gzip > ../initrd.img-3.10.62-rel5.0.2+.gz
% cd ..
% cp uInitrd uInitrd.old
% mkimage -A arm -O linux -T ramdisk -C none -a 0 -e 0 -n initramfs -d ./initrd.img-3.10.62-rel5.0.2+.gz uInitrd
```

## zImage
```shell:root
% cp /mnt/zImage /mnt/zImage.old
% cp /usr/src/linux/arch/arm/boot/zImage /mnt
```

# まとめ
以上の手順を踏まえた上で再起動すれば、u-bootから新しいカーネルが読まれるはず。起動しなくなったらSDカードを別のマシンに入れて、避けておいたoldを戻して再起動して再挑戦して下さい。

今のところ、目的だったfbtftは不安定。特定の引数でクラッシュするらしいけど、syslogがないので何がおきてるのか把握できてない状況。（追記：今思えば指定していたGPIOポートに問題があったと思われる。C系のポートは特殊なので用途が限定されるのと、ポート番号がC系とD系で並びが逆転している……ABDCの順に並んでいる、などなど）