Skip to content

Instantly share code, notes, and snippets.

@levihuayuzhang
Created January 2, 2023 07:20
Show Gist options
  • Save levihuayuzhang/da5b5937cdeb932aedd13a705f831141 to your computer and use it in GitHub Desktop.
Save levihuayuzhang/da5b5937cdeb932aedd13a705f831141 to your computer and use it in GitHub Desktop.
Arch Linux ARM build for M1 (Apple Silicon) VMs

Arch Linux ARM build for M1 (Apple Silicon) VMs

This guide is for building your own Arch Linux ARM VM image and runnig in QEMU, UTM, Parallels...

Preparations in Linux

What you need in Linux phase:

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

Create a image

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 

Now Format partition

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

Back to MacOS

For UTM

  1. create a Linux vm using virtualization
  2. use qemu not hypervisor framework of apple (Arch Linux ARM not support M1, thus need qemu to emulate (Cortex-a72 works fine))
  3. use OpenGL if you need DE
  4. 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)
  5. change the cpu from default to Cortex-A72 (an ARM64 CPU, same as raspberry pi 4b(?) which is supported by alarm)

For QEMU

  1. install qemu from brew or build your own, then, you may need sudo for creating netdev
  2. prepare image for UEFI BIOS and an additional image for saving BIOS settings:
     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
    (if you installed qemu using homebrew) the .fd files is located under /opt/homebrew/Cellar/qemu/<version-of-qemu>/share/qemu/
  3. following script will create a
    1. 8 core cpu with host CPU features enabled
    2. RAM for 16GB
    3. Using virt (alias of newest virt machine) to emulate
    4. Accelation not using kvm but hvf (Apple's new Hypervisor Framework)
    5. Network card: virtio-net-pci (user network (can access internet, but cannot detected by other guests))
    6. Video card: virtio-gpu-pci (OpenGL currently not supported in brew version of qemu)
    7. Virtual display: using cocoa backend (default under MacOS)
    8. Usb bus & controller & tablet & mouse & keyboard
    9. Disk device: virtio-blk-pci
    10. aarch64 uefi app from qemu, and use a additional image to save bios settings
    11. 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)

For Parallels

Parallels can run vhdx image from the create panel.

qemu-img convert -O vhdx archlinux.img archlinux.vhdx

Run

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)

Comparation

  1. UTM has a experiential OpenGL video card (need SPICE tools, and graphic performance quite poor (only ~200fps in glmark2))
  2. qemu is more flexible (no GPU accerlation)
  3. paralell is paid but simple (with Hardware Accerlation, has 80009000+ FPS in glmark2, same as other Linux Distro)

Hints:

Grub:

  1. the first boot can be loaded by startup.nsh, if you want to use bootloader like grub, install aarch64 version grub and select the .efi file under ESP in BIOS to add it to the boot options.

References

  1. thalamus/ArchLinuxARM-M1: https://gist.github.com/thalamus/561d028ff5b66310fac1224f3d023c12
  2. ctsrc/README.md: https://gist.github.com/ctsrc/a1f57933a2cde9abc0f07be12889f97f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment