ラズパイのカーネルをセルフビルドする

![Raspbian-Jessie-Lite-680x486.jpg](https://qiita-image-store.s3.amazonaws.com/0/258841/69da9505-14ad-a18c-a0bb-22a784ac3fc3.jpeg)

## 概要

ラズパイ用のカーネルをセルフビルドしてインストールしたときの実行ログ
最終的に下記のようにカーネル名に自分の名前が入ることを目標とする。
尚、ラズパイの初期設定などは既に完了しているところから始めます。
自前ビルドとクロスコンパイルがあるが本記事ではクロスコンパイルの手順は非対象です。

ちなみに自前ビルドせずとも公式では下記の方法でカーネルアップデートの方法を提供している。

``` bash
$ sudo apt-get update

$ sudo apt-get dist-upgrade
```

## 環境

本記事では下記の環境で検証しています。

* raspberry pi 3 * 1
* raspbianのソース [raspberrypi/linux](https://github.com/raspberrypi/linux)

## 前準備

カーネルを置く場所を決めます。
慣例として/home/pi以下に置くようなので同様にそちらに配置します。

``` bash
$ cd /home/pi
$ mkdir ./kernel_ryu
```

次にカーネルソースを持ってきます。
ソースはGitHubで公開されているので楽に持ってこれます。
コミット履歴を見ると今でも割と頻繁に開発は行われている模様。
gitが無い方は事前にインストールしておいてください。
ついでにbcも依存関係上必要になるようなのでそちらも入れておきます。

``` bash
$ sudo apt-get install git bc
```

上記のインストールが完了したらカーネルソースを入手します。
gitコマンドで最新のカーネルのみを入手します。
別ブランチをダウンロードするには「--branch」を指定して入手することが出来ます。

``` bash
$ git clone --depth=1 https://github.com/raspberrypi/linux
```

次にconfigファイルのコピーをします。
尚★のところがそれぞれラズパイのバージョン毎に変わりますのでご注意ください。
Raspberry Pi 1、Pi Zero、Pi Zero Wでは「KERNEL=kernel」
Raspberry Pi 2、Pi 3、Pi 3+では「KERNEL=kernel7」となります。

``` bash
$ cd linux
$ KERNEL=kernel7 #★
$ sudo modprobe configs
$ cat /proc/config.gz > .config
```

その後はカーネルに自分が分かりやすい名前を設定してください。
設定するのはMakefie内の下記の箇所です。例ではryuichiを指定しています。

``` :Makefile
# SPDX-License-Identifier: GPL-2.0
VERSION = 4
PATCHLEVEL = 14
SUBLEVEL = 91
EXTRAVERSION = -ryuichi #ここに記載
NAME = Petit Gorille
```

## 余談

ここでカーネルの設定をカスタマイズすることもできます。が今回は軽く紹介する程度で留めます。
設定方法はmenuconfigを実行することでカスタマイズが可能です。

menuconfigを事項するにはlibncurses5-devというライブラリが必要なのでインストールします。

``` bash
$ sudo apt-get install libncurses5-dev

$ make menuconfig
```

## カーネルコンパイル

いよいよコンパイルします。
処理時間は結構まちまちのようで機種の処理性能に大きく依存するようです。
ビルド中は他の作業をして待ちましょう。
makeにはオプションとしてジョブ数を指定しています。ラズパイのCPU数に合わせて指定することで
高速化が望めます。

https://linuxjm.osdn.jp/html/GNU_make/man1/make.1.html

``` bash
$ sudo make -j4 zImage modules dtbs
```

## インストール

ビルドが完了したら次はインストールです。
以下のコマンドを実行してください。
バックアップが必要な方は適宜行うようにしましょう。

``` bash
$ cd ~/linux/
$ sudo cp arch/arm/boot/dts/*.dtb /boot/
$ sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
$ sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/
$ sudo scripts/mkknlimg arch/arm/boot/zImage /boot/$KERNEL.img
```

既存カーネルをバックアップするなら

``` bash
$ cd /boot
$ sudo mkdir -p boot_org/overlays
$ sudo cp *.dtb boot_org/
$ sudo cp overlays/*.dtb boot_org/overlays/
$ sudo cp overlays/README boot_org/overlays/
$ sudo cp kernel7.img boot_org/
```

ビルド/インストールが終わりました。
最後に再起動してunameコマンドを実行して確認してみます。

``` bash
$ sudo shutdown -r now

$ uname -r
4.1.7-ryuichi
```

はい、成功していますね！独自のカーネル名が入ったカーネルの完成。
特に何か機能を開発したわけではないけどラズパイへの愛着が一層増しますね。

## クロスコンパイルについて

クロスコンパイルについても少し触れます。

クロスコンパイルとはソースコードを元に、開発に使用しているOSとは別の環境向けにコンパイルすることです。
ここではraspberry pi用のカーネルをUbuntuでコンパイルする。といったイメージです。

クロスコンパイルを行うには適したホストが必要になります。
特に制限等が無ければUbuntuを使う傾向があるようです。
詳しい手順は公式リファレンスに記載してありますので興味がある方は実施してみてください。
https://www.raspberrypi.org/documentation/linux/kernel/building.md


## まとめ

思っていたよりも簡単にカーネルビルド/インストールが行えました。
次にやりたいことはといえば特に決まっていませんが、とりあえずGitHubの本家をforkして
何か知らして遊んでいこうかなと考えています。
まずはmenuconfigで何が設定できて何が出来ないのかの理解が優先ですかね。

## 参考URL

https://www.raspberrypi.org/documentation/linux/kernel/
https://karaage.hatenadiary.jp/entry/2015/10/07/073000