This guide is for building your own Arch Linux ARM VM image and runnig in QEMU, UTM, Parallels...
1. qemu-img
2. fdisk
3. kpartx
4. bsdtar
5. wget
6. if you are using QEMU, you may need EFI BIOS code from https://github.com/qemu/qemu/raw/master/pc-bios/edk2-aarch64-code.fd.bz2
7. you also need the alarm (Arch Linux ARM build files) from http://os.archlinuxarm.org/os/ArchLinuxARM-aarch64-latest.tar.gz
qemu-img create archlinux.img 32GB
Format the image into two partition: 1. 200M(+) vfat for EFI (use t
in fdisk
to add label for EFI); 2. rest space ext4 for root file system
fdisk archlinux.img
Become root
sudo -s
Read partition info and map to devices
kpartx -av archlinux.img
ls /dev/mapper
format partition refer to ls
output
mkfs.vfat /dev/mapper/loop0p1
mkfs.ext4 /dev/mapper/loop0p2
mount partition and extract files from tarball
mkdir root
mount /dev/mapper/loop0p2 root
mkdir root/boot
mount /dev/mapper/loop0p1 root/boot
bsdtar -xpf ArchLinuxARM-aarch64-latest.tar.gz -C root
edit fstab
for kernel reading and startup.nsh
for EFI shell
# show UUID for both partitions
# the vfat partition looks like: UUID="XXXX-XXXX"
# and the ext4 one looks like UUID="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
blkid
# 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/etc/fstab
# The startup.nsh is read by the EFI as a last resort. We need this to be able to do the initial boot.
nano root/boot/startup.nsh
# 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
unmount and exit
umount root/boot
umount root
kpartx -d archlinux.img
sync
exit
- create a Linux vm using virtualization
use qemu not hypervisor framework of apple (Arch Linux ARM not support M1, thus need qemu to emulate (Cortex-a72 works fine))- use OpenGL if you need DE
- edit setting -> disk -> delete all the disks -> add a new one (virtio) -> import ->select your image you created in Linux (why? Because UTM creates the images as CDROM not DISK by default, this cause the image NOT writable) (using this method, UTM will create a new disk image from origianl one, and this one is writable, and you can resize it on your need)
- change the cpu from default to Cortex-A72 (an ARM64 CPU, same as raspberry pi 4b(?) which is supported by alarm)
- install
qemu
frombrew
or build your own, then, you may needsudo
for creatingnetdev
- prepare image for UEFI BIOS and an additional image for saving BIOS settings:
(if you installed qemu using homebrew) the
dd if=/dev/zero of=pflash0.img bs=1m count=64 dd if=/dev/zero of=pflash1.img bs=1m count=64 dd if=edk2-aarch64-code.fd of=pflash0.img conv=notrunc dd if=edk2-arm-vars.fd of=pflash1.img conv=notrunc
.fd
files is located under/opt/homebrew/Cellar/qemu/<version-of-qemu>/share/qemu/
- following script will create a
- 8 core cpu with host CPU features enabled
- RAM for 16GB
- Using
virt
(alias of newest virt machine) to emulate - Accelation not using
kvm
buthvf
(Apple's new Hypervisor Framework) - Network card: virtio-net-pci (user network (can access internet, but cannot detected by other guests))
- Video card: virtio-gpu-pci (OpenGL currently not supported in brew version of qemu)
- Virtual display: using cocoa backend (default under MacOS)
- Usb bus & controller & tablet & mouse & keyboard
- Disk device: virtio-blk-pci
- aarch64 uefi app from qemu, and use a additional image to save bios settings
- A serial device if you need
qemu-system-aarch64 \
-cpu host \
-smp cpus=8,sockets=1,cores=8,threads=1 \
-machine virt \
-accel hvf \
-m 16384 \
-device virtio-net-pci,mac=<your-own-mac-address>,netdev=net0 \
-netdev user,id=net0 \
-device virtio-gpu-pci \
-display cocoa,showcursor=on \
-device nec-usb-xhci,id=usb-bus \
-device usb-tablet,bus=usb-bus.0 \
-device usb-mouse,bus=usb-bus.0 \
-device usb-kbd,bus=usb-bus.0 \
-device qemu-xhci,id=usb-controller-0 \
-device virtio-blk-pci,drive=<your-drive-ID>,bootindex=0 \
-drive if=none,media=disk,id=<your-drive-ID>,file=<path-to-your-image>,discard=unmap,detect-zeroes=unmap -device virtio-rng-pci \
-device virtio-serial-pci \
-drive if=pflash,format=raw,unit=0,file=<path-to-your-efi-app-image(plash0.img)>,readonly=on \
-drive if=pflash,format=raw,file=<path-to-your-efi-var-image(plash1.img)>
if you want to use serial but not display (add -nographic
flag after above)
Parallels can run vhdx image from the create panel.
qemu-img convert -O vhdx archlinux.img archlinux.vhdx
Now you should get into efi shell and the efi shell will read the startup.nsh
and boot into Arch Linux (please do follow https://archlinuxarm.org/platforms/armv8/generic to initialize the pacman keys and read about others info)
(for Parallels: Boot Manager -> UEFI shell)
- UTM has a experiential OpenGL video card (need SPICE tools, and graphic performance quite poor (only ~200fps in
glmark2
)) - qemu is more flexible (no GPU accerlation)
- paralell is paid but simple (with Hardware Accerlation, has
80009000+ FPS inglmark2
, same as other Linux Distro)
Grub:
- the first boot can be loaded by
startup.nsh
, if you want to use bootloader likegrub
, installaarch64
version grub and select the.efi
file under ESP in BIOS to add it to the boot options.
- thalamus/ArchLinuxARM-M1: https://gist.github.com/thalamus/561d028ff5b66310fac1224f3d023c12
- ctsrc/README.md: https://gist.github.com/ctsrc/a1f57933a2cde9abc0f07be12889f97f