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 have successfully installed an app that I needed within this for a long time but only yesterday finally got to work within this QEMU, redroid, so I am documenting the steps here. I haven't got GPU acceleration working in this so its graphics are a lot slower than the Arch Linux ARM emulator itself, but it works with software rendering.
Prerequisites
hostfwd=tcp::5555-:5555
setting to forward theadb
port through QEMU forscrcpy
Build necessary kernel
Install Docker
sudo pacman -S docker sudo systemctl enable --now docker
Install and run redroid
sudo docker run -itd --privileged -v ~/redroid-data:/data -p 5555:5555 -p 8022:8022 --name redroid redroid/redroid:14.0.0_64only-latest
Important
There is one step during redroid's boot that sometimes takes an extremely long time within the emulator. The longest I had to wait was 7 hours and then it eventually booted fully. You can use
dmesg -w
within QEMU to monitor redroid's boot progress (and compare it with the kernel log of a native redroid instance outside the emulator to see what point you're at)Install
scrcpy
on the hostamd64
OS and connect to the emulated redroidNote
These commands can be run outside the emulator