# How to run Windows 10 on ARM or Ubuntu for ARM64 in QEMU on Apple Silicon Mac Here is easy steps to try Windows 10 on ARM or Ubuntu for ARM64 on your Apple Silicon Mac. Enjoy! > NOTE: that this is current, 2/8/2021 state. I think it will be improved in upcoming a few months. ## Running Windows 10 on ARM 1. Install Xcode from App Store or install Command Line Tools on your Mac running on Apple Silicon. ``` xcode-select --install ``` 2. Install ARM64 Homebrew and QEMU dependencies. **If you already installed x86_64 Homebrew in `/usr/local`, please uninstall it.** **It's not possible to build QEMU with x86_64 Homebrew** https://brew.sh/ ``` /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" brew install ninja pkgconfig glib pixman ``` 3. Clone QEMU source code. ``` git clone https://git.qemu.org/git/qemu.git ``` 4. Create a local branch then apply Hypervisor.framework patches that @[_AlexGraf](https://twitter.com/_AlexGraf) made. ``` cd qemu git checkout d0dddab40e -b wip/hvf curl 'https://patchwork.kernel.org/series/418581/mbox/'|git am --3way ``` 5. Build QEMU ``` mkdir build cd build ../configure --target-list=aarch64-softmmu --enable-cocoa make -j ``` 6. Download pre-build EDK II OVMF EFI image for QEMU. This EFI image is built from `stable202011` tag with additional resolutions in `QemuRamfb.c`. https://gist.github.com/niw/4f1f9bb572f40d406866f23b3127919b/raw/f546faea68f4149c06cca88fa67ace07a3758268/QEMU_EFI-cb438b9-edk2-stable202011-with-extra-resolutions.tar.gz To build it from the source code for adding more resolutions, see the following section. 7. Prepare pflash for non-volatile variable store, such as screen resolution. In the directory where you downloaded `QEMU_EFI-....tar.gz`, run following commands. ``` cd ~/Downloads tar xzvf QEMU_EFI-*.tar.gz dd if=/dev/zero of=pflash0.img bs=1m count=64 dd if=/dev/zero of=pflash1.img bs=1m count=64 dd if=QEMU_EFI.fd of=pflash0.img conv=notrunc dd if=QEMU_VARS.fd of=pflash1.img conv=notrunc ``` - This step is optional, you can use `-bios ~/Downloads/QEMU_EFI.fd` instead of `-drive ...if=pflash` lines in the next step, but in that case, any changes in EFI will not be persistent. 8. Download Windows 10 on ARM Insider Preview https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewARM64 9. Convert VHDX downloaded Windows image to qcow2 format It seems that VHDX often gets broken while it is being used, so probably it is better to convert it to qcow2 format before using it. ``` qemu-img convert -p -O qcow2 ~/Downloads/Windows10_InsiderPreview_Client_ARM64_en-us_21286.VHDX ~/Downloads/Windows10_InsiderPreview_Client_ARM64_en-us_21286.qcow2 ``` 10. Run Windows 10 ``` ./qemu-system-aarch64 \ -monitor stdio \ -M virt,highmem=off \ -accel hvf \ -cpu cortex-a72 \ -smp 4 \ -m 4096 \ -drive file=~/Downloads/pflash0.img,format=raw,if=pflash,readonly=on \ -drive file=~/Downloads/pflash1.img,format=raw,if=pflash \ -device ramfb \ -device qemu-xhci \ -device usb-kbd \ -device usb-tablet \ -device intel-hda \ -device hda-duplex \ -nic user,model=virtio \ -drive file=~/Downloads/Windows10_InsiderPreview_Client_ARM64_en-us_21286.qcow2,format=qcow2,if=none,id=boot,cache=writethrough \ -device nvme,drive=boot,serial=boot ``` - Please modify each path to the image depends on your environment. - Hit `ESC` while you see TianoCore, then `Device Manager`, `OVMF Platform Configuration`, `Change Preferred Resolution for Next Boot` to change screen resolution. - To add more resolutions, follow "Build EDK II OVMF EFI image from the source code" below and modify `OvmfPkg/QemuRamfbDxe/QemuRamfb.c` then build new `QEMU_EFI.fd`. - Use `-device usb-tablet` instead of `-device usb-mouse` allows transparently moving mouse cursor. - `-device intel-hda -device hda-duplex` to enable audio. - `-nic user,model=virtio` is the network interface. To enable it, see the following section. ## Enable the internet VirtIO NIC is not enabled by default. To make it works, you need to device driver. 1. Download VirtIO device drivers ISO from [Fedora Project](https://docs.fedoraproject.org/en-US/quick-docs/creating-windows-virtual-machines-using-virtio-drivers/index.html#virtio-win-direct-downloads). https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.190-1/virtio-win-0.1.190.iso 2. Mount device drivers ISO Add next options to `qemu-system-aarch64`. ``` -drive file=~/Downloads/virtio-win-0.1.190.iso,media=cdrom,if=none,id=drivers \ -device usb-storage,drive=drivers ``` Please modify each path to the image depends on your environment. 3. Disable device driver signature enforcement Boot Windows, then right click Windows Start button, then select Command Prompt (Admin). Use bcdedit to enable test-signed device drivers. ``` bcdedit.exe -set TESTSIGNING ON ``` Then reboot Windows. See [here](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/the-testsigning-boot-configuration-option) for the details. 4. Install driver Once Windows booted again, then right click Windows Start button, then select Device Manager. In Device Manager, select View menu then Devices by Connection. Navigate in the device tree, select `ACPU ARM64-based PC`, `Microsoft ACPI-Compliant System`, `PCI Express Root Complex`, then you will see one `Unknown device` there. (There are many `Unknown device` in tree but the one under `PCI Express Root Complex` is the VirtIO NIC.) Right click `Unknown device` then select Update Drivers, then Browse my computer for drivers, then select `D:\NetKVM\w10\ARM64`. Click Next to install `Red Hat VertIO Ethernet Adapter`. ## Running Ubuntu Server for ARM64 Follow the same steps for Windows 10 to prepare QEMU, then download Ubuntu Server for ARM64 and install it. 1. Follow previous steps from 1. to 7. to prepare QEMU. 2. Create an empty disk image. ``` ./qemu-img create -f qcow2 ~/Downloads/ubuntu.qcow2 40G ``` 3. Download Ubuntu Server for ARM64 https://ubuntu.com/download/server/arm 4. Install Ubuntu Server for ARM ``` ./qemu-system-aarch64 \ -monitor stdio \ -M virt,highmem=off \ -accel hvf \ -cpu cortex-a72 \ -smp 4 \ -m 4096 \ -drive file=~/Downloads/pflash0.img,format=raw,if=pflash,readonly=on \ -drive file=~/Downloads/pflash1.img,format=raw,if=pflash \ -device virtio-gpu-pci \ -display default,show-cursor=on \ -device qemu-xhci \ -device usb-kbd \ -device usb-tablet \ -device intel-hda \ -device hda-duplex \ -drive file=~/Downloads/ubuntu.qcow2,if=virtio,cache=writethrough \ -cdrom ~/Downloads/ubuntu-20.04.1-live-server-arm64.iso ``` - Follow instruction to install Ubuntu Server. Once it's installed, `-cdrom` argument is not needed. ## Build EDK II OVMF EFI image from the source code Follow the previous instructions to run Ubuntu Server for ARM64. 1. Checkout EDK II source code. ``` git clone --depth 1 --branch edk2-stable202011 https://github.com/tianocore/edk2.git cd edk2 git submodule update --init --recursive ``` You may want to disable xHCI due to current Hypervisor.framework patch limitation. Comment out `MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf` in `/ArmVirtPkg/ArmVirtQemu.dsc` and `/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc`. Probably this is no longer needed. 2. Build it. ``` sudo apt install iasl python3 python3-distutils uuid-dev make g++ source edksetup.sh make -C BaseTools build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtQemu.dsc ``` Then, you will get `QEMU_EFI.fd` and `QEMU_VARS.fd` in `Build/ArmVirtQemu-AARCH64/DEBUG_GCC5/FV`. - The easiest way to take these files to the host macOS, run Remote Login on macOS then `scp` these to `10.0.2.2`. - To build these on x86_64 environment, use following toolchain to cross compile. ``` sudo apt install gcc-aarch64-linux-gnu env GCC5_AARCH64_PREFIX=aarch64-linux-gnu- build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtQemu.dsc ```