Prerequisites:
- A PC with a Linux distribution - Arch Linux
amd64
used here
Dependencies (for Arch Linux amd64
):
edk2-armvirt
qemu-arch-extra
wget
gvim
openssh
- Download the Arch Linux ARM generic tarball and create an image, replacing
60G
with your desired maximum size.
$ wget http://os.archlinuxarm.org/os/ArchLinuxARM-aarch64-latest.tar.gz
$ qemu-img create -f qcow2 archlinuxarm.qcow2 60G
- Become
root
, connect the image tonbd
and partition it withfdisk
.
$ sudo su
# modprobe nbd
# qemu-nbd --connect=/dev/nbd0 archlinuxarm.qcow2
# fdisk /dev/nbd0
- then
g
(to create a new GPT partition table) - then
n
(to create a new partition), then Enter twice, then+400M
and Enter - then
t
(to change the type), then1
for EFI System Partition - then
n
and Enter three times, thenw
to write changes and exit
- Format the partitions of the image, mount them, and extract the Arch Linux ARM tarball to them.
# mkfs.vfat /dev/nbd0p1
# mkfs.ext4 /dev/nbd0p2
# mkdir rootfs
# mount /dev/nbd0p2 rootfs
# mkdir rootfs/boot
# mount /dev/nbd0p1 rootfs/boot
# bsdtar -xpf ArchLinuxARM-aarch64-latest.tar.gz -C rootfs
- Edit
fstab
.
- You will need both partitions' UUIDs - the UUID of the
vfat
partition in/dev/nbd0p1
looks likeUUID="XXXX-XXXX"
and the UUID of theext4
partition in/dev/nbd0p2
looks likeUUID="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
:
# blkid
- Then, edit
rootfs/etc/fstab
:
# vim rootfs/etc/fstab
- Paste the following, replacing each instance of
X
with the corresponding digit of the UUID of the corresponding partition,/dev/nbd0p1
and/dev/nbd0p2
respectively, then save the file:
/dev/disk/by-uuid/XXXX-XXXX /boot vfat defaults 0 0
/dev/disk/by-uuid/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX / ext4 defaults 0 0
- Create
startup.nsh
, which is read by the UEFI firmware to initially boot.
- Edit
rootfs/boot/startup.nsh
:
# vim rootfs/boot/startup.nsh
- Paste the following, replacing each instance of
X
with the corresponding digit of the UUID of the/dev/nbd0p2
partition, then save the file:
Image root=UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX rw initrd=\initramfs-linux.img
- Unmount the partitions,
sync
, disconnect the image fromnbd
, and exit theroot
shell.
# umount -R rootfs
# sync
# qemu-nbd --disconnect /dev/nbd0
# rmmod nbd
# exit
- Create flash images for the UEFI firmware and variables:
$ truncate -s 64M flash0.img
$ truncate -s 64M flash1.img
$ dd if=/usr/share/edk2-armvirt/aarch64/QEMU_CODE.fd of=flash0.img conv=notrunc
- Launch QEMU, removing or adding anything you see fit.
$ qemu-system-aarch64 -M virt -m 8192 -cpu cortex-a72 -smp 8 \
-drive if=pflash,media=disk,format=raw,cache=writethrough,file=flash0.img \
-drive if=pflash,media=disk,format=raw,cache=writethrough,file=flash1.img \
-drive if=none,file=archlinuxarm.qcow2,format=qcow2,id=hd0 \
-device virtio-scsi-pci,id=scsi0 \
-device scsi-hd,bus=scsi0.0,drive=hd0,bootindex=1 \
-nic user,model=virtio-net-pci,hostfwd=tcp::2222-:22 \
-monitor none -display none -vga none
- Upon successful first boot, initialize Arch Linux ARM and install a new bootloader.
- Log in as
alarm
, passwordalarm
:
$ ssh -p 2222 alarm@localhost
- Become
root
, passwordroot
:
$ su
- Initialize the
pacman
keyring, update the system and installefibootmgr
, replacing each instance ofX
with the corresponding digit of the UUID of the/dev/nbd0p2
partition from earlier (which is now/dev/sda2
), then shut down:
# pacman-key --init
# pacman-key --populate archlinuxarm
# pacman -Syu
# pacman -S efibootmgr
# efibootmgr --disk /dev/sda --part 1 --create --label "Arch Linux ARM" --loader /Image --verbose \
--unicode 'root=UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX rw initrd=\initramfs-linux.img'
# poweroff
- Launch QEMU again, exactly as in step 8.
$ qemu-system-aarch64 -M virt -m 8192 -cpu cortex-a72 -smp 8 \
-drive if=pflash,media=disk,format=raw,cache=writethrough,file=flash0.img \
-drive if=pflash,media=disk,format=raw,cache=writethrough,file=flash1.img \
-drive if=none,file=archlinuxarm.qcow2,format=qcow2,id=hd0 \
-device virtio-scsi-pci,id=scsi0 \
-device scsi-hd,bus=scsi0.0,drive=hd0,bootindex=1 \
-nic user,model=virtio-net-pci,hostfwd=tcp::2222-:22 \
-monitor none -display none -vga none
- Proceed with configuring Arch Linux ARM as normal (time, locales, users, software, configuration), using the Arch Linux Wiki as a guide.
I'm glad to hear that!
I'm not sure whether you'd need this at all, but this QEMU has some very useful OpenGL acceleration capabilities that I never really explained here before either, and at least for me, there is a quirk with it I can explain that causes it to seem stuck in a permanent multiseat mode. That is to say, It might seem like you can't interact your keyboard with the QEMU window itself, and have to use
ssh
. But the real truth is that you can if you add certain types of QEMU arguments - and for me, it's only worked with a second keyboard/mouse plugged into the host!Here are my current QEMU arguments for an Emulator with virgl OpenGL passthrough to real GPU and multiseat input with a USB mouse and keyboard.
#!/bin/bash qemu-system-aarch64 -M virt \ -m 16384 \ -cpu cortex-a72 \ -smp 32 \ -drive if=pflash,media=disk,format=raw,cache=writethrough,file=flash0.img \ -drive if=pflash,media=disk,format=raw,cache=writethrough,file=flash1.img \ -drive if=none,file=archarmvm.qcow2,format=qcow2,id=hd0 \ -device virtio-scsi-pci,id=scsi0 \ -device scsi-hd,bus=scsi0.0,drive=hd0,bootindex=1 \ -nic user,model=virtio-net-pci,hostfwd=tcp::2222-:22,hostfwd=tcp::5555-:5555 \ -device virtio-rng-device \ -device virtio-balloon-device \ -device virtio-serial-device \ -device virtio-tablet-device \ -object cryptodev-backend-builtin,id=cryptodev0 \ -device virtio-crypto-pci,id=crypto0,cryptodev=cryptodev0 \ -device virtio-gpu-gl-pci,xres=1280,yres=1024 \ -display sdl,gl=on \ -device qemu-xhci,id=xhci \ -device usb-host,bus=xhci.0,hostdevice=/dev/bus/usb/003/009 \ -device usb-host,bus=xhci.0,hostdevice=/dev/bus/usb/003/010
When I change the USB port that the keyboard or mouse is plugged into, or sometimes update the host OS which can also change how those numbers are assigned, I use the
lsusb -tvv
command on the host to find their new device file paths, by finding the paths associated with the names of the USB devices that match their manufacturers.First, you would make sure the
virglrenderer
package is installed in your host, then the-device virtio-gpu-gl-pci
argument combined with the-display sdl,gl=on
argument should allow the guest to spawn a DRM TTY within the QEMU SDL window which you should then be able to launch Xorg on with OpenGL acceleration using thevirgl
Mesa driver.Unfortunately, it seems like there is a hardware-cursor-rendering-related issue with QEMU and Xorg operating together in this mode. To work around it, I use andykitchen/swcursor in the guest.
Of course, this is all very useless for you if you only need the
ssh
connection and no GUI, but I always wanted to add it as an update here since I feel that it is a very underrated configuration that I've never seen anyone else actually using.