OpenBlocks で FreeBSD

第1回 OpenBlocks で FreeBSD

2012.09.03

はじめに

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 を動くようにします。

  • データシート

    一般公開されているデータシートです。カーネル改造、ドライバ作成の参考にします。

移植手順

移植は以下の通りに進めました。

  1. 母艦を NFS/TFTP/DHCP サーバにします
  2. FreeBSD のソースコードを取得します
  3. FreeBSD カーネルを改造します
  4. ベースシステムおよび改造したカーネルを母艦でクロスコンパイルします
  5. 改造した FreeBSD カーネルでブートします
  6. ログインできたら移植完了

基本的に、カーネルが起動できるようになるまで 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

著者プロフィール

usuke

たなか。新しいプリント基板の匂いが好きな FreeBSD ユーザ。普通の人なので利き基板はできません。社内では、ネットワークや組み込みの開発をしています。

記事一覧Index