Hello, UEFI
Warning
Please make sure you've completed all the setup steps before proceeding with this tutorial. We will be working inside the development container, so ensure that you can run it and connect to it via SSH.
Before we start, we need to configure our QEMU virtual machine and set up UEFI firmware to run on the VM.
QEMU
To run an AArch64 virtual machine using QEMU, we will be using the qemu-system-aarch64 binary. Inside the container, it should be available in PATH by default.
First, we'll need to set some basic parameters. These are configured using flags passed to the QEMU executable:
-
Machine type (
-machine):virt– a generic PC-like system. This is a versioned machine, where breaking changes can occur with new QEMU versions, so we explicitly specify version 8.2 (latest as of writing) for reproducibility. -
CPU model (
-cpu):cortex-a72– ARM Cortex-A72, a common AArch64 processor. It is not particularly important which one we use, but, for reasons beyond my understanding, a QEMU executable built specifically for AArch64, a 64-bit architecture, still defaults to a 32-bit CPU model, meaning that we have to specify a 64-bit one explicitly. -
CPU core count (
-smp):1– we will only be using one core for now. -
RAM amount (
-m):1024– 1GiB, this should be more than enough for our purposes. -
Disable graphical output (
-nographic): we'll start out with a simple shell-based interface, so we don't need a graphical window. -
Disconnect networking devices (
-nic):none– we won't connect any networking hardware to the VM for now, so we can disable it to simplify our configuration. This needs to be specified explicitly to override the default networking configuration that comes with thevirtmachine type.
Your final command should look like this:
This will start a VM with the specified parameters, which will do nothing – we've not given it any code to run yet.
QEMU will redirect all keyboard input in the terminal to the VM, so you'll need to use an escape sequence, Ctrl+A, to access QEMU commands. Press that, followed by X, to stop and exit the VM.
UEFI
Most real machines supporting UEFI will have their own UEFI firmware, provided and, usually, pre-installed by the manufacturer. When using QEMU, however, we need to provide our own.
We will be using AAVMF, an AArch64 build of TianoCore EDK II, specifically configured for QEMU. EDK II is an open-source cross-platform implementation of the UEFI standard by Intel.
AAVMF should already be installed in the container and available at /usr/share/AAVMF/. The installation includes a few files: binaries and variable stores in various configurations. We are only interested in two:
AAVMF_CODE.fd– the UEFI binary, configured to run without secure boot (simplest option).AAVMF_VARS.fd– a variables file, holding persistent UEFI configuration, configured with defaults.
The first file is just code, so we can mount it as read-only and share it between any number of VMs. The second one, however, will be modified as we make changes to the UEFI configuration, so we'll need to have our own copy:
# This will be the directory for files related to the VM
mkdir -p qemu
cp /usr/share/AAVMF/AAVMF_CODE.fd qemu/AAVMF_CODE.fd
Connect both of these files to our virtual machine as system flash memory (this is the role fulfilled by the motherboard EEPROM in a real machine) with the -drive flag. As both files are raw binaries, we will also need to specify the raw format. Finally, mark the firmware as read-only to avoid any accidental changes.
qemu-system-aarch64 -machine virt -cpu cortex-a72 -smp 1 -m 1024 -nographic -nic none \
-drive if=pflash,format=raw,readonly=on,file=/usr/share/AAVMF/AAVMF_CODE.fd \
-drive if=pflash,format=raw,file=qemu/AAVMF_VARS.fd
After you run this command, the VM should boot into the UEFI firmware, which will look for a drive to boot from. Not finding any (because we've not set one up yet), it will drop to the UEFI shell. This is a bare-bones command line interface for interacting with the UEFI firmware. The output should look something like this:
UEFI Interactive Shell v2.2
EDK II
UEFI v2.70 (EDK II, 0x00010000)
map: No mapping found.
Press ESC in 1 seconds to skip startup.nsh or any other key to continue.
Shell>
Alternatively, you can start mashing the Esc key as soon as you start the VM. This will open a graphical UEFI configuration menu, which you can explore. Any changes you make here will be saved to the AAVMF_VARS.fd file and will persist across reboots. You can overwrite this file with a copy of the default configuration to reset the UEFI settings at any time.
To get to the UEFI shell from the graphical menu, navigate to the Boot Manager option and select EFI Internal Shell.