Arm QEMU Debian 11 VM on x86/64 (amd64) Linux
This was last tested using QEMU 6.1.0
running on an
Arch Linux x86_64 host. The goal is to get a 32-bit armv7 (armhf)
Debian VM running in QEMU.
The author’s lack of knowledge about Arm and QEMU probably make this process a bit more complex than it needs to be. This is a solution, but most likely not the best solution.
% qemu-system-arm --version
QEMU emulator version 6.1.0
Copyright (c) 2003-2021 Fabrice Bellard and the QEMU Project developers
Download Files
Download the latest armhf vmlinux
kernel and
initrd.gz
initramfs from
Debian.
curl -O http://ftp.us.debian.org/debian/dists/stable/main/installer-armhf/current/images/cdrom/initrd.gz \
&& curl -O http://ftp.us.debian.org/debian/dists/stable/main/installer-armhf/current/images/cdrom/vmlinuz
Download the latest
Debian armhf DVD ISO. Version debian-11.1.0-armhf-DVD-1.iso
at time of
writing.
curl -O -L https://cdimage.debian.org/debian-cd/current/armhf/iso-dvd/debian-11.1.0-armhf-DVD-1.iso
Install Debian
Create a disk for the Arm QEMU emulator image.
qemu-img create -f qcow2 debian-arm.sda.qcow2 100G
Boot the VM to install Debian.
qemu-system-arm \
-m 4G \
-machine type=virt \
-cpu cortex-a7 \
-smp 4 \
-initrd "./initrd.gz" \
-kernel "./vmlinuz" \
-append "console=ttyAMA0" \
-drive file="./debian-11.1.0-armhf-DVD-1.iso",id=cdrom,if=none,media=cdrom \
-device virtio-scsi-device \
-device scsi-cd,drive=cdrom \
-drive file="./debian-arm.sda.qcow2",id=hd,if=none,media=disk \
-device virtio-scsi-device \
-device scsi-hd,drive=hd \
-netdev user,id=net0,hostfwd=tcp::5555-:22 \
-device virtio-net-device,netdev=net0 \
-nographic
The installer will eventually error out when trying to install
Grub. That is fine. Choose Continue
.
┌────────────────┤ [!!] Install the GRUB boot loader ├────────────────┐
│ │
│ GRUB installation failed │
│ The 'grub-pc' package failed to install into /target/. Without the │
│ GRUB boot loader, the installed system will not boot. │
│ │
│ <Go Back> <Continue> │
│ │
└─────────────────────────────────────────────────────────────────────┘
When prompted at the menu choose
Continue without boot loader
, which should show this
information.
┌─────────────────┤ [!] Continue without boot loader ├──────────────────┐
│ │
│ No boot loader installed │
│ No boot loader has been installed, either because you chose not to or │
│ because your specific architecture doesn't support a boot loader yet. │
│ │
│ You will need to boot manually with the /vmlinuz kernel on partition │
│ /dev/sda1 and root=/dev/sda2 passed as a kernel argument. │
│ │
│ <Continue> │
│ │
└───────────────────────────────────────────────────────────────────────┘
When installation completes it is crucial to not reboot
when prompted. Rather, choose Go Back
at the
Finish the installation
menu.
┌───────────────────┤ [!!] Finish the installation ├────────────────────┐
│ │
│ Installation complete │
│ Installation is complete, so it is time to boot into your new system. │
│ Make sure to remove the installation media, so that you boot into the │
│ new system rather than restarting the installation. │
│ │
│ <Go Back> <Continue> │
│ │
└───────────────────────────────────────────────────────────────────────┘
Choose to Execute a shell
from the main installer
menu. Start sshd
on the Debian installation so that
we can copy out the kernel and initramfs from the guest to the
host.
chroot /target/ sh -c "mkdir -p /var/run/sshd && /sbin/sshd -D"
Use scp
on the host machine to copy boot files out of
the guest.
scp -P 5555 <your username in the VM>@localhost:/boot/vmlinuz ./vmlinuz-from-guest \
&& scp -P 5555 <your username in the VM>@localhost:/boot/initrd.img ./initrd.img-from-guest
Use ctrl + c
or another mechanism to stop
sshd
and shut down the guest VM.
Run VM Normally
Modify a few of the options for subsequent “normal” booting into the VM after installing Debian.
Required:
-
-kernel
will now reference the kernel copied from the guest vm, not the version downloaded from Debian -
-initrd
will now reference the initramfs copied from the guest vm, not the version downloaded from Debian -
-append
must haveroot=/dev/sda2
(or another valid/dev
location) added in order to boot from the virtual hard drive.
Optional:
-
-drive
for thecdrom
is not needed at this point and can be removed
qemu-system-arm \
-m 4G \
-machine type=virt \
-cpu cortex-a7 \
-smp 4 \
-initrd "./initrd.img-from-guest" \
-kernel "./vmlinuz-from-guest" \
-append "console=ttyAMA0 root=/dev/sda2" \
-drive file="./debian-arm.sda.qcow2",id=hd,if=none,media=disk \
-device virtio-scsi-device \
-device scsi-hd,drive=hd \
-netdev user,id=net0,hostfwd=tcp::5555-:22 \
-device virtio-net-device,netdev=net0 \
-nographic
Note: QEMU Arm Hardware is Picky
Please note that
Arm emulated boards/machine types are extremely specific about
the type of hardware they support. See the
QEMU docs on choosing a board model. For example, the virt
machine type (-M / -machine
) only supports PCI ethernet devices. Specifying a board that
supports 64-bit
/aarch64
vs
32-bit
boards has implications on the
cpu
and other options that will be allowed.
The orangepi-pc
machine type requires exactly 1GB of
RAM. The Raspberry Pi related machine types have similar
restrictions. Boards that simulate physical hardware must accept
parameters that align with that device type.
See this text here regarding the
QEMU Arm Versatile Express
boards.
Note that as this hardware does not have PCI, IDE or SCSI, the only available storage option is emulated SD card.
See some example errors here for
qemu-system-arm
configuration options that were
incompatible with the selected machine type.
qemu-system-arm: This machine can only be used with 512MiB or 1GiB RAM
qemu-system-arm: This board can only be used with cortex-a7 CPU
qemu-system-arm: Unsupported NIC model: rtl8139
qemu-system-arm: Invalid SD card size: 100 GiB
SD card size has to be a power of 2, e.g. 128 GiB.