RISC-VボードVisionFive2でTFTPとNFSによってLinuxをネットワークブートする手順

ミラクシアエッジテクノロジーの吉田です。

最近StarFive社のRISC-VボードであるVisionFive2を立ち上げる機会がありました。
今までRaspberry PiシリーズでOSイメージをSDカードに書き込んで立ち上げ、アプリケーション開発などをした経験はありました。
しかし今回はLinux Kernelの開発やドライバの動作確認を行う目的があったため、Linux Kernelの更新を容易に実施できるようにしたいことや、リモート開発をしやすい環境にしたいという理由から、SDカードの差し替えが不要なLinuxのネットワークブートに挑戦してみました。

本記事では、以下の手順について説明します。

  • VisionFive2のセットアップ
  • VisionFive2 SDKによるLinux Kernelのビルド
  • TFTP/NFSによるLinuxのネットワークブート

この記事の対象読者

本記事は以下のような方を対象としています。

  • 組込みLinuxボードでKernelの開発やドライバ開発を行いたい方
  • VisionFive2でネットワークブート環境を構築したい方
  • SDカードの抜き差しなしで効率的にKernelを更新したい方
  • U-BootやTFTP/NFSの基本的な知識はあるが、VisionFive2での具体的な設定方法を知りたい方

目次

必要な機材

本記事では以下の機材を使用します。

  • VisionFive2本体(8GBモデルを使用)
  • USB Type-C 電源(VisionFive2への給電用)
  • LANケーブル(VisionFive2用)
  • USBシリアル変換ケーブル(VisionFive2のシリアルコンソール用)
  • Linux PC
  • 本記事ではUbuntu 22.04.5 LTSを使用
  • Linux KernelのビルドおよびTFTP/NFSサーバー用

ネットワーク構成

本記事では最終的に以下のネットワーク構成でVisionFive2をセットアップし、Linuxを起動します。IPアドレスやシリアルポートは環境に応じて適宜読み替えてください。

構成の説明:

  • Linux PC: TFTP/NFSサーバーとして動作し、VisionFive2にブートイメージとrootfsを提供します
  • VisionFive2: TFTPブートでLinuxを起動し、NFSマウントしたrootfsを使用します
  • 接続:
  • LANケーブル: TFTP/NFS通信用
  • USBシリアル変換ケーブル: コンソール出力確認用

VisionFive2のセットアップ

まず、VisionFive2とLinux PCを物理的に接続し、シリアルコンソールとネットワーク通信ができるようにします。

Linux PCとVisionFive2の接続

USBシリアル変換ケーブルの接続

VisionFive2 Documentation Centerのクイックスタートガイドに掲載されている図を参考に、USBシリアル変換ケーブルをVisionFive2に接続し、VisionFive2とLinux PCを接続します。

接続ができたら、VisionFive2の起動ログを確認するため、VisionFive2の電源を入れる前にLinux PCからscreenコマンドでシリアル接続しておきます。

$ screen /dev/ttyUSB0 115200  # ttyUSB0は環境に応じて変更してください

LANケーブルの接続

VisionFive2のEthernetポートは2つありますが、今回は固定IPを使用するため、VisionFive2の内側のポート(eth1)に接続します。

躓きポイント:

外側のポート(eth0)を使用すると、Linux起動後にDHCPクライアントが動作してしまうため、内側のポート(eth1)を使用してください。
詳細はeth0を使用した場合にDHCPクライアントが動作し固定IPが設定されなかったを参照してください。

VisionFive2を起動

VisionFive2の電源はUSB Type-Cポートから供給します。
VisionFive2にUSB Type-C電源を接続すると、シリアルコンソールに以下のような起動ログが表示され、U-Bootが起動します。

U-Boot SPL 2021.10 (Feb 28 2023 - 21:44:53 +0800)
DDR version: dc2e84f0.
Trying to boot from SPI

OpenSBI v1.2

(~中略~)

U-Boot 2021.10 (Feb 28 2023 - 21:44:53 +0800), Build: jenkins-VF2_515_Branch_SDK_Release-31

(~中略~)

StarFive #

U-BootとSPLの更新

VisionFive2購入時にインストールされているU-BootとSPLはバージョンが古い可能性があるため、最新バージョンに更新します。

U-Boot / SPL の最新版はVisionFive2のGitHubリリースページ(VisionFive2 Software v6.0.0)から入手可能です。

TFTPサーバーの準備

U-Boot / SPLの更新はTFTP経由で行います。Linux PCをTFTPサーバーとして準備するため、tftpd-hpaをインストールします。

$ sudo apt install tftpd-hpa

インストールが完了したら、tftpd-hpa.serviceが起動していることを確認します。

$ systemctl status tftpd-hpa.service
● tftpd-hpa.service - LSB: HPA's tftp server
     Loaded: loaded (etc/init.d/tftpd-hpa; generated)
     Active: active (running) since Mon 2026-02-02 14:38:29 JST; 7s ago
       Docs: man:systemd-sysv-generator(8)
    Process: 2111994 ExecStart=etc/init.d/tftpd-hpa start (code=exited, status=0/SUCCESS)
      Tasks: 1 (limit: 57334)
     Memory: 1.1M
        CPU: 12ms
     CGroup: /system.slice/tftpd-hpa.service
             mq2112002 /usr/sbin/in.tftpd --listen --user tftp --address :69 --secure /srv/tftp

 2月 02 14:38:29 Ubuntu systemd[1]: Starting LSB: HPA's tftp server...
 2月 02 14:38:29 Ubuntu tftpd-hpa[2111994]:  * Starting HPA's tftpd in.tftpd
 2月 02 14:38:29 Ubuntu tftpd-hpa[2111994]:    ...done.
 2月 02 14:38:29 Ubuntu systemd[1]: Started LSB: HPA's tftp server.

tftpd-hpaでは、etc/default/tftpd-hpaTFTP_DIRECTORYで指定されたディレクトリがTFTPサーバーの公開ディレクトリとなります。

$ cat etc/default/tftpd-hpa
# etc/default/tftpd-hpa

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="--secure"

デフォルトではTFTP_DIRECTORY="/srv/tftp"が指定されているため、U-Boot / SPL の最新版イメージを/srv/tftpに配置します。
今回はwgetコマンドで直接ダウンロードします。

$ sudo wget -P /srv/tftp/ https://github.com/starfive-tech/VisionFive2/releases/download/JH7110_VF2_6.12_v6.0.0/visionfive2_fw_payload.img
$ sudo wget -P /srv/tftp/ https://github.com/starfive-tech/VisionFive2/releases/download/JH7110_VF2_6.12_v6.0.0/u-boot-spl.bin.normal.out

/srv/tftp/の中身を確認し、以下のようにU-Boot / SPL の最新版イメージが配置されていれば準備完了です。

$ ls -l /srv/tftp/
total 3304
-rw-r--r-- 1 root root  157454 10月 16 20:02 u-boot-spl.bin.normal.out
-rw-r--r-- 1 root root 3221077 10月 16 20:02 visionfive2_fw_payload.img

U-BootからTFTPサーバーに接続できるようにする

VisionFive2をTFTPサーバーに接続するため、VisionFive2のU-Bootプロンプトで以下のコマンドを実行し、VisionFive2のIPアドレスを固定IPで設定します。

StarFive # setenv ipaddr 192.168.128.9

次にTFTPサーバー(Linux PC)のIPアドレス(192.168.128.10)を設定します。

StarFive # setenv serverip 192.168.128.10

設定できたらpingコマンドでTFTPサーバーとの接続を確認します。

StarFive # ping 192.168.128.10
Using ethernet@16040000 device
host 192.168.128.10 is alive

接続が確認できたら、saveenvコマンドで設定内容を保存しておきます。

StarFive # saveenv

更新を実施

TFTPサーバーの設定が完了したので、実際にU-BootとSPLの更新を行います。

SPL

sf probeコマンドでSPIフラッシュを初期化します。

StarFive # sf probe
SF: Detected gd25lq128 with page size 256 Bytes, erase size 4 KiB, total 16 MiB

次にtftpbootコマンドで、TFTPサーバーのu-boot-spl.bin.normal.outをメモリ上にロードします。

StarFive # tftpboot ${loadaddr}  u-boot-spl.bin.normal.out
Using ethernet@16040000 device
TFTP from server 192.168.128.10; our IP address is 192.168.128.9
Filename 'u-boot-spl.bin.normal.out'.
Load address: 0xa0000000
Loading: ###########
         375 KiB/s
done
Bytes transferred = 157454 (2670e hex)

以下のコマンドで、ロードしたSPLイメージをフラッシュに書き込めばSPLの更新は完了です。

StarFive # sf update ${loadaddr} 0x0 $filesize
device 0 offset 0x0, size 0x2670e
157454 bytes written, 0 bytes skipped in 0.965s, speed 166562 B/s

U-Boot

U-Bootも同様に、tftpbootコマンドで、TFTPサーバーからvisionfive2_fw_payload.imgをメモリ上にロードします。

StarFive # tftpboot ${loadaddr}  visionfive2_fw_payload.img
Using ethernet@16040000 device
TFTP from server 192.168.128.10; our IP address is 192.168.128.9
Filename 'visionfive2_fw_payload.img'.
Load address: 0xa0000000
Loading: #################################################################
         #################################################################
         #################################################################
         #########################
         376 KiB/s
done
Bytes transferred = 3221077 (312655 hex)

以下のコマンドで、ロードしたU-Bootイメージをフラッシュに書き込めばU-Bootの更新は完了です。

StarFive # sf update ${loadaddr} 0x100000 $filesize
device 0 offset 0x100000, size 0x312655
1291861 bytes written, 1929216 bytes skipped in 10.266s, speed 321166 B/s

最後にresetコマンドで再起動します。

StarFive # reset
resetting ...

U-Boot SPL 2021.10 (Oct 10 2025 - 11:25:33 +0800)
LPDDR4: 8G version: g8ad50857.
Trying to boot from SPI

OpenSBI v1.2

(~中略~)

U-Boot 2021.10 (Oct 10 2025 - 11:25:33 +0800), Build: jenkins-github_visionfive2_6.12-16

(~中略~)

StarFive #

更新前の起動ログと比較すると、以下のようにSPLとU-Bootのバージョンが変化していました。
これでU-BootとSPLの更新は完了です。

-U-Boot SPL 2021.10 (Feb 28 2023 - 21:44:53 +0800)
+U-Boot SPL 2021.10 (Oct 10 2025 - 11:25:33 +0800)

-U-Boot 2021.10 (Feb 28 2023 - 21:44:53 +0800), Build: jenkins-VF2_515_Branch_SDK_Release-31
+U-Boot 2021.10 (Oct 10 2025 - 11:25:33 +0800), Build: jenkins-github_visionfive2_6.12-16

Linuxの起動準備

U-Bootの更新が完了したので、次はU-Bootから起動するLinux Kernelとrootfsの準備を行います。
VisionFive2 SDKを使用してビルドし、TFTP/NFSサーバー経由でブートできるように設定していきます。

Linux Kernelのビルド

Linux KernelのビルドにはVisionFive2 SDKを使用します。まずVisionFive2 SDKをクローンします。

$ git clone https://github.com/starfive-tech/VisionFive2.git
$ cd VisionFive2

今回は最新に近いLinux Kernelのバージョン6.12系を使用するためJH7110_VisionFive2_6.12.y_develブランチに切り替えます。

$ git checkout --track origin/JH7110_VisionFive2_6.12.y_devel

サブモジュールを初期化し、Linux KernelのブランチもJH7110_VisionFive2_6.12.y_develに切り替えます。

$ git submodule update --init --recursive
$ cd linux && git branch JH7110_VisionFive2_6.12.y_devel origin/JH7110_VisionFive2_6.12.y_devel && cd ..

ビルドを実施します。

$ make -j$(nproc)

ビルドが完了したら、Linux Kernelイメージがwork/image.fitに生成されていることを確認します。

$ ls work/image.fit
work/image.fit

Linux KernelをTFTPサーバーへ配置

Linuxの起動もTFTP経由で行います。TFTPサーバーの設定は前述のU-BootとSPLの更新手順で既に実施済みのため、特に変更は不要です。
ビルドしたLinux KernelイメージをTFTPサーバーの公開ディレクトリに配置します。

$ sudo cp work/image.fit /srv/tftp/

/srv/tftp/の中身を確認し、以下のようにimage.fitが配置されていれば完了です。

$ ls -l /srv/tftp/
total 19192
-rw-r--r-- 1 root root 16262313  2月  2 17:30 image.fit
-rw-r--r-- 1 root root   157454 10月 16 20:02 u-boot-spl.bin.normal.out
-rw-r--r-- 1 root root  3221077 10月 16 20:02 visionfive2_fw_payload.img

Linux KernelのTFTPブート設定

VisionFive2のU-Bootプロンプトで以下のコマンドを実行し、TFTP経由でLinux Kernelを起動するためのコマンドを記載した環境変数bootcmd_tftpを作成します。

StarFive # setenv bootcmd_tftp 'tftpboot ${loadaddr} image.fit; run fdt_conf_set;bootm start ${loadaddr}#${fdt_conf};bootm loados ${loadaddr};run chipa_set_linux;run cpu_vol_set; booti ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdt_addr_r};'

次に、デフォルトの起動コマンドをTFTPブートに変更します。

StarFive # setenv bootcmd 'run bootcmd_tftp'

最後にsaveenvコマンドで設定内容を保存しておきます。

StarFive # saveenv

rootfsのビルド

rootfsもVisionFive2 SDKでビルドします。buildroot_rootfsターゲットでビルドを実施します。

$ make buildroot_rootfs -j$(nproc)

ビルドが完了したら、rootfsイメージがwork/buildroot_rootfs/images/rootfs.ext2に生成されていることを確認します。

$ ls work/buildroot_rootfs/images/rootfs.ext2
work/buildroot_rootfs/images/rootfs.ext2

NFSサーバーの準備

rootfsをNFS経由でマウントするため、nfs-kernel-serverをインストールします。

$ sudo apt install nfs-kernel-server

インストールが完了したら、nfs-server.serviceが起動していることを確認します。

$ systemctl status nfs-server.service
● nfs-server.service - NFS server and services
     Loaded: loaded (/lib/systemd/system/nfs-server.service; enabled; preset: enabled)
     Active: active (exited) since Tue 2026-02-03 14:04:49 JST; 3min 50s ago
   Main PID: 148246 (code=exited, status=0/SUCCESS)
        CPU: 4ms

 2月 03 14:04:49 Ubuntu systemd[1]: Starting nfs-server.service - NFS server and services...
 2月 03 14:04:49 Ubuntu exportfs[148245]: exportfs: can't open etc/exports for reading
 2月 03 14:04:49 Ubuntu systemd[1]: Finished nfs-server.service - NFS server and services.

上記のログで以下の警告が表示されています:

exportfs: can't open etc/exports for reading

これはまだNFSの公開ディレクトリを設定していないためで、次の手順で解決します。

etc/exportsファイルを編集し、NFSサーバーの公開ディレクトリとして/srv/nfs/vf2-rootfsを設定します。

$ sudo vi etc/exports

以下の行を追加します。

/srv/nfs/vf2-rootfs 192.168.128.0/24(rw,sync,no_subtree_check,no_root_squash,insecure)

NFSサーバーの公開ディレクトリとして/srv/nfs/vf2-rootfsを実際に作成します。

$ sudo mkdir -p /srv/nfs/vf2-rootfs

公開ディレクトリに、先ほどビルドしたrootfsイメージをマウントします。(rootfsイメージはwork/buildroot_rootfs/images/rootfs.ext2に生成されています。)

$ sudo mount -o loop work/buildroot_rootfs/images/rootfs.ext2 /srv/nfs/vf2-rootfs

NFSサーバーの設定を反映するため、nfs-kernel-serverを再起動します。

$ sudo systemctl restart nfs-kernel-server

再度nfs-server.serviceの状態を確認し、先ほどとは違いexportfsの警告が表示されなければNFSサーバーの準備完了です。

$ systemctl status nfs-server.service
● nfs-server.service - NFS server and services
     Loaded: loaded (/lib/systemd/system/nfs-server.service; enabled; preset: enabled)
     Active: active (exited) since Tue 2026-02-03 15:16:16 JST; 9s ago
    Process: 148748 ExecStartPre=/usr/sbin/exportfs -r (code=exited, status=0/SUCCESS)
    Process: 148749 ExecStart=/usr/sbin/rpc.nfsd (code=exited, status=0/SUCCESS)
   Main PID: 148749 (code=exited, status=0/SUCCESS)
        CPU: 5ms

 2月 03 15:16:16 Ubuntu systemd[1]: Starting nfs-server.service - NFS server and services...
 2月 03 15:16:16 Ubuntu systemd[1]: Finished nfs-server.service - NFS server and services.

rootfsのNFSマウント設定

VisionFive2のU-Bootプロンプトで以下のコマンドを実行し、rootfsをNFS経由でマウントするためのbootargsを設定します。

躓きポイント:

${serverip}${ipaddr}を展開して渡す必要があるため、二重引用符("")で囲んで展開されるようにします。
詳細はbootargsの設定で${serverip}と${ipaddr}を展開して渡す必要があったを参照してください。

StarFive # setenv bootargs "console=tty1 console=ttyS0,115200 debug rootwait earlycon=sbi root=/dev/nfs rw nfsroot=${serverip}:/srv/nfs/vf2-rootfs ip=${ipaddr}:${serverip}::255.255.255.0::eth1:off"

saveenvコマンドで設定内容を保存しておきます。

StarFive # saveenv

Linuxの起動確認

すべての設定が完了したので、いよいよVisionFive2を再起動してLinuxのネットワークブートが正常に動作するか確認します。
再起動すると、U-BootがTFTP経由でLinux Kernelをロードし、NFSマウントしたrootfsを使用してLinuxが起動します。以下のようなログが表示されれば起動成功です。

StarFive # reset
resetting ...

U-Boot SPL 2021.10 (Oct 10 2025 - 11:25:33 +0800)
LPDDR4: 8G version: g8ad50857.
Trying to boot from SPI

OpenSBI v1.2

(~中略~)

Hit any key to stop autoboot:  0
ethernet@16040000 Waiting for PHY auto negotiation to complete...... done
Using ethernet@16040000 device
TFTP from server 192.168.128.10; our IP address is 192.168.128.9
Filename 'image.fit'.
Load address: 0x60000000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #####
         181.6 KiB/s
done
Bytes transferred = 16286033 (f88151 hex)
## Loading kernel from FIT Image at 60000000 ...
   Using 'config-default' configuration
   Trying 'vmlinux' kernel subimage
     Description:  vmlinux
     Type:         Kernel Image
     Compression:  gzip compressed
     Data Start:   0x600000c8
     Data Size:    9886593 Bytes = 9.4 MiB
     Architecture: RISC-V
     OS:           Linux
     Load Address: 0x40200000
     Entry Point:  0x40200000
## Loading fdt from FIT Image at 60000000 ...
   Using 'config-default' configuration
   Trying 'fdt' fdt subimage
     Description:  unavailable
     Type:         Flat Device Tree
     Compression:  uncompressed
     Data Start:   0x60f4e530
     Data Size:    58144 Bytes = 56.8 KiB
     Architecture: RISC-V
     Load Address: 0x46000000
   Loading fdt from 0x60f4e530 to 0x46000000
   Booting using the fdt blob at 0x46000000
## Loading loadables from FIT Image at 60000000 ...
   Trying 'ramdisk' loadables subimage
     Description:  buildroot initramfs
     Type:         RAMDisk Image
     Compression:  uncompressed
     Data Start:   0x6096dd00
     Data Size:    6162356 Bytes = 5.9 MiB
     Architecture: RISC-V
     OS:           Linux
     Load Address: 0x46100000
     Entry Point:  unavailable
   Loading loadables from 0x6096dd00 to 0x46100000
   Uncompressing Kernel Image
## Flattened Device Tree blob at 46000000
   Booting using the fdt blob at 0x46000000
   Using Device Tree in place at 0000000046000000, end 000000004601131f

Starting kernel ...

(~中略~)

Welcome to Buildroot
buildroot login:

ログインプロンプトが表示されたら、ユーザー名root、パスワードstarfiveでログインできます。

buildroot login: root
Password:
#

/proc/cmdlineを確認し、NFSマウントの設定が反映されていることを確認します。

# cat /proc/cmdline
console=tty1 console=ttyS0,115200 debug rootwait earlycon=sbi root=/dev/nfs rw nfsroot=192.168.128.10:/srv/nfs/vf2-rootfs ip=192.168.128.9:192.168.128.10::255.255.255.0::eth1:off

U-Bootのbootargsで設定した内容が反映されており、VisionFive2上でLinuxが正常に動作していることが確認できました。
最後に、IPアドレスの設定を確認します。

# ifconfig
eth0      Link encap:Ethernet  HWaddr 6C:CF:39:00:B6:C8
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:3 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:15

eth1      Link encap:Ethernet  HWaddr 6C:CF:39:00:B6:C9
          inet addr:192.168.128.9  Bcast:192.168.128.255  Mask:255.255.255.0
          inet6 addr: fe80::6ecf:39ff:fe00:b6c9/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:17726 errors:0 dropped:35 overruns:0 frame:0
          TX packets:10535 errors:1 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:21036374 (20.0 MiB)  TX bytes:1197236 (1.1 MiB)
          Interrupt:18

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:322 errors:0 dropped:0 overruns:0 frame:0
          TX packets:322 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:23820 (23.2 KiB)  TX bytes:23820 (23.2 KiB)

設定通り、eth1インターフェースにIPアドレス192.168.128.9が割り当てられていることが確認できました。

躓きポイント

本環境構築を進める中で、特に注意が必要だったポイントを2つ紹介します。
同じ課題に直面した際の参考になれば幸いです。

eth0を使用した場合にDHCPクライアントが動作し固定IPが設定されなかった

実は最初に作業していた時は、外側のポートにLANケーブルを接続して以下のようにbootargsにeth0を設定していました。

StarFive # setenv bootargs "console=tty1 console=ttyS0,115200 debug rootwait earlycon=sbi root=/dev/nfs rw nfsroot=${serverip}:/srv/nfs/vf2-rootfs ip=${ipaddr}:${serverip}::255.255.255.0::eth0:off"

それでもLinuxは問題なく起動するのですが、ifconfigコマンドでIPアドレスを確認すると、固定IPとして設定したかった192.168.128.9ではなくDHCPで割り当てられたIPアドレス(192.168.128.8)が設定されていました。

# ifconfig
eth0      Link encap:Ethernet  HWaddr 6C:CF:39:00:B6:C8
          inet addr:192.168.128.8  Bcast:192.168.128.255  Mask:255.255.255.0
          inet6 addr: fe80::6ecf:39ff:fe00:b6c8/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:16109 errors:0 dropped:10 overruns:0 frame:0
          TX packets:8119 errors:1 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:20723465 (19.7 MiB)  TX bytes:869536 (849.1 KiB)
          Interrupt:15

Linuxの起動ログを確認するとudhcpcから以下のようなメッセージが出力され、DHCPクライアントが動作していることがわかりました。

udhcpc: started, v1.34.1
udhcpc: broadcasting discover
udhcpc: broadcasting select for 192.168.128.8, server 192.168.128.1
udhcpc: lease of 192.168.128.8 obtained from 192.168.128.1, lease time 86400

調査したところ、VisionFive2 SDKのBuildrootの初期設定でeth0がDHCPクライアントとして設定されていることがわかりました。

conf/buildroot_initramfs_config

BR2_SYSTEM_DHCP="eth0"

BR2_SYSTEM_DHCPを空にして動作確認します。

-BR2_SYSTEM_DHCP="eth0"
+BR2_SYSTEM_DHCP=""

変更前のコンフィグが残らないように、make distcleanしてから再ビルドします。

$ make distclean
$ make

ビルドが完了したら、再度Linux Kernelイメージ(work/image.fit)をTFTPサーバーの公開ディレクトリに配置して起動します。
起動ログを確認すると、udhcpcのメッセージが表示されなくなり、固定IP(192.168.128.9)が設定されていることが確認できました。

# ifconfig
eth0      Link encap:Ethernet  HWaddr 6C:CF:39:00:B6:C8
          inet addr:192.168.128.9  Bcast:192.168.128.255  Mask:255.255.255.0
          inet6 addr: fe80::6ecf:39ff:fe00:b6c8/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:16134 errors:0 dropped:9 overruns:0 frame:0
          TX packets:8086 errors:1 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:20725332 (19.7 MiB)  TX bytes:869446 (849.0 KiB)
          Interrupt:15

eth0で固定IPを使用する場合は、上記のようにBR2_SYSTEM_DHCPの設定を変更する必要があります。

bootargsの設定で${serverip}${ipaddr}を展開して渡す必要があった

最初にbootargsを設定した時は、以下のように単一引用符('')で囲んでいました。

StarFive # setenv bootargs 'console=tty1 console=ttyS0,115200 debug rootwait earlycon=sbi root=/dev/nfs rw nfsroot=${serverip}:/srv/nfs/vf2-rootfs ip=${ipaddr}:${serverip}::255.255.255.0::eth1:off'

その結果、Linuxの起動ログで以下のようなエラーが表示され、rootfsのマウントに失敗していました。

mount: bad address '${serverip}'
mount: mounting /proc on /rootfs/proc failed: No such file or directory
mount: mounting /sys on /rootfs/sys failed: No such file or directory
mount: mounting /run on /rootfs/run failed: No such file or directory
mount: mounting /tmp on /rootfs/tmp failed: No such file or directory
mount: mounting /dev on /rootfs/dev failed: No such file or directory
mount: mounting /dev/shm on /rootfs/dev/shm failed: No such file or directory
mount: mounting /dev/pts on /rootfs/dev/pts failed: No such file or directory
/init: line 71: can't open /rootfs/dev/console: no such file
[   20.985373] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100
[   20.993830] CPU: 0 UID: 0 PID: 1 Comm: init Tainted: G                T  6.12.5+ #1
[   21.001552] Tainted: [T]=RANDSTRUCT
[   21.005078] Hardware name: StarFive VisionFive 2 v1.3B (DT)
[   21.010689] Call Trace:
[   21.013178] [<ffffffff80006148>] dump_backtrace+0x1c/0x24
[   21.018642] [<ffffffff80b99258>] show_stack+0x2c/0x38
[   21.023756] [<ffffffff80bac6fa>] dump_stack_lvl+0x48/0x72
[   21.029212] [<ffffffff80bac738>] dump_stack+0x14/0x1c
[   21.034317] [<ffffffff80b995e6>] panic+0x100/0x2f8
[   21.039168] [<ffffffff80017b1e>] do_exit+0x7e2/0x7e8
[   21.044183] [<ffffffff80017c84>] do_group_exit+0x28/0x74
[   21.049543] [<ffffffff80017cec>] pid_child_should_wake+0x0/0x5c
[   21.055515] [<ffffffff80bad20e>] do_trap_ecall_u+0x154/0x1e2
[   21.061229] [<ffffffff80bb503a>] _new_vmalloc_restore_context_a0+0xc2/0xce
[   21.068161] SMP: stopping secondary CPUs
[   21.072160] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100 ]---

mount: bad address '${serverip}'というエラーから、${serverip}が展開されずに文字列のまま渡されていました。
bootargsの設定を単一引用符('')から二重引用符("")に変更して再度設定し、Linuxを起動したところ、${serverip}${ipaddr}が展開されて正常に起動できるようになりました。

まとめ

本記事では、RISC-VボードVisionFive2に対して以下を実施し、TFTPとNFSを使用したLinuxのネットワークブート環境を構築しました。

  • U-Boot/SPLをGitHubリリースの最新版に更新
  • VisionFive2 SDKを使用したLinux KernelおよびrootfsのビルドとTFTP/NFS配置
  • U-Bootの環境変数設定によるTFTPブートおよびNFSマウントの構成

また、作業を通じて躓いたポイントとして、eth0を使用するとBuildrootのデフォルト設定によりDHCPクライアントが動作して固定IPが設定されないこと、
およびbootargsでU-Bootの環境変数を展開するには二重引用符が必要なことを確認しました。

ネットワークブート環境が整うと、Kernelの更新のたびにSDカードの抜き差しが不要になります。
開発PCから直接ビルドしてTFTPサーバーに配置するだけで新しいKernelを起動できるため、Linux Kernelの開発やドライバの動作確認のイテレーションを大幅に短縮できます。

採用情報

ミラクシアでは一緒に組込みソフト開発をする仲間を募集しています。

参考文献