NetBSDカーネルをビルドしてみる
今日のNetBSD Advent Calendarでは、NetBSDカーネルのビルド手順について書いてみたいと思います。
NetBSDカーネルソースコードを用意する
ソースCD(ISOイメージ)の入手
まずはカーネルのソースコードを用意します。NetBSDのインストールCD-ROM配布サイトから、ソースコード一式が入ったISOイメージをダウンロードします。
ダウンロードしたNetBSD-6.1.5-source.isoを、仮想マシンのCD-ROMとして接続します。
あとは普通にNetBSDからmountするだけでOKです。
ソースファイルを展開する
$ sudo mount /dev/cd0a /mnt
$ mount | grep mnt
/dev/cd0a on /mnt type cd9660 (read-only, local)
$ df -h | grep mnt
/dev/cd0a 432M 432M 0B 100% /mnt
ソースファイルは.tgzの形で格納されています。
$ find /mnt/ | grep \.tgz$
/mnt/source/sets/gnusrc.tgz
/mnt/source/sets/sharesrc.tgz
/mnt/source/sets/src.tgz
/mnt/source/sets/syssrc.tgz
/mnt/source/sets/xsrc.tgz
各.tgzファイルは、カレントディレクトリから見て./usr/以下に展開される形になっています。
$ for i in `find /mnt/ | grep \.tgz$`;do tar ztvf $i | head -n1; done 2> /dev/null
drwxrwxr-x 2 root wsrc 0 Sep 29 16:17 usr/src/gnu
drwxrwxr-x 2 root wsrc 0 Sep 29 16:17 usr/src/share
drwxrwxr-x 2 root wsrc 0 Sep 29 16:17 usr/src
drwxrwxr-x 2 root wsrc 0 Sep 29 16:17 usr/src
drwxrwxr-x 2 root wsrc 0 Sep 29 16:17 usr/xsrc
慣習的にソースコードの展開先は/usr/src/なので、それに倣い展開します。tarのオプションで"-C /"を指定することで、展開先のディレクトリを指定できます。
rootユーザで以下のコマンドを実行し、ソースファイル一式を展開します。
$ sudo -i
kimiuso# for i in `find /mnt/ | grep \.tgz$`; do tar zxvf $i -C / ; done
ソースファイルが展開された後の/usr/src/ディレクトリは以下のようになります。ソースファイル全体のサイズは1.6GBほどのようですね。
$ ls -F /usr/src/
BUILDING common/ external/ regress/ usr.bin/
CVS/ compat/ extsrc/ rescue/ usr.sbin/
Makefile crypto/ games/ sbin/ x11/
Makefile.inc dist/ gnu/ share/
UPDATING distrib/ include/ sys/
bin/ doc/ lib/ tests/
build.sh* etc/ libexec/ tools/
$ du -h /usr/src/ | tail -n1
1.6G /usr/src/
ISOイメージをCDのようにmountする
蛇足になりますが、ISOイメージ自体をmountすることも可能です。場合によってはこちらの方が手順的には楽かもしれません。
vnconfigコマンドにより、ISOイメージを擬似的なディスクデバイスに見せかけ、それをmountするという形になります。
(Linuxだとmount -o loopbackとかだったような...)
$ ls NetBSD-6.1.5-source.iso
NetBSD-6.1.5-source.iso
$ sudo vnconfig vnd0 NetBSD-6.1.5-source.iso
$ sudo vnconfig -l
vnd0: / (/dev/wd0a) inode 1562384
vnd1: not in use
vnd2: not in use
vnd3: not in use
$ sudo mount -t cd9660 /dev/vnd0a /mnt
$ mount | grep mnt
/dev/vnd0a on /mnt type cd9660 (read-only, local)
$ df -h | grep mnt
/dev/vnd0a 432M 432M 0B 100% /mnt
mountしてしまえば、後の手順はCD-ROMと同じです。使い終わったら、以下の手順でunmountし、疑似デバイスからも外します。
$ sudo umount /mnt
$ sudo vnconfig -u vnd0
$ sudo vnconfig -l
vnd0: not in use
vnd1: not in use
vnd2: not in use
vnd3: not in use
カーネルのビルド
では早速、展開したソースファイルからNetBSDカーネルをビルドしてみます。
まず、カーネルビルド時に組み込むデバイスやオプションを指定するためのファイルとして、カーネルコンフィギュレーションファイルというものがあります。
長ったらしい呼び名なので、単に「configファイル」と呼ばれることもあります。以降は「configファイル」という表記で説明します。
例えばNetBSD-amd64の場合のconfigファイルは/usr/src/sys/arch/amd64/conf/にあります。NetBSDは複数のCPUアーキテクチャで動作するので、arch/{CPUアーキテクチャ名}の下にconfigが置かれている構成になっています。
$ cd /usr/src/sys/arch/amd64/conf/
$ ls -F
CVS/ Makefile.amd64 kern.ldscript majors.amd64
GENERIC XEN3_DOM0 kern.ldscript.2MB std.amd64
INSTALL XEN3_DOMU kern.ldscript.Xen std.xen
INSTALL_XEN3_DOMU files.amd64 largepages.inc
インストールCDでは「GENERICカーネル」という、一般的なカーネル構成でビルドされたカーネルがインストールされます。GENERICカーネルのconfigファイルは、その名前の通り、GENERICというファイル名になっています。
このGENERICなconfigファイル、コメントにいろいろと書かれており、その部分をgrepするだけで、どんな機能やドライバがあるかが何となく見えてきます。
$ grep '^# ' GENERIC | egrep -i '(controller|device|support)'
# and device drivers, but should be useful for most applications.
# For further information on hardware support for this architecture, see
# of each device driver in this file see the section 4 man page for the
# device.
# Diagnostic/debugging support options
# Wedge support
# console scrolling support.
# enable splash screen support; requires genfb or radeonfb
# Device configuration
# ACPI devices
# Mainboard devices
# Basic Bus Support
# PCI bus support
# ISA bus support
# CardBus bridge support
# CardBus bus support
# Console Devices
# Cryptographic Devices
# PCI cryptographic devices
# Serial Devices
# AMD 768 and 8111 power/ACPI controllers
# NVIDIA nForce2/3/4 SMBus controller
# Intel PIIX4 power management controllers
# Intel ICH SMBus controller
# Thermal monitor and fan controller
# iTE IT87xxF Super I/O with watchdog and sensors support
# I2O devices
# GPIO devices
# 1- Wire support
# I2C support
# Keylock support
# SCSI Controllers and Devices
# PCI SCSI controllers
# PCMCIA SCSI controllers
# SCSI bus support
# SCSI devices
# RAID controllers and devices
# IDE and related devices
# PCI IDE controllers - see pciide(4) for supported hardware.
# a machine hang with some controllers.
# PCMCIA IDE controllers
# CardBus IDE controllers
# ISA ST506, ESDI, and IDE controllers
# Some controllers pass the initial 32bit test, but will fail later.
# ATA (IDE) bus support
# Flags are used only with controllers that support DMA operations
# and mode settings (e.g. some pciide controllers)
# 0x0000 means "use whatever the drive claims to support".
# ATAPI bus support
# ATA RAID configuration support, as found on some Promise controllers.
# ATAPI devices
# Miscellaneous mass storage devices
# MII/PHY support
# USB Controller and Devices
# PCI USB controllers
# CardBus USB controllers
# ISA USB controllers
# PCMCIA USB controllers
# USB bus support
# USB HID device
# USB Generic HID devices
# IrDA and Consumer Ir devices
# PCI IEEE1394 controllers
# CardBus IEEE1394 controllers
# Audio Devices
# PCI audio devices
# Audio support
# MIDI support
# FM-Radio devices
# PCI radio devices
# Radio support
# Video capture devices
# Bluetooth Controller and Device support
# Bluetooth PCMCIA Controllers
# Bluetooth SDIO Controllers
# Bluetooth USB Controllers
# Bluetooth Device Hub
# Bluetooth HID support
# Bluetooth Audio support
# SD/MMC/SDIO Controller and Device support
# SD/MMC controller
# devices (watchdog timer, etc.)
# Virtio devices
# Pseudo-Devices
# disk/mass storage pseudo-devices
# network pseudo-devices
# miscellaneous pseudo-devices
# a pseudo device needed for Coda # also needs CODA (above)
# a pseudo device needed for SMBFS
# wscons pseudo-devices
# pseudo audio device driver
# a pseudo device needed for veriexec
何はともあれ、このGENERICなconfigファイルを元にカーネルをビルドしてみます。単にGENERICファイルを使うのは面白味にかけるので、例によって四月は君の嘘になぞらえたKIMIUSOコンフィグでビルドしてみましょう(と言っても、単にGENERICファイルをコピーするだけですが...)。
まずはKIMIUSOコンフィグを用意します。単にGENERICをcpするだけ。
$ sudo -i
kimiuso# cd /usr/src/sys/arch/amd64/conf/
kimiuso# cp GENERIC KIMIUSO
ここからカーネルビルドの一連の手順です。"config <コンフィグファイル>"を実行すると、ビルドに必要なディレクトリが生成されます。
"make depend"でconfigファイルに合わせたビルド用の構成にして、makeでカーネルをビルドするという流れになります。
kimiuso# config KIMIUSO
Build directory is ../compile/KIMIUSO
Don't forget to run "make depend"
kimiuso# cd ../compile/KIMIUSO/
kimiuso# make depend
kimiuso# make 2>&1 | tee _make.20141205.0.log
これでサクッとNetBSDカーネルができあがります。
kimiuso# make
...中略...
# link KIMIUSO/netbsd
ld -Map netbsd.map --cref -T ../../../../arch/amd64/conf/kern.ldscript -Ttext 0xffffffff80100000 -e start -z max-page-size=0x100000 -X -o netbsd ${SYSTEM_OBJ} ${EXTRA_OBJ} vers.o
NetBSD 6.1.5 (KIMIUSO) #0: Thu Dec 4 22:37:11 UTC 2014
text data bss dec hex filename
11734705 632104 645216 13012025 c68c39 netbsd
kimiuso#
ビルドが完了すると、"netbsd"という名前でカーネルが生成されます。
kimiuso# find . -name netbsd
./netbsd
kimiuso# file netbsd
netbsd: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, for NetBSD 6.1.5, not stripped
kimiuso# ls -lh netbsd
-rwxr-xr-x 1 root wheel 14M Dec 4 22:37 netbsd
後は"make install"でカーネルを置き換えるのですが、今回は単にコピーしてみましょう。マシンのブート時に、ルートパーティションにあるカーネルを参照するので、/netbsd.kimiusoという名前でコピーしておきます。
kimiuso# cp -pi netbsd /netbsd.kimiuso
カーネルソースを編集してブート時に好きな文言を表示してみる
NetBSDカーネルのビルド手順が分かったので、せっかくだからカーネルソースコードもちょっと触ってみましょう。
ブート時に何か好きなメッセージを表示するくらいであれば、比較的簡単に実現できそうです。
NetBSDカーネルのmain()は、init_main.cにあります。
kimiuso# cd /usr/src/sys/
kimiuso# vi kern/init_main.c
init_main.cの中に、banner()という関数があり、ここで起動時に表示するメモリサイズ等を出力しているようです。
kern/init_main.c:
1110 /*
1111 * Print the system start up banner.
1112 *
1113 * - Print a limited banner if AB_SILENT.
1114 * - Always send normal banner to the log.
1115 */
1116 #define MEM_PBUFSIZE sizeof("99999 MB")
1117
1118 void
1119 banner(void)
1120 {
1121 static char notice[] = " Notice: this software is "
1122 "protected by copyright";
1123 char pbuf[81];
1124 void (*pr)(const char *, ...);
1125 int i;
1126
1127 if ((boothowto & AB_SILENT) != 0) {
1128 snprintf(pbuf, sizeof(pbuf), "%s %s (%s)",
1129 ostype, osrelease, kernel_ident);
1130 printf_nolog("%s", pbuf);
1131 for (i = 80 - strlen(pbuf) - sizeof(notice); i > 0; i--)
1132 printf(" ");
1133 printf_nolog("%s\n", notice);
1134 pr = aprint_normal;
1135 } else {
1136 pr = printf;
1137 }
1138
1139 memset(pbuf, 0, sizeof(pbuf));
1140 (*pr)("%s%s", copyright, version);
1141 format_bytes(pbuf, MEM_PBUFSIZE, ctob((uint64_t)physmem));
1142 (*pr)("total memory = %s\n", pbuf);
1143 format_bytes(pbuf, MEM_PBUFSIZE, ctob((uint64_t)uvmexp.free));
1144 (*pr)("avail memory = %s\n", pbuf);
1145 }
一昨日の記事のように、何か表示させてみましょう。変更内容は以下の通りです。
kimiuso# diff -u kern/init_main.c.orig kern/init_main.c
--- kern/init_main.c.orig 2013-03-14 16:33:10.000000000 +0000
+++ kern/init_main.c 2014-12-04 23:31:25.000000000 +0000
@@ -1142,4 +1142,5 @@
(*pr)("total memory = %s\n", pbuf);
format_bytes(pbuf, MEM_PBUFSIZE, ctob((uint64_t)uvmexp.free));
(*pr)("avail memory = %s\n", pbuf);
+ (*pr)("Your lie in April.\n");
}
これを先ほど同じ手順でビルドします。
kimiuso# cd /usr/src/sys/arch/amd64/conf/
kimiuso# config KIMIUSO
kimiuso# cd ../compile/KIMIUSO/
kimiuso# make depend
kimiuso# make 2>&1 | tee _make.1.log
念のため中身を確認してみます。それっぽい文字列が入っているようですね。
kimiuso# strings ./netbsd | grep 'Your lie'
Your lie in April.
生成されたカーネルファイルを/netbsd.kimiusoとしてコピーします。
kimiuso# cp -pi ./netbsd /netbsd.kimiuso
起動してみる
仮想マシンを再起動すると、ブート直後に以下の画面が表示されます。ここでスペースキーを押すことで、起動時のオプションを選択することができます。
"5. Drop to boot prompt"を選ぶと、プロンプトに落ちます。
"help"と入力すると、利用可能なコマンド一覧が表示されます。"boot"というコマンドにカーネルファイル名を指定することで、任意のカーネルで起動できそうです。
以下のように入力してみます。
> boot netbsd.kimiuso
すると、起動時にそれらしき文字列が!
ログインしてuname -aとか実行してみます。KIMIUSOコンフィグによるカーネルであることが分かります。
-bash-2.05b$ uname -a
NetBSD kimiuso 6.1.5 NetBSD 6.1.5 (KIMIUSO) #1: Thu Dec 4 22:59:42 UTC 2014 root@kimiuso:/usr/src/sys/arch/amd64/compile/KIMIUSO amd64
dmesgも見てみます。ばっちり"Your lie in April."という出力が記録されていて、幸せな気分になれます。
$ dmesg | head -n11
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.
NetBSD 6.1.5 (KIMIUSO) #1: Thu Dec 4 22:59:42 UTC 2014
root@kimiuso:/usr/src/sys/arch/amd64/compile/KIMIUSO
total memory = 511 MB
avail memory = 481 MB
Your lie in April.
まとめ
今日のNetBSD Advent Calendarでは、カーネルのビルド手順をつらつらと書いてみました。カーネルのビルドは意外と簡単、と感じてもらえると嬉しいです。