PIの間でデバッグの度にファイルをコピーする必要がなくなり、アプリケーション開発の効率化に繋がる。カーネルを変更した場合には、ビルドしたカーネルをSDカードに書き込まなくてはならないので、相変わらず面倒なコピー作業が必要となる。SDカードを何度も抜き差ししていると、故障の原因にもなってしまう(1台それで逝ってしまった...)。PI対応版がリリースされていることを見つけた(元ページ)。何種類かの実装があるようだが、Mainlineのものを使ってみよう。PI用のバイナリは含まれていないので自分でビルドしなくてはならない。クロス開発環境を構築するで述べたクロス開発環境を整備したマシン上で作業する。U-Bootのソースコードを持ってきて、クロスコンパイルして実機用のバイナリを作成する。u-boot.binU-bootディレクトリに作成された`u-boot.bin'が、ブートローダの実行ファイルとなる。SDカードに置くファイルSDカードのvfatでフォーマットされた第1パーティションに、予めLaspbianの/bootディレクトリにあるファイルを全てコピーしておく。LaspbianのSDカードをそのまま使用しても構わない。以下のファイルをコピー、ないしは作成、編集する。u-boot.binダウンロードしたソースからビルドした、u-boot.binをそのままコピーする。config.txtオリジナルのブートローダ設定ファイルであるが、最後に以下の行を追加して、(Linuxカーネルではなくて)u-boot.binを最後に実行することを指定する。kernel=u-boot.binuEnv.txtu-boot用の変数を定義するためのテキストファイルである。u-bootが起動した時に、自動的に読み込まれる。ここでは、以下の変数を定義することにする。serverNFSサーバのIPアドレスを指定する。rootpathNFSサーバにおけるルートファイルシステムのパス名を指定する。kernelfileロードして実行するNFSサーバ上のカーネル・イメージ・ファイル名を、rootpathで指定したディレクトリからのパスで指定する。fbwidthコンソール(HDML接続のディスプレィ)の横解像度を指定する。fbheightコンソール(HDML接続のディスプレィ)の縦解像度を指定する。まとめると次のようになる。serverip=192.168.3.51rootpath=/export/raspbian/20140909kernelfile=/boot/kernel.imgfbwidth=1824fbheight=984コンソールの解像度は、SoCのFirmwareによって検出と決定が行われる。Laspbianの通常のブートローダでは、それらの値をカーネルパラメータとしてLinuxに引き渡しており、その値を使って画面解像度が初期化される。現在のU-Bootでは、Firmwareが決定した値を使用することができないので、環境に応じてユーザが指定することにした。fbwidthとfbheightに指定する値を決定するためには、使用するHDMI接続のディスプレイを接続した状態でRaspbianを起動して、カーネル起動時に指定されたパラメータを参照する。rootwaitここで、bcm2708_fb.fbwidthに指定されている値をfbwidthに、bcm2708_fbheightに指定されている値をfbwidthにそれぞれ指定する。boot.scrU-Bootが起動した時に自動実行するコマンド・スクリプトのソースファイルである。全体を示してから、個々に説明する。13bootz1行目U-Bootの組み込み変数autloadをセットして、ブートデバイスを初期化(指定)した時に、ブートファイル(やカーネル)を自動的に読み込まないことを指定する。これを指定しておかないと、dhcpコマンドを実行した時に、tftpでファイルを探しに行ってしまう。組み込み変数bootfileに、ロードするファイルの名前をセットする。uEnv.txtで指定した変数を使用して、ファイルサーバのIPアドレスとファイル名(フルパス)を組み合わせている。3行目Linuxカーネルに渡すパラメータの前半部分、すなわち、Raspbianのオリジナル・ブートシステムでは、自動的に渡されるパラメータ群を定義する。SDカードからブートしたRaspbianの/proc/cmdlineを参照して、必要な箇所を変数などで置き換えればよい。usbethaddr変数だけは、U-BootがFirmwareが決定した値にセットしているので、そのまま引きわたす。SoCのシリアル番号(bcm2708.serialパラメータで指定する)も引き渡してくれれば、SDカードからブートしたものと同じ状態にできるのだが。bcm2708.serialパラメータを渡さなくても、/proc/cpuinfoで参照できるシリアル番号が0になるだけで実害はなさそうだ。4行目Linuxカーネルに渡すパラメータの後半部分、すなわち、Raspbianのオリジナル・ブートシステムでは、cmdline.txtファイルに書かれているパラメータ群を定義する。ここで、NFSルートを使用するためのパラメータを指定している。スクリプトはU-Bootに組み込まれたhushで実行されるので、簡単な変数置換や条件分岐を書くことができる。一種のマクロを定義する。定義したマクロを実行する。PIの内臓Ethernetポートが使用可能となる。その後、そのEhtenetポートから、DHCPでネットワーク設定を行う。定義したマクロを実行する。引数なしでnfsコマンドを実行すると、変数bootfileで指定したファイルを、NFSでメモリ上にロードする。無くてもよいが、USBデバイスのサービスを停止する。Linxuカーネルが初期化するので、止めておいたほうがいいだろう程度のもの。13行目メモリにロードしたLinuxカーネル・イメージ(圧縮)を実行する。カーネルパラメータとして、変数bootargsが引き渡される。PI版ではsetenvコマンドが使用できず、setコマンドしか認識されない。これに気づかなくて、かなりハマってしまった。boot.scr.uimg作成したboot.scrファイルを、U-Bootが理解出来るフォーマットに変換する。mkimageコマンドは、UbuntuでもRaspbianでも、u-boot-toolsパッケージとして提供されているので、あらかじめインストールしておく。boot.scr.img生成されたboot.src.imgファイルを、SDカードにコピーするNFS上のファイルシステムの調整NFSサーバには、ブート・パーティション(vfat)に置かれている/boot以下のディレクトリも、エクスポートするディレクトリにコピーしておくとよいだろう。SDカードと同じディレクトリ構成としておけば、カーネルがアップデートされた場合などにも、カーネル・イメージをコピーするといった作業が必要なくなる。次のように/etc/fstabの調整を調整しておく。ルートファイルシステムのエントリは必要無いので削除するSDカードの第1パーティション(vfat)をどこかにマウントしておくと、boot.scrの書き換えなどが便利。/sdcardなどにマウントする実行例ネットワークブートした際に、コンソール(シリアルポート)に表示される起動メッセージを示しておく。うまくブートしないときは、U-Bootのプロンプトに入って、定義されている変数を確認する。スクリプトで実行するはずのコマンドを1つずつ入力して実行してみて、スクリプトの誤りを見つけよう。Ethernetインターフェイスが100Mbpsなので、それほど早いとは感じないかもしれないが、大量の書き込みを行った場合には差が歴然になるだろう。何よりも、SDの寿命や容量を気にせずに使えるし、カーネルの書き換えもホスト機上で簡単に行えるのが一番のメリットである。カーネル・イメージのフォーマットについてブートするカーネル・イメージ・ファイルのフォーマットが、2014年10月頃のアップデートで変更になっている。圧縮されたカーネルイメージ(zImage)に、imagetool-uncompressed.pyというツールを使って32KBのヘッダを付加したもの。(/boot/kernel.img)は、raspberrypi-bootfilesというパッケージに、ブートローダ/ファームウェアと共に含まれている。そのパッケージの2014年10月頃のアップデートで、kernel.imgは単純な圧縮されたカーネル・イメージ(zImage)になった。ここまでの説明は、新しいzImageフォーマットのカーネルについて説明している。Linuxは「今のところ」古いフォーマットのままである)を使用する場合は、以下の変更が必要となる。kernel.imgをU-Bootが扱えるフォーマットに変換する。mkimageコマンドでkernel.imgを処理して、U-Boot用のヘッダがついたファイルとする。U-Boot用のカーネル・イメージを、uEnv.txtで指定する。(メモリ上のカーネルを実行する)に変更する。検証が不十分なので、例は示さない。