[QEMU][boot] U-boot on arm QEMU

QEMU では kernel が直接起動するので bootloader は必要ないのですが、手元に Das U-boot が動作する環境がないので、とりあえず動かした例がないか探していたところ、結構古い記事が多くてトレースできなかったので、最新環境で手元でやり直してみました。

arm ではマシンに versatilepb を使うことが多いのですが、こちらの記事でも言及されている通り、U-boot では versatile が削除されてしまっています。今だと vexpress でやればいい気もするので、とりあえずメモということで qemu のビルドから始めてみます。

QEMU と U-boot のビルドと起動

QEMU の repository から clone してビルド。もちろん package でインストールでもよいです。

$ git clone git://git.qemu.org/qemu.git
$ cd qemu
$ ./configure --target-list=arm-softmmu,aarch64-softmmu
$ make
$ sudo make install

U-boot も同様に最新版をビルド。マシンは vexpress_ca9x4 を指定します。

$ git clone git://git.denx.de/u-boot.git
$ cd u-boot
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- vexpress_ca9x4_defconfig
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

そして QEMU を起動…あれ何やらエラーが。バイナリが正しく読めない?

$ qemu-system-arm -M vexpress-a9 -nographic -kernel u-boot/u-boot.bin

qemu-system-arm: Trying to execute code outside RAM or ROM at 0x04000000
This usually means one of the following happened:

(1) You told QEMU to execute a kernel for the wrong machine type, and it crashed on startup (eg trying to run a raspberry pi kernel on a versatilepb QEMU machine)
(2) You didn't give QEMU a kernel or BIOS filename at all, and QEMU executed a ROM full of no-op instructions until it fell off the end
(3) Your guest kernel has a bug and crashed by jumping off into nowhere

This is almost always one of the first two, so check your command line and that you are using the right type of kernel for this machine.
If you think option (3) is likely then you can try debugging your guest with the -d debug options; in particular -d guest_errors will cause the log to include a dump of the guest register state at this point.

Execution cannot continue; stopping here.

ELF バイナリを指定したら動きました。何故だろう…

$ qemu-system-arm -M vexpress-a9 -nographic -kernel u-boot/u-boot

U-Boot 2017.07-00001-g13e3ef2 (Aug 13 2017 - 00:26:23 +0900)

DRAM:  128 MiB
WARNING: Caches not enabled
Flash: 128 MiB
MMC:   MMC: 0
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   smc911x-0
Hit any key to stop autoboot:  0
=>

Network を使う

このままの U-boot だと何もできないので network を設定します。QEMU の vexpress モデルは SMC911X NIC をモデル化しているので U-boot でも使えます。当然ですが I/O を経由しない virtio-net は使えません。

QEMU のネットワークは仮想 I/F である tap と bridge を通して host PC の物理 I/F (eth0) に通します。例として以下のように設定します。

$ sudo tunctl -g `id -u`          # tap 作成
Set 'tap0' persistent and owned by gid 1000
$ sudo brctl addbr br12345        # bridge 作成
$ sudo brctl addif br12345 eth0   # host I/F を bridge に参加
$ sudo brctl addif br12345 tap0   # tap を bridge に参加
$ sudo ifconfig tap0 up
$ sudo ifconfig br12345 up

tap0 と eth0 が bridge で接続されたので、それを使用して U-boot を起動します。

$ qemu-system-arm -M vexpress-a9 -nographic -kernel u-boot/u-boot -net nic -net tap,ifname=tap0

自分の環境に合わせて hostPC と target(QEMU) の IP アドレスを設定します。

=> setenv ipaddr 192.168.1.200     # target(QEMU) の IP アドレス
=> setenv serverip 192.168.1.1     # tftp サーバの IP アドレス

ロードするバイナリを tftp サーバにコピーして、ロードするアドレスを指定してメモリに転送します。

=> tftp 0x62000000 image
smc911x: MAC 52:54:00:12:34:56
smc911x: detected LAN9118 controller
smc911x: phy initialized
smc911x: MAC 52:54:00:12:34:56
Using smc911x-0 device
TFTP from server 192.168.1.1; our IP address is 192.168.1.200
Filename 'image'.
Load address: 0x62000000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ##############
         2.7 MiB/s
done
Bytes transferred = 7833916 (77893c hex)

無事転送できました。試し終わったら、先のネットワーク設定の後片付けを忘れずに。

$ sudo ifconfig br12345 down
$ sudo ifconfig tap0 down
$ sudo brctl delif br12345 tap0
$ sudo brctl delif br12345 eth0
$ sudo brctl delbr br12345
$ sudo tunctl -d tap0 

arm64 の場合

では arm64 でも同じことができるかというと、QEMU には arm64 は virt モデルが主流のため vexpress モデルはありません。同様に U-boot は virt モデルには対応していません。つまり arm64 では U-boot が適合するモデルの組み合わせは今のところなさそうです。

後者の virt モデルをちょっと試しに(見よう見まねで) U-boot に追加してみたものの、flash のところでハマったのでやはり簡単ではなさそうです。また、この時も ELF でないと起動しなかったのが気になるところです。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です