Skip to content

Instantly share code, notes, and snippets.

@niw
Last active October 24, 2024 03:04
Show Gist options
  • Save niw/e4313b9c14e968764a52375da41b4278 to your computer and use it in GitHub Desktop.
Save niw/e4313b9c14e968764a52375da41b4278 to your computer and use it in GitHub Desktop.
How to run Windows 10 on ARM or Ubuntu for ARM64 in QEMU on Apple Silicon Mac

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, 10/1/2021 state.

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

    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
    brew install ninja pkgconfig glib pixman
    
  3. Clone the latest QEMU source code

    The latest master at 10/1/2021 has Apple Silicon support.

    git clone --depth 1 https://git.qemu.org/git/qemu.git
    
  4. Build QEMU.

    In qemu directory, run following commands.

    mkdir build
    cd build
    ../configure --target-list=aarch64-softmmu --enable-cocoa
    make -j
    

    It creates qemu-img, qemu-system-aarch64 etc, which we use later.

  5. 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.

  6. Prepare pflash for non-volatile variable store, such as screen resolution.

    Create a working directory and run following command.

    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
    
    • Please use each path to where you download it.
    • This step is optional, you can use -bios 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.
  7. Download Windows 10 on ARM Insider Preview

    https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewARM64

  8. Convert VHDX downloaded Windows image to raw format

    It seems that VHDX often gets broken while it is being used, so probably it is better to convert it to raw format before using it. Using raw format makes the disk image file a sparse file on APFS disk. See "Compact raw disk image" section below for the details.

    qemu-img convert -p -O raw Windows10_InsiderPreview_Client_ARM64_en-us_21354.VHDX Windows10.raw
    
    • Please use each path to where you download it.
  9. Run Windows 10

    qemu-system-aarch64 \
      -monitor stdio \
      -M virt,highmem=off,virtualization=on \
      -accel hvf \
      -cpu host \
      -smp 4 \
      -m 4096 \
      -drive file=pflash0.img,format=raw,if=pflash,readonly=on \
      -drive file=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=Windows10.raw,format=raw,if=none,id=boot \
      -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 install a device driver.

  1. Download VirtIO device drivers ISO from Fedora Project.

    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=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 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.

Compact raw disk image

If you use ls or similar tool, you will notice that Windows10.raw is using large like 64GB disk space, however, it is not actually using that space.

By using Finder, you will see in info panel of that file, that shows the actual disk usage is much lower than that, like 10GB. Or, you can see actual size on disk by using the following command.

$ du -h Windows10.raw
 10G	Windows10.raw

This is because APFS is using a sparse file format automatically and doesn’t actually allocate the space until it is used. However, even though, the actual size on disk can be getting bigger as using Windows, especially after Windows Update, even if you delete files.

If the disk image is too big, you may want to compact it to release free space by using Defragment and Optimize Drives coming with Windows 10 and optimize C: drive, then use my HolePunch tool to reduce the actual disk usage.

$ git clone https://github.com/niw/HolePunch.git
$ ce HolePunch
$ swift build -c release
$ .build/release/holepunch --show-progress /path/to/Windows10.raw

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 6. to prepare QEMU.

  2. Create an empty disk image.

    qemu-img create -f raw ubuntu.raw 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,virtualization=on \
      -accel hvf \
      -cpu host \
      -smp 4 \
      -m 4096 \
      -drive file=pflash0.img,format=raw,if=pflash,readonly=on \
      -drive file=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=ubuntu.raw,format=raw,if=virtio,cache=writethrough \
      -cdrom 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
      

ARM 版 Windows 10 や Ubuntu for ARM64 を Apple Silicon な Mac で動かす

ARM 版 Windows 10 や Ubuntu を Apple Silicon な Mac で動かす簡単な方法です。

メモ: 2021年10月1日現時点での方法で、今後まだ改善されていくと思います。

ARM 版 Windows 10 を動かす

  1. Xcode を App Store で、あるいは Command Line Tools を Apple Silicon な Mac にインストール

    xcode-select --install
    
  2. ARM64 対応の Homebrew で QEMU の依存ライブラリをインストール

    すでに x86_64 の Homebrew が /usr/local にインストールされている場合は 削除するなどしてください。 x86_64 の Homebrew では QEMU がビルドできません

    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
    brew install ninja pkgconfig glib pixman
    
  3. 最新の QEMU のソースを取得

    2021年10月1日現時点での最新の master は Apple Silicon の対応がなされています。

    git clone --depth 1 https://git.qemu.org/git/qemu.git
    
  4. QEMU をビルドする

    qemu ディレクトリで以下を実行。

    mkdir build
    cd build
    ../configure --target-list=aarch64-softmmu --enable-cocoa
    make -j
    

    qemu-img, qemu-system-aarch64 などが作成されますので、これらを使用します。

  5. QEMU 用の EDK II OVMF EFI イメージをダウンロードする

    このイメージは stable202011 タグに、QemuRamfb.c に追加の解像度を足したものです。

    https://gist.github.com/niw/4f1f9bb572f40d406866f23b3127919b/raw/f546faea68f4149c06cca88fa67ace07a3758268/QEMU_EFI-cb438b9-edk2-stable202011-with-extra-resolutions.tar.gz

    さらに解像度を追加するなど、ソースコードからビルドする場合は以下を参照のこと。

  6. pflash イメージを作って、画面サイズなどを設定する不揮発なストレージを準備する

    作業用のディレクトを作成して、以下を実行。

    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
    
    • 各パスはダウンロードした場所などに適宜修正してください。
    • このステップは省略可能。その場合は次のステップで -drive ...,if=pflash,... のかわりに -bios QEMU_EFI.fd を指定すること。 ただし、EFI での変更が保存されなくなります。
  7. Windows 10 on ARM Insider Preview をダウンロードする

    https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewARM64

  8. VHDX から raw に変換する

    VHDX フォーマットのままだとかなりの頻度でイメージが壊れる印象があるので raw フォーマットに 変換しておく。 raw フォーマットを使うことで APFS ではスパースファイルとして扱うことができるので、 実際に使用するまで実際のファイルサイズを抑えることができる。 詳しくは以下の「raw フォーマットのディスクイメージを縮小する」を参照のこと。

    qemu-img convert -p -O raw Windows10_InsiderPreview_Client_ARM64_en-us_21354.VHDX Windows10.raw
    
    • 各パスはダウンロードした場所などに適宜修正してください。
  9. Windows 10 を起動する

    qemu-system-aarch64 \
      -monitor stdio \
      -M virt,highmem=off,virtualization=on \
      -accel hvf \
      -cpu host \
      -smp 4 \
      -m 4096 \
      -drive file=pflash0.img,format=raw,if=pflash,readonly=on \
      -drive file=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=Windows10.raw,format=raw,if=none,id=boot \
      -device nvme,drive=boot,serial=boot
    
    • イメージへのパスなどは適宜修正してください。
    • TianoCore のロゴが出ている時に ESC を押して、Device ManagerOVMF Platform ConfigurationChange Preferred Resolution for Next Boot と進めて解像度を変更できます。
    • 解像度を追加するには、下記の「EDK II の OVMF EFI イメージをビルドする」に従って OvmfPkg/QemuRamfbDxe/QemuRamfb.c を変更し、新しい QEMU_EFI.fd を作ってください。
    • -device usb-mouse より -device usb-tablet を使うことでマウスカーソルがロック されなくなり使いやすくなります。
    • -device intel-hda -device hda-duplex でオーディオが使えるようになります。
    • -nic user,model=virtio がネットワークインターフェイスです。有効にするには 以下を参照してください。

インターネットに接続する

VirtIO NIC は標準では有効にならないので、デバイスドライバを入れる必要がある。

  1. VirtIO デバイスドライバの ISO を Fedora Project からダウンロード。

    https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.190-1/virtio-win-0.1.190.iso

  2. デバイスドライバの ISO をマウント

    qemu-system-aarch64 のオプションに以下を追加する。

    -drive file=virtio-win-0.1.190.iso,media=cdrom,if=none,id=drivers \
    -device usb-storage,drive=drivers
    

    イメージへのパスなどは適宜修正してください。

  3. デバイスドライバの署名検証を無効にする

    Windows を起動して Windows スタートボタン を右クリック、Command Prompt (Admin) を選択。

    bcdedit を使ってテスト署名されたデバイスドライバを有効にする。

    bcdedit.exe -set TESTSIGNING ON
    

    このあと Windows を再起動すること。

    詳細はこちらを参照のこと。

  4. デバイスドライバのインストール

    Windows が再度起動したら Windows スタートボタン を右クリック、Device Manager を選択。

    Device Manager のウィンドウで、View メニューの Devices by Connection を選択。

    デバイスのツリーから、ACPU ARM64-based PCMicrosoft ACPI-Compliant System PCI Express Root Complex と選択してその中にある Unknown device を探す。 (Unknown device はデバイスのツリーに沢山あるけれど、PCI Express Root Complex の下にあるのが、VirtIO NIC。)

    該当の Unknown device を右クリックして、Update Drivers を選択、 Browse my computer for drivers を選んで、D:\NetKVM\w10\ARM64 を指定。

    Next をクリックして Red Hat VertIO Ethernet Adapter をインストール。

raw フォーマットのディスクイメージを縮小する

ls や似たようなツールを使うと、Windows10.raw ファイルが実際より多くの、 例えば64GBのディスクを使っているように表示されることがあります。 しかし、実際には利用している容量しか使っていません。

Finder を使うことで、ファイルの情報を見ると実際のディスクの使用量を表示できます。 もしくは、以下のコマンドでも同じことができます。

$ du -h Windows10.raw
 10G	Windows10.raw

これは APFS がスパースファイルを自動で使うためで、実際にファイルの領域が使われるまでディスクの 領域を割り当てないからです。 しかしながら、ファイルは Windows Update などをすると容量まで大きくなる可能性があり、 たとえファイルを削除してもディスクイメージのサイズは減らないことがあります。

そのため、ディスクサイズが大きくなりすぎた場合などは Windows 10 に付属の Defragment and Optimize Drives で、C: ドライブを Optimize して使用していない領域を 開放したあと、以下の拙作のHolePunchツールを使って Windows10.raw を縮小してください。

$ git clone https://github.com/niw/HolePunch.git
$ ce HolePunch
$ swift build -c release
$ .build/release/holepunch --show-progress /path/to/Windows10.raw

Ubuntu Server for ARM64 を動かす

ARM 版 Windows 10 を動かす手順に従って QEMU を準備して、Ubuntu Server for ARM64 をダウンロードしてインストールします。

  1. 上記の手順 1. から 6. までに従って QEMU を準備する。

  2. 空のディスクイメージを作成する。

    qemu-img create -f raw ubuntu.raw 40G
    
  3. Ubuntu Server for ARM64 をダウンロードする。

    https://ubuntu.com/download/server/arm

  4. Ubuntu Server for ARM をインストールする。

    qemu-system-aarch64 \
      -monitor stdio \
      -M virt,highmem=off,virtualization=on \
      -accel hvf \
      -cpu host \
      -smp 4 \
      -m 4096 \
      -drive file=pflash0.img,format=raw,if=pflash,readonly=on \
      -drive file=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=ubuntu.raw,format=raw,if=virtio,cache=writethrough \
      -cdrom ubuntu-20.04.1-live-server-arm64.iso
    
    • 指示に従ってインストールしたあとは -cdrom は不要です。

EDK II の OVMF EFI イメージをビルドする

上記の手順に従って Ubuntu Server for ARM64 を動かします。

  1. EDK II のソースコードを取ってくる

    git clone --depth 1 --branch edk2-stable202011 https://github.com/tianocore/edk2.git
    cd edk2
    git submodule update --init --recursive
    

    Hypervisor.framework パッチの制限で xHCI を無効にする必要があれば /ArmVirtPkg/ArmVirtQemu.dsc/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc にある MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf の行をコメントアウト。 たぶん現状は問題ない。

  2. ビルドする

    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
    

    Build/ArmVirtQemu-AARCH64/DEBUG_GCC5/FVQEMU_EFI.fdQEMU_VARS.fd ができるはず。

    • これらのファイルを簡単に macOS ホストに取り出すには macOS でリモートアクセスを 有効にして scp10.0.2.2 にコピー。

    • x86_64 の環境でビルドする場合は以下のツールチェーンでクロスコンパイル。

      sudo apt install gcc-aarch64-linux-gnu
      env GCC5_AARCH64_PREFIX=aarch64-linux-gnu- build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtQemu.dsc
      
@conath
Copy link

conath commented Feb 27, 2021

Thanks, the build instructions for the Tianocore EFI were especially helpful.

@sh4d0wph03n1x
Copy link

@niw Thanks for this!

@fcicq
Copy link

fcicq commented Apr 21, 2021

@muyouming
Copy link

@fcicq
thanks for your info.

I already extract it and upload to here.

@echofoxtrotpl
Copy link

echofoxtrotpl commented May 15, 2021

It works great! Could you please describe more precisely how to add custom resolutions? I was trying to do so, but when I do "make -C BaseTools" I get compile error, even if I don't change any line of code.

Edit: I managed it! It didn't work on Fedora, but worked on Ubuntu.

Copy link

ghost commented May 23, 2021

I tried following this with OracleLinux-R8-U3-aarch64 and it boots up and then when trying to install I got: synchronous exception. The same happened in Parallels. Is this due to the RedHat kernel?

@nrjdalal
Copy link

nrjdalal commented Jun 6, 2021

Most updated way to install QEMU as of June 2021.

  • removes redundant patch for building
  • update state to June 2021, instead of May

QEMU Silicon Mac Installation

The link above also provides one command installer.

@niw
Copy link
Author

niw commented Jun 6, 2021

@nrjdalal nice! and so the patches are partially merged to master now, that's good news. I updated SHA1 accordingly to get the latest one.

@niw
Copy link
Author

niw commented Jun 6, 2021

@echofoxtrotpl Yeah, Fedora may require another packages or setups to build EFI, I didn't test Fedora.

@niw
Copy link
Author

niw commented Jun 6, 2021

@Altitude-Dashboard I didn't try other kernels than Ubuntu ARM64 version of it. If the kernel doesn't support UEFI boot, that might not work. As I found the documentation on Oracle site, it said their Oracle Linux 8 only released with UEK, which may need some requirements on UEFI or bootloader?

@woachk
Copy link

woachk commented Jun 6, 2021

@niw

RHEL and CentOS derivatives, including Oracle Linux, use kernels with 64KB granule (base page size). Such a configuration is not supported on Apple M1.

@niw
Copy link
Author

niw commented Jun 6, 2021

@woachk Ah, I see. That makes sense! Thanks.

@asheeshmathur
Copy link

Wonderful, with your instructions, could install and run Ubuntu 20.4 Server, but battery of errors when trying with Ubuntu Desktop on Mac M1.

Any tips will be appreciated.

@sejevici
Copy link

sejevici commented Jul 1, 2021

I can't seem to mount the network driver.. nothing but the C: drive shows up when I open an instance of windows 10.
I have changed the filepath to match that of mine, other than that I have used all the given examples with great success!
I'm running on MacBook Air M1 Big Sur 11.4.
Hope that anyone can help!

@lucasmatoscc
Copy link

Does anyone know how to enable NAT? I installed the windows VM on a MacOs machine and I want to use VPN, but it's not working.

Copy link

ghost commented Sep 1, 2021

Unable to open uwp applications (e.g. Microsoft Store, Camera ...),Is there any solution?

@CombinedEffort
Copy link

Dumped a gist here based on this, with the steps I needed to get Windows 11 ARM working on my M1 - https://gist.github.com/CombinedEffort/bb7ffd950692f80a42f0400bd9c10ac3

@bforpc
Copy link

bforpc commented Apr 26, 2022

I get
`
Disabling PIE due to missing toolchain support

...

Run-time dependency appleframeworks found: NO (tried framework)
../meson.build:328:2: ERROR: Dependency "appleframeworks" not found, tried framework
`

at building.

Bfo

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