概要
Raspbianにデフォルトで入っているEthernet-USB変換ICのドライバーを入れ替える必要があったので、ソースコードからドライバー(カーネルモジュール)をビルドしてデフォルトのドライバと入替えた。
ラズパイの有線LANはLAN9514というUSBハブ内蔵タイプのUSB-Ethernet変換ICを使用しており、ドライバーはカーネルに組み込まれていて、変更するにはカーネルのコンパイルが必要となる。
(モジュール化されていないのでmodprobeで入れ替えができない)
このため、実機では日が暮れてもビルドが終わらないと思うのでクロスコンパイルで作業する。
あまり需要はないと思うけど、個人的なメモとして。
作業項目
- RaspberryPiのカーネルソースとビルドツールを取得する
- カーネルをクロスコンパイル環境でコンフィグ&ビルド
- ドライバーのソースコードを準備する
- ビルドしたカーネルのディレクトリでドライバーをビルド
- カーネルとドライバーを実機にコピー
- モジュール依存関係の更新
- お疲れ様でした
RaspberryPiのカーネルソースとビルドツールを取得する
冒頭に書いた通り、カーネルのリコンパイルが必要になるので、githubからカーネルを持ってきて編集します。
(事前準備としてbuild-essentials, git, libncurses5-dev, libssl-devが必要なのでapt-get installしておきます。)
適当な作業ディレクトリに移動して
git clone https://github.com/raspberrypi/linux.git
git clone https://github.com/raspberrypi/tools.git
でカーネルソースとツールを準備します。
カーネルをクロスコンパイル環境でコンフィグ&ビルド
toolディレクトリ下に何種類かツールチェーンがダウンロードされるので最適と思われるものを使いましょう。
今回は
tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf
を使用して、長くなるので
XCC=~/wdir/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf
として変数に入れておきました。
RaspberryPiデフォルトのコンフィグ情報は実機の/proc/config.gzにあるので、実機があるならこれを何らかの方法でコピーしてきて作業フォルダで
zcat config.gz > .config make ARCH=arm CROSS_COMPILE=${XCC} oldconfig
とすると現在のビルド対象のコンフィグ情報として反映されます。
(追記)
config.gzが見つからない場合はconfigsモジュールをmodprobeすると出てくるようです。
configs moduleで/proc/config.gzを呼び出す
kernel buildしようと現在のconfigをコピーしようとしたところ/boot以下にも/proc/config.gzも見当たらない.こういう場合configsというモジュールを読み込むと/proc/config.gzが出来るらしい.
(追記)
実機がなくても下記のコマンドでデフォルトのconfigが作れると思います。
KERNEL=kernel7
make bcm2709_defconfig
このあと
make ARCH=arm CROSS_COMPILE=${XCC} menuconfig
で必要なコンフィグ情報を変更して該当のドライバーを組込対象から外します。
コンフィグが完了したら
make ARCH=arm CROSS_COMPILE=${XCC}
make ARCH=arm CROSS_COMPILE=${XCC} modules
でビルド。
-j8
オプションをつけて30分くらいかかりました。
ドライバーのソースコードを準備する
ICのメーカー(Microchip)のwebサイトからLAN9500シリーズ用のLinuxドライバーのソースコードをダウンロード、必要な修正をもにょもにょ加えます。
この辺はご自由にどうぞ。
ビルドしたカーネルのディレクトリでドライバーをビルド
今回のドライバーはビルドスクリプトが付属していたので、その内容を書き換えて、
make -C ~/wdir/linux ARCH=arm CROSS_COMPILE=${XCC} modules
になるように修正します。
具体的にはbuildというファイル名のメインのスクリプトから呼ばれるbuild_scriptを変更しました。
変更後./build
でドライバーをビルド。
公開されているドライバーのソースコードが古いためか、kernel4.4.39ではエラーが出ましたが、デバッグ関係と構造体の予約領域(reserved1)の初期化コードだったのでとりあえず全部コメントアウトで対応しました。
(ちなみにkernel3.13.0では問題なくビルドできた)
カーネルとドライバーを実機にコピー
今回はカーネルから組込みのドライバを外しているのでドライバだけでなくカーネルごと入替えます。
まずは
mkdir ~/wdir/modinst make ARCH=arm CROSS_COMPILE=${XCC} INSTALL_MOD_PATH=~/wdir/modinst modules_install
としてモジュールをまとめます。これを実機の/libにコピーします。
次にカーネル本体
~/wdir/linux/arch/arm/boot/zImage
を実機の/boot/kernel.imgとしてコピーします。
まずはこのカーネルが起動するか確認。
OKならLAN9500のドライバーを実機にコピー。
~/smsc9500/smsc9500.ko ~/smsc9500/smscusbnet.ko
を
/lib/modules/4.4.39+/kernel/drivers/net/usb
にコピーします。
モジュール依存関係の更新
モジュールを追加したので
sudo depmod
します。
実は何かあったときのためにカーネルコンフィグで、デフォルトのsmsc95xxをモジュールとしてインストールしていたので、新しいドライバが動くことを確認できたら/etc/modprobe.d下にblacklistを作ってデフォルトのモジュールをロードしないようにします。lan9500-blaclist.confというファイル名で下記の記述をしました。
blacklist smsc95xx
それから/etc/modulesに新しいモジュール名smsc9500を追加しておきます。
これで再起動時に自動的に修正済みのLAN9514用ドライバがロードされます。
お疲れ様でした。