2013年7月26日金曜日

FreeBSD で RaspberryPi (その2) FreeBSD で RaspberryPi のイメージをビルドする(作業メモ)

出来合いのイメージよりも、やっぱり、どうせなら最新機能使いたいし〜、という、そこのアナタ。
楽しいギャンブル道にようこそ。
この記事は、FreeBSD で RaspberryPi のイメージを自分でビルドする際の作業メモです。

といっても、だいぶ最近は博打率が減ってきたような気がしなくもないので、そんなに苦労しないでいけるかもしれません。運が良ければ。
特に、ちゃんと動く、当たりのリビジョン(!)を引けるかどうかというのが、結構重要ですので、動くイメージがビルド出来たら、すぐに次のイメージで上書きせず、ある程度の期間は大事に保存しておきましょう。

1: FreeBSD CURRENT 環境を構築する

FreeBSD で RaspberryPi のイメージをビルドするには、 現時点では、CURRENT を導入する必要があります。 もちろん、仮想環境でも、実機でも構いません。ただし、SD カードの読み書きが出来る必要はあります。
ここでは、イメージ作成に必要な、FreeBSD CURRENT 環境の最低限の構築法について簡単に説明します。

(1) FreeBSD CURRENT をインストールする

まず、FreeBSD CURRENT snapshots のダウンロードサイトから適当なファイルをダウンロードして、メディアに焼くなりして、インストールします。 尚、インストールする際に、src や ports は、インストール後に最新に更新するため、特に 展開する必要はありません。

64bit版
ftp://ftp.freebsd.org/pub/FreeBSD/snapshots/amd64/amd64/ISO-IMAGES/11.0/
32bit版
ftp://ftp.freebsd.org/pub/FreeBSD/snapshots/i386/i386/ISO-IMAGES/11.0/

(2) FreeBSD CURRENT のソースコードを最新にする

インストールが完了したら、 最新のソースツリーを取得します。 現在の CURRENT には svn がデフォルトで入っています。ただ、ports にも svn が存在するため、 衝突を避けるため、システムの svn を利用する場合は svnlite として使用します。

# cd /usr

src にソースを既に展開済みの場合は src を一旦削除します。 src ディレクトリが空の場合は削除する必要はありません。

# rm -rf src

初回のソースツリーの取得の場合は checkout します。

# svnlite checkout svn://svn.freebsd.org/base/head/ src

一旦 checkout したあとは、

# cd /usr/src
# svnlite update

で更新出来ます。 尚、取得したソースツリーのリビジョン番号を後から確認したくなることがよくありますが、そのときは、それぞれのソースツリーのルートで、

# svnlite info

を実行するとよいでしょう。

次に、最新の ports ツリーを取得します。 ports に ports ツリーを既に展開済みの場合は ports を一旦削除します。 ports ディレクトリが空の場合は削除する必要はありません。

# rm -rf ports

初回の ports ツリーの取得の場合は checkout します。

# svnlite checkout svn://svn.freebsd.org/ports/head/ ports

次回以降は、

# cd /usr/ports
# svnlite update

で ok です。

(3) /etc/make.conf 及び /etc/src.conf を修正する

これから、大量のビルドをするにあたって、/etc/make.conf 及び /etc/src.conf を設定しておくと多少幸せになれるかもしれません。

# cp /usr/share/examples/etc/make.conf /etc/
# vi /etc/make.conf

src.conf はテンプレートに当たるものはないので、使用する場合は新規作成します。

# vi /etc/src.conf

最低限のおすすめ設定をいくつか挙げます。

  1. make.conf の以下の行のコメントを外して最適化オプションを有効化する
    COPTFLAGS= -O -pipe
    
  2. src.conf に、以下の行を新規で追加し、malloc デバッグ機能を無効化する
    #disable malloc_debug function
    MALLOC_PRODUCTION=YES
    
  3. src.conf に、以下の行を新規で追加し、gcc を有効にする。特に arm は gcc をports から入れることが現時点ではできないので、ここは要注意です。もっとも、有効にしても、gcc の標準ライブラリが入るわけではないので、gcc 依存のアプリはビルドできないことが多々出てきます。
    WITH_GCC=yes
    WITH_GNUCXX=yes
    

(4) カーネルコンフィグレーションファイルをカスタマイズする

カーネルコンフィグレーションファイルはアーキテクチャ毎に場所が分かれているため、
64bit版なら

# cd /usr/src/sys/amd64/conf

32bit版なら

# cd /usr/src/sys/i386/conf

に移動して、 デフォルトの GENERIC カーネルコンフィグレーションファイルをコピーして、カスタマイズします。

# cp GENERIC MYKERNEL
# vi MYKERNEL

MYKERNEL の部分は任意の名前に修正してください。ここでは例として MYKERNEL をカスタムカーネルファイル名として作成します。

カーネルファイルの主な修正箇所は以下の通りです。

以下の行の GENERIC の部分を MYKERNEL に書き換えます。
ident MYKERNEL

その他の最低限のおすすめは、各種デバッグオプションの無効化です。
以下の行が主なデバッグオプションですので、それぞれ先頭に#をつけてコメントにするとよいでしょう。
#makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols



# Debugging support. Always need this:
# KDB # Enable kernel debugger support.
# For minimum debugger support (stable branch) use:
#options KDB_TRACE # Print a stack trace for a panic.
# For full debugger support use this instead:
# DDB # Support DDB.
# GDB # Support remote GDB.
# DEADLKRES # Enable the deadlock resolver
# INVARIANTS # Enable calls of extra sanity checking
# INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
# WITNESS # Enable checks to detect deadlocks and cycles
# WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
# MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones

これ以外のオプションについては必要に応じて追加修正してください。
ここではあえて触れません。

(5) 最新のソースコードをベースにシステムを再構築する

簡単に手順のみを書きます。
CURRENT は build に失敗することが時々あります。
そのため、script コマンドなどでログをとっておくと失敗した場合に役に立ちます。
例)

# script hoge.log(ログを保存する任意のファイル名)
# (ログを取りたい作業を実行)
# exit(ログの取得を終了)

ユーザランドとカーネルのビルドについては、基本的に決まった手順がありますので、それに則って行います。以下がその手順で、(a)-(b)、もしくは(a)-(c)の順番で実行します。

make installworld はシングルユーザモードで実行することが一般的には推奨されていますが、 自分一人しか使わない環境であればそこまで気にする必要はありません。ですので、マルチユーザモードで構わない場合は、(a)-(b)で、 シングルユーザモードでやる場合は、installkernel 後の再起動時に、 シングルユーザモードを選択して起動後、(b)の手順の代わりに(c)を実行します。

(a) ユーザランドのビルドと、カスタムカーネルのビルド・インストール(共通)

# cd /usr/src
# make buildworld
# make buildkernel KERNCONF=MYKERNEL
# make installkernel KERNCONF=MYKERNEL
# reboot

(b) make installworld をマルチユーザモードで実行する場合

# cd /usr/src
# mergemaster -p
# make installworld
# mergemaster
# reboot

(c) make installworld をシングルユーザモードで実行する場合

# mount -u /
# mount -a -t ufs
# swapon -a
# adjkerntz -i
# mergemaster -p
# cd /usr/src
# make installworld
# mergemaster
# reboot

CURRENT のインストールについては、こちらのブログのFreeBSD-CURRENT を導入してみた (3) 最新状態に更新してみたに詳しい説明や失敗した場合の復帰方法などが書いてあるため、併せて読まれるといいかもしれません。

(6) 一般ユーザを作成する

ここまでで、まだ一般ユーザをシステムに追加していない場合は、 ユーザを追加します。

# adduser

管理者ユーザであれば、所属する group に wheel に追加するのを忘れないようにしましょう。

2: RaspberryPi のビルド環境を作成する

(1) arm のクロスコンパイル環境を作成する

次に、arm のクロスコンパイル環境を作成します。これは、できれば、ソースコードを更新した場合はこちらも併せてビルドし直すようにしたほうがよいでしょう。ビルドし直すときは、同じオプションで make コマンドを実行するだけです。

# cd /usr/src
# make XDEV=arm XDEV_ARCH=armv6 xdev

尚、2回目以降のビルドの場合は、余計な不具合を避けるために、一旦 /usr/obj を全削除してから実行することをお勧めします。

# rm -rf /usr/obj

(2) ports から git をインストールする

必要なファイルの修得に git が必要になりますので、devel/git をインストールします。

# cd /usr/ports/devel/git
# make config-recursive
# make install clean

(3) arm ビルド用のソースツリーを取得する

arm ビルド用のソースツリーは、頻繁にリビジョン変更が必要になるため、管理の都合上、/usr/src とは別に用意したほうが安全です。そのため、/usr/src とは別の場所にもうひとつ CURRENT のソースツリーを取得します。
ここでは、/usr/src.arm とします。

# cd /usr
# svnlite checkout svn://svn.freebsd.org/base/head/ src.arm

この後、取得したソースツリーに何らかの変更をする場合は、一旦ソースツリーに移動し、

# cd /usr/src.arm

ソースツリーを最新にしたい場合は

# svnlite update

現在のリビジョン番号等を確認したい場合は

# svnlite info

取得済みのソースツリーを指定したリビジョンに戻したい場合は

# svnlite -r <リビジョン番号> update

です。

(4) RaspberryPi 向けのカスタムカーネルファイルを作成する

ここは特に重要で、INVARIANTS が有効になっているとカーネルがパニックするという障害報告があります。 そのため、現時点では必ずカーネルはデフォルトではなく、カスタムにする必要があります。ただ、試して見たところ、少なくとも 2013 年 8 月末時点ではデバッグオプションを有効にした状態でもあまり問題なく動作しましたので、現時点では、少しでも速度を出したい場合はデバッグオプションを無効にする、という考え方でいいようです。
注意しなければいけないのは、修正するカーネルコンフィギュレーションファイルは、/usr/src ではなく、/usr/src.arm にあるものになります。また、デフォルトファイル名は GENERIC ではなく、RPI-B です。

# cd /usr/src.arm/sys/arm/conf
# cp RPI-B MYKERNEL

修正する必要があるのは以下の場所で、行頭に#をいれてコメントにします。
ident MYKERNEL

#makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols



#options KDB
#options DDB #Enable the kernel debugger
#options INVARIANTS #Enable calls of extra sanity checking
#options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS

尚、この他、無線LANの設定等、使用したいデバイスを追加しておくと、非常に便利です。
if_runを使う場合は、こんな感じに設定しておくと良いでしょう。

# wlan support
device          ehci
device          uhci
device          ohci
device          run
device          runfw
device          firmware
device          wlan            # 802.11 support
options         IEEE80211_DEBUG
options         IEEE80211_AMPDU_AGE
options         IEEE80211_SUPPORT_MESH
device          wlan_amrr
device          wlan_wep
device          wlan_ccmp
device          wlan_tkip

その他、適宜使用したい環境に合わせてデバイスの設定などを修正します。

(5) crochet-freebsd を導入する

(a) crochet-freebsd のリポジトリを取得する

Tim Kientzle 氏が作成された、各種 arm 向けビルドを行う支援用スクリプト、crochet-freebsd が git-hub に公開されているので、それをローカルに取得します。
ここでは、一般ユーザのホームディレクトリに展開します。

% cd
% git clone git://github.com/kientzle/crochet-freebsd.git

このスクリプトはそれなりにアップデートされていますので、イメージを作る際には更新するようにしたほうがよいでしょう。
その場合は、

% cd /path/to/crochet-freebsd
% git pull

になります。

(b) config.sh をカスタマイズする

設定ファイルである config.shconfig.sh.sample をベースに編集します。

% cd crochet-freebsd
% cp config.sh.sample config.sh
% vi config.sh

最低限の設定は、ビルド対象となるボードの種類の指定で、 以下の行の先頭の#を外すだけで、基本的な RapsberryPi 向けの設定は終了します。

board_setup RaspberryPi

ここから下はやったほうが幸せかもしれない設定です。

次の行をの先頭の#を外すことで UFS パーティションサイズを メディアのサイズに合わせて自動調整することができます。ただし、メディアによってはうまくいかないこともあるようです。

option AutoSize

あらかじめ作成しておきたいユーザアカウントを指定することができます。パスワードは指定したユーザ名と同一になります。

option User username

RaspberryPi は結構遅いのですが、swapfile を有効にすると、多少幸せになれる気がします。オプションの後のファイルサイズは任意に指定できます。1gb 程度確保しておくと、セルフビルドもそれなりに通るようです。

option SwapFile "1gb"

デフォルトで用意されている RaspberryPi のカーネルコンフィグファイルでは現時点では動かないことが多いので、 先頭の#を削除して設定を有効にし、カスタマイズ後のカーネルコンフィグファイルを指定するのが吉です。

KERNCONF=MYKERNEL

また、以下の指定で、arm 専用のソースツリーの指定ができます。 イメージが動くかどうかは、ビルドしたリビジョンに非常に左右されるため、 頻繁にソースツリーの入れ替えを行う必要がありますので、システムのソースツリーとは分けたほうが良いでしょう。先頭の#を削除するとともに、/usr/srcを自分のソースツリーの場所に書き換えます。

FREEBSD_SRC=/usr/src.arm

make.confsrc.confはデフォルトでは make 用のコンフィグファイルとして設定されていないので、指定しておくことを激しく推奨します。なぜかというと、コンパイル時に MALLOC_PRODUCTION が指定されていないと、遅くなるとかそういう問題の他に、jemalloc のバグを踏んではめられる恐れがあるからです・・。

 SRCCONF="/etc/src.conf"
 __MAKE_CONF="/etc/make.conf"

(c) OVERLAY FILES について

~/crochet-freebsd/board/RaspberryPi/overlay/にデフォルトで設定したい設定ファイルなどを事前に作成して、置いておくと、インストール時に既存のファイルなどを上書きしてくれます。/etc/rc.confや/etc/wpa_supplicant.confなど、階層をあわせて入れておくだけで、イメージを作成するたびに設定ファイルを修正する必要がなくなるため、非常に便利な機能です。

(d) その他

crochet-freebsd には、その他にも、様々なオプションが用意されています。config.sh にコメントとして書かれている内容が、イメージをビルドする際の非常に重要なドキュメントになりますので、一度目を通されることをお勧めします。

(6) RapsberryPi の firmwere を取得する

RapsberryPi の 最新 firmwere がgit-hub に公開されているので、それをローカルに取得します。
ここでは、一般ユーザのホームディレクトリに展開します。

% cd
% git clone git://github.com/raspberrypi/firmware/

crochet-freebsd に同包されている firmwere は結構古いので、今回取得したものを crochet-freebsd にコピーします。

% cp ./firmware/boot/* ./crochet-freebsd/board/RaspberryPi/boot/

これで、基本的な事前準備は終了です。いよいよイメージのビルドに移ります。

3: crochet-freebsd を実行してイメージを作成する

crochet-freebsd は、基本的にイメージ作成に足りないものなどがあれば、./crochet.shが実行時にチェックをして、必要なもののダウンロードなどを促してくれるので、あとは、出力されるメッセージに従って作業を進めるだけです。

% su
# ./crochet.sh -c config.sh

問題なくイメージの作成が終了すると、デフォルトでは crochet-freebsd/work/FreeBSD-armv6-RPI-B.img というファイルが出来上がっているはずです。これを終了時に表示される dd コマンドで SD カードに書き込みます。

# dd if=/path/to/crochet-freebsd/work/FreeBSD-armv6-RPI-B.img of=/dev/da0 bs=1m

ファイル名やデバイスは環境に合わせて修正してください。
あとは、お祈りしながら、RaspberryPi に SD カードをいれ、ディスプレイやキーボードをつないでから、おもむろに電源ケーブルを挿します。
無事に起動したら、 root(パスワード無し)でログインすることができます。

FreeBSD で RaspberryPi (その1) FreeBSD RaspberryPi のイメージをダウンロードして使う

FreeBSD 10-CURRENT には2012年8月に RapsberryPi に対応するコードが追加されたことで、RapsberryPi も FreeBSD で動かせるようになりました。

現時点で、RaspberryPi を FreeBSD で利用する方法は2つあり、動作可能なイメージが既に公開されているので、それをダウンロードして 使用する方法と、自分でイメージを作成する方法があります。

お手軽さから言えば、イメージをダウンロードしたほうがはるかに楽ですが、 利用したい最新の修正を反映させたい場合は、イメージを作成することになります。

ここでは、公開されている、FreeBSD RaspberryPi のイメージをダウンロードして使う方法について書きます。

db.net downloads page に作成済みのイメージが複数公開されています。
ダウンロードして SD カードに焼くだけで、RaspberryPi があっという間に FreeBSD で動くようになります。
イメージ作成がうまくいかないときにも(実際うまくいかないことは多いです・・)、動く環境がひとつあるだけで、心の拠り所になるような気がしますので、自分でビルドしたい場合でも、一度試してみるのはいいかもしれません。

イメージに付いている番号は svn リビジョン番号ですので、番号が大きいほうが新しいです。

以下の手順は、このサイトから、 bsd-pi-252209M.img.xz を FreeBSD 上でダウンロードして SD カードに焼く場合の例です。 ファイル名や デバイス(/dev/da0) は環境に合わせて書き換えてください。

イメージファイルをダウンロードします。

% fetch http://www.db.net/downloads/bsd-pi-252209M.img.xz

ダウンロードしたファイルを解凍します。

% unxz bsd-pi-252209M.img.xz

解答したファイルを SD カードに焼きます。

# dd if=./bsd-pi-252209M.img of=/dev/da0 bs=1m

あとは、RaspberryPi に電源を入れてを立ち上げるだけです。 root(パスワードなし)でログインすることができます。 素晴らしいですね。

ビルド方法については長くなるので(その2)に続きます・・。

2013年7月24日水曜日

Mac OS X Mountain Lion で OpenSSH をビルド・インストールする ( 作業メモ )

先日 Mac OS X Mountain Lion から RaspberryPi(FreeBSD) に ssh 接続しようとすると、RaspberryPi 側から接続がはねられる(Connection colosed by host)という現象に悩まされました。

鍵交換アルゴリズムが hmac-sha1 だとダメで、hmac-md5-xx だと OK のようだ、という情報を得たので、

% ssh -m hmac-md5 host-ip-address
Connection closed by host-ip-address
% ssh -m hmac-md5-96 host-ip-address
Connection closed by host-ip-address

( 認証は公開鍵暗号方式で、ホストには公開鍵を登録済 )

とやっぱりダメです。 ターミナルで確認すると、デフォルトで Mountain Lion に入っている OpenSSH のバージョンがそもそも結構古いです。

% which ssh
/usr/bin/ssh
% ssh -V
OpenSSH_5.9p1, OpenSSL 0.9.8x 10 May 2012

ちなみにこの記事時点での最新は以下の通りで、FreeBSD 側はこれです。

raspberry-pi% ssh -V
OpenSSH_6.2p2, OpenSSL 1.0.1e-freebsd 11 Feb 2013

そこで、試しに Mac OS X の OpenSSH をソースコードからビルドインストールしてみることにしました。

尚、Mac OS X Mountain Lion でこの作業を行うには、Xcode 及び、Command Line Tools ( Xcode の Preferences からインストール) が必要となります。
現在は Command Line Tools はどうもターミナルから以下のコマンドを入力しないとインストールできないようです。

% xcode-select --install

1:OpenSSH のソースコードを取得する

まず、OpenSSH のミラーサイトからソースコードを取得します。
Portable OpenSSH のページの下の方にダウンロード用のミラーサイト一覧があるので適当なものを選択してダウンロードします。

今回は現時点の最新である openssh-6.2p2 をダウンロードしようとしたら、 最初に開いたミラーサイトにはなぜか存在しませんでした。こんなこともあるんですね。 次に開いたミラーサイトには存在したので、そちらからダウンロードしました。

ダウンロードした openssh-6.2p2.tar.gz をダブルクリックで解凍します。
本当はファイルの正真性を確認すべきなのでしょうが、ここでは省略します。
興味が有る方は入門OpenSSH 2.3.2. ダウンロードしたパッケージの正真性を確認する を参考にするとよいでしょう。

2:OpenSSL のソースコードを取得する

合わせて OpenSSL も更新するため、こちらも OpenSSL のソースコードダウンロードページから現時点での最新版 openssl-1.0.1e をダウンロードします。 最新版は[LATEST]と表示されています
ダウンロードした openssl-1.0.1e.tar.gz をダブルクリックで解凍します。

3:OpenSSL をコンパイル、インストールする

OpenSSH は ssl に依存していますので、 最初に OpenSSL を ビルド・インストールします。
ターミナルを立ち上げて、

% cd Downloads/openssl-1.0.1e

64bit 版 Mac の場合は、./Configure darwin64-x86_64-cc を使用して構成します。
32bit 版 Mac の場合は、通常通り ./config を使用します。
他の ssl とかぶらないインストール場所を --openssldir でオプション指定します。今回は /usr/local/openssl を指定しています。また、共有ライブラリオプション shared をつけています。

% ./Configure darwin64-x86_64-cc --openssldir=/usr/local/openssl shared
% make
% sudo make install

4:OpenSSH をコンパイル、インストールする

無事に終了したら、いよいよ本命の OpenSSH の ビルド・インストール です。

% cd ../openssh-6.2p2

今回は、/usr/local 以下にインストール、PAM サポート有効、MD5 形式パスワードサポート、 zlib のバージョンチェックなし、ssl は先ほどインストールした OpenSSL を使用、で build することにするため、 以下のオプションを付けて configure スクリプトを実行します。
インストール先はデフォルトで /usr/local になっているため、今回は特に指定しませんが、/usr/local 以外にインストールしたい場合は、別途 --prefix オプション等で指定します。
OpenSSL を今回のように新規でインストールしない場合でも、システム上に複数の ssl が存在していると Your OpenSSL headers do not match your library. のようなエラーを吐いて終了してしまうので、その場合は --with-ssl-dir で ssl のディレクトリを指定する必要があります。

% ./configure --with-pam --with-md5-passwords --without-zlib-version-check --with-ssl-dir=/usr/local/openssl
% make
% sudo make install
% rehash

5: 環境変数 PATH の修正をする

インストールが完了したら、今後 ssh クライアントを使用する際は、 /usr/local/bin のものを優先的に使用したいため、環境変数の設定をする必要があります。 要は PATH の先頭に、/usr/local/bin が入っていればいいわけなので、

% printenv

で表示される PATH の値を確認して、問題なければ修正をする必要はありません。 わたしの環境では以下の状態でした。

 
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

Mountain Lion 以前では環境変数の修正をする場合は ~/.MacOSX/environment.plist に設定すれば良かったらしいのですが、Mountain Lion からはこのファイルが使えなくなった(!)そうなので、
今回は代わりに、 /etc/paths を修正します。

尚、OpenSSL も今回インストールするバージョンに切り替えるのであれば ( いろんな意味でそのほうが良いでしょう )、 /usr/local/openssl/binも合わせて追加する必要があります。

現在の内容を確認すると

% more /etc/paths
/usr/bin
/bin
/usr/sbin
/sbin
/usr/local/bin

これを、

% sudo vi /etc/paths

で以下のように修正し、保存して終了します。

/usr/local/openssl/bin
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin

一旦再起動します。
再びコンソールから環境変数の確認をします。

% printenv
PATH=/usr/local/openssl/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

これで PATH が修正されました。

6:インストール後のバージョンを確認する

ここで、正しくインストールが実行されたか、ssh のバージョンを確認します。

% which ssh
/usr/local/bin/ssh
% ssh -V
OpenSSH_6.2p2, OpenSSL 1.0.1e 11 Feb 2013
% which openssl
/usr/local/openssl/bin/openssl
% openssl version
OpenSSL 1.0.1e 11 Feb 2013

上記のように表示されれば、無事 update に成功となります。

sshd を起動済みの場合は、システム環境設定のインターネットとワイヤレスの共有から、リモートログインのオンオフをすれば sshd が再起動します。

ちなみに、この update で、無事に Mac OS X Mountain Lion からも、 RaspberryPi(FreeBSD) に ssh 接続できるようになりました。