QEMU Board Emulation introduction with Cubieboard
- March 24, 2024
Why QEMU?
There are many cheap COTS (Commercial Off-The-Shelf) development boards available for playing with and learning Embedded linux: Raspberry Pi, BeagleBone, OrangePi …
The benefit of using COTS platform is that there are A LOT of available resources and examples, so one can create (mostly) functional prototype in a very short time. And this is good for someone who needs a quick solution for some problem without the need to go into all the details.
However, for someone who wishes to go deeper into Embedded linux, boot process, optimization, driver development, etc, the COTS platform can provide only limited experience. Yes, one can develop drivers for some devices connected over external serial busses (even though someone has probably already developed a driver for that device), but that is about everything that can be done. There is no playing with memory maps, system-level device tree, bootloader adjustment, i.e. all of the things that are done when a custom board needs to be brought up.
One solution is to use development board based on SoC which combines Hard CPU core and FPGA parts, like Xilinx Zynq or Altera Cyclone. This SoC allows custom memory mapped hardware to be developed, which would require the developer to create a novel driver and learn a lot in the process. However, the ‘creative’ process is limited only to certain devices, not the system as a whole.
This is where QEMU (Quick EMUlator) can be very useful. QEMU has been used in industry during the design stage for new SoCs, since software development can be done before the hardware is not production ready (ZynqMP, RiscV).
QEMU has support for various development boards and devices, but new devices and development boards can be created with ease. For instance, one can create a new platform or I2C device, new system on chip with completely new memory map, or even new architecture (ok, highly unlikely that someone will go this far for educational purposes, but it is possible).
In this post, the goal is to show the steps for setting up and running QEMU for the first time. The Cubieboard is chosen since it has support for loading bootloader from an emulated SD card image, so the process of running an image is very close to using the real hardware.
Getting QEMU
Before we start with the development, prerequisites need to be installed.
I am using Ubuntu 22.04 as the host system, so if different system is used it is possible that some additional packages from prerequisites need to be installed.
# Installing prerequisites
sudo apt -y install git libglib2.0-dev libfdt-dev libpixman-1-dev \
zlib1g-dev libnfs-dev libiscsi-dev git-email libaio-dev \
libbluetooth-dev libbrlapi-dev libbz2-dev libcap-dev \
libcap-ng-dev libcurl4-gnutls-dev libgtk-3-dev libibverbs-dev \
libjpeg8-dev libncurses5-dev libnuma-dev librbd-dev \
librdmacm-dev libsasl2-dev libsdl2-dev libseccomp-dev \
libsnappy-dev libssh2-1-dev libvde-dev libvdeplug-dev \
libxen-dev liblzo2-dev valgrind xfslibs-dev kpartx libssl-dev \
net-tools python3-sphinx python3-sphinx-rtd-theme libsdl2-image-dev \
flex bison libgmp3-dev libmpc-dev device-tree-compiler u-boot-tools \
bc git libncurses5-dev lzop make tftpd-hpa uml-utilities \
nfs-kernel-server swig ninja-build libusb-1.0-0-dev python3-venv
The development will be done in the $HOME/work/
directory.
Building QEMU
The latest stable version at the time of writing is 8.2.2.
Downloading source code
The QEMU emulator source code can be obtained as an archive from here using following commands
wget -c https://download.qemu.org/qemu-8.2.2.tar.xz
tar xf qemu-8.2.2.tar.xz && mv qemu-8.2.2 qemu
cd qemu
Configuring and building
Before building QEMU, it needs to be configured. In this process various options can be selected. For these posts following configuration command will be used
# configuration
mkdir -p build && cd build
../configure --target-list=arm-softmmu \
--enable-sdl \
--enable-tools \
--enable-fdt \
--enable-libnfs
After the configuration step is done, code can be compiled using
make -j
The output files will be in ./arm-softmmu
directory, where the most import one is qemu-system-arm
. The tools, like
qemu-img
, will be in the ./
directory. We need to add those directories to the $PATH
before we can use them
export PATH=$HOME/work/qemu/build/arm-softmmu:$HOME/work/qemu/build:$PATH
Running QEMU
Before we can run QEMU, we need an appropriate software. For this post we will use OpenWRT SD card image for Cubieboard, which can be obtained from here.
wget -c https://downloads.openwrt.org/releases/23.05.3/targets/sunxi/cortexa8/openwrt-23.05.3-sunxi-cortexa8-cubietech_a10-cubieboard-ext4-sdcard.img.gz -O cubieboard-openwrt.img.gz
gunzip cubieboard-openwrt.img.gz
QEMU requires the image to have a size which is a power of 2, so we will use qemu-img
tool to resize the image. This
image is little under 128 MB, so we will resize it to 256 MB to be on the safe side.
qemu-img resize cubieboard-openwrt.img 256M
After we have the image ready, we can start the execution using
qemu-system-arm -M cubieboard -m 1G -drive file=cubieboard-openwrt.img,format=raw,if=sd -serial mon:stdio
U-Boot SPL 2020.07-OpenWrt-r23809-234f1a2efa (Mar 22 2024 - 22:09:42 +0000)
DRAM: 1024 MiB
CPU: 1008000000Hz, AXI/AHB/APB: 3/2/2
Trying to boot from MMC1
U-Boot 2020.07-OpenWrt-r23809-234f1a2efa (Mar 22 2024 - 22:09:42 +0000) Allwinner Technology
CPU: Allwinner A10 (SUN4I)
Model: Cubietech Cubieboard
[snip]
Starting kernel ...
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 5.15.150 (builder@buildhost) (arm-openwrt-linux-muslgnueabi-gcc (OpenWrt GCC 12.3.0 r23809-234f1a2efa) 12.3.0, GNU ld (GNU Binutils) 2.40.0) #0 SMP Fri Mar 22 22:09:42 2024
[ 0.000000] CPU: ARMv7 Processor [410fc080] revision 0 (ARMv7), cr=10c5387d
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
[ 0.000000] OF: fdt: Machine model: Cubietech Cubieboard
[snip]
Please press Enter to activate this console.
BusyBox v1.36.1 (2024-03-22 22:09:42 UTC) built-in shell (ash)
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
|_______|| __|_____|__|__||________||__| |____|
|__| W I R E L E S S F R E E D O M
-----------------------------------------------------
OpenWrt 23.05.3, r23809-234f1a2efa
-----------------------------------------------------
=== WARNING! =====================================
There is no root password defined on this device!
Use the "passwd" command to set up a new password
in order to prevent unauthorized SSH logins.
--------------------------------------------------
root@OpenWrt:/#
And that is all!
We can see U-Boot (bootloader) running, then starting up Linux kernel and getting to the serial prompt.
Summary and further work
This was a simple introduction to using QEMU Board Emulation to run Linux on Cubieboard and it is just a beginning.
QEMU provides many more options and some very interesting things can be done with it, especially if one is looking to understand bootloaders and linux.
For more detailed instructions you can go to the tutorial located here.
Thanks for your time! If you have any questions or comments you can reach me using the links at the bottom.