以下の内容はhttps://daisuke20240310.hatenablog.com/entry/buildroot2より取得しました。


QEMUで組み込みLinux(Buildroot+BusyBox)をやってみる、の補足

前回 は、QEMU で Arm の組み込み Linux(Buildroot+BusyBox)を動かしました。

今回は、前回の起動について、カーネルのパラメータなど、可能な限り、調査してみたいと思います。

それでは、やっていきます。

はじめに

「QEMUを動かす」の記事一覧です。良かったら参考にしてください。

QEMUを動かすの記事一覧
・第1回:STM32(ARM Cortex-M)をQEMUで動かす(環境構築編)
・第2回:STM32(ARM Cortex-M)をQEMUで動かす(ソースコード確認編)
・第3回:STM32(ARM Cortex-M)をQEMUで動かす(スタートアップルーチン編)
・第4回:STM32(ARM Cortex-M)をQEMUで動かす(リンカスクリプト編)
・第5回:STM32(ARM Cortex-M)のELFファイルの内容を確認する
・第6回:STM32(ARM Cortex-M)のELFファイル⇔バイナリの変換を行う
・第7回:STM32(ARM Cortex-M)のバイナリから構築したELFファイルをQEMUで動かす
・第8回:QEMUのビルドに必要なxpm(xPack Project Manager)について学ぶ
・第9回:QEMUをソースからビルドして動かす
・第10回:QEMUのソースコードを変更してSTM32の動作を変える
・第11回:QEMUに似たRenodeというOSSの組込みデバイスエミュレータを試す
・第12回:QEMUに似たRenodeでSTM32をGDBを使ってデバッグする
・第13回:QEMUに似たRenodeでSTM32をバイナリファイルで動かす
・第14回:QEMUに似たRenodeをソースからビルドする
・第15回:QEMUに似たRenodeでVSCodeを使ってデバッグする
・第16回:QEMUに似たRenodeでVSCodeを使ってRenode自体をデバッグする
・第17回:QEMUで組み込みLinux(Buildroot+BusyBox)をやってみる
・第18回:QEMUで組み込みLinux(Buildroot+BusyBox)をやってみる、の補足 ← 今回

それでは、やっていきます。

start-qemu.shの内容

Buildroot のビルドが完了したら、output/images/start-qemu.sh を実行するだけで Buildroot が起動しました。

start-qemu.sh の内容を確認してみます。まず、全文を貼り付けます。

#!/bin/sh

BINARIES_DIR="${0%/*}/"
# shellcheck disable=SC2164
cd "${BINARIES_DIR}"

mode_serial=false
mode_sys_qemu=false
while [ "$1" ]; do
    case "$1" in
    --serial-only|serial-only) mode_serial=true; shift;;
    --use-system-qemu) mode_sys_qemu=true; shift;;
    --) shift; break;;
    *) echo "unknown option: $1" >&2; exit 1;;
    esac
done

if ${mode_serial}; then
    EXTRA_ARGS='-nographic'
else
    EXTRA_ARGS='-serial stdio'
fi

if ! ${mode_sys_qemu}; then
    export PATH="/home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/host/bin:${PATH}"
fi

exec qemu-system-arm -M vexpress-a9 -smp 1 -m 256 -kernel zImage -dtb vexpress-v2p-ca9.dtb -drive file=rootfs.ext2,if=sd,format=raw -append "console=ttyAMA0,115200 rootwait root=/dev/mmcblk0"  -net nic,model=lan9118 -net user  ${EXTRA_ARGS} "$@"

少しずつ見ていきます。

最初から難しいですね。${0%/*}/ は、${var%word} で、後方一致除去(最短一致)という文法です。変数 ${var} の文字列を末尾から word を探索して、初めて見つけたら、word を含み、末尾まで削除します。

あと、${0} は、実行したコマンドそのものが入るので、今回は、output/images/start-qemu.sh が入ります。最初に / を見つけたら、以降を削除するので、output/images が、BINARIES_DIR にセットされることになります。

その後、start-qemu.sh のあるディレクトリに移動しています。

#!/bin/sh

BINARIES_DIR="${0%/*}/"
# shellcheck disable=SC2164
cd "${BINARIES_DIR}"

次は、まず、変数に値(false)を設定して、コマンドライン引数のパース処理をしています。

--serial-only が指定されると、mode_serial 変数に true が設定されます。

--use-system-qemu が指定されると、mode_sys_qemu に true が設定されます。

mode_serial=false
mode_sys_qemu=false
while [ "$1" ]; do
    case "$1" in
    --serial-only|serial-only) mode_serial=true; shift;;
    --use-system-qemu) mode_sys_qemu=true; shift;;
    --) shift; break;;
    *) echo "unknown option: $1" >&2; exit 1;;
    esac
done

先ほど設定した2つの変数によって分岐します。

--serial-only が指定されると、EXTRA_ARGS に '-nographic' が設定されて、指定されない場合は、'-serial stdio' が設定されます。

--use-system-qemu が指定されない場合は、output/host/bin がパスに設定されます。なるほど、前回、QEMU をインストールしましたが、Buildroot でビルドした QEMU が使われていたようです。

if ${mode_serial}; then
    EXTRA_ARGS='-nographic'
else
    EXTRA_ARGS='-serial stdio'
fi

if ! ${mode_sys_qemu}; then
    export PATH="/home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/host/bin:${PATH}"
fi

最後に QEMU で Buildroot を起動するところです。

exec は、同じプロセス内で QEMU を実行するという意味になります(通常はサブプロセスで実行される)。

QEMUのコマンドライン引数

あとは、QEMU のコマンドライン引数です。調べて分かったところだけ書きます。

QEMU の公式ドキュメントのコマンドライン引数の説明のリンクです。

www.qemu.org

  • -M:-machine と同じ意味だと思うのですが、--help にも、QEMU 公式のドキュメントにも記載がありません
  • -smp:QEMU の仮想マシンに割り当てる CPU数の指定です
  • -m:QEMU の仮想マシンに割り当てるメモリ量(MB単位)です
  • -kernel:カーネルイメージの指定です
  • -dtb:device tree blob ファイルの指定です
  • -drive:仮想マシンに接続するドライブの指定で、今回の場合、ファイル名(file=)は「rootfs.ext2」、インタフェース(if=)は「SDカード」、フォーマット(format=)は「raw」となります
  • -append:カーネルに渡すコマンドライン引数(カーネルパラメータ)の指定で、今回の場合、コンソール(console=)は「ttyAMA0 で 115200 の速度で接続」、ルートファイルシステム(=root)は「/dev/mmcblk0 にマウント」となり、rootwait はルートファイルシステムが準備できるまで待機するオプションです
  • -net:仮想マシンにネットワーク機能を追加します、今回は nic(Network Interface Card)で、model は品種だと思います、user はホストのインターネット接続の共有です
  • -nographic:グラフィカルウィンドウをサポートせず、コマンドラインで起動します
  • -serial:仮想シリアルポートを接続します、今回の場合は標準出力です(標準入力も?)

最後に $@ は、start-qemu.sh に指定したコマンドライン引数(上で処理した2つ以外)を QEMU に指定するということだと思います。

ChatGPT に「-M」と「-machine」の違いを聞くと、「-M」は単にマシンタイプを指定するのに対して、「-machine」はマシンタイプに加えて、さまざまな追加オプションを指定することができるそうです。初めて知りました。

exec qemu-system-arm -M vexpress-a9 -smp 1 -m 256 -kernel zImage -dtb vexpress-v2p-ca9.dtb -drive file=rootfs.ext2,if=sd,format=raw -append "console=ttyAMA0,115200 rootwait root=/dev/mmcblk0"  -net nic,model=lan9118 -net user  ${EXTRA_ARGS} "$@"

start-qemu.sh は以上になります。

start-qemu.shを別のオプションで起動してみる

start-qemu.sh には、2つのオプションがあることが分かりました。

まず、--serial-only を指定して起動してみます。

これによって、QEMU に対して、-serial stdio を指定していたのを、-nographic に変更することになります。

やってみたところ、一見は、同じように起動しただけに見えました。

そこで、--serial-only を指定した場合と、指定しなかった場合で、起動ログを比較してみました。

すると、いくつか違いはあるのですが、--serial-only を指定しなかった場合は、以下のメッセージがありました。

VNC server running on 127.0.0.1:5900

今回起動した Buildroot は、最小構成なので、GUI は無いと思うのですが、一応、VNC サーバが起動されているようです。

実際に、Ubuntu 22.04 に Real VNC をインストールして、127.0.0.1:5900 に接続してみました。

もちろん、GUI のデスクトップなどは見えませんでしたが、接続は出来たようです。

RealVNCで接続
RealVNCで接続

現在の使用方法では、--serial-only を指定する方がいいと思います。

もう1つのオプションは、指定しない場合は、Buildroot でビルドした QEMU を使用しますが、オプションを指定すると、Ubuntu にインストールした QEMU を使えます。違いはあまりないと思うので、試すのは割愛します。

Buildrootのディレクトリ構成

tree コマンドで調べます。2階層に絞っても 3000 以上のディレクトリがありました。

適当にカットしたものを貼り付けます。

$ tree -d -L 2
.
|-- arch
|-- board
|   |-- aarch64-efi
|   |-- bananapi
|   |-- beagleboardx15
|   |-- beaglebone
|   |-- beagleboneai
|   |-- beaglev
|   |-- qemu
|   |-- raspberrypi
|   |-- raspberrypi0 -> raspberrypi
|   |-- raspberrypi0w -> raspberrypi
|   |-- raspberrypi2 -> raspberrypi
|   |-- raspberrypi3 -> raspberrypi
|   |-- raspberrypi3-64 -> raspberrypi
|   |-- raspberrypi4 -> raspberrypi
|   |-- raspberrypi4-64 -> raspberrypi
|   |-- raspberrypicm4io -> raspberrypi
|   |-- raspberrypicm4io-64 -> raspberrypi
|   |-- raspberrypizero2w -> raspberrypi
|   |-- roseapplepi
|   |-- versal
|-- boot
|   |-- afboot-stm32
|   |-- arm-trusted-firmware
|   |-- at91bootstrap
|   |-- at91bootstrap3
|   |-- at91dataflashboot
|   |-- barebox
|   |-- beaglev-ddrinit
|   |-- beaglev-secondboot
|   |-- binaries-marvell
|   |-- boot-wrapper-aarch64
|   |-- edk2
|   |-- grub2
|   |-- mv-ddr-marvell
|   |-- mxs-bootlets
|   |-- opensbi
|   |-- optee-os
|   |-- s500-bootloader
|   |-- shim
|   |-- syslinux
|   |-- ti-k3-boot-firmware
|   |-- ti-k3-image-gen
|   |-- ti-k3-r5-loader
|   |-- uboot
|   `-- vexpress-firmware
|-- configs
|-- dl
|   |-- (省略)
|-- docs
|   |-- conf
|   |-- images -> website/images
|   |-- manual
|   `-- website
|-- fs
|   |-- cpio
|   |-- ext2
|   |-- initramfs
|   |-- iso9660
|   |-- squashfs
|   |-- tar
|-- linux
|   `-- 5.10.162-cip24-rt10
|-- output
|   |-- build
|   |-- host
|   |-- images
|   |-- staging -> /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/host/arm-buildroot-linux-gnueabihf/sysroot
|   `-- target
|-- package
|   |-- (省略)
|-- support
|   |-- config-fragments
|   |-- dependencies
|   |-- docker
|   |-- download
|   |-- gnuconfig
|   |-- kconfig
|   |-- legal-info
|   |-- libtool
|   |-- misc
|   |-- scripts
|   `-- testing
|-- system
|   `-- skeleton
|-- toolchain
|   |-- toolchain
|   |-- toolchain-bare-metal-buildroot
|   |-- toolchain-buildroot
|   `-- toolchain-external
`-- utils
    |-- checkpackagelib
    `-- checksymbolslib

3058 directories

なるほど、たくさんありますね。

ビルドした内容は、すべて output に生成されるとのことなので、output に移動して、output だけを見てみます。

build ディレクトリは数が多かったので省略してます。

$ tree -d -L 2
.
|-- build
|   |-- (省略)
|-- host
|   |-- arm-buildroot-linux-gnueabihf
|   |-- bin
|   |-- etc
|   |-- include
|   |-- lib
|   |-- lib64 -> lib
|   |-- libexec
|   |-- sbin
|   |-- share
|   `-- usr -> .
|-- images
|-- staging -> /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/host/arm-buildroot-linux-gnueabihf/sysroot
`-- target
    |-- bin
    |-- dev
    |-- etc
    |-- lib
    |-- lib32 -> lib
    |-- media
    |-- mnt
    |-- opt
    |-- proc
    |-- root
    |-- run
    |-- sbin
    |-- sys
    |-- tmp
    |-- usr
    `-- var

93 directories

target ディレクトリが、起動で使用したルートファイルシステムなのかと思ったのですが、target ディレクトリに「THIS_IS_NOT_YOUR_ROOT_FILESYSTEM」というファイルがあります。実際の組み込みシステムで、このルートファイルシステムを使わないでください、とのことでした。

imagesのファイルの作られ方

output/images には、以下のファイルがあります。

$ ll -h images/
合計 13M
drwxr-xr-x 2 daisuke daisuke 4.0K  618 23:15 ./
drwxrwxr-x 6 daisuke daisuke 4.0K  618 23:15 ../
-rw-r--r-- 1 daisuke daisuke  64M  622 22:01 rootfs.ext2
-rwxr-xr-x 1 daisuke daisuke  846  622 16:25 start-qemu.sh*
-rwxr-xr-x 1 daisuke daisuke  14K  618 23:15 vexpress-v2p-ca9.dtb*
-rw-r--r-- 1 daisuke daisuke 5.1M  618 23:15 zImage

上から順に、ルートファイルシステム、start-qemu.sh、DTB、カーネルです。

ルートファイルシステム、DTB、カーネルが、どこで作られたかを調べておきます。

$ find . -name rootfs.ext2
./images/rootfs.ext2
$ find . -name zImage
./images/zImage
./build/linux-6.1.44/arch/arm/boot/zImage
$ find . -name vexpress-v2p-ca9.dtb
./images/vexpress-v2p-ca9.dtb
./build/linux-6.1.44/arch/arm/boot/dts/vexpress-v2p-ca9.dtb

カーネルと DTB は、output/build/linux-6.1.44 で作られたようです。

ルートファイルシステムは分からなったので、ビルドログから探します。

関係ありそうなログは以下でした。

>>>   Generating filesystem image rootfs.ext2
mkdir -p /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/images
rm -rf /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2
mkdir -p /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2
rsync -auH --exclude=/THIS_IS_NOT_YOUR_ROOT_FILESYSTEM /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/target/ /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/target
echo '#!/bin/sh' > /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/fakeroot
echo "set -e" >> /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/fakeroot
echo "chown -h -R 0:0 /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/target" >> /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/fakeroot
PATH="/home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/host/bin:/home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/host/sbin:/home/daisuke/.nvm/versions/node/v20.13.1/bin:/home/daisuke/Downloads/xpack-arm-none-eabi-gcc-13.2.1-1.1/bin:/home/daisuke/Downloads/xpack-qemu-arm-8.2.2-1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/support/scripts/mkusers /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/full_users_table.txt /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/target >> /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/fakeroot
echo "/home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/host/bin/makedevs -d /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/full_devices_table.txt /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/target" >> /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/fakeroot
printf '        rm -rf /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/target/usr/lib/udev/hwdb.d/ /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/target/etc/udev/hwdb.d/\n' >> /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/fakeroot
echo "find /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/target/run/ -mindepth 1 -prune -print0 | xargs -0r rm -rf --" >> /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/fakeroot
echo "find /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/target/tmp/ -mindepth 1 -prune -print0 | xargs -0r rm -rf --" >> /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/fakeroot
printf '   \n' >> /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/fakeroot
printf '   \n' >> /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/fakeroot
printf '        rm -f /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/images/rootfs.ext2\n     /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/host/sbin/mkfs.ext2 -d /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/target -r 1 -N 0 -m 5 -L "rootfs" -I 256 -O ^64bit /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/images/rootfs.ext2 "64M" || { ret=$?; echo "*** Maybe you need to increase the filesystem size (BR2_TARGET_ROOTFS_EXT2_SIZE)" 1>&2; exit $ret; }\n' >> /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/fakeroot
chmod a+x /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/fakeroot
PATH="/home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/host/bin:/home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/host/sbin:/home/daisuke/.nvm/versions/node/v20.13.1/bin:/home/daisuke/Downloads/xpack-arm-none-eabi-gcc-13.2.1-1.1/bin:/home/daisuke/Downloads/xpack-qemu-arm-8.2.2-1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" FAKEROOTDONTTRYCHOWN=1 /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/host/bin/fakeroot -- /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/fakeroot
rootdir=/home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/ext2/target
table='/home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/build/buildroot-fs/full_devices_table.txt'
mke2fs 1.47.0 (5-Feb-2023)
Creating regular file /home/daisuke/svn_/qemu/linux/buildroot-2024.02.3/output/images/rootfs.ext2
Creating filesystem with 65536 1k blocks and 16384 inodes
Filesystem UUID: 5ef0e39c-49e5-42f0-9d1f-2fc756b89405
Superblock backups stored on blocks:
        8193, 24577, 40961, 57345

ちょっと分かりにくいですが、output/target と output/build/buildroot-fs/ext2 あたりに見えます。

しかし、今見てみると、後者は fakeroot というファイルが1つあるだけですので、前者がルートファイルシステムっぽいです。

おわりに

今回は、前回 起動した、QEMU の組み込み Linux について、補足をしました。

次回こそは、u-boot の組み込みなど、やってみたいと思います。

最後になりましたが、エンジニアグループのランキングに参加中です。

気楽にポチッとよろしくお願いいたします🙇

今回は以上です!

最後までお読みいただき、ありがとうございました。




以上の内容はhttps://daisuke20240310.hatenablog.com/entry/buildroot2より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14