-----------------------------------------------------------
Raspberry Pi Zero W to Qemu - Physical to Virtual Migration
-----------------------------------------------------------
April 2022
Prerequisities:
1] Raspberry Pi Zero W (or just any raspberry) on Raspbian
with sshd running
2] Qemu sources
https://github.com/qemu/qemu
here tested with qemu 6.2.93
3] Linux Computer
here Debian 10 we will call it deb
4] good tcp/ip connection between rpi and deb
-----------------------------------------------------------
The process:
0] We will store the data to ~/virtual/rpi
d# mkdir -p ~/virtual/rpi
a] We will first transfer the boot partition to deb
1] first ssh to rpi (ssh root@rpi)
I assume You have:
/dev/mmcblk0p1 mounted on /boot (cca 256 MB)
2] We will make binary copy of the boot partition to deb
on rpi:
r# ssh deb "sudo -S dd if=/dev/mmcblk0p1 bs=64k status=progress | gzip -1 -" | dd of=rpi_boot_part.gz bs=64k
b] Now we will prepare the disk for the virtual machine
1] to create qemu e.g. 32 GB disk
d# cd ~/virtual/rpi
d# qemu-img create -f qcow2 sys.qcow2 32G
c] Next we will mount and partition the virtual disk
1] first mount the disk
d# qemu-nbd -c /dev/nbd0 sys.qcow2
2] now we will prepare the same partitions as it is on physical rpi
d# sudo fdisk /dev/nbd0
3] For reference use on physical rpi:
r# fdisk -l /dev/mmcblkp01
e.g.
Device Boot Start End Sectors Size Id Type
/dev/mmcblk0p1 8192 532479 524288 256M c W95 FAT32 (LBA)
/dev/mmcblk0p2 532480 249737215 249204736 118.8G 83 Linux
4] With this knowledge prepare virtual hdd on deb
d# sudo fdisk /dev/ndb0
i] create boot partition in fdisk e.g.
enter: n # new partition
enter: p # primary
enter: 1 # partition number
enter: 8192 # first sector (from step 3 the same as on source)
enter: 532479 # last sector (from step 3 the same as on source)
ii] change boot partition type
enter: t # change the type
enter: 1 # partition number (boot partition)
enter: c # the same type as in step 3 (W95 FAT32 LBA)
iii] prepare the root partition
enter: n # new partition
enter: p # primary
enter: 2 # partition number
enter: 532480 # first sector (from step 3 the same as on source)
enter: 249737215 # last sector (from step 3 the same as on source)
iv] change type of the root partition
enter: t # change the type
enter: 1 # partition number (boot partition)
enter: 83 # the same type as in step 3 (Linux)
v] save virtual disk partitions
enter: w # writes partition table to virtual disk and exits
5] Prapare the root filesystem (/dev/nbd0p2)
d# mkfs.ext4 /dev/nbd0p2
6] Binary copy the boot partition (/dev/nbd0p1)
d# gunzip rpi_boot_part.gz
d# sudo dd if=rpi_boot_part of=/dev/nbd0p1
7] Now mount the root partition
d# mkdir /mnt/rpiroot
d# mount /dev/nbd0p2 /mnt/rpiroot
8] Copy files from the rpi to mounted virtual partition on deb
p# rsync -aAXv / --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} root@deb:/mnt/rpiroot
9] We will copy current physical dtb and kernel from the boot to use it in emulation
d# mkdir /mnt/rpiboot
d# mount /dev/nbd0p1 /mnt/rpiboot
d# cp /mnt/rpiboot/bcm2709-rpi-2-b.dtb ~/virtual/rpi
d# cp /mnt/rpiboot/kernel7.img ~/virtual/rpi
10] Now on deb unmount the root partition and virtual disk
d# umount /dev/nbd0p2
d# sudo qemu-nbd -d /dev/nbd0
d] Prepare the newest qemu (we need only qemu-system-arm
1] get the qemu sources
# git clone https://github.com/qemu/qemu.git
2] build it
# cd qemu
# mkdir build
# cd build
# ../configure
# make
3] get the qemu-system-arm and put it to the virtual rpi folder
# cp qemu-system-arm ~/virtual/rpi
e] Boot the virtual machine (with usb networking)
1] now we will boot the machine using:
# cd ~/virtual/rpi
# prepare run.sh with following content:
./qemu-system-arm \
-M raspi2b \
-dtb bcm2709-rpi-2-b.dtb \
-kernel kernel7.img \
-append 'rw earlycon=pl011,0x3f201000 console=ttyAMA0 loglevel=2 root=/dev/mmcblk0p2 fsck.repair=yes net.ifnames=0 rootwait memtest=1 dwc_otg.fiq_fsm_enable=0' \
-m 1024 \
-smp 4 \
-serial stdio \
-hda sys.qcow2 \
-usb \
-device usb-kbd \
-device usb-tablet \
-device usb-net,netdev=ulan \
-netdev user,id=ulan,hostfwd=tcp::2222-:22 \
-display none \
-no-reboot
2] boot the virtualized rpi:
# ./run.sh
-----------------------------------------------------------