Skip to content

Instantly share code, notes, and snippets.

@thalamus
Last active March 11, 2024 16:55
Show Gist options
  • Save thalamus/561d028ff5b66310fac1224f3d023c12 to your computer and use it in GitHub Desktop.
Save thalamus/561d028ff5b66310fac1224f3d023c12 to your computer and use it in GitHub Desktop.
How to boot Arch Linux ARM in QEMU (patched for M1)
/*
* This document is provided to the public domain under the
* terms of the Creative Commons CC0 public domain license
*/
How to boot Arch Linux ARM in QEMU (patched for M1)
Prerequisites:
QEMU - patched for M1 processors - patches: https://github.com/utmapp/qemu
A working linux distribution of some description.
I personally used Ubuntu 20.10 ARM64 running in Parallels TP to carry out this originally,
but any should work, and it doesn't have to be ARM64.
The following software on said linux system:
qemu-img
fdisk
kpartx
bsdtar
wget
Additionally, if you wish to use QEMU you may need to download this on your M1 Mac
EFI BIOS - https://github.com/qemu/qemu/raw/master/pc-bios/edk2-aarch64-code.fd.bz2
if you have installed QEMU from source, it will be located in the 'share' folder within
the installation prefix.
Knowledge of the command line.
Commands prefixed with $ are ran as a normal user and those prefixed # require root.
$ sudo -s is a suitable way of getting root.
1) Create a suitable directory, download the Arch tarball and create the raw image:
$ mkdir ~/alarm
$ cd ~/alarm
$ wget http://os.archlinuxarm.org/os/ArchLinuxARM-aarch64-latest.tar.gz
$ qemu-img create archlinux.img 32GB
2) Partition the image with fdisk:
$ fdisk archlinux.img
- then g (to create a new GPT partition table)
- then n (to create a new partition), then enter twice, then +200M and enter
- then t (to change the type), then 1 for EFI System Partition
- then n and enter three times, then w to write changes and exit
3) Become root, create the loop devices and format the partitions of the image.
$ sudo -s
# kpartx -av archlinux.img
# ls /dev/mapper - you should see two new devices - something like loop6p1 / loop6p2
# mkfs.vfat /dev/mapper/loop6p1
# mkfs.ext4 /dev/mapper/loop6p2
4) Mount the partitions and extract the Arch Linux ARM tarball to them.
# mkdir root
# mount /dev/mapper/loop6p2 root
# mkdir root/boot
# mount /dev/mapper/loop6p1 root/boot
# bsdtar -xpf ArchLinuxARM-aarch64-latest.tar.gz -C root
5) Edit /etc/fstab and create /boot/startup.nsh files.
# blkid
- you'll need the UUID for both partitions - the vfat partition looks like: UUID="XXXX-XXXX"
and the ext4 one looks like UUID="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
# nano root/etc/fstab
Paste the following (with the correct UUIDs to suit your system of course:
/dev/disk/by-uuid/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX / ext4 defaults 0 0
/dev/disk/by-uuid/XXXX-XXXX /boot vfat defaults 0 0
# nano root/boot/startup.nsh
The startup.nsh is read by the EFI as a last resort. We need this to be able to do the initial boot.
This should look exactly like this (with the correct UUID for the ext4 partition):
Image root=UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX rw initrd=\initramfs-linux.img
6) Unmount the partitions and exit from the root shell.
# umount root/boot
# umount root
# kpartx -d archlinux.img
# sync
# exit
7) Convert the image to a qcow2 (optional, but much smaller), and create flash partitions with EFI BIOS.
$ qemu-img convert -O qcow2 archlinux.img archlinux.qcow2
- then move the image to your M1 Mac filesystem
In the Mac terminal - do the following:
$ truncate -s 64M flash0.img (this is for the EFI BIOS)
$ truncate -s 64M flash1.img (this is to store EFI variables)
- Unzip the EFI Bios file
$ dd if=/path/to/edk2-aarch64-code.fd of=flash0.img conv=notrunc
- Put the flash0.img, flash1.img and archlinux.qcow2 into a suitable folder.
Use a command similar to this to boot the VM:
qemu-system-aarch64 -L ~/bin/qemu/share/qemu \
-smp 8 \
-machine virt,accel=hvf,highmem=off \
-cpu cortex-a72 -m 4096 \
-drive "if=pflash,media=disk,id=drive0,file=flash0.img,cache=writethrough,format=raw" \
-drive "if=pflash,media=disk,id=drive1,file=flash1.img,cache=writethrough,format=raw" \
-drive "if=virtio,media=disk,id=drive2,file=archlinux.qcow2,cache=writethrough,format=qcow2" \
-nic user,model=virtio-net-pci,hostfwd=tcp::50022-:22 -nographic \
-device virtio-rng-device -device virtio-balloon-device -device virtio-keyboard-device \
-device virtio-mouse-device -device virtio-serial-device -device virtio-tablet-device \
-object cryptodev-backend-builtin,id=cryptodev0 \
-device virtio-crypto-pci,id=crypto0,cryptodev=cryptodev0
- QEMU should boot the VM automatically after dropping to the EFI shell.
8) Upon successful first boot, login as root, password root
You now need to get pacman up and running, update the system and install efibootmgr:
# pacman-key --init
# pacman-key --populate archlinuxarm
# pacman -Syu
# pacman -S efibootmgr
We now need to create the EFI boot entry:
# blkid - you'll need the UUID for vda2
# efibootmgr --disk /dev/vda --part 1 --create --label "Arch Linux ARM" --loader /Image --unicode 'root=UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX rw initrd=\initramfs-linux.img' --verbose
- you should get output which shows a list of the boot entries.
9) Poweroff and boot the system again
# poweroff
- start the QEMU VM
- this time it should just boot without dropping into an EFI shell.
10) Post Install notes
Arch Linux ARM is a bit basic out of the box - you will probably want to set a suitable locale,
create a user and install some useful stuff,
You'll find info on doing all of that on the Arch Wiki - https://wiki.archlinux.org
- which, in my opinion, is one of the best distro wikis available.
This was originally written up mainly from memory and bash history - but the missing bits have been added!
Edited on 10/08/2021 to remove all references to Parallels - use QEMU instead.
@thalamus
Copy link
Author

thalamus commented Jun 3, 2022

Not sure. You're following a different set of steps for the most part so it's difficult to know. I know that the instructions given above don't have that issue, so it's whatever you're doing.

I would guess the issue is the boot order in the UEFI bios - try putting PXE as the last one, but other than that, you're on your own I'm afraid.

@bantling
Copy link

bantling commented Jun 4, 2022

Actually, it's exactly the same steps - I'm just using a Linux VM rather than a physical machine to create the image file, partition it, make the filesystems, and extract the base image to it. It's still Linux creating the file with the same tools. Maybe you used a different Linux distro, but that doesn't matter.

Judging by the dating of this article, it is probably written for QEMU 6.2, and I am using 7.0, which does cause some known issues on Mac OS as I am finding, so that is probably the real difference.

I read at utmapp/UTM#2333 that using the ESC key can allow quickly bypassing the delay and going straight to the EFI shell. This did in fact work for me in two ways:

  • If I hit ESC during the EFI loader progress bar, I get the OVMF EFI shell (same one VirtualBox uses), and can choose EFI Shell.
  • If I wait until the error appears, I can get the EFI shell.

So it seems I'm probably right about some kind of UEFI boot order issue. I've tried various things I found online, and none of them seem to work, so I'm going with QEMU 7 is doing something different that somehow affects EFI. I have a work around that does not require waiting a couple of minutes, so am satisfied for now :)

@bantling
Copy link

I found the solution, and wrote a self-contained script to automate the process, it takes about 5 minutes to run, and all you have to is download and run the script, and follow a few manual steps. See https://github.com/bantling/tools/tree/master/qemu-vms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment