今回は、Raspberry Pi 4にインストールしたAlmaLinuxのカーネルをビルドしたいと思います。カーネルのビルドというと敷居が高そうにも思えますが、手順通りに実行すればさほど難しいものでもないかと思います。
また、カーネルを自前でビルドできるようになれば公開されているイメージには含まれていないドライバーや機能を追加することが出来ますから、Raspberry Pi 4で動かすAlmaLinuxをより便利に使用できるようになります。
カーネルも自分の好みに合わせて作り上げることができるというのも、RHEL互換のLinuxとして公開されているAlmaLinuxの醍醐味の一つではないでしょうか。
ここでは、例として配布されている状態のままでカーネルをビルドしていくことにします。必要に応じて構成する場合には、途中で実行するmenuconfig
を使用してドライバーや機能を追加、削除することが可能です。
前提ソフトウェアのインストール
カーネルをビルドするために必要となる、前提ソフトウェアをインストールします。まず、開発環境としてDevelopment Tools
のパッケージグループをインストールします。ここでは、さらにcmake
、rsync
、vim
などをインストールしています。
$ sudo dnf group install -y "Development Tools"
$ sudo dnf install -y cmake rsync vim
AlmaLinuxのソースは、rpm
形式で提供されていますから、それを展開するためにrpmdevtools
もインストールします。
$ sudo dnf install -y rpmdevtools
また、途中で実行するmenuconfig
で必要となるncurses-devel
とビルド時に使用されているbc
、openssl-devel
パッケージもインストールしておきます。
$ sudo dnf install -y ncurses-devel bc openssl-devel
AlmaLinuxカーネルソースの入手
Raspberry Pi用のAlmaLinuxのカーネルはraspberrypi2-kernel4
パッケージで提供されています。そこで、このソースのURLを参照します。
$ dnf download raspberrypi2-kernel4 --source --url
しばらくするとソースのURLが表示されました。
http://repo.almalinux.org/vault/9.2/raspberrypi/Source/Packages/raspberrypi2-6.1.31-v8.1.el9.src.rpm
ちなみに、現在実行しているカーネルとしては次の状態になっています。
$ uname -a
Linux almalinux.local 6.1.31-v8.1.el9 #1 SMP PREEMPT Wed Jun 14 12:18:16 UTC 2023 aarch64 aarch64 aarch64 GNU/Linux
ソースのURLがわかりましたから、wget
またはcurl
でダウンロードします。
$ wget http://repo.almalinux.org/vault/9.2/raspberrypi/Source/Packages/raspberrypi2-6.1.31-v8.1.el9.src.rpm
入手したソースの展開とパッチの適用
入手したソースのrpm
ファイルをrpmdev-extract
コマンドで展開します。
$ rpmdev-extract ./raspberrypi2-6.1.31-v8.1.el9.src.rpm
raspberrypi2-6.1.31-v8.1.el9.src
ディレクトリーが作成されて、次のようなファイルが展開されます。
$ ls
bcm2709_selinux_config.patch patch-6.1.31.xz
bcm2711_selinux_config.patch raspberrypi2.spec
cb9500d6021e083a182ba168fe4424e3db2494cf.tar.gz rpi-6.1.x.patch
linux-6.1.tar.xz
まず、linux-6.1.tar.xz
ファイルを解凍します。
$ tar Jxvf linux-6.1.tar.xz
作成されたlinux-6.1
ディレクトリーで、用意されているパッチを適用していきます。
$ cd linux-6.1
$ xz -dc ../patch-6.1.31.xz | patch -p1
$ cat ../rpi-6.1.x.patch | patch -p1
$ cat ../bcm2709_selinux_config.patch | patch -p1
$ cat ../bcm2711_selinux_config.patch | patch -p1
すべてのパッチを適用したら、カーネルのバージョンを確認してみます。
$ sed 4q Makefile
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 1
SUBLEVEL = 31
現在実行しているカーネルと同じ6.1.31
になっていました。
カーネルビルドの準備
カーネルをビルドする準備として、次のコマンドを実行しておきます。
$ KERNEL=kernel8
$ make bcm2711_defconfig
menuconfig
の実行
次に、menuconfig
を実行します。実際には、このメニュー画面から必要なドライバーや機能を追加・削除することが出来ます。
$ make menuconfig
このmenuconfig
の画面で矢印キーで画面と項目を移動して、Y
、N
、M
などのキーを押下してドライバー、機能を選択することが出来ます。
ここでは、既定値のままとしてタブキーで「Save」を選択して「Enter」キーを押下します。
.config
を作成するという画面が表示されますから、「Ok」のまま「Enter」キーを押下します。
以降、「Exit」を選択してmenuconfig
を終了します。
これで、menuconfig
でドライバー、機能を選択した結果の.config
ファイルが作成されました。
次に、.config
ファイルのCONFIG_LOCALVERSION
の内容を編集しておきます。
$ vi .config
CONFIG_LOCALVERSION="-v8.1.el9-rpi"
ここでは、例として-v8
となっていた内容を-v8.1.el9-rpi
に修正してみました。実際には、構成するカーネルの内容がわかるようにしておくと良いでしょう。
注意点としてビルドしたモジュールが/lib/modules
ディレクトリーに登録されます。その際に、名前が重複してしまわないようにしておくのが良いでしょう。
現在の内容は次のようになっています。
$ ls /lib/modules
6.1.31-v8.1.el9
先に確認したバージョンが6.1.31
で同じですから、上記のCONFIG_LOCALVERSION
の内容が-v8.1.el9
になると重複してしまいます。そのため、この例ではRaspberry Pi用ということで-rpi
を追加しています。
カーネルビルドの実行
用意ができましたから、実際にカーネルをビルドします。
$ make Image modules dtbs -j4
ここでは、Raspberry Pi 4のCPUコア数が4ですから並列度の引数を-j4
として実行しています。今回は、Raspberry Pi 4の8GBモデルを使用してビルドしていますが、約4時間30分ほどでビルドを完了しています。
ビルドしたカーネルの登録
ビルドが完了したら、新しいカーネルモジュールなどを登録していきます。その前に、念のために/boot
にある内容をバックアップしておきます。
$ sudo mkdir /boot.backup
$ sudo rsync -avhP /boot/ /boot.backup/
万が一、新しいカーネルモジュールなどを登録した後で起動できなくなったような場合には、他で稼働しているコンピューターを使用してバックアップしていた/boot
のファイルをリストアします。これで、元々のカーネルで起動できるようになります。
それでは、実際に新しいカーネルモジュールを登録していきます。
$ 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/
$ sudo mv /boot/Image /boot/${KERNEL}.img
ここでは、最初に設定していたKERNEL
環境変数を使用している点に注意して下さい。ここまでの作業で、KERNEL環境変数の値が設定されていない場合には、再度設定する必要があります。
注:Raspberry Pi OSの場合には、カーネルイメージがgzip圧縮されていますが、AlmaLinuxの場合には非圧縮のイメージが使用されています。
AlmaLinux用の設定
Raspberry Pi OSの場合であれば、これまでの設定で大丈夫なのですが、AlmaLinuxの場合には次の作業を追加で実行します。
$ KERNEL_VERSION=6.1.31-v8.1.el9-rpi
$ sudo cp .config /boot/config-$KERNEL_VERSION
$ cd /boot
$ sudo cp kernel8.img kernel-$KERNEL_VERSION.img
$ sudo dracut . --kver $KERNEL_VERSION --gzip
$ sudo chmod 755 initramfs.img
$ sudo cp initramfs.img initramfs-$KERNEL_VERSION.img
$ sudo vi config-kernel.inc
arm_64bit=1
kernel kernel-6.1.31-v8.1.el9-rpi.img
initramfs initramfs-6.1.31-v8.1.el9-rpi.img followkernel
$ sudo cp config-kernel.inc config-kernel-$KERNEL_VERSION
AlmaLinuxでは、カーネルイメージは非圧縮ですがinitramfs
はgzip
圧縮されていますからdracut
コマンドの実行時に--gzip
を引数として追加しています。
新しいカーネルで起動
すべての設定が完了したら、新しいカーネルで起動するために再起動します。
$ sudo reboot
無事に起動したら、カーネルのバージョンを確認してみます。
$ uname -a
Linux almalinux.local 6.1.31-v8.1.el9-rpi #1 SMP PREEMPT Sun Sep 17 00:07:44 JST 2023 aarch64 aarch64 aarch64 GNU/Linux
uname
コマンドで表示されるカーネルリリース番号からも、新しくビルドしたカーネルで起動していることがわかります。
今回は、何も新しいドライバーや機能を追加したりしていませんが、これでRaspberry Pi用のAlmaLinuxのカーネルを好みに合わせてカスタマイズできるようになりました。