クロスコンパイル環境でNetBSD-hpcmipsなカーネルをビルドしてみる
NetBSDのクロスコンパイル環境
NetBSDはMIPSやPowerPC,SHやVAX,SPARCといった、Intel系以外のCPUアーキテクチャでも動作します。これらのアーキテクチャには、自身でカーネルをビルドするとかなり時間がかかったりするものもあります。NetBSDではクロスコンパイルに対応したツールチェインが用意されており、他のCPUアーキテクチャ向けにカーネルをクロスコンパイルすることが容易に行えます。
今日のNetBSD Advent Calendarでは、このツールチェインの構築と、これを利用してクロスコンパイルしたNetBSD-hpcmipsなカーネルを実機(初代シグマリオン)で動かしてみる記事を書こうと思います。
前準備
ソースコードの展開
まずはNetBSDのソースコードを展開します。前回のカーネルコンパイルの記事と同じく、仮想マシン上でクロスコンパイル環境を構築してみます。
仮想マシンにソースCD-ROM(NetBSD-5.1.5-source.iso)をセットして、NetBSD側から以下の手順でmountします。/cdromというマウントポイントが存在しているので、そこにmountするとよさそうです。
nibossy ~ $ sudo mount -t cd9660 /dev/cd0a /cdrom
nibossy ~ $ mount | grep cdrom
/dev/cd0a on /cdrom type cd9660 (read-only, local)
NetBSDのソースコード一式を展開します。展開先のトップディレクトリを"-C /"としている点に注意してください。
nibossy ~ $ sudo -i
nbsd515_yuusyabu# cd /cdrom/source/sets/
nbsd515_yuusyabu# ls
MD5 gnusrc.tgz src.tgz xsrc.tgz
SHA512 sharesrc.tgz syssrc.tgz
# for i in *.tgz; do tar zxvf $i -C / ; done
ツールチェインの構築
次に、NetBSD-hpcmipsをクロスコンパイルするためのツールチェインを作成します。といっても、展開したソースコードに含まれるbuild.shスクリプトが全部やってくれるので、そんなに難しくありません。
/usr/src/BUILDINGを見ると、build.shは以下のように説明されています。
# cat BUILDING
BUILDING(8) NetBSD System Manager's Manual BUILDING(8)
NAME
BUILDING -- Procedure for building NetBSD from source code
...中略...
build.sh Bourne-compatible shell script used for building the host
build tools and the NetBSD system from scratch. Can be
used for both native and cross builds, and should be used
instead of make(1) for any source tree that is updated and
recompiled regularly.
ツールチェインの格納先として/usr/cross/NetBSD-5.1.5/hpcmipsを指定し、以下の手順を実行してみます。
nibossy ~ $ sudo -i
# cd /usr/src/
# mkdir /usr/cross
# uname -r
5.1.5
# ./build.sh -m hpcmips -a mipsel -T /usr/cross/NetBSD-5.1.5/hpcmips -r -o -U tools
こんな感じでツールチェインが生成されます。
# time ./build.sh -m hpcmips -a mipsel -T /usr/cross/NetBSD-5.1.5/hpcmips -r -o -U tools
===> build.sh started: Thu Dec 18 02:09:55 JST 2014
===> NetBSD version: 5.1.5
===> MACHINE: hpcmips
===> MACHINE_ARCH: mipsel
===> Build platform: NetBSD 5.1.5 amd64
===> HOST_SH: /bin/sh
===> No /usr/cross/NetBSD-5.1.5/hpcmips/bin/nbmake, needs building.
===> Bootstrapping nbmake
...中略...
===> build.sh ended: Thu Dec 18 02:16:29 JST 2014
===> Summary of results:
build.sh command: ./build.sh -m hpcmips -a mipsel -T /usr/cross/NetBSD-5.1.5/hpcmips -r -o -U tools
build.sh started: Thu Dec 18 02:09:55 JST 2014
NetBSD version: 5.1.5
MACHINE: hpcmips
MACHINE_ARCH: mipsel
Build platform: NetBSD 5.1.5 amd64
HOST_SH: /bin/sh
No /usr/cross/NetBSD-5.1.5/hpcmips/bin/nbmake, needs building.
Bootstrapping nbmake
TOOLDIR path: /usr/cross/NetBSD-5.1.5/hpcmips
DESTDIR path: /usr/src/destdir.hpcmips
RELEASEDIR path: /usr/src/releasedir
Removing /usr/cross/NetBSD-5.1.5/hpcmips
Removing /usr/src/destdir.hpcmips
Created /usr/cross/NetBSD-5.1.5/hpcmips/bin/nbmake
makewrapper: /usr/cross/NetBSD-5.1.5/hpcmips/bin/nbmake-hpcmips
Updated /usr/cross/NetBSD-5.1.5/hpcmips/bin/nbmake-hpcmips
Tools built to /usr/cross/NetBSD-5.1.5/hpcmips
build.sh ended: Thu Dec 18 02:16:29 JST 2014
===> .
394.82s real 283.10s user 62.80s system
ここまででクロスコンパイル用のツールチェインの準備は完了です。
hpcmips向けのカーネルをクロスビルドしてみる
カーネルのビルド
単にカーネルをビルドするだけでは面白みに欠けるので、NetBSDカーネルをビルドしてみるの記事にならい、カーネルソースコードを少し修正してみます。この記事ではNetBSD-6.1.5を対象にした手順でしたが、今回は都合上、NetBSD-5.1.5を対象にします。
このNetBSD-5.1.5でも起動時に好きなメッセージを表示するようにしてみます。ただ、NetBSD-6.1.5では起動時に呼ばれていたbanner()関数が存在していません。
そこで、"total memory"という文字列を元にソースコードをgrepしてみます。sys/arch/hpcmips/hpcmips/machdep.cを修正すればよさそうです。
nibossy ~ $ cd /usr/src/sys
nibossy sys $ find . -type f | grep \\.c$ | xargs grep 'total memory' | grep hpcmips
./arch/hpcmips/hpcmips/machdep.c: printf("total memory = %s\n", pbuf);
./arch/hpcmips/hpcmips/machdep.c: printf("total memory banks = %d\n", mem_cluster_cnt);
sys/arch/hpcmips/hpcmips/machdep.cを見ると、cpu_startup()という関数の中で"total memory"を出力しています。ここに自分の好きなメッセージを表示する処理を追加します。
sys/arch/hpcmips/hpcmips/machdep.c:
538 /*
539 * Machine-dependent startup code.
540 * allocate memory for variable-sized tables, initialize CPU.
541 */
542 void
543 cpu_startup()
544 {
...
558 printf("%s%s", copyright, version);
559 sprintf(cpu_model, "%s (%s)", platid_name(&platid), cpu_name);
560 printf("%s\n", cpu_model);
561 format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
562 printf("total memory = %s\n", pbuf);
563 if (bootverbose) {
564 /* show again when verbose mode */
565 printf("total memory banks = %d\n", mem_cluster_cnt);
...
592 printf("avail memory = %s\n", pbuf);
593 }
今回は「結城友奈は勇者である」のWikipediaの記事の一部を表示してみましょう。
修正内容は以下のような感じです。
# diff -u arch/hpcmips/hpcmips/machdep.c.orig arch/hpcmips/hpcmips/machdep.c
--- arch/hpcmips/hpcmips/machdep.c.orig 2014-12-18 02:43:53.000000000 +0900
+++ arch/hpcmips/hpcmips/machdep.c 2014-12-18 02:56:07.000000000 +0900
@@ -590,6 +590,11 @@
#endif
format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
printf("avail memory = %s\n", pbuf);
+
+ printf("Y^ki Y^na wa Ysha de Aru (Y^na Y^ki is a Hero) is \n");
+ printf("a Japanese anime television series produced by \n");
+ printf("Studio Gokumi and directed by Seiji Kishi as part of \n");
+ printf("a media project called Takahiro IV Project. \n");
}
void
カーネルのクロスコンパイル
NetBSD-hpcmipsなカーネルをビルドする際、一点確認しておくことがあります。それは実機のCPUがTX39XXなのか、VR41XXのどちらなのか、という点です。私が持っているのは初代シグマリオンで、Wikipediaによると、CPUはVR4121(MIPS)です。
hpcmipsのカーネルコンフィグには、VR41XXというファイルが用意されているので、これを使います。
# cd /usr/src/sys/arch/hpcmips/conf/
# ls
CVS MPC303 VR41XX std.hpcmips.tx39
GENERIC NULLCONF files.hpcmips std.hpcmips.vr41
INSTALL_TX3912 RAMDISK ioconf.incl.hpcmips std.lcard
LCARD TX3912 majors.hpcmips
LROUTER TX3922 std.hpcmips
カーネルコンフィグを好きな名前でコピーします。今回は矢澤にこ...ではなく、にぼっしーにしてみます(自分で分かればどんな名前でもOKです)。
# cp VR41XX NIBOSSY
カーネルをビルドする
ここからカーネルをクロスコンパイルします。といっても、クロスコンパイル用のコマンド(ツールチェイン)を使うというだけで、手順としてはNetBSDカーネルをビルドしてみるで紹介した手順と同じです。
こんな感じで、同じ手順で他アーキテクチャ向けのNetBSDカーネルがクロスコンパイル可能というお手軽さがNetBSDを使う利点の一つですね!
# /usr/cross/NetBSD-5.1.5/hpcmips/bin/nbconfig NIBOSSY
Build directory is ../compile/NIBOSSY
Don't forget to run "make depend"
# cd ../compile/NIBOSSY/
# /usr/cross/NetBSD-5.1.5/hpcmips/bin/nbmake-hpcmips depend
# /usr/cross/NetBSD-5.1.5/hpcmips/bin/nbmake-hpcmips
そうこう言っているうちに、カーネルのクロスコンパイルが完了です。
# time /usr/cross/NetBSD-5.1.5/hpcmips/bin/nbmake-hpcmips
...中略...
NetBSD 5.1.5 (NIBOSSY) #0: Thu Dec 18 03:08:47 JST 2014
text data bss dec hex filename
3091252 59840 381400 3532492 35e6cc netbsd
123.10s real 107.22s user 13.90s system
fileコマンドでファイルの種類を確認してみます。amd64な環境でhpcmips(MIPS)なNetBSDカーネルが生成されています。
# uname -a
NetBSD nbsd515_yuusyabu 5.1.5 NetBSD 5.1.5 (GENERIC) #0: Sat Nov 15 19:01:43 UTC 2014 snj@b45.netbsd.org:/home/builds/ab/netbsd-5-1-5-RELEASE/amd64/201411151803Z-obj/home/source/ab/netbsd-5-1-5-RELEASE/src/sys/arch/amd64/compile/GENERIC amd64
# file ./netbsd
./netbsd: ELF 32-bit LSB executable, MIPS, MIPS-II version 1 (SYSV), statically linked, for NetBSD 5.1.5, not stripped
念のため、ホントにNIBOSSYコンフィグが使われているのか確認してみます。ちゃんとNIBOSSYなコンフィグですね。
# strings ./netbsd | grep -i nibossy
@(#)NetBSD 5.1.5 (NIBOSSY) #0: Thu Dec 18 03:08:47 JST 2014
root@nbsd515_yuusyabu:/usr/src/sys/arch/hpcmips/compile/NIBOSSY
NetBSD 5.1.5 (NIBOSSY) #0: Thu Dec 18 03:08:47 JST 2014
root@nbsd515_yuusyabu:/usr/src/sys/arch/hpcmips/compile/NIBOSSY
NIBOSSY
カーネルサイズは3.8Mほど。
# ls -lha ./netbsd
-rwxr-xr-x 1 root wheel 3.8M Dec 18 03:08 ./netbsd
ついでにバイナリの中身も少し見てみます。以下のような感じです。
# /usr/cross/NetBSD-5.1.5/hpcmips/bin/mipsel--netbsd-objdump -CxS ./netbsd | grep -A 20 '<main>:'
8015385c <main>:
8015385c: 27bdffb8 addiu sp,sp,-72
80153860: afbf0040 sw ra,64(sp)
80153864: afb10034 sw s1,52(sp)
80153868: afb3003c sw s3,60(sp)
8015386c: afb20038 sw s2,56(sp)
80153870: afb00030 sw s0,48(sp)
80153874: 8ee3000c lw v1,12(s7)
80153878: 3c028030 lui v0,0x8030
8015387c: 2451d0e0 addiu s1,v0,-12064
80153880: ae23000c sw v1,12(s1)
80153884: 0c0888b4 jal 802222d0 <consinit>
80153888: 00000000 nop
8015388c: 0c05a469 jal 801691a4 <kernel_lock_init>
80153890: 00000000 nop
80153894: 0c065923 jal 8019648c <once_init>
80153898: 00000000 nop
8015389c: 3c048034 lui a0,0x8034
801538a0: 00003021 move a2,zero
801538a4: 24845dc0 addiu a0,a0,24000
801538a8: 0c05b19f jal 8016c67c <mutex_init>
興味がある方は、以下のURLでMIPSの命令が解説されていますので、照らし合わせてみるのも面白いかと。
NIBOSSYコンフィグなカーネルで起動してみる
では早速、ビルドしたNIBOSSYコンフィグなカーネルを実機で起動させてみます。
まず、WindowsCE上でhpcboot.exeを起動します。
"DoCoMo Sigmarion"な設定が既に用意されているので、これを指定し、起動するカーネルとして、先ほどビルドしたNetBSDカーネル(予めFAT領域にコピーしておく)を指定します。
"Boot"ボタンを押すと、諸々の設定とNetBSDカーネルの読み込みが行われ...
NetBSD-hpcmipsが起動し始めます。よく見ると、先ほど追加したメッセージが表示されています!
無事にクロスコンパイルしたNetBSD-hpcmipsなカーネルで起動できました。
まとめ
昨日に引き続き、NetBSD-hpcmipsなネタで記事を書いてみました。クロスコンパイルしたバイナリが実機で動作すると、「よっしゃー、動いたー!」感がありますね。
明日からは@tisiharaさんのAdvent Calendarになります。お楽しみに!