Raspberry Pi 4Bの64-bit Kernelのローカルビルドとドライバーの開発環境をつくってみた。

#はじめに
Raspberry Pi 4B+上で、64-Bitカーネルとドライバーの開発を勉強したかったのですが、ほどよいドキュメントがなかったので、参考例になればと思い、実際に私が行った作業を記録として残すことにしました。
気づいた点があればコメントをお願いします。

#環境
- Raspberry Pi 4B+
- SD Card 32GB

#１．環境の確認
まず、環境の確認方法は以下の方法で行いました。参考のために結果のスクリーンショットも載せておきます。

```shell
$ uname -a
```

```shell
$ gcc -v
```
![raspberry-pi-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1615141/b1be14a6-5d87-8e2c-e1e3-53aab57f8933.jpeg)

#２．GITとコンパイルに必要なパッケージのインストール
以下のコマンドでGITとビルドに必要なパッケージをインストールします。

```shell
$ sudo apt install git bc bison flex libssl-dev make
```

#３．ソースコードのダウンロード
以下のGITコマンドでソースコードをCloneします。ビルドに不必要なもをダウンロードしないために"--depth=1"を付けます。このオプションがないとブランチのヒストリーを含むリポジトリ全体をダウンロードしてしまいます。

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

#４．カーネルコンフィギュレーション
デフォルトのコンフィギュレーションを設定します。ここでは64-bit のカーネルなのでARCH=arm64を指定して、Raspberry Pi 4B+で使うためにbcm2711_defconfigを指定します。

```shell
cd linux
KERNEL=kernel8
make ARCH=arm64 bcm2711_defconfig
```

#５．カーネルビルド
Raspberry Piの公式ドキュメントではカーネルビルドの時には、"Image modules dtbs"の３つを指定します。Raspberry Pi 4B+にはCPUのコアが４つあるので、ビルド時間の短縮のために、-j4を指定して４つのコアを使ってビルドしました。

```shell
make -j4 ARCH=arm64 Image modules dtbs
```

#５．カーネルインストール
注：カーネルのインストールの前に、必要であれば必ずSDカードのバックアップを取っておくことをお勧めします。
以下のコマンドを実行して、それぞれ必要なファイルを必要な場所に配置し再起動をします。

```shell
sudo make modules_install
sudo cp arch/arm64/boot/dts/broadcom/*.dtb /boot/
sudo cp arch/arm64/boot/dts/overlays/*.dtb* /boot/overlays/
sudo cp arch/arm64/boot/dts/overlays/README /boot/overlays/
sudo cp arch/arm64/boot/Image /boot/$KERNEL.img
```
#６．再起動と確認
再起動した後に"uname -a"コマンドを実行すると、インストール前と後ではリリース、バージョンが変わっていることが確認できると思います。

###インストール前
![Rasp64_check_varsion_before_install.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1615141/dccfb476-76b8-fc3e-366a-9f639b0f42ea.jpeg)

###インストール後
![Rasp64_check_varsion.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1615141/38ceff61-86cc-ffcb-8ca2-04ea590bfb13.jpeg)


#７．モジュールのビルド環境
カーネルのビルドとインストールが終わったら、次にモジュールビルドの環境と確認用のhello.cを作ってモジュールのロードとアンロードを実行して開発環境を確認します。

###フォルダーの作成
```shell
mkdir hello_driver
cd hello_driver
```
###Makefileを書く
```shell
vi Makefile
```
###Makefileの内容
```text
obj-m := hello.o
```
###hello.cを書く
```shell
vi hello.c
```
###hello.cの内容
```C
#include <linux/init.h>
#include <linux/module.h>

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Ken Shimizu");

static int hello_init(void)
{
    printk(KERN_INFO "Hello World\n");
    return 0;
}

static void hello_exit(void)
{
    printk(KERN_INFO "Sayonara!\n");
}

module_init(hello_init);
module_exit(hello_exit);
```

#８．コンパイル
Makefile、ソースコード（hello.c）の用意ができたら次はコンパイルをします。コマンドは以下のようになります。-Cオプションでカーネルのソースコードがあるフォルダーを指定して、Mオプションでモジュールのソースコードがあるフォルダーを指定します。

```shell
make -C ../linux/ M=`pwd` modules
```
![Rasp64_make_modules.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1615141/72699310-b2cc-29ff-54b5-84a6eb3208ac.jpeg)

#９．ロードモジュール
insmodで出来上がったモジュールをロードして、lsmodで確認をしてみたいと思います。lsmodの結果のスクリーンショットも参考のために載せておきます。

```shell
sudo insmod ./hello.ko
lsmod | grep hello
```
![Rasp64_lsmod.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1615141/2cab6c64-96a9-3ddf-864c-edba59a699ae.jpeg)

最後にロードしたモジュールをアンロードして、syslogを確認してみましょう。printkで出力した文言が確認できると思います。

```shell
sudo rmmod hello
less /var/log/syslog
```
![Rap64_less_syslog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1615141/d28212b1-3fb6-0c41-f9f4-70ff617afa41.jpeg)

#終わりに
これでRaspberry Pi 4B+と64-bit OS上で、最小限のドライバーを開発するための環境が整いました。


#参考URL
https://www.raspberrypi.org/documentation/linux/kernel/building.md
https://qengineering.eu/install-raspberry-64-os.html
https://medium.com/@knownsec404team/how-to-develop-linux-driver-from-scratch-cc143e0c08a1