QEMUlating a Rasbian (ARM)
December 15, 2020
Quick how-to download and run a Raspbian Buster (ARM) emulating the vm with QEMU.
- Download Raspbian lite image (Buster)
- Download kernel image for Raspbian (
kernel-qemu-*-buster
) and the dtb file for that kernel (versatile-pb-buster-*.dtb
) - Install QEMU:
apt-get install qemu-system
Preparing the image
Unpack and check the disk file.
$ unzip 2020-12-02-raspios-buster-armhf-lite.zip
Archive: 2020-12-02-raspios-buster-armhf-lite.zip
inflating: 2020-12-02-raspios-buster-armhf-lite.img
$ sudo fdisk -l 2020-12-02-raspios-buster-armhf-lite.img
Disk 2020-12-02-raspios-buster-armhf-lite.img: 1.7 GiB, 1858076672 bytes, 3629056 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: 0x067e19d7
Device Boot Start End Sectors Size Id Type
2020-12-02-raspios-buster-armhf-lite.img1 8192 532479 524288 256M c W95 FAT32 (LBA)
2020-12-02-raspios-buster-armhf-lite.img2 532480 3629055 3096576 1.5G 83 Linux
Mount the second partition. Because the file has 2 partitions, we need to set the offset where the second starts: the start sector number multiplied by the size of each sector in bytes.
$ sudo mount -v -o offset=$((532480 * 512)) -t ext4 2020-12-02-raspios-buster-armhf-lite.img ~/mnt
Why we need to do this? No idea. May be is related with this
Comment out any entry of ld.so.preload
adding a #
at the begin of each line.
$ cat ~/mnt/etc/ld.so.preload
/usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so
$ sudo sed -i 's/^.*$/#\0/' ~/mnt/etc/ld.so.preload
Check the fstab
. Replace /dev/mmcblk0p1
and /dev/mmcblk0p2
with /dev/sda1
and /dev/sda2
.
In my case there are not explicit names like /dev/mmcblk0p1
. Instead, there are UUIDs so I didn’t touch them.
$ cat ~/mnt/etc/fstab
proc /proc proc defaults 0 0
PARTUUID=067e19d7-01 /boot vfat defaults 0 2
PARTUUID=067e19d7-02 / ext4 defaults,noatime 0 1
We are done.
$ sudo umount ~/mnt
Now it is show time!
Running the OS
$ qemu-system-arm \
-M versatilepb \
-cpu arm1176 \
-m 256 \
-drive "file=2020-12-02-raspios-buster-armhf-lite.img,if=none,index=0,media=disk,format=raw,id=disk0" \
-device "virtio-blk-pci,drive=disk0,disable-modern=on,disable-legacy=off" \
-net "user,hostfwd=tcp::3022-:22" \
-dtb versatile-pb-buster-5.4.51.dtb \
-kernel kernel-qemu-5.4.51-buster \
-append 'root=/dev/vda2 panic=1' \
-no-reboot \
-net nic \
-nographic
The hostfwd=tcp::3022-:22
tells QEMU to forward TCP connections to the 3022 port from the host to the 22 port on the guest side. More forward rules can be added.
Enable ssh (now and on boot); login with pi
/raspberry
. This will allows us to upload/retrieve files to the vm and have additional consoles.
$ sudo service ssh start
$ sudo update-rc.d ssh enable
Now, from your host connect to the vm through the port 3022.
Install gdbserver
for remote debugging:
sudo apt-get install gdbserver
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
gdbserver
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
<...>
Preparing to unpack .../gdbserver_8.2.1-2_armhf.deb ...
Unpacking gdbserver (8.2.1-2) ...
Setting up gdbserver (8.2.1-2) ...
Enlarge the disk
Optionally, you can expand the disk image to have more room for your programs.
First, with QEMU turned off, expand the disk image
$ qemu-img resize 2020-12-02-raspios-buster-armhf-lite.img +1G
Now, turn on the vm and redefine the partition. In my case is the partition number 2 (/dev/vda2
):
pi@raspberrypi:~$ sudo fdisk /dev/vda
Command (m for help): p
Disk /dev/vda: 2.7 GiB, 2931818496 bytes, 5726208 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: 0x067e19d7
Device Boot Start End Sectors Size Id Type
/dev/vda1 8192 532479 524288 256M c W95 FAT32 (LBA)
/dev/vda2 532480 3629055 3096576 1.5G 83 Linux
Command (m for help): d
Partition number (1,2, default 2): 2
Partition 2 has been deleted.
Command (m for help): n
Partition type
p primary (1 primary, 0 extended, 3 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): 2
First sector (2048-5726207, default 2048): 532480
Last sector, +/-sectors or +/-size{K,M,G,T,P} (532480-5726207, default 5726207):
Created a new partition 2 of type 'Linux' and of size 2.5 GiB.
Partition #2 contains a ext4 signature.
Do you want to remove the signature? [Y]es/[N]o: n
Command (m for help): w
The partition table has been altered.
Syncing disks.
Note that fdisk
offered by default the first sector to be 2048. This is the space before /dev/vda1
and it is too small, only 8kb.
Instead we want to start after /dev/vda1
, in the same sector that the original /dev/vda2
: the 532480.
From there, to the end of the disk: 5726207.
With the partition expanded, reboot and then update the filesystem:
pi@raspberrypi:~$ sudo resize2fs /dev/vda2
resize2fs 1.44.5 (15-Dec-2018)
Filesystem at /dev/vda2 is mounted on /; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 1
The filesystem on /dev/vda2 is now 649216 (4k) blocks long.
References
This tutorial setups a Raspbian Jessie in Qemu.
I adapted the steps to use a modern Raspbian Buster image.
The tutorial is super complete and includes how to enlarge the disk and setup the network.
But for the enlarge the disk part, this gist explains the thing a little better.
embiggen-disk seems to be a tool to facilite the task.