Running a USB Update in QEMU¶
This guide covers building a SWUpdate package, placing it on a USB storage device, and triggering a USB update on a ToloMEO QEMU image using QEMU's USB hot-plug mechanism.
Table of Contents¶
- Running a USB Update in QEMU
- Table of Contents
- Prerequisites
- Build the Update Package
- Prepare USB Storage
- Prepare the Working Directory
- Run QEMU
- Simulate USB Insertion
- Monitor the Update
Prerequisites¶
- QEMU installed with
qemu-system-x86_64available socatinstalled on the host:- QEMU boot artifacts already available (see
meta-tolomeo-qemu/README.md) - An image built with
update-localinDISTRO_FEATURES(see Configure Update Modes)
Build the Update Package¶
Build a full SWUpdate package from inside the devcontainer:
The recipe uses the stable,update software selection and targets /dev/vdb via GPT partition swap.
After the build completes, the .swu package is collected under:
artifacts/tolomeo-qemux86-64/image-prod/<version>/updates/imgen-update-full/
└── imgen-update-full-tolomeo-qemux86-64.rootfs.swu
Prepare USB Storage¶
The .swu package must be placed at the root of a FAT filesystem on a USB storage device. Use either
a real USB stick or a disk image file.
Option A — real USB stick:
Copy the package to the root of the USB stick:
cp artifacts/tolomeo-qemux86-64/image-prod/<version>/updates/imgen-update-full/imgen-update-full-tolomeo-qemux86-64.rootfs.swu /media/<mount>/
sync
Option B — disk image file:
Create a FAT image and copy the package onto it:
dd if=/dev/zero of=usb-stick.img bs=1M count=128
mkfs.vfat usb-stick.img
mcopy -i usb-stick.img \
artifacts/tolomeo-qemux86-64/image-prod/<version>/updates/imgen-update-full/imgen-update-full-tolomeo-qemux86-64.rootfs.swu \
::imgen-update-full-tolomeo-qemux86-64.rootfs.swu
Prepare the Working Directory¶
Your working directory should contain the following before launching QEMU:
.
├── bzImage
├── image-prod-tolomeo-qemux86-64.rootfs.ext4
├── qemu-disk.img # provisioned disk with certificates
├── shared/ # local directory for shared mount
└── usb-stick.img (or a real block device)
Create the shared directory if it does not exist:
Run QEMU¶
Launch the VM with the QEMU monitor socket enabled and the USB storage backend declared. The -drive if=none option makes
the storage available to QEMU without exposing it to the guest immediately — the hot-plug step in the next section attaches
it as a USB device at runtime.
Replace usb-stick.img with your real block device path (e.g. /dev/sde) if using a physical USB stick.
qemu-system-x86_64 \
-kernel bzImage \
-append 'root=/dev/vda rw mem=1024M ip=dhcp console=ttyS0 console=ttyS1 oprofile.timer=1 tsc=reliable no_timer_check rcupdate.rcu_expedited=1 swiotlb=0' \
-drive file=image-prod-tolomeo-qemux86-64.rootfs.ext4,if=virtio,format=raw \
-drive file=qemu-disk.img,if=virtio,format=raw,id=qemu-disk \
-drive file=usb-stick.img,if=none,id=usb-stick,format=raw \
-virtfs local,path=shared,mount_tag=shared,security_model=mapped-xattr \
-device virtio-net-pci,netdev=net0,mac=52:54:00:12:35:02 \
-netdev user,id=net0,hostfwd=tcp:127.0.0.1:2222-:22,hostfwd=tcp:127.0.0.1:2323-:23 \
-object rng-random,filename=/dev/urandom,id=rng0 \
-device virtio-rng-pci,rng=rng0 \
-cpu IvyBridge -machine q35,i8042=off \
-smp 4 -m 1024 \
-usb -device usb-tablet -usb -device usb-kbd \
-monitor unix:/tmp/qemu-monitor.sock,server,nowait \
-serial mon:stdio -serial null -nographic
KVM acceleration: Add
-enable-kvmfor better performance. This may requiresudodepending on your system configuration.Real block device access: Passing a physical block device (e.g.
/dev/sde) requires read access to that device, which typically requiressudo.
Simulate USB Insertion¶
Once the VM has fully booted, run the following script on the host to hot-plug the USB storage device
into the guest. QEMU exposes it as a USB mass storage device and the guest udev rules fire
swupdate-usb@<device>.service automatically.
#!/bin/bash
SOCK=/tmp/qemu-monitor.sock
# Wait for the QEMU monitor socket to become available
echo "Waiting for QEMU monitor socket..."
until [ -S "$SOCK" ]; do sleep 1; done
echo "Monitor ready."
# Wait for the guest to finish booting before hot-plugging.
# Increase this value if udev does not fire — the guest may still be initialising.
sleep 15
echo "Hot-plugging USB stick..."
echo 'device_add usb-storage,drive=usb-stick,id=stick0' | socat - "UNIX-CONNECT:$SOCK"
echo "Done. udev should fire swupdate-usb@<device>.service inside the guest."
Save the script (e.g. as hotplug-usb.sh), make it executable, and run it from a second terminal while QEMU is running:
Monitor the Update¶
Connect to the running VM via SSH to watch the update progress:
Inside the guest, follow the swupdate service log:
A successful update writes upgrade_available=1 to the boot environment and reboots the VM into the
new image. After the VM restarts, confirm the rollback guard was cleared:
The value should be unset once the new image has booted and confirmed itself healthy.