|
現: 2023-04-23 (日) 07:28:07 yuji  |
| + | * Raspberry Pi3でPXEネットワークブート [#h1cf15cf] |
| + | Raspberry Pi3Bでは,GPUのROMの [[1stステージ・ブートローダー>../../ブートシーケンス]] にPXEブートが実装されているようだ。((注意:このGPUのファームウェア(1stステージ・ブートローダー)には,ネットワークブートがうまくいかないことがあるバグがあります。)) ~ |
| + | それを利用してPXEブートが出来るようにしてみる。(この機能は,Pi3Bのみの機能) |
| | | |
| + | PXEブートを使ってシステムをブートするには,Pi3BのROM設定をPXEブート出来るようにしておく必要がある。 |
| + | |
| + | ブートシーケンスは,~ |
| + | + 内蔵LANチップを初期化。(System RESET) |
| + | + RPi3BからDHCP要求が行われる。(DHCP) |
| + | + DHCPサーバからRPi3BへIPアドレス情報をおくる。(DHCP) |
| + | + PXEサーバのアドレス要求が行われる。(ARP) |
| + | + PXEサーバからアドレス情報をおくる。(ARP) |
| + | + RPi3BはPXEサーバに対してPXE要求を送信し,NBP(Network Bootstrap Program)と呼ばれるOSイメージを取得して起動するためのプログラムのファイル名を取得する。(TFTP) |
| + | + RPi3Bは,TFTPプロトコルを使用してNBPをダウンロードして,実行する。(TFTP)~ |
| + | Raspbianの/boot(kernel)にあるブートプログラムをロードする。それを実行して,Raspbianを起動する。 |
| + | |
| + | という手順になる。 |
| + | |
| + | * Raspberry Pi3Bでの準備 [#j5ff2c6b] |
| + | |
| + | Pi3Bのraspbianを最新にしておく |
| + | # apt-get update |
| + | # apt-get upgrade |
| + | # apt-get dist-upgrade |
| + | # rpi-update |
| + | |
| + | ** PXEブートできるように設定する [#j8350cc7] |
| + | PXEブートできるように,USBブートモードをイネーブルにします。おそらく,Raspberry Pi3のGPUのOTP-ROMの設定を書き換えているんだと思います。~ |
| + | PXEブート以外にも,USBに接続したMass Strageからブートすることも出来るようになる。 |
| + | |
| + | Raspberry Piでは,EthernetやUSBの機能もLANチップ経由で行っており,SoCとLANチップ間は内部にあるUSB接続されているので,NetworkブートもUSBブートモードの機能の内ということになります。 |
| + | |
| + | ブート選択するモードに2つの設定ができます。 |
| + | |
| + | *** program_usb_boot_mode=1 の方法 [#wee35023] |
| + | /boot/config.txtの最後に,program_usb_boot_mode=1を追加する。 |
| + | # echo program_usb_boot_mode=1 | tee -a /boot/config.txt |
| + | |
| + | リブートして,USBブートモードに設定されたかどうかを確認する。 |
| + | # vcgencmd otp_dump | grep 17: |
| + | 17:3020000a |
| + | 0x3020000a が出力されれば正常。 |
| + | program_usb_boot_mode=1 する前は,17:1020000a になっている。 |
| + | |
| + | /boot/config.txtを, |
| + | program_usb_boot_mode=1 |
| + | を削除して,元の状態に戻しておきます。 |
| + | |
| + | なお,''program_usb_boot_mode=1でUSBブートモードをイネーブルにした場合は,元に戻す事は出来なくなる。(OTP領域を書き換えるため)'' |
| + | |
| + | *** program_gpio_boot_mode=1 の方法 [#l201e6e1] |
| + | ブートに関しては,''program_gpio_boot_mode=1 という設定も出来るようになった。この場合も,元に戻す事は出来なくなる。(OTP領域を書き換えるため)'' |
| + | |
| + | 注意することとして,program_gpio_boot_mode=1をイネーブルにした場合,5個のGPIOをどこからbootさせるかの選択に使うので,他の目的のためにこの5つのGPIOを使用することが出来なくなる。 |
| + | |
| + | bit20の設定により,ブートデバイスの選択にGPIO22-26を使用するか,GPIO39-43を使用するかを設定できるが,GPIO39-43を使用できるのはCompute Moduleしか使用できないのに注意。 |
| + | |
| + | また,古いPi3のfirmwareでは設定するところでバグが有り,firmwareが4.9.60以前の場合,program_gpio_boot_modeを使うとOTP-ROMにbit20=1がセットされてしまいます。~ |
| + | このバグがある古いfirmwareの場合,~ |
| + | # vcgencmd otp_dump | grep 17: |
| + | 17:1030000a |
| + | になる。表示から,bit20=1になっていて,GPIO39-43を使用するための設定になっている。~ |
| + | ただし,このバグが有る場合でも,結果的にはprogram_gpio_bootmodeにするためのbit19が0のままのため,GPIOでのブートの制御が実質使用できない状態で,program_usb_boot_modeは使用できるので,まったくブートしないというどうしょうもないことにはならない。 |
| + | |
| + | firmwareが4.9.60以降の場合では,program_gpio_bootmode=1とprogram_usb_boot_mode=1を同時に設定した場合, |
| + | 17:3028000a |
| + | にOTP領域が設定されます。~ |
| + | bit19=1になり,正しくprogram_gpio_bootmodeとprogram_usb_boot_modeが使用できる設定になったということになります。 |
| + | |
| + | program_gpio_bootmodeでのブートの流れ |
| + | + 設定されたブート場所にあるbootcode.binのチェックを行う。~ |
| + | + 問題なければ,128Kのローカルキャッシュにロードし,実行する。~ |
| + | + 以下の順番でブートを試みる。~ |
| + | program_gpio_bootmodeを使用して,GPIO22-26または39-43を読んで,これらの値により,ブート先を有効・無効を判断させることが出来る。~ |
| + | 0: 無効,1:有効~ |
| + | SD1,SD2,NAND,SPI,USBそれぞれのブートモードを個別に無効・有効に設定できる。~ |
| + | '1'の場合:つまり4.7KΩでプルアップされた場合,そのブートモードが有効になる。Pi3では,チップ内部でGPIO22-26は約50KΩでプルダウンされているため,''なにもpinに接続していないと'0'になり,どこからもブート出来なくなります。''~ |
| + | primary SD~ |
| + | secondary SD~ |
| + | NAND~ |
| + | SPI~ |
| + | USB(OTG pin==0)~ |
| + | hub~ |
| + | MSD~ |
| + | LAN951x~ |
| + | dhcp/tftp boot~ |
| + | |
| + | この''program_gpio_bootmodeは5つのGPIOを別の用途に使えなくなるので,このモードは使用しないほうが良いと思う。'' |
| + | |
| + | * PXEブート用のサーバ側の準備 [#xf0e1460] |
| + | |
| + | ** dhcpサーバ [#u0470633] |
| + | dhcpサーバをインストールする。 |
| + | yum install dhcp |
| + | |
| + | 設定のサンプルがあるので,それをコピーして編集する。 |
| + | # cp /usr/share/doc/dhcp-3.0.1/dhcpd.conf.sample /etc/dhcpd.conf |
| + | |
| + | IP アドレスはネットワーク環境に合わせる。 |
| + | |
| + | filename~ |
| + | クライアントに読み込ませるブートローダーファイルを指定する。~ |
| + | 指定するパスは,tftpサーバのルートに対してのパスになるので注意。~ |
| + | |
| + | next-server~ |
| + | filenameで指定するファイルをホストするサーバのアドレスを指定する。~ |
| + | next-serverを指定しない場合,dhcpサーバのアドレスが使用される。(と思う)~ |
| + | dhcpサーバとtftpサーバを別にする場合などに使うのだと思う。~ |
| + | |
| + | /etc/dhcp/dhcpd.confの編集(RPi3Bに対して追加する)~ |
| + | #code(bash,,nonumber){{ |
| + | host rpi3 { |
| + | hardware ethernet B8:27:EB:XX:XX:XX; # Pi3のEthernetのMAC Address |
| + | fixed-address 192.168.1.xxx; # Pi3へ割り当てるIP Address |
| + | next-server 192.168.1.yyy; # nfs ServerのIP Address |
| + | option root-path "/var/exports/pi3-netboot"; # nfs Serverでのexports場所 |
| + | option vendor-class-identifier "PXEClient"; |
| + | option vendor-encapsulated-options "Raspberry Pi Boot "; |
| + | } |
| + | }} |
| + | このように編集します。 |
| + | |
| + | dhcpサーバを起動しなおす。 |
| + | # systemctl restart dhcpd |
| + | |
| + | ** tftpサーバ [#b670cc5e] |
| + | 起動ディスクイメージやブートローダを転送するため,tftpサーバをインストールする。 |
| + | # yum install tftp-server |
| + | |
| + | /etc/xinetd.d/tftpを編集する。~ |
| + | disable no |
| + | にするとTFTPサービスが有効になる。 |
| + | server_argsで指定しているディレクトリが TFTPサーバのルートになる。 |
| + | server_args = -s /var/lib/tftpboot |
| + | disable = no |
| + | xinetdを再起動し,tftpサーバを有効にする。 |
| + | # systemctl restart xinetd |
| + | |
| + | ** /var/lib/tftpboot にRaspberry Pi用ブートファイルを用意 [#i9ed025b] |
| + | SDカードの/boot(最初のパーテーション)にあるすべてのファイルを,/var/lib/tftpbootにコピーする。~ |
| + | ''/var/lib/tftpboot/pxeboot''~ |
| + | /start.elf |
| + | : |
| + | (bootcode.bin以外の/boot以下のファイル全部) |
| + | : |
| + | /bootcode.bin |
| + | |
| + | このようにファイルを用意する。 |
| + | |
| + | # mkdir /var/lib/tftpboot/pxeboot |
| + | # scp -r yuji@192.168.1.xxx:/boot/* /var/lib/tftpboot/pxeboot/ |
| + | これでRPi3Bの/bootがコピーできた。 |
| + | |
| + | 起動した後のルートファイル(NFSでマウントして使用)を指示するのはcmdline.txtを使用する。~ |
| + | ''/var/lib/tftpboot/pxeboot/cmdline.txt''を編集する。~ |
| + | root=/dev/nfs nfsroot=192.168.1.xxx:/var/exports/pi3-netboot,vers=3 rw ip=dhcp rootwait elevator=deadline |
| + | |
| + | ** ルートファイル・システムの用意(NFS) [#rd69dde7] |
| + | ルートファイルシステムはNFSサーバを用いて用意し,Rpi3Bではネットワーク越しにマウントして使用する。 |
| + | |
| + | NFSサーバ側で,/etc/exportsでNFSエクスポートの設定をする。~ |
| + | /etc/exports~ |
| + | /var/exports/pi3-netboot *(rw,no_root_squash,no_subtree_check) |
| + | |
| + | /var/exports/pi3-netbootには,Raspbianで言うところのmmcblk0p2の中身を置く。~ |
| + | mmcblk0p2は,raspbianのルートファイルシステムが入っている。どうにかして,Pi3のmmcblk0p2を/var/exports/pi3-netbootにコピーする。 |
| + | |
| + | *** イメージファイルからコピーする方法 [#zfcad8a3] |
| + | 現在のPi3BのMicroSDカードを,ディスクイメージにバックアップする。 |
| + | backupxxxx.img |
| + | これをNFSサーバにコピーする。 |
| + | |
| + | NFSのexportするディレクトリを作成する。 |
| + | # mkdir /var/exports/pi3-netboot |
| + | |
| + | 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/pi3-netboot |
| + | |
| + | /mnt/raspberrypiをアンマウントする。 |
| + | # umount /mnt/raspberrypi |
| + | |
| + | /dev/loop0を削除する。 |
| + | # kpartx -d /dev/loop0 |
| + | # losetup -d /dev/loop0 |
| + | # losetup -a |
| + | |
| + | *** コピーしたRaspbianの中身を少し書き換える [#se230420] |
| + | MicroSDをマウントしているところを削除する。 |
| + | この設定をするため,/var/exports/pi3-netboot/etc/fstab を編集。 |
| + | ''/var/exports/pi3-netboot/etc/fstab'' |
| + | proc /proc proc defaults 0 0 |
| + | #/dev/mmcblk0p1 /boot vfat defaults 0 2 # コメント化して無効にする |
| + | #/dev/mmcblk0p2 / ext4 defaults,noatime 0 1 # コメント化して無効にする |
| + | |
| + | ** ネットワークブートを試す [#z90f23a5] |
| + | Pi3BからSDカードを抜いて,LANケーブルだけ挿した状態でON。 |