Last active
July 11, 2023 00:44
-
-
Save mdeanda/b11ba916fb93c9cd438b94c86f03e004 to your computer and use it in GitHub Desktop.
Scripted generation of Arch Linux ARM image to run in QEMU in an Arch Linux host (x86_64)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# Script to build and run Arch Linux ARM in QEMU inside of Arch Linux (x86_64) | |
# | |
# | |
# Original how-to and script from: | |
# * https://gist.github.com/thalamus/561d028ff5b66310fac1224f3d023c12 | |
# * https://git.sr.ht/~whynothugo/m1-vm/tree/main/item/prepare.sh | |
set -euo pipefail | |
TARBALL=ArchLinuxARM-aarch64-latest.tar.gz | |
TARGET_IMAGE_BASE=archlinux | |
TIMEZONE=America/Los_Angeles | |
# Check if all the dependencies are present. | |
check() { | |
which qemu-img > /dev/null && \ | |
which fdisk > /dev/null && \ | |
which kpartx > /dev/null && \ | |
which bsdtar > /dev/null && \ | |
which curl > /dev/null || | |
return 1 | |
} | |
# Install dependencies. | |
install_deps() { | |
DEPS=( | |
curl | |
qemu-headless # qemu-img | |
multipath-tools # kpartx | |
util-linux # fdisk | |
libarchive # bsdtar | |
) | |
# shellcheck disable=SC2068 | |
sudo pacman -S --needed --asdeps ${DEPS[@]} | |
} | |
check || install_deps | |
ls QEMU_EFI.fd 2> /dev/null || curl -LO https://releases.linaro.org/components/kernel/uefi-linaro/latest/release/qemu64/QEMU_EFI.fd | |
dd if=/dev/zero of=flash0.img bs=1M count=64 | |
dd if=QEMU_EFI.fd of=flash0.img conv=notrunc | |
dd if=/dev/zero of=flash1.img bs=1M count=64 | |
ls $TARBALL 2> /dev/null || curl -LO http://os.archlinuxarm.org/os/$TARBALL | |
qemu-img create $TARGET_IMAGE_BASE.img 32G | |
# Partition the disk: | |
sfdisk $TARGET_IMAGE_BASE.img <<EOF | |
label: gpt | |
label-id: 1745B3CF-E63C-4440-8A20-13CC871B5BE8 | |
device: $TARGET_IMAGE_BASE.img | |
unit: sectors | |
first-lba: 2048 | |
last-lba: 67108830 | |
sector-size: 512 | |
$TARGET_IMAGE_BASE.img1 : start= 2048, size= 614400, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B | |
$TARGET_IMAGE_BASE.img2 : start= 616448, size= 66492383, type=B921B045-1DF0-41C3-AF44-4C6F280D3FAE | |
EOF | |
set -x | |
# Treat this image as a block device. | |
# Extract both loop devices from the output. | |
LOOP_DEVS=$(sudo kpartx -av $TARGET_IMAGE_BASE.img | grep -Po 'loop.p.') | |
BOOT_DEV=$(echo "$LOOP_DEVS" | head -n1) | |
ROOT_DEV=$(echo "$LOOP_DEVS" | tail -n1) | |
# Format the partitions | |
sudo mkfs.vfat /dev/mapper/"$BOOT_DEV" | |
sudo mkfs.ext4 /dev/mapper/"$ROOT_DEV" | |
# Mount the partitions | |
mkdir -p root | |
sudo mount /dev/mapper/"$ROOT_DEV" root | |
sudo mkdir -p root/boot | |
sudo mount /dev/mapper/"$BOOT_DEV" root/boot | |
sudo bsdtar -xpf $TARBALL -C root | |
BOOT_UUID=$(lsblk -no uuid /dev/mapper/$BOOT_DEV) | |
ROOT_UUID=$(lsblk -no uuid /dev/mapper/$ROOT_DEV) | |
echo "UUID=$ROOT_UUID / ext4 defaults 0 0" | sudo tee root/etc/fstab | |
echo "UUID=$BOOT_UUID /boot vfat defaults 0 0" | sudo tee -a root/etc/fstab | |
echo "Image root=UUID=$ROOT_UUID rw initrd=\initramfs-linux.img" | \ | |
sudo tee root/boot/startup.nsh | |
cat > first_run.sh << EOF | |
#!/bin/bash | |
set -xe | |
pacman-key --init | |
pacman-key --populate archlinuxarm | |
pacman -Syu --noconfirm | |
pacman -S efibootmgr --noconfirm | |
BLKID=\$(lsblk -no uuid /dev/vda2) | |
efibootmgr --disk /dev/vda --part 1 --create --label "Arch Linux ARM" --loader /Image --unicode "root=UUID=\$BLKID rw initrd=\initramfs-linux.img" --verbose | |
ln -sf /usr/share/zoneinfo/$TIMEZONE /etc/localtime | |
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen | |
locale-gen | |
localectl set-locale LANG=en_US.UTF-8 | |
EOF | |
chmod +x first_run.sh | |
sudo mv first_run.sh root/root/ | |
sudo umount root/boot | |
sudo umount root/ | |
sudo kpartx -d $TARGET_IMAGE_BASE.img | |
sync | |
qemu-img convert -O qcow2 $TARGET_IMAGE_BASE.img $TARGET_IMAGE_BASE.qcow2 | |
rm -rf root $TARGET_IMAGE_BASE.img | |
cat > run.sh << EOF | |
#!/bin/bash | |
qemu-system-aarch64 -m 4096 -smp 2 -cpu cortex-a72 -M virt -nographic \ | |
-pflash flash0.img \ | |
-pflash flash1.img \ | |
-drive "if=virtio,media=disk,id=drive2,file=archlinux.qcow2,cache=writethrough,format=qcow2" \ | |
-device virtio-net-device,netdev=user0 \ | |
-netdev user,id=user0,hostfwd=tcp::2222-:22 | |
EOF | |
chmod +x run.sh | |
cat << EOF | |
************************************************************ | |
After starting the VM run ./first_boot.sh to finish setting | |
it up as described in the original how-to. The script may | |
time out if the mirror takes long so you may need to run it | |
a few times until it works. | |
Default user/pass is: root/root | |
************************************************************ | |
EOF | |
You could replace your regular expressions to find the UUID with
lsblk -no uuid "$BOOT_DEV"
.
Thanks. This is nicer.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You could replace your regular expressions to find the UUID with
lsblk -no uuid "$BOOT_DEV"
.