taiさんのLinux v2.6.32.71ビルドと実機での実行テスト
環境の用意
docker-compose.ymlに下記のサービスを追加する。
code:yaml
gcluster-dev:
build:
context: ./dsm232
command: /bin/bash
volumes:
- ./app/buildlog:/env/ott/
/env/ottに元からあるファイルは何かしらの方法./app/buildlogに前もってコピーしておく。
docker-compose run gcluster-devでgclusterの開発環境を起動。
code:shell
mkdir build-tai-kernel && cd build-tai-kernel
apt install git
configの用意
configファイルは、gclusterのビルドに元から使われているものをそのまま利用する
(dlinkのkernel.configはmake ARCH=arm cnc1800l_TigaMini_defconfigをベースにネットワーク関連やHID関連のconfigをいじったように見える)
code:shell
root@d7a03ea377d4:/env/ott/build-tai-kernel/linux# cp /env/ott/dlink/config/kernel.config .config
make ARCH=arm oldconfig
ここで、自作バージョンだと分かるようにlocal versionを加える
code:shell
apt install ncurses-dev
make ARCH=arm menuconfig
General setup -> Local version で、任意のバージョン名に変更
https://scrapbox.io/files/61d93a8beed1e1001d4d9570.png
code:shell
root@d7a03ea377d4:/env/ott/build-tai-kernel/linux# make ARCH=arm prepare
CHK include/linux/version.h
UPD include/linux/version.h
Generating include/asm-arm/mach-types.h
CHK include/linux/utsrelease.h
UPD include/linux/utsrelease.h
SYMLINK include/asm -> include/asm-arm
CC kernel/bounds.s
GEN include/linux/bounds.h
CC arch/arm/kernel/asm-offsets.s
GEN include/asm/asm-offsets.h
CALL scripts/checksyscalls.sh
root@d7a03ea377d4:/env/ott/build-tai-kernel/linux# make ARCH=arm kernelrelease
2.6.32.71-gpioblink-v1.0
make ARCH=arm kernelreleaseにより、バージョンが更新されていることを確認。
ビルド作業
dockerの環境内でクロスコンパイル用のツールチェーンは用意済みですので、次の作業で簡単にビルドできます。
code:shell
make -j 4 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- zImage
エラー対処
カーネルビルドの最中に、次のエラーが発生したので、修正していきます。
code:shell
net/core/filter.c: In function 'sk_run_filter':
net/core/filter.c:294: error: implicit declaration of function 'WARN_RATELIMIT'
make: *** Waiting for unfinished jobs....
code:shell
WARN_RATELIMIT(1, "Unknown code:%u jt:%u tf:%u k:%u\n",
fentry->code, fentry->jt,
fentry->jf, fentry->k);
WARN_ON(1);
return 0;
正しくビルドができれば、
code:shell
OBJCOPY arch/arm/boot/Image
Kernel: arch/arm/boot/Image is ready
AS arch/arm/boot/compressed/head.o
GZIP arch/arm/boot/compressed/piggy.gz
CC arch/arm/boot/compressed/misc.o
AS arch/arm/boot/compressed/piggy.o
LD arch/arm/boot/compressed/vmlinux
OBJCOPY arch/arm/boot/zImage
Kernel: arch/arm/boot/zImage is ready
arch/arm/boot/zImageが作成されている。
モジュールのビルド
code:shell
make -j 4 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- modules
ここでモジュールとして設定されている、無線ドライバをビルド。
これは、本来はmake modules_installsをやってRootFSに差し込まないといけないが、今回は自作カーネルが動くかの検証なので、RootFSは既存のものを使う想定。
パッケージの作成
次に、uBootから扱えるイメージを作っていく。具体的には、zImageの先頭64バイトにU-Bootのヘッダーをつけ、uImageにしていく。
code:shell
root@d7a03ea377d4:/env/ott/build-tai-kernel/linux# mkimage -a 0x8000 -A arm -O linux -T kernel -C none -e 0x8000 -n kernel -d arch/arm/boot/zImage uImage
Image Name: kernel
Created: Sat Jan 8 07:55:18 2022
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2522724 Bytes = 2463.60 kB = 2.41 MB
Load Address: 00008000
Entry Point: 00008000
これでuImageの準備は完了。
次はUARTを経由して、gclusterに焼いて実行を試してみる。
実機でのkernel実行テスト
FATでフォーマットされたUSBメモリのルートに、上のuImageをコピーしたものを用意し、gclusterに入り、UARTでU-Bootに入る。
code:shell
CNCl800L> usb start
(Re)start USB...
USB: scanning bus for devices... 2 USB Device(s) found
scanning bus for storage devices... 1 Storage Device(s) found
CNCl800L> fatload usb 0 00008000 uImage
reading uImage
.................................................................................................................
2522788 bytes read
CNCl800L> bootm 00008000
## Booting kernel from Legacy Image at 00008000 ...
Image Name: kernel
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2522724 Bytes = 2.4 MiB
Load Address: 00008040
Entry Point: 00008040
XIP Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux..............................................................................................
mmc0: Version ID 0x5342230a.
Root-NFS: No NFS server available, giving up.
VFS: Unable to mount root fs via NFS, trying floppy.
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0)
で、ここまでで作成したファームウェアが起動できることは分かった。
ただし、RootFSがないと当然動かないので、さくっとファイルシステムを用意していく。
起動用のinitramfsを用意
ここからやることは、initramfsが含まれるkernelイメージであるbootpImageを作成することである。
ここでは、動作検証ができればいいので、もともとのGPLコードでビルド済みのinitramfsを使うことにする。
まずは、/env/ott/tools/rootfs/buildに行き、次の行をコメントアウトして、消されてしまうinitramfsを残るようにする。
code:/env/ott/tools/rootfs/build
#rm -f initramfs.cpio.gz ubootpImage #rm -f "$ROOTDIR/mediademo/work/target/"gen_init_cpio #rm -f "$ROOTDIR/mediademo/work/target/"gen_init_cpio.* #rm -f "$ROOTDIR/mediademo/work/target/"gen_initramfs_list.sh #rm -f "$ROOTDIR/mediademo/work/target/"xcp.pl #rm -f "$ROOTDIR/mediademo/work/target/"Makefile この上で./buildを実行すると、initramfs.cpio.gzを見つけることが出来る。
あとは、これを、先程ビルドしたカーネルにくっつければOK!
code: shell
root@d7a03ea377d4:/env/ott/build-tai-kernel/linux# make ARCH=arm INITRD="$ROOTDIR"/tools/rootfs/initramfs.cpio.gz bootpImage
mkimage -a 0x8000 -A arm -O linux -T kernel -C none -e 0x8000 -d arch/arm/boot/bootpImage -n gpioblink_gcluster_v1.0! ubootpImage
では、このubootpImageを、USBに移し、U-bootから先程の手順でブートしてみる
code:shell
CNCl800L> usb start
(Re)start USB...
USB: scanning bus for devices... 2 USB Device(s) found
scanning bus for storage devices... 1 Storage Device(s) found
CNCl800L> fatload usb 0 ${RAM} ubootpImage
reading ubootpImage
.........................
25217487 bytes read
CNCl800L> bootm ${RAM}
これで正常にLinuxが起動すればOK
(GPLを非改造でビルドしたinitramfsの場合、シェルに入るために、HDMIの入力と、シェルが見えるまで「stty cread」の入力が必要です)
あとは uname -aなんかをして、自分でビルドしたLinuxが動いているか確認してみましょう
code:shell
DSM232:/ # uname -a
Linux DSM232 2.6.32.71-gpioblink-v1.0 #1 PREEMPT Sat Jan 8 07:44:45 UTC 2022 armv6l GNU/Linux