How to emulate Raspberry Pi Raspbian with QEMU?
You should expand the Raspbian Image file before starting
Mount the Raspbian Image file with kpartx (might have to install kpartx)
$ sudo kpartx -av your-image.imgadd map loop0p1 (252:5): 0 117187 linear /dev/loop0 1add map loop0p2 (252:6): 0 3493888 linear /dev/loop0 118784$ sudo mount /dev/mapper/loop0p2 /mnt/img1$ cd /mnt/img1
Modify the /etc/fstab and comment out the MMCBLK mounts
$ sudo nano etc/fstabproc /proc proc defaults 0 0#/dev/mmcblk0p1 /boot vfat defaults 0 2#/dev/mmcblk0p2 / ext4 defaults,noatime 0 1# a swapfile is not a swap partition, no line here# use dphys-swapfile swap[on|off] for that
Modify /etc/ld.so.preload and comment out lines ...
$ sudo nano etc/ld.so.preload#/usr/lib/arm-linux-gnueabihf/libarmmem.so
Unmount and destroy loops from kpartx
$ sudo umount /mnt/img1$ sudo kpartx -d your-image.img
Get the Qemu kernel matching the Raspbian image here...
https://github.com/dhruvvyas90/qemu-rpi-kernel
I used this command to successfully emulate Raspbian Jessie
qemu-system-arm -kernel kernel-qemu-4.4.12-jessie -cpu arm1176 -m 256 -M versatilepb \-no-reboot -serial stdio -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw" \-redir tcp:5022::22 \-hda 2016-05-27-raspbian-jessie-lite.img
You need a modified kernel in order to run in QEMU, because the raspberry PI board hardware is not available in QEMU. That is why your first approach failed.
Your second approach uses a kernel properly patched to run on the versatile board (supported by QEMU), so that is good, but the kernel 3.x is too old for a modern Raspbian. In principle your last approach should have worked.
I recommend this updated guide (feb 2017), I tested it with a 4.4 kernel and it works straight away.
qemu-system-arm -kernel $KERNEL -cpu arm1176 -m 256 -M versatilepb -net nic,macaddr=$MAC -net tap -no-reboot -append "root=/dev/sda2 panic=1" -drive format=raw,file=$IMG
I had to use format=raw,file=$IMG
option to avoid a QEMU warning.
You don't need to comment out /etc/fstab
, you can add to /etc/udev/rules.d/90-qemu.rules
KERNEL=="sda", SYMLINK+="mmcblk0"KERNEL=="sda?", SYMLINK+="mmcblk0p%n"KERNEL=="sda2", SYMLINK+="root"
Also, The ld.so.preload thing is old and does not apply anymore
The script provided on the mentioned guide does all this for you, and also provides network access to your raspbian by sharing your network interface with raspbian.
Ubuntu 16.04 host, QEMU 2.9.0 -M raspi2, Raspbian 2016-05-27, vanilla kernel
Advantages:
- with
-M raspi2
, we can use the vanilla kernel, so the system is more representative
Limitations:
-M raspi2
was added in QEMU 2.6.0, and Ubuntu 16.04 only has QEMU 2.5.0, so we have to compile QEMU from source. But this is not hard.- the GUI shows but is not responding to the mouse / keyboard, tested on both SDL and VNC. But CLI works perfectly however. So you might as well use the Lite image which has go GUI for now.
- no networking
Steps:
Compile QEMU 2.9.0 from source:
sudo apt-get build-dep qemu-system-armgit clone --recursive git://git.qemu-project.org/qemu.gitcd qemugit checkout v2.9.0./configuremake `nproc`
Download image and extract the kernel and dts from it:
Download the image and unzip it:
wget http://downloads.raspberrypi.org/raspbian/images/raspbian-2016-05-31/2016-05-27-raspbian-jessie.zipunzip 2016-05-27-raspbian-jessie.zip
Mount the second image of the partition. The easiest way is:
sudo losetup -f --show -P 2016-05-27-raspbian-jessie.img
This only works with latest
losetup
on Ubuntu 16.04, other methods at: https://askubuntu.com/questions/69363/mount-single-partition-from-image-of-entire-disk-device/496576#496576This prints a loop device, e.g.:
/dev/loop0
so we do:
sudo mkdir /mnt/rpisudo mount /dev/loop0p1 /mnt/rpicp /mnt/rpi/kernel7.img bcm2709-rpi-2-b.dtb .sudo umount /mnt/rpisudo losetup -d /dev/loop0
Run:
./arm-softmmu/qemu-system-arm \ -M raspi2 \ -append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2" \ -cpu arm1176 \ -dtb bcm2709-rpi-2-b.dtb \ -sd 2016-05-27-raspbian-jessie.img \ -kernel kernel7.img \ -m 1G \ -smp 4 \ -serial stdio \;
You can then login on the terminal that shows on your host terminal.
[failed] Ubuntu 17.04, QEMU 2.8.0 -M raspi2, Raspbian 2016-05-27, vanilla kernel
On this newer Ubuntu, QEMU 2.8.0 is the default, so we don't need to compile QEMU from source for -M raspi2
. However, 2.8.0 hangs on boot after the message:
Console: switching to colour frame buffer device 100x30
This goes to show how unstable -M raspi2
still is.
[failed] Ubuntu 16.04, QEMU 2.9.0 -M raspi2, Raspbian 2017-08-16, vanilla kernel
On this newer image, using the same method for 2016-05-27, the kernel panics at boot with:
Please append a correct "root=" boot option; here are the available partitions:...[ 4.138114] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
bztsrc/raspi3-tutorial
RPI3 bare metal on QEMU
https://github.com/bztsrc/raspi3-tutorial is a good set of examples that just work on QEMU, ultraquick getting started at: https://raspberrypi.stackexchange.com/questions/34733/how-to-do-qemu-emulation-for-bare-metal-raspberry-pi-images/85135#85135