ネットワークのサーバーにRaspberry Piがロードするファイル(カーネルやルートファイル)を置いて,それを使ってRaspbianを起動させてみる。
Raspberry Piでこのようなネットワークブートさせるには,U-Bootを使う方法があります。
通常のブートプロセスの代わりに,SDカードのFAT/FAT32パーテーションにu-boot.binを置いて,ネットワーク越しにブートファイル(Linuxカーネル)をロードし,ルートファイルシステムをマウントすることによりRaspbianを起動させる。
Raspberry PiにはRAMがあまり実装されていないので,直接ネットワーク越しにファイルシステムをマウントする必要がある。このためにnfsサーバーを利用する。
U-Bootをデフォルトのブートローダーの代わりに使ってみます。
使用しているRaspbianが入ったMicroSDカードのFAT/FAT32パーテーション(/boot)に,ビルドしたu-boot.bin をコピーする。
/boot/config.txtで,u-boot.binを使うように変更します。/boot/config.txtの最後の変に,
kernel=u-boot.bin
を追加する。
これでリブートすると,デフォルトだとkernel.img(Raspberry PiBの場合)をロードされる代わりにU-Bootがブートローダーとして起動するようになる。
boot.txtを作成する。
setenv serverip 192.168.24.xxx setenv rootpath /var/exports/raspbian setenv kernelfile kernel.img setenv fdtfile bcm2708-rpi-b.dtb setenv fbwidth 1824 setenv fbheight 984 setenv bootarg_def "dma.dmachans=0x7f35 bcm2708_fb.fbwidth=${fbwidth} \ bcm2708_fb.fbheight=${fbheight} bcm2708.boardrev=0x10 smsc95xx.macaddr=${usbethaddr} \ bcm2708.disk_led_gpio=47 bcm2708.disk_led_active_low=0 sdhci-bcm2708.emmc_clock_freq=250000000 \ vc_mem.mem_base=0x1ec00000 vc_mem.mem_size=0x20000000" setenv bootarg_opt "dwc_otg.lpm_enable=0 ip=dhcp console=ttyAMA0,115200 console=tty1 \ kgdboc=ttyAMA0,115200 root=/dev/nfs nfsroot=${serverip}:${rootpath} \ elevator=deadline rootwait" setenv bootargs "${bootarg_def} ${bootarg_opt}" usb start dhcp ${kernel_addr_r} ${kernelfile} tftp ${fdt_addr_r} ${fdtfile} bootz ${kernel_addr_r} - ${fdt_addr_r}
tftpサーバーからkernel.imgとDevice treeをロードするようにして,カーネルにルートファイルシステムの場所をパラメータで渡して起動する。
usb startは,Raspberry PiはEthernetコントローラがUSBで接続されているため。
serverip(tftpサーバーのIPアドレス)やrootpath(ルートファイルシステムがあるディレクトリ)は,dhcpサーバーから渡すようにした方が良いかも。
作成した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カードの/bootにコピーする。
これで,Raspberry Pi側の設定はOK。
/etc/dhcpd.confファイルの編集。
: host rpi { hardware ethernet B8:27:EB:XX:XX:XX; # RPiのEthernetのMACアドレス fixed-address 192.168.24.xxx; # 割り当てるIPアドレス next-server 192.168.24.yyy # tftp serverのIPアドレス(dhcpdと違う場合はこここで設定する) option root-path "/var/lib/tftpboot"; # tftp serverのtopディレクトリ } :
このように編集する。
dhcpdを再起動する。
# /etc/init.d/dhcpd restart
tftpサーバーをパッケージでインストールする。
# yum install tftp-server
/etc/xinetd.d/tftpを編集する。
server_args = -s /var/lib/tftpboot disable no
のようにする。
server_argsで指定しているディレクトリがtftpサーバのルートディレクトリになる。
xinetdを再起動し,tftpサーバを有効にする。
# /etc/init.d/xinetd restart
nfsサーバーは,既にインストールされていた。インストールされていなければ,
yum install nfs-utils
として,パッケージでインストールできる。
nfsの共有ディレクトリを作成する。
# mkdir -p /var/export/raspbian # chown -R nfsnobody:nfsnobody /var/export
nfs設定ファイル/etc/exportsを編集する。
/var/exports/raspbian *(rw,no_root_squash,no_subtree_check)
nfsを再起動する。
/etc/init.d/nfs restart
/var/exports/raspbianには,Raspbianの/にあるファイルをすべてコピーする。(mmcblk0p2)
どうにかして,RPiのmmcblk0p2を/var/exports/raspbianにコピーする。
イメージファイルからコピーする場合は,以下のようにする。
現在のRPiのSDカードを,ディスクイメージにバックアップする。
backupxxxx.img
これをNFSサーバにコピーする。
NFSのexportするディレクトリを作成する。
# mkdir /var/exports/raspbian
loopデバイスで空いているループバックデバイスを探す。
# losetup -a # losetup -f /dev/loop0
/dev/loop0が空いているのがわかる。空きが無い場合は,modprobeコマンドで増やす。
# modprobe loop max_loop=32
/dev/loop0にイメージファイルを割り当てる。
# losetup /dev/loop0 /temp/backupxxxx.img
kpartx -aを使って,イメージファイルのパーティションを識別する。
# kpartx -a /dev/loop0
/dev/mapperに,loop0p1とloop0p2が出来ている。
/dev/loop0p2を,/mnt/raspberrypiにマウントする。
# mount /dev/loop0p2 /mnt/raspberrypi
/mnt/raspberrypiの中身をrsyncでコピーする。
# rsync -xa /mnt/raspberrypi /var/exports/raspbian
/mnt/raspberrypiをアンマウントする。
# umount /mnt/raspberrypi
次に,/dev/loop0p1を,/mnt/raspberrypiにマウントする。
# mount /dev/loop0p1 /mnt/raspberrypi
/mnt/raspberrypiの中身をrsyncでコピーする。
# rsync -xa /mnt/raspberrypi /var/exports/raspbian/boot
/mnt/raspberrypiをアンマウントする。
# umount /mnt/raspberrypi
/dev/loop0を削除する。
# kpartx -d /dev/loop0 # losetup -d /dev/loop0 # losetup -a
新しくコメントをつける