はじめに¶
FreeBSD ユーザのたなかです。OpenBlocks A6 で遊んでいるところを弊社のくろまく [1] に見つかり、この記事を書くことになりました。くろまくこわい。
というわけで、今回は FreeBSD を OpenBlocks A6 に移植したときの作業内容をまとめてみました [2]。
使用機材¶
今回は以下の機材を用意して移植を試みました。
OpenBlocks A6
ぷらっとホーム株式会社の新型 OpenBlocks。弊社の NetBSD コミッタ清原が個人的にお借りした発売前の開発版です。本記事中では A6 と呼ぶことにします。
A6 には Marvell 88F6282 (Kirkwood) という SoC が搭載されています [3]。清原によると SheevaPlug に搭載されている Marvell 88F6281 とほぼ同じものだそうです。
母艦 (FreeBSD 9-STABLE r237988)
FreeBSD マシンです。ここで FreeBSD カーネルの改造や buildkernel, buildworld を実施します。NFS/TFTP/DHCP サーバも母艦が担当します。
RJ45 - RS232C 変換アダプタ (クロス)
A6 付属品です。パッケージ構成によっては付属していないので注意してください。この変換アダプタ自体はクロスなので、ストレートのシリアルケーブルを使用して母艦と接続します。
シリアルケーブル (ストレート)
母艦を A6 のシリアルコンソールへ接続するのに使います。たなかは USB - RS232C 変換ケーブルを使用しました。FreeBSD からは /dev/cuaU0 として見えるようになります。
USB2.0 イーサネットアダプタ
たなかは社内ネットワークに A6 を繋げたくないので、PLANEX UE-1000T-G2 を母艦に挿して A6 と直結しました。FreeBSD からは ue0 として見えるようになります。このネットワークで後述の dnsmasq を動かし、TFTP ブート、NFSROOT を実現します。
LAN ケーブル (クロス)
母艦の USB2.0 イーサネットアダプタと A6 のイーサネットポートの直結に使用します。
dnsmasq
母艦を TFTP/DHCP サーバにするために使用します。すでに DHCP サーバの存在するネットワークで使用する場合、DHCP サーバではなく Proxy DHCP サーバとして稼働させてください。
FreeBSD 9-STABLE r237988 のソースコード
FreeBSD のソースコードです。これを改造して A6 で FreeBSD を動くようにします。
データシート
一般公開されているデータシートです。カーネル改造、ドライバ作成の参考にします。
移植手順¶
移植は以下の通りに進めました。
- 母艦を NFS/TFTP/DHCP サーバにします
- FreeBSD のソースコードを取得します
- FreeBSD カーネルを改造します
- ベースシステムおよび改造したカーネルを母艦でクロスコンパイルします
- 改造した FreeBSD カーネルでブートします
- ログインできたら移植完了
基本的に、カーネルが起動できるようになるまで 3 ~ 5 を繰り返します。NFS で / を マウントしてログインできるようになったら移植完了です [4]。
母艦を NFS/TFTP/DHCP サーバにする¶
組み込み開発では TFTP ブート、NFSROOT が便利です。本章では母艦を NFS/ TFTP/DHCP サーバにします。このうち TFTP/DHCP サーバには dnsmasq を使用します。
NFS サーバ¶
まずは母艦を NFS サーバにするために /etc/rc.conf に下記を追加します
# NFSv3 server
rpcbind_enable="YES"
rpc_statd_enable="YES"
rpc_lockd_enable="YES"
mountd_enable="YES"
mountd_flags="-r"
nfs_server_enable="YES"
nfs_server_flags="-u -t -n 2"
nfsd_enable="YES"
次に /etc/exports を設定して A6 から /export/openblocksa6 を NFS マウントできるようにします。ネットワークセグメントについては適宜変更してください
/export/openblocksa6 -maproot=root -alldirs -network 192.168.3.0 -mask 255.255.255.0
/etc/hosts.allow も忘れずに設定します。こちらは差分を掲載します。こちらもネットワークセグメントについては適宜変更してください。リブートすれば NFSv3 サーバのできあがりです
diff -u /etc/hosts.allow.old /etc/hosts.allow
- rpcbind : ALL : deny
+ rpcbind : 192.168.3.0/255.255.255.0 : allow
TFTP/DHCP サーバ¶
次に母艦を TFTP/DHCP サーバにするために dnsmasq をインストールします
make config-recursive install -C /usr/ports/dns/dnsmasq
/usr/local/etc/dnsmasq.conf を設定します。ue0 は USB イーサネットアダプタです。こちらも DHCP で配布する IPv4 アドレスレンジについては適宜変更してください
port=0 # DNS サーバとして動作しないようにします
interface=ue0 # dnsmasq の動作する I/F を限定します
enable-tftp # TFTP サーバとして動作させます
dhcp-range=192.168.3.100,192.168.3.200,24h # TFTP ブートした FreeBSD に IPv4 アドレスを配ります
dhcp-option=17,"/export/openblocksa6" # TFTP ブートした FreeBSD に NFSROOT のパスを教えます
dnsmasq の設定が済んだら dnsmasq を起動します。これで TFTP/DHCP サーバのできあがりです
dnsmasq -C /usr/local/etc/dnsmasq.conf
rc.conf¶
ついでに TFTP ブートする FreeBSD の設定もここでやっておきましょう。/export/openblocksa6/etc/rc.conf で設定します
hostname="openblocksa6.soum.co.jp"
sshd_enable="YES"
sendmail_enable="NONE"
rpcbind_enable="YES"
rpc_statd_enable="YES"
rpc_lockd_enable="YES"
nfsclient_enable="YES"
ifconfig_mge0="DHCP"
FreeBSD のソースコードを取得する¶
移植作業に入る前に、FreeBSD のソースコードを取得します。本章では Subversion をインストールして FreeBSD のソースコードを取得します。
まず Subversion をインストールします。コンパイルオプションはデフォルトのままで OK です
make config-recursive install -C /usr/ports/devel/subversion
Subversion をインストールしたら、FreeBSD のソースコードを取得します
svn co -r r237988 svn://svn.freebsd.org/base/stable/9 /usr/src
FreeBSD カーネルを改造する¶
本章では取得した FreeBSD のソースコードを改造します。作成したパッチは こちら。NetBSD のソースコードや A6 同梱のドキュメント、Marvell や SII のデータシートを参考にしています。
88F6282¶
A6 には SheevaPlug に搭載されている 88F6281 とほぼ同じ 88F6282 が搭載されています。FreeBSD は SheevaPlug で動作実績があるので、88F6281 に関するコードが入っているはずです。まずは sys 以下を 6281 で grepします
grep -r 6281 /usr/src/sys
ずらずらと 88F6281 が出てくるので、新しい定数を定義して条件分岐を追加します。
E1116R rev 29¶
清原によると、Gigabit Ehternet PHY として E1116R 互換の E1116R rev 29 が搭載されているとのことです。これについても 88F6282 と同様に grep し、新しい定数を定義して条件分岐を追加します。これを忘れると別物である ukphy と認識されてしまい、ネットワークが使えません。
S35390A¶
88F6282 には RTC である S35390A が TWSI を介して外付けされています [5]。NetBSD や Linux は起動時にここから時刻を復旧していますが、FreeBSD には S35390A のドライバが無いため、それができません。NetBSD から s390rtc ドライバを移植して時刻を復旧できるようにします [6]。移植したドライバについては、sys/conf/files に登録することでカーネルに組み込みます。
openblocksa6.dts¶
デバイスの認識に使用する Device Tree Source ファイル openblocksa6.dtsを作成します。ベースになるのは sys/boot/fdt/dts/sheevaplug.dts です。SATA の設定を追加し、MPP の設定を A6 付属ドキュメントの通りに修正します。また、SheevaPlug の88F6281 と違い、TWSI が 2 つ搭載されているので 2 つ目の TWSI の設定も追加します。NetBSD のソースコードを読むと、1 つ目から + 0x100 したアドレスに居るようです。
OPENBLOCKSA6¶
最後にカーネルコンフィグファイル OPENBLOCKSA6 を作成します。ベースとなるのは sys/arm/conf/SHEEVAPLUG です。NFS サーバ、AHCI, TWSI, S35390A ドライバ、FAT ファイルシステム、ISO 9660 ファイルシステムなどに対応させます。また S35390A については OPENBLOCKSA6.hints に親デバイスとスレーブアドレスを記述して FreeBSD が S35390A を認識できるようにします。
ベースシステムおよび改造したカーネルを母艦でクロスコンパイルする¶
本章では、いよいよ母艦でカーネルとベースシステムをクロスコンパイルします。まずはクロスコンパイルのために環境変数を設定します
export TARGET_ARCH=arm # A6 の SoC にあわせて arm でクロスコンパイルします
export KERNCONF=OPENBLOCKSA6 # A6 用に作ったカーネルコンフィグを使います
export DESTDIR=/export/openblocksa6 # ここに A6 が NFS マウントする / (NFSROOT) を作ります
export CROSS_BUILD_TESTING=yes # /usr/obj ではなく /usr/obj/arm.arm にバイナリを出力するようにします
export TFTPBOOT=/tftpboot # ここに TFTP ブートしたい FreeBSD カーネルを配置します
続いて、buildworld, buildkernel でベースシステムとカーネルを作ります。最近の組み込み系では Flattened Device Tree を使用してデバイスを認識するらしいので -D で WITH_FDT を定義しています
mkdir -p ${TFTPBOOT}
mkdir -p ${DESTDIR}
cd /usr/src
make buildworld -DWITH_FDT
make buildkernel
cp /usr/obj/arm.arm/usr/src/sys/${KERNCONF}/kernel.bin ${TFTPBOOT}/kernel.bin
make installworld distribution
たなかの母艦では、buildworld, buildkernel にそれぞれ 5400sec, 360sec かかりました。/usr/obj/arm.arm, ${DESTDIR} については、それぞれ 800MB, 230MB 消費しました [7]。
注釈
sudo コマンドを使用して make コマンドを実行する場合は、sudo コマンドのオプション -E で環境変数を継承してください。
改造した FreeBSD カーネルでブートする¶
本章では前章で作成したカーネルで TFTP ブートし、母艦の ${DESTDIR} を NFS で / にマウントしてログインします。
まず、シリアルケーブルと cu コマンドで A6 に接続します
cu -l /dev/cuaU0 -115200
接続したら、A6 の電源を入れます。U-Boot が起動して「NAND: 」が表示されたら直ぐに適当なキーを押下して U-Boot のプロンプトを表示させます。プロンプトが表示されたら、下記のように入力して FreeBSD カーネルを TFTP ブートします
tftpboot 0x900000 kernel.bin
go 0x900000
0x900000 はカーネルのロードアドレスです。これは sys/arm/mv/kirkwood/std.kirkwood に記述されています。ブートメッセージが流れ、/ を NFS マウントして「login: 」が表示されたら「root」でログインします。これで移植は完了です。
まとめ¶
今回は OpenBlocks A6 に FreeBSD を移植しました。FreeBSD コミッタの佐藤先生も、ほぼ同等のパッチを FreeBSD 10-CURRENT にコミットされています [8]。本記事で作成したパッチに含まれる S35390A ドライバについては、佐藤先生に送付しました。若干の手直しの後、無事にコミットされました [9]。
A6 の 上位機種である AX3 に関しては、8/15 付けで FreeBSD 10-CURRENT に Marvell Armada XP 対応コードが入りました。MPP の設定値を弄ってビルドしてみましたが、コンソールに文字を出すことすらできませんでした。ゴールは遠そうです。
最後に本記事で作成したパッチと各種バイナリを置いておきます。興味のある方は A6 を購入して、遊んでみてください。
[1] | 原稿執筆者の確保に暗躍する運用技術部マネージャ兼 Ubuntu Japanese Team の中の人。 |
[2] | たなかは趣味で FreeBSD を移植し、趣味でこの記事を書いています。記事の内容や配布物を試す場合は自己責任でお願いいたします。 |
[3] | A6 付属のドキュメントには 88F6283 が搭載されていると記述されていますが、Chip ID が 88F6282 と同じなので 88F6282 で話を進めます。 |
[4] | ログインに成功しただけでは完全に移植できたとは言えませんが、本記事ではログイン成功をゴールということにして話を進めます。 |
[5] | 88F6282 には Marvell の I2C コントローラ TWSI が 2 つ搭載されています。このうち 2 つ目 に S35390A が繋がっています。 |
[6] | S35390A ドライバの移植については、機会があれば別の記事として書こうと思います。 |
[7] | 母艦は Pentium 4 3.0GHz, 1GB RAM です。最近の CPU や SSD を搭載したものならもっと速くコンパイルできると思います。 |
[8] | たなかは 10-CURRENT が A6 で動くか試していません。 |
[9] | http://svnweb.freebsd.org/base/head/sys/dev/iicbus/s35390a.c?view=log |