Skip to content

Instantly share code, notes, and snippets.

@daemonhorn
Last active October 3, 2023 12:20
Show Gist options
  • Save daemonhorn/a3a3d271a7e3f4528975cdcbcfc06c71 to your computer and use it in GitHub Desktop.
Save daemonhorn/a3a3d271a7e3f4528975cdcbcfc06c71 to your computer and use it in GitHub Desktop.
FreeBSD-arm64-aarch64 via Qemu from ports

Intro

  • Notes from setting up FreeBSD ARM64 (aarch64) for FreeBSD 14-Beta1 in a Qemu runtime
  • include guest console via vnc, novnc(web) - WIP
  • include guest console via serial(telnet)
  • include resizing of disk image qemu-img resize

Dependancies

  • Sufficient disk space on a mounted disk (e.g.: /qemu-data in this example)
  • Network environment that allows for multiple mac addresses on one switch port (or vswitch port configuration) for bridging mode

Getting Started

  1. Download qcow2 image from FreeBSD site, decompress, and resize (to increase by desired size. Example shows adding 40GB):
mkdir /qemu-data
cd /qemu-data
fetch https://download.freebsd.org/releases/VM-IMAGES/14.0-BETA1/aarch64/Latest/FreeBSD-14.0-BETA1-arm64-aarch64.qcow2.xz
unxz FreeBSD-14.0-BETA1-arm64-aarch64.qcow2.xz
qemu-img resize FreeBSD-14.0-BETA1-arm64-aarch64.qcow2 +40G
  1. Install qemu, novnc, python
pkg install qemu novnc python
  1. Configure networking bridge for use by Qemu guests (replace vmx0 with host network interface name)
ifconfig bridge0 create
ifconfig bridge0 addm vmx0 edge vmx0 up

Make permanant in /etc/rc.conf by adding:

ifconfig_bridge0="addm vmx0 edge vmx0 up"
cloned_interfaces="bridge0"
  1. Create Qemu network ifup/ifdown scripts to handle bridge and tap syntax.
    vi /etc/qemu-ifup
#!/bin/sh
ifconfig bridge0 addm $1 up
ifconfig $1 up


vi /etc/qemu-ifdown

#!/bin/sh
ifconfig $1 down
ifconfig bridge0 deletem $1
  1. Enable the scripts to be directly executed by root user from qemu using:
chmod +x /etc/qemu_if*
  1. Boot Qemu with the pre-installed qcow2 image (text mode)
qemu-system-aarch64 -m 4096M -cpu cortex-a57 -M virt  \
        -bios edk2-aarch64-code.fd -serial telnet:localhost:4444,mux=on,server,wait=off -vnc :0,websocket=on \
        -drive if=none,file=/qemu_data/FreeBSD-14.0-BETA1-arm64-aarch64.qcow2,id=hd0 \
        -device virtio-blk-device,drive=hd0 \
        -device virtio-net-device,netdev=net0 \
        -netdev tap,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown,id=net0
  1. (optional) /qemu/data/start_arm.sh Example:
#!/bin/sh
if [ ! -z ${1} ] ; then
        echo "Attempting to passthrough usb host device based on query string: ${1}"
        usb_map_count=`usbconfig | grep -cie ${1}`
        [ ${usb_map_count} -ne 1 ] && echo "Total devices matched: ${usb_map_count} is not equal to 1, please refine." && usbconfig && exit 1
        usb_map=`usbconfig | grep -ie ${1} | grep -o -e [0-9]\.[0-9]`
        usb_map_bus=`echo ${usb_map} | grep -o -e ^[0-9]`
        usb_map_addr=`echo ${usb_map} | grep -o -e [0-9]$`
        usb_host_qemu_cli="-device usb-host,hostbus=${usb_map_bus},hostaddr=${usb_map_addr},id=${1}"
        echo "Mapping usb device `usbconfig | grep -ie ${1}` into the guest."
fi
ifconfig tap0 | grep -cq -e "Opened by PID" || ifconfig tap0 destroy
ps -aux | grep -v grep | grep -cq qemu-system && \
        echo "Qemu is already running. Shutdown the guest(s), then retry." && exit 1
echo "Starting Qemu in background..."
qemu-system-aarch64 -m 4096M -cpu max -smp cpus=4 -M virt \
        -bios edk2-aarch64-code.fd \
        -serial telnet:localhost:4444,mux=on,server,wait=off \
        -monitor telnet:localhost:4445,mux=on,server,wait=off \
        -display none \
        -drive if=none,file=/data/FreeBSD-14.0-BETA3-arm64-aarch64.qcow2,id=hd0 \
        -device virtio-blk-device,drive=hd0 \
        -device virtio-net-device,netdev=net0 \
        -netdev tap,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown,id=net0 \
        -usb \
        -device qemu-xhci,id=xhci \
        ${usb_host_qemu_cli} \
        -daemonize
  1. (optional) Connect over telnet protocol from localhost to the guest console. Note: Use Ctrl+] to get a telnet prompt, then quit to exit telnet
telnet localhost 4444
  1. Login as root with no password, immediately set one using passwd.
  2. Create users using adduser, start sshd using service sshd enable && service sshd start
  3. Edit configuration file in /etc/rc.conf and give a hostname. verify settings.
  4. Use the new Arm64 (aarch64) version of FreeBSD 14 Beta 1. Since this is now a higher tier variant, there will be pre-built packages for use with pkg utility as well as all of the other normal FreeBSD base things.

TODO

  • Determine why attempting to destroy tapX interface using ifconfig tap0 destroy format hangs instead of erroring out when there is still a pid associated with the interrface.
  • Write a detection script to check if there is a pid attached, and destroy if not: ifconfig tap0 | grep -cq -e "Opened by PID" || ifconfig tap0 destroy
  • Document Yubikey passthrough from ESXi->FreeBSD VM(amd64)->FreeBSD QEMU(aarch64)
  • Document u2f virtual device (emulated and passthrough)
  • Document Fresh aarch64 install via ISO vs QCOW Image

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment