Raspberry Piでネットワークブートする場合に全モデルで共通に使用できる方法としては,汎用ブートローダである U-Boot を使う方法がある。
実際にRaspberry Piで利用できるRaspbian以外のいくつかのOSでU-Bootが使われています。これには理由があり,RaspbianのブートローダーはRaspberry Pi Foundation(ラズベリーパイ財団)により開発された非公開プログラムなので,他のOSのブートに利用しにくいため。
ネットワークブートする方法としては,通常のブートシーケンスでSD/MicroSDカードのFAT/FAT32パーテーションにあるLinux kernelをロード・実行する代わりにU-Bootをロード・起動して,ネットワーク越しにブートファイル(Linux kernel)をロードして起動するようにする。
Raspberry PiにはRAMがあまり実装されていないので,直接ネットワーク越しにルートファイルシステムをマウントする必要がある。このためにnfsサーバーを利用する。
ローカルネットワークのサーバーにRaspberry Piがロードするファイル(Kernelやルートファイルシステム)を置いて,それを使って初代Raspberry Pi BでRaspbian Baster Liteを起動してみる。
ブート時に本来最後にKernelをロードする代わりにU-Bootをロードして実行し,そこからネットワーク上にあるKernelをロードするようにするために,Raspbianが入ったSD/MicroSDカードの第1パーテーション(FAT/FAT32パーテーション)に,こちらでビルドしたu-boot.bin をコピーする。
SD/MicroSDカードの/boot/config.txtを編集して,u-boot.binを使うように変更する。
これには,/boot/config.txtの最後のあたりに,
kernel=u-boot.bin
と追加する。
これでRaspberry Piをブートすると,start.elfによるkernel.img(Raspberry Pi Bの場合)をロードする代わりに,u-boot.binがロードされネットワーク上のKernelをロードするブートローダーとして起動するようになる。
この時のブートシーケンスは以下のようになると思われる。
U-Bootの処理を自動化するために,boot.txtを作成する。
|
usb startはEthernetの初期化を行う。Raspberry PiのEthernetコントローラが内部USBで接続されているため。
dhcpコマンドで,ネットワークの設定を行いkernel.img(Kernel)をRAMにロードする。
tftpコマンドで,tftpサーバーからdevice treeファイルをRAMにロードする。
Kernelに渡すoptionで,ルートファイルシステムの場所とnfsを使って直接マウントするように指定している。
kernel.imgとdevice treeもnfsを使ってロードすることも出来るが,今回はtftpを使っている。
serverip(tftpサーバーのIP Address)やrootpath(ルートファイルシステムがあるディレクトリ)は,dhcpサーバーからoptionで渡すようにした方が良いかも。
最後にbootzコマンドでKernelを起動している。
作成したboot.txtをmkimageコマンドを使って,U-Bootが認識できるファイルに変換する。
$ mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n "Network Boot" -d boot.txt boot.scr.uimg
作成されたboot.scr.uimgをSD/MicroSDカードの第1パーテーション(/boot)にコピーする。
これで,Raspberry Pi側の設定は完了。
tftpを使ってブートファイルをダウンロード出来るようにして,nfsを使ってルートファイルシステムをマウント出来るようにする。
Raspbianのブートファイルやルートファイルシステムを用意する必要があるが,これらはRaspbianのOSイメージファイルから抜き出している。
またサーバーマシンには,このWEBサービスも行っているCentOSのローカルサーバーマシンを使用している。
ローカルネットワークでのDHCPサーバーを使って,ネットワークブートするRaspberry PiへIP Addressをアサインし,tftpサーバーのIP Addressとルートファイルシステムがあるディレクトリを通知するようにした。
/etc/dhcp/dhcpd.confファイルの編集。
|
このように編集した。
DHCPサーバーを再起動する。
# systemctl restart dhcpd
tftpサーバーをパッケージ管理ツールでインストールする。
# yum install tftp-server
/etc/xinetd.d/tftpを編集する。
server_args = -s /var/exports/raspbian/boot disable no
tftpサーバーはxinet経由でサービスされる。
server_argsでtftpサーバーのファイル場所のルートを設定している。
これは,nfsでマウントするルートファイルシステムの/bootと同じディレクトリになるように設定している。Raspbianのaptによるブートファイルの更新と同期するようにするため。
xinetdを再起動しtftpサーバを起動する。
# systemctl restart xinetd # systemctl enable xinetd
/var/exports/raspbian/bootに,Raspbianのkernelファイル(ブート)を用意する。
上記で設定した/var/exports/raspbian/bootに,ブートファイル(第1パーテーションのファイル)のすべてをコピーする。
とりあえず以下のようにした。
# mkdir -p /var/exports/raspbian/boot
公式のraspbianのimgファイルをmountしてコピーしてみた。
まずraspbianのimgファイルを確認する。
# fdisk -l -u 2020-02-13-raspbian-buster-lite.img Disk 2020-02-13-raspbian-buster-lite.img: 1849 MB, 1849688064 bytes, 3612672 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト Disk label type: dos ディスク識別子: 0x738a4d67 デバイス ブート 始点 終点 ブロック Id システム 2020-02-13-raspbian-buster-lite.img1 8192 532479 262144 c W95 FAT32 (LBA) 2020-02-13-raspbian-buster-lite.img2 532480 3612671 1540096 83 Linux
2つのパーテーションがあり,始点がオフセットになっている。(8192 * 512 = 4194304)
なので,そのオフセット分を追加すれば,mountコマンドでマウントできる。
# mount -t vfat -o loop,offset=4194304 2020-02-13-raspbian-buster-lite.img /mnt/rpi # cp -rp /mnt/rpi/* /var/exports/raspbian/boot # umount /mnt/rpi
このようにファイルを用意した
nfsサーバーは,既にインストールされていた。
インストールされていなければ,
yum install nfs-utils
として,パッケージ管理ツールでインストールできる。
nfsの共有ディレクトリを作成する。
# chown -R nfsnobody:nfsnobody /var/exports
nfs設定ファイル/etc/exportsを編集する。
/var/exports/raspbian 192.168.XXX.0/255.255.255.0(rw,no_root_squash,sync,no_subtree_check)
ローカルネットワークに限定している。
nfsを再起動する。
# systemctl restart nfs # systemctl enable nfs
上記で設定した/var/exports/raspbianに,ルートファイルシステム(第2パーテーションのファイル)の全てをコピーする。
今回はブートファイルと同様に,公式のraspbianのimgファイルをmountしてコピーしてみた。
オフセット値は,532480 * 512 = 272629760。
# mount -t ext4 -o loop,offset=272629760 2020-02-13-raspbian-buster-lite.img /mnt/rpi # cp -rp /mnt/rpi/* /var/exports/raspbian # umount /mnt/rpi
新しくコメントをつける