自分なりにQEMUで最小構成のLinux環境を構築する
自分なりにQEMUで最小構成のLinux環境を構築する
QEMU + ARM64用の最小Linuxカーネルをビルドする と
LinuxをQEMUで動かす(Armv8-A中心) を参考にQEMUで最小構成のLinux環境を作ってみる。
まずは、defconfigを使って、Linuxカーネルをコンパイルしてみた。 qemu-busybox-min.configは参考にしたサイトに書いてあるのをそのまま利用した(qemu-busybox-min.config。
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make defconfig >& log_defconfig00.txt
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make qemu-busybox-min.config >& log_defconfig_qemu-busybox-min-config00.txt
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -j$(nproc) >& log_make_kernel01.txt &
arch/arm64/configs/qemu-busybox-min.config
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_PL061=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_CMDLINE="console=ttyAMA0 nokaslr rdinit=/sbin/init"
allnoconfigというのを使う場合は、以下のようにする。 allnoconfigは全てのカーネルのコンパイルオプションを NOに設定する。
実用的なオプションは全て外されてしまうが、後で、必要なコンパイルオプションだけを足していくイメージ。
最後のカーネルのコンパイルは、 defconfigを使った時に比べて、相当早く終わる。
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make allnoconfig >& log_allnoconfig00.txt
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make qemu-busybox-min.config >& log_qemu-busybox-min-config00.txt
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -j$(nproc) >& log_make_kernel00.txt &
カーネルをコンパイルしたら、qemuを起動する。
qemu-system-aarch64 -machine virt,virtualization=on,gic-version=2 \
-net none \
-cpu cortex-a53 \
-m 1G \
-kernel arch/arm64/boot/Image \
-nographic
実行は、initコマンドとかがないのでエラーができるが、カーネルのブートするところまでは確認できた。
ちなみに、QEMUコマンドラインを終了するには、Ctrl-A x を押す。
emacsのshellの中からだと、Ctrl-Q Ctrl-A x の順番に押した。
Busyboxのコンパイル
BusyBoxでinit ramdisk構築を参考にしながら、Busyboxのコンパイルを行った。
シェルの設定
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
- busyboxのgit clone
- make menuconfig
-
Build static binary (no shared libs)をオンにする - ネットワークのコンフィグを全てoff にしておいた (使わない可能性が高いから)
make install
cd _install
find . | cpio -H newc -ov -F ../initramfs.cpio
cd ../
gzip initramfs.cpio
今度は、さっきのQEMUのコマンドに、initの部分を追加して起動した。
qemu-system-aarch64 -machine virt,virtualization=on,gic-version=2 \
-net none \
-cpu cortex-a53 \
-m 1G \
-kernel arch/arm64/boot/Image \
-initrd ../busybox/initramfs.cpio.gz \
-nographic
参考にしたサイトと同様に、以下のようなエラーが発生した。
can't open /dev/tty4: No such file or directory
can't open /dev/tty2: No such file or directory
can't open /dev/tty3: No such file or directory
can't open /dev/tty4: No such file or directory
can't open /dev/tty2: No such file or directory
can't open /dev/tty3: No such file or directory
can't open /dev/tty4: No such file or directory
can't open /dev/tty2: No such file or directory
can't open /dev/tty3: No such file or directory
can't open /dev/tty4: No such file or directory
can't open /dev/tty2: No such file or directory
can't open /dev/tty3: No such file or directory
can't open /dev/tty4: No such file or directory
can't open /dev/tty2: No such file or directory
can't open /dev/tty3: No such file or directory
can't open /dev/tty4: No such file or directory
参考にしたサイトと同じように、以下のように特殊なディレクトリを作成して回避できた。
cd busybox
cd _install
mkdir proc sys dev run etc dev/pts etc/init.d
sudo mknod -m 666 dev/null c 1 3
sudo mknod -m 600 dev/console c 5 1
vi etc/init.d/rcS
#!/bin/sh
mount -v --bind /dev /dev
mount -v --bind /dev/pts /dev/pts
mount -vt proc proc /proc
mount -vt sysfs sysfs /sys
mount -vt tmpfs tmpfs /run
/sbin/mdev -s
chmod +x rcS
U-Bootを使ったブート
参考にしたサイトの通り、以下のような手順で行った。
git clone https://source.denx.de/u-boot/u-boot.git
git checkout v2025.10
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
make qemu_arm64_defconfig
make -j
コンパイル中に以下のようなエラーが発生したので、足りないパッケージをインストールした。
tools/mkeficapsule.c:20:10: fatal error: gnutls/gnutls.h: そのようなファイルやディレクトリはありません
20 | #include <gnutls/gnutls.h>
| ^~~~~~~~~~~~~~~~~
compilation terminated.
make[1]: *** [scripts/Makefile.host:114: tools/mkeficapsule.o] エラー 1
make[1]: *** 未完了のジョブを待っています....
make: *** [Makefile:2124: tools] エラー 2
sudo apt install libgnutls28-dev
再度、実行をした。
make qemu_arm64_defconfig
make -j
コンパイルが完了後、以下のコマンドでu-bootが使用するディスクイメージを作成する。
mkimageの uRamdiskというのは、RAM Disk用のイメージのファイル名。
cd ../
./u-boot/tools/mkimage -A arm64 -O linux -T ramdisk -d ./busybox/initramfs.cpio.gz uRamdisk
Image Name:
Created: Wed Dec 31 16:19:38 2025
Image Type: AArch64 Linux RAMDisk Image (gzip compressed)
Data Size: 1051129 Bytes = 1026.49 KiB = 1.00 MiB
Load Address: 00000000
Entry Point: 00000000
uRamdiskは以下のような感じで作られる
ls
-rw-rw-r-- 1 aaaaa aaaaa 1051193 Dec 31 16:19 uRamdisk
参考にしたサイトの通り、 ramdiskというディレクトリを作って、カーネルイメージとRAMDISKをおいた。
mkdir ramdisk
cp linux-6.12.63/arch/arm64/boot/Image ramdisk/.
cp uRamdisk ramdisk/.
QEMUを起動するコマンドは、以下の通り。ramdiskというディレクトを指定している。
qemu-system-aarch64 \
-bios u-boot/u-boot.bin \
-machine virt \
-cpu cortex-a72 \
-m 1G \
-nographic \
-drive file=fat:rw:"./ramdisk",format=raw,if=none,media=disk,id=drive0 \
-device virtio-blk,drive=drive0
U-Bootが起動したら以下のコマンドを実行した (これも参考にしたサイトの通りに実行した)。
すると、Busyboxのシェルが起動するようになった。
load virtio 0 $kernel_addr_r Image
load virtio 0 $ramdisk_addr_r uRamdisk
booti $kernel_addr_r $ramdisk_addr_r $fdt_addr
さらにコンパクトなLinuxカーネルを作ってみる
defconfigだと、コンパイル時間がそれなりにかかったので、allnoconfigをベースに必要なconfigのみを設定してスリムにしてみる。
Linux を(わりと)シンプルな構成でビルドして Qemu で起動するを参考にした。
[*] 64-bit kernel
-> General setup
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
-> General setup
-> Configure standard kernel features
[*] Enable support for printk
-> Executable file formats / Emulations
[*] Kernel support for ELF binaries
-> Device Drivers
-> Character devices
[*] Enable TTY
-> Device Drivers
-> Character devices
-> Serial drivers
[*] 8250/16550 and compatible serial support
[*] Console on 8250/16550 and compatible serial port
実際のところ、以下のようなコンフィグファイル(qemu-busybox-min2.config)を作成して、組み込んだ。
足したのは、最後の2行のみ。
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_PL061=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_CMDLINE="console=ttyAMA0 nokaslr rdinit=/sbin/init"
#
CONFIG_BLK_DEV_INITRD=y
CONFIG_BINFMT_ELF=y
Discussion