This guide is a summary of the steps I had to take to emulate Raspbian Bullseye using QEMU, after a lot of online research.
Last tried Jan 2023 on a Lubuntu 22.04 LTS VM
-
(Recommended) Update your system
$sudo apt update && sudo apt upgrade
-
Install qemu packages
$sudo apt install qemu-system-arm qemu-utils
-
Check your qemu version
$qemu-system-arm --version
This guide uses version 6.2.0. If yours is lower, it may not work for you. -
This guide is for emulating Bullseye Lite (No GUI).
In theory, it should also work with Bullseye Desktop, but make sure to delete-nographic
in the launch command. -
The internet connection within the VM is very slow (~50kB/s while running apt upgrade).
This guide uses USB as a network interface for the VM.
If possible, setting up a bridged connection or a NAT interface would probably be better. -
There seems to be a bug which makes it impossible to use virt utils to manager this VM.
-
Some steps in the VM's boot sequence fail, but they do not seem to affect functionality.
I honestly do not recommend doing this, but if you insist, good luck.
- $
sudo mkdir rpidir && cd rpidir
- $
wget https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2022-09-26/2022-09-22-raspios-bullseye-armhf-lite.img.xz
- (Or go to the official download page.)
- $
unxz 2022-09-22-raspios-bullseye-armhf-lite.img.xz
- $
mv 2022-09-22-raspios-bullseye-armhf-lite.img bullseye.img
(The rest of this guide assumes it's renamed to bullseye.img)
- $
fdisk -l bullseye.img
Sample output:
Disk bullseye.img: 1.75 GiB, 1874853888 bytes, 3661824 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xb1214a26
Device Boot Start End Sectors Size Id Type
bullseye.img1 8192 532479 524288 256M c W95 FAT32 (LBA)
bullseye.img2 532480 3661823 3129344 1.5G 83 Linux
- Then multiply the start address of the first device by the the sector size to obtain the offset.
8192 * 512 = 4194304
- $
sudo mkdir /mnt/tmpmnt
- $
sudo mount -o loop,offset=4194304 bullseye.img /mnt/tmpmnt
- $
cp /mnt/tmpmnt/kernel8.img kernel.img
(Renamed to kernel.img for convenience)
- $
cp /mnt/tmpmnt/bcm2710-rpi-3-b-plus.dtb treeblob.dtb
(Renamed to treeblob.dtb for convenience)
- $
echo 'password' | openssl passwd -6 -stdin
(The output of this command is an encrypted version of the password, necessary for the next step)
- $
sudo nano /mnt/tmpmnt/userconf.txt
- Type your crendentials in it, following the format
username:encrypted_password
. - Press Ctrl+S to save and Ctrl+X to exit.
- $
sudo umount /mnt/tmpmnt
- $
qemu-img resize bullseye.img 8G
(You may choose another size, but make sure it's a power of 2 and greater than the initial size)
qemu-system-aarch64 \
-machine raspi3b \
-cpu cortex-a72 \
-smp 4 -m 1G \
-kernel kernel.img \
-dtb treeblob.dtb \
-drive "file=bullseye.img,format=raw,index=0,if=sd" \
-append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootdelay=1" \
-device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::5555-:22 \
-nographic
- Make sure to edit the command according to your files' names.
- (Recommended: save the command as a shell script for easier/faster launch)
It's okay if you don't see anything in the terminal. Just wait. The VM should start booting.
The boot sequence takes a while and some boot steps may fail, but that's probably fine.
Once it's done, you'll be prompted to login. Enter the username and password you specified earlier.
(Note: Some boot messages may keep popping up as you log in.)
At this point, the VM is set up and usable. However, it is recommended that you do the following:
-
Start the cfdisk utility
- $
sudo cfdisk /dev/mmcblk0
(/dev/mmcblk0 is the device file of the SD card on the Raspberry Pi 3. The cfdisk utility allows us to modify the partitions on the SD card) - In the utility, you can use the up and down arrow keys to navigate the partitions, and the side arrow keys to navigate the options.
- $
-
Select the
/dev/mmcblk0p2
partition and Resize it to fill the available space.
(The default given size should be just fine.) -
Save changes with Write, then Quit.
-
Resize the file system
- $
sudo resize2fs /dev/mmcblk0p2
- $
-
Shutdown and restart the VM
- $
sudo shutdown now
- $
- $
sudo apt update && sudo apt upgrade
(Note: The internet connection within the VM is very slow, and this will take a long time.)
- $
sudo raspi-config
(This tool enables you to configure your locale, keyboard layout, hostname, password, as well as turn on SSH server, and more)
- Make sure that you have enabled the SSH server through the raspi-config utility.
- $
ssh username@localhost -p 5555
(5555 being the forward port configured for the VM in the launch command.) - If you intend to change the VM's ssh server port, make sure to change the forwarded port (from 22) in the launch command as well.
- Emulate Raspberry Pi with QEMU on Azeria-Labs.com.
- Emulating ARM64 Raspberry Pi Image using QEMU (Sep 2022) by Source Meets Sink.
- System emulation using qemu: Raspberry PI 3 (Sep 2022) by Radu Zaharia.
- (Password configuration) An update to Raspberry Pi OS Bullseye (Apr 2022) by Simon Long.
- More sources and information in my Rasbian Buster emulation guide.
Thank you to the linux emulation community, and to the FOSS community as a whole.