U-Bootでネットワークブート anchor.png

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を起動してみる。

Page Top

U-Bootの用意 anchor.png

ブート時に本来最後に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をロードするブートローダーとして起動するようになる。

この時のブートシーケンスは以下のようになると思われる。

  • ROMブートローダが起動し,L2 Cacheに2番目のブートローダーbootcode.binをロードする。
  • 2番目のブートローダbootcode.binが起動し,SDRAMを有効にし,start.elfをロードする。
  • start.elfが起動し,SD/MicroSDカードにあるDevice Tree xxxxx.dtbを読み込んでFlattened Device Tree(FDT)を作成する。
    • Displayに虹色画面(テスト画像)を表示する。
    • config.txtを読み込んでoverlay情報をFDTに適用する。
    • FDT情報をパラメータとしてu-bootをロードする。
      cmdline.txtもKernelパラメータとして渡されると思う。しかしu-bootがKernelを起動する時のパラメーターとしては使われない。
  • start.elfがkernel.imgの代わりにu-boot.binをロードする。
  • u-bootを起動し,ネットワーク上のKernelをRAMにロードする。
    boot.scr.uimgに記載されている処理を行っていく。
    • Ethernetの初期化を行う。
    • DHCPを使ってネットワークの初期化を行う。
    • Kernelをロードする。
    • FDTをロードする。
      ロードしたDevice Tree xxxxx.dtbとstart.elfでロードされたconfig.txtとともにFlattened Device Tree(FDT)を作成しているようだ。
      つまりSD/MicroSDカードのconfig.txtで設定を行っておく必要があるので注意する。Kernelパラメーターでも設定できると思うが・・・
    • Kernelパラメータを用意する。
  • u-bootがKernelを起動する。
    FDT情報とKernelパラメータを指定してKernelを起動する。
  • Kernelがルートファイルシステムをマウントする。
    initramfs等を使用せずnfsを使用して直接ルートファイルシステムをマウントしている。
  • /sbin/initを起動する。
Page Top

U-Bootスクリプトファイルを作成 anchor.png

U-Bootの処理を自動化するために,boot.txtを作成する。

Everything is expanded.Everything is shortened.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
setenv serverip 192.168.XXX.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 bcm2708.serial=0x12345678 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 console=ttyAMA0,115200 console=tty1 kgdboc=ttyAMA0,115200 root=/dev/nfs nfsroot=${serverip}:${rootpath},rsize=32768,wsize=32768,proto=tcp,vers=4.1 rw ip=dhcp rootfstype=nfs smsc95xx.turbo_mode=N 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}

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.txtfilemkimageコマンドを使って,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側の設定は完了。

Page Top

サーバー側の設定 anchor.png

tftpを使ってブートファイルをダウンロード出来るようにして,nfsを使ってルートファイルシステムをマウント出来るようにする。

Raspbianのブートファイルやルートファイルシステムを用意する必要があるが,これらはRaspbianのOSイメージファイルから抜き出している。

またサーバーマシンには,このWEBサービスも行っているCentOSのローカルサーバーマシンを使用している。

Page Top

dhcpdの設定 anchor.png

ローカルネットワークでのDHCPサーバーを使って,ネットワークブートするRaspberry PiへIP Addressをアサインし,tftpサーバーのIP Addressとルートファイルシステムがあるディレクトリを通知するようにした。

/etc/dhcp/dhcpd.confファイルの編集。

Everything is expanded.Everything is shortened.
 
 
 
 
 
 
 
 
 :
host rpi {
   hardware ethernet B8:27:EB:XX:XX:XX;             # RPiのEthernetのMAC Address
   fixed-address 192.168.xx.yyy;                    # RPiへ割り当てるIP Address
   next-server 192.168.xx.xxx                       # tftpサーバーのIP Address
   option root-path "/var/exports/raspbian";        # nfsサーバーのexportsディレクトリ
}
 :

このように編集した。

DHCPサーバーを再起動する。

# systemctl restart dhcpd
Page Top

tftpサーバーの用意 anchor.png

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
Page Top

tftpサーバーにファイルを用意する anchor.png

/var/exports/raspbian/bootに,Raspbianのkernelファイル(ブート)を用意する。

Page Top

ブートファイル類 anchor.png

上記で設定した/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

このようにファイルを用意した

Page Top

nfsサーバーの用意 anchor.png

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
Page Top

ルートファイルシステムをnfsでexportする場所に用意する anchor.png

上記で設定した/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
Page Top

コピーしたRaspbianの中身を少し書き換える anchor.png

Kernelが起動時にブートとルートファイルシステムを直接nfsマウントしているため,SD/MicroSDカードのパーテーションをマウントしているところをコメント化してマウントしないように設定する。
/var/exports/raspbian/etc/fstabファイルを編集する。

proc            /proc           proc    defaults          0       0
#/dev/mmcblk0p1  /boot           vfat    defaults          0       2
#/dev/mmcblk0p2  /               ext4    defaults,noatime  0       1
Page Top

Raspbianを起動 anchor.png

Raspberry Piを電源ONすると,U-Bootが起動してkernelがロードされた後,kernelを起動し,その後ルートファイルシステムがマウントされて,無事Raspbianのログインプロンプトが表示された。


新しくコメントをつける

題名
ゲスト名
投稿本文
より詳細なコメント入力フォームへ

Front page   Freeze Diff Backup Copy Rename Reload   New Page Page list Search Recent changes   Help   RSS of recent changes (RSS 1.0) RSS of recent changes (RSS 2.0) RSS of recent changes (RSS Atom)
Counter: 1077, today: 3, yesterday: 1
Last-modified: 2023-04-23 (Sun) 07:33:52 (JST) (696d) by yuji