在 QEMU 安装 Windows on ARM

前言

你还可以参阅 在 QEMU 安装 Windows on ARM - 云萧的咕咕屋

更新日志

2023/1/2 更新
建议在构建镜像的时候用 https://uup.rg-adguard 的镜像,可以移除安装检查,可以有效避免 TPM 等硬件问题
或者自己手动修改镜像,抑或是本地安装完成后再挂载到 QEMU

2024/5/5 更新
下面的操作中,你可以将 Dism++ 文件夹放到 virtio-win.iso 内,在安装完磁盘驱动的时候(或提前注入后),按 Shift + F10 呼出 CMD,然后打开 Dism++ARM64.exe
随后使用 DiskPartDism++ 分别创建分区与安装系统,安装完后使用 Dism++ 的“驱动管理”,选择 virtio-win.iso 的根目录即可自动安装驱动
不知道如何使用 DiskPart 可以参阅 UEFI 使用 DISM 命令安装系统章节中 #操作磁盘 的部分

2024/7/28 更新
在 QEMU 2024 以后的版本中(目前截止到 qemu-w64-setup-20240720.exe)均有 ramfb 显示不正常问题,但 2023 最后一版的 QEMU 还能正常显示,下载链接:https://qemu.weilnetz.de/w64/2023/qemu-w64-setup-20231224.exe

2025/2/2 更新
重写了该文章
关于加快安装进程,请参阅#后话7.
文章已从旧文章(https://goo-aw233.github.io/zh-CN/tutorial/VM/QEMU/WindowsARMonQEMU)迁移至此

实验环境

Windows on ARM 镜像

Windows ARM 镜像获取

或者参阅 Getting Windows images | Windows on R

QEMU

QEMU 最新版
需要记住 QEMU 的安装位置,将其 配置环境变量 时需要用到
QEMU 安装路径

UEFI 固件

项目链接(已不再更新)
下载文件名开头为 edk2.git-aarch64 的文件,并用 7-Zip 等解压缩工具多次解压,直至提取出 QEMU_EFI.fdvars-template-pflash.raw 这两个文件。(可能在 \edk2.git-aarch64-....cpio\.\usr\share\edk2.git\aarch64\ 下找到)
大约路径

VirtIO ARM64 驱动光盘

最新版下载链接

懒人包

如果你觉得从以上的站点下载解压文件太麻烦,可以直接到我的 OneDrive 站点下载打包好的所需文件(不一定为最新,系统镜像单独发放,只有 Windows 10 22H2 与 Windows 11 23H2,已去安装校验及集成 .NET3.5,未作精简)
OneDrive

配置环境变量

按下 Windows 徽标键 + R,输入 SystemPropertiesAdvanced.exe 并回车
点击“环境变量(N)…”

环境变量 1

在“系统变量(S)”里找到名为“Path”的项并双击,点击旁边的“新建(N)”,最后在矩形框中输入 QEMU 的安装目录

环境变量 2

然后全部点击“确定”即可

创建硬盘文件

按下 Windows 徽标键 + Q 以打开“搜索”,输入 CMD 后选择“命令提示符”,再选择“以管理员身份运行”

开启 CMD

输入如下命令来创建硬盘文件

1
qemu-img.exe create -f <硬盘格式> "<自定义存放路径\文件名.硬盘格式>" <容量大小><单位>

比如我的存放位置为 E:\QEMU\Windows_11,文件名为 OS,硬盘格式为 qcow2(可选的有还 rawhost_deviceqcowcowvdivmdkvpccloopimg),容量大小为 80 GB(单位有 KMGTPE
那么我的命令如下(需要区分大小写,而且路径和文件名最好不要有空格,用下划线 _ 来代替,硬盘文件存放的目录需要提前创建好

1
qemu-img.exe create -f qcow2 "E:\QEMU\Windows_11\OS.qcow2" 80G

若没有别的错误则创建成功

创建硬盘文件

你也可以创建 VHDX 或 VHD 而不是使用以上硬盘格式

使用 VHDX 或 VHD 的好处是可以直接挂载到文件资源管理器,可以直接简单地操作里面的文件,性能更好,也可以挂载后直接使用 Dism++ 安装系统,安装完成后再启动到虚拟机
管理虚拟硬盘 (VHD) | Microsoft Learn

由于硬盘文件较脆弱,切勿强制关机,否则会造成硬盘文件损坏(特别是 VHD(X))

启动系统

我的存放目录:E:\QEMU\Windows_11
QEMU_EFI.fdvars-template-pflash.raw 这两个文件一并复制到存放位置下
在存放的目录下新建文本文档,命名为 start.cmd,并编辑内容

<> 里的内容(包括引号)是需要自行修改的内容,修改时需要将 <...> 以内的东西修改掉;你可以在最顶端插入 chcp 65001,这样 CMD 内提示的中文报错就不会乱码,但是会导致 QEMU 变成英文

1
2
3
4
5
6
7
8
qemu-system-aarch64.exe -M virt,virtualization=true -cpu cortex-<CPU 型号> -smp <CPU 核心数> -m <运行内存大小> ^
-device qemu-xhci -device usb-kbd -device usb-tablet ^
-drive file=<"硬盘文件路径\文件名.qcow2">,if=virtio ^
-nic user,model=virtio ^
-drive file=<"系统镜像路径\文件名.iso">,media=cdrom,if=none,id=cdrom -device usb-storage,drive=cdrom ^
-drive file=<"virtio-win 所在路径\virtio-win 的名称.iso">,media=cdrom,if=none,id=cdrom1 -device usb-storage,drive=cdrom1 ^
-bios <"存放目录\QEMU_EFI.fd"> -device ramfb ^
-drive file=<"存放目录\vars-template-pflash.raw">,if=pflash,index=1,format=raw

比如我的 CPU 型号为 a76(可选的还有 a72a57a53,亦或者是其他)
CPU 核心数量为 4,运行内存大小为 6144 MiB硬盘文件系统镜像virtio-win 镜像命名分别为 Image.isoOS.qcow2virtio-win.iso(若 start.cmd 与前面几个文件在同一目录下就不需要指定目录,直接填写名称即可)
那么我的命令如下(需要区分大小写,而且路径和文件名最好不要有空格,用下划线 _ 来代替,硬盘文件存放的目录需要提前创建好

特别注意:自 Windows 11 24H2 采用 Rust 重写 Windows 内核文件后,所模拟的 SoC 需要为 ARMv8.1 及以上(即支持 SSE 4.2),否则将无法启动;不支持的 SSE 4.2 的 Soc 最高可启动的 Windows 版本为:Windows 11 Build 25163
Windows 11 build 25163 is the last one than can boot on the Raspberry Pi 4 and older.
Recent insider builds no longer work as they make extensive use of the new atomic instructions introduced in ARMv8.1.
[3]

QEMU 查询可用的硬件命令

查询支持模拟的主板:qemu-system-aarch64.exe -M help
查询支持模拟的 CPU:qemu-system-aarch64.exe -cpu help

1
2
3
4
5
6
7
8
qemu-system-aarch64.exe -M virt,virtualization=true -cpu cortex-a76 -smp 4 -m 6144 ^
-device qemu-xhci -device usb-kbd -device usb-tablet ^
-drive file="E:\QEMU\Windows_11\OS.qcow2",if=virtio ^
-nic user,model=virtio ^
-drive file="E:\QEMU\Windows_11\Image.iso",media=cdrom,if=none,id=cdrom -device usb-storage,drive=cdrom ^
-drive file="E:\QEMU\Windows_11\virtio-win.iso",media=cdrom,if=none,id=cdrom1 -device usb-storage,drive=cdrom1 ^
-bios "E:\QEMU\Windows_11\QEMU_EFI.fd" -device ramfb ^
-drive file="E:\QEMU\Windows_11\vars-template-pflash.raw",if=pflash,index=1,format=raw

保存后双击运行,如果正常运行则可以进入到 TinaoCore Logo 的引导页

启动 Windows


若有如下报错为正常,无需理会(第二个不知道有什么用(反正不影响.jpg

QEMU 报错


启动时按下 ESC 以进入 BIOS 设置界面,并选择“Device Manager” > “OVMF Platform Configuration”

Device Manager

OVMF Platform Configuration

按下 Enter,将 <640x480> 改为 <1024x768> 后回车,按下 F10 再按下 Y 以保存设置,最后多次按下 ESC 回到主页,选择“Reset”以继续

修改分辨率

重启虚拟机

安装系统

然后就这样漫长的等待,就会进入到 Windows 安装程序页面

推荐开启:“视图(V)” > “鼠标经过时捕获(H)”或“视图(V)” > “捕获输入(G)”;若要将鼠标脱离虚拟机,请按下 Ctrl + Alt + G

Windows 安装程序

Windows 11 24H2 之后新版安装程序界面有所变化,但是操作基本一致

如果遇到 Synchronous Exception at ... 的问题,请替换 QEMU_EFI.fdvars-template-pflash.raw 文件,并重新配置 BIOS,或者是重新尝试使用其他任意键以继续(偶然发现的另一个小妙招)
Synchronous Exception

在选择磁盘的时候,点击“加载驱动程序(L)”

加载驱动程序

选择“浏览”

浏览

选择 VirtIO-Win 光驱,找到名为“viostor”的文件夹,选择里面“w11”文件夹下的“ARM64”文件夹(如果安装的是 Windows 10 则选择 w10,以此类推)

viostor 文件夹一般在最后一个文件夹,在 Boot (X:) 分区之上

选择 VirtIO 驱动

选择驱动程序,然后点击“安装(I)”,这样就可以正常安装系统了

选择驱动

最后进入无尽的等待…

复制文件

x86 转译 AArch64 性能会有所下降(不止一点点,再加上 QEMU 是软件模拟),所以安装时间会比普通的虚拟机要长不知道多少倍(

小吐槽

这里不得不说一下 CPU 默认才 1.00 GHz 属实吝啬,不过不难看出它真的在动了(
有需要的话可以自己搜一下 QEMU 配置 CPU

CPU 信息

当我把 QEMU 升级之后之后就被识别出是虚拟机力(无慈悲

CPU 信息 2

按下 Shift + F10 来打开 CMD,并输入以下命令

1
oobe\msoobe.exe

然后就会跳过那漫长的准备就绪阶段

命令(卡一下才会自动重启)

下一阶段

从进入安装程序到准备就绪,花了近一个半小时(
没什么意外的话,可能这个要转 114514h(悲
(而且鉴于无法联网,且硬盘驱动都要自己加载,所以这个过程跳过也没啥问题()

准备就绪

再等待亿会,就可以进入 OOBE 了

OOBE

由于暂时没有网卡驱动,且 Windows 11 要求联网才能继续,所以需要跳过联网激活验证(Windows 10 可跳过该步骤)
按下 Shift + F10 打开 CMD,并输入以下命令

1
oobe\BypassNRO.cmd
如果没有这个文件可以手动输入代码
1
2
reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE /v BypassNRO /t REG_DWORD /d 1 /f
shutdown /r /t 0

命令

等待一会,系统会自动重启,然后就可以继续正常安装了

如果这期间 OOBE 仍要求联网,可以按下 Shift + F10 打开 CMD,输入 explorer 并回车,然后再按网卡驱动的方式安装网卡驱动后继续


若无法跳过账户登录或只能登录到工作账户

如果发现只能登录到工作账户的话可以按 Ctrl + Shift + F3 跳过 OOBE
然后在计算机管理里启用 Administrator 或新建其他管理员账户,然后以管理员身份运行 CMD 并输入命令

1
xcopy "%SystemRoot%\System32\svchost.exe" "%SystemRoot%\System32\oobe\audit.exe" /X

完成后重启虚拟机即可

可能有风险,建议备份源文件到桌面,命令如下(先备份再执行上面的代码):

1
xcopy "%SystemRoot%\System32\oobe\audit.exe" "%Public%\Desktop\Backup" /X

一切都开始好起来力)

此操作可能需要几分钟

进入桌面

网卡驱动

右键“开始菜单”,选择“终端(管理员)”、“Windows PowerShell(管理员)”或“命令提示符(管理员)”
输入以下命令并重启

1
bcdedit /set testsigning on

关于加载已进行测试签名的驱动程序,请参阅 允许加载已进行测试签名的驱动程序 - Windows drivers | Microsoft Learn

开启测试模式

在文件资源管理器里打开 VirtIO-Win 光驱,然后定位到 \NetKVM\w11\ARM64(如果是 Windows 10 就选择 w10 文件夹,以此类推)
右键类型为“安装信息”的 netkvm 文件,选择“安装”

安装 netkvm

在弹出的 UAC 窗口中选择“是”

UAC

等待一会,就提示安装完成

安装完成

再等一会就有网络了

使用体验

这是后在里面运行 Dism++ ARM64(Win32)与微软电脑管家(MSIX 打包的 C#/WebView2 应用)的效果(启动速度和运行效率会比 x64 转译 ARM64 快许多)

Dism++ ARM64

微软电脑管家

后话

  1. 光驱
    如果你后面不需要光驱了可以把
1
2
-drive file=<"系统镜像路径\文件名.iso">,media=cdrom,if=none,id=cdrom -device usb-storage,drive=cdrom ^
-drive file=<"virtio-win 所在路径\virtio-win.iso">,media=cdrom,if=none,id=cdrom1 -device usb-storage,drive=cdrom1 ^

这两行代码删除

  1. 性能
    因为没有显卡驱动以及其他的驱动,在 QEMU 模拟 Windows ARM 性能会大打折扣,整个过程会非常漫长,建议将文件存放在 SSD 内
    或许你可以试试将 -device virtio-gpudevice virtio-gpu,virgl=on 添加到 start.cmd 内,然后在“视图(V)” 里选择 virtio-GPU,但或许更糟糕(

  2. 对应驱动
    默认情况下,Windows 不会加载测试签名的内核模式驱动程序,需要加载则必须启用测试签名的驱动程序

    关于加载已进行测试签名的驱动程序,请参阅 允许加载已进行测试签名的驱动程序 - Windows drivers | Microsoft Learn

1
bcdedit /set testsigning on

文章内仅模拟了所需的硬件及网卡,其他的硬件需要自行查询
镜像内其他驱动的大致意思如下:[4]
NetKVM: Virtio 网络驱动
viostor: Virtio 块驱动
vioscsi: Virtio SCSI 驱动
viorng: Virtio RNG 驱动
vioser: Virtio 串口驱动
Balloon: Virtio 内存气球驱动
qxl: 用于 Windows 7 及之前版本的 QXL 显卡驱动. (virtio-win-0.1.103-1 和之后版本会创建)
qxldod: 用于 Windows 8 及之后版本的 QXL 显卡驱动. (virtio-win-0.1.103-2 和之后版本会创建)
pvpanic: QEMU pvpanic 设备驱动 (virtio-win-0.1.103-2 和之后版本会创建)
guest-agent: QEMU Guest Agent 32bit 和 64bit 安装包
qemupciserial: QEMU PCI 串口设备驱动
vfd: 用于 Windows XP 下的 VFD 软驱镜像

  1. 优化
    如果真的很慢可以看看 BetaWiki 给出的解决方案(不一定 100% 有效)
    以及关闭 Microsoft Defender 防病毒等
1
2
3
4
5
6
7
8
9
10
11
sc stop "Spooler"
sc config "Spooler" start= disabled
sc stop "WSearch"
sc config "WSearch" start= disabled
REM Disable Automatic Defragmentation
schtasks /Delete /TN "\Microsoft\Windows\Defrag\ScheduledDefrag" /F
REM Disable Pagefile
wmic computersystem set AutomaticManagedPagefile=FALSE
wmic pagefileset delete
REM Disable Hibernation
powercfg -h off
  1. 传输文件
    在物理机内添加共享文件夹,权限改成 Everyone 并允许读取写入(如果你怕会被其他人截取则在映射网络驱动器时需要输入物理机的系统账户以登录到共享文件夹),然后在虚拟机内映射网络驱动器即可

  2. 其他
    你可以使用 Dism++ 手动添加所有驱动到 install.wimboot.wim,这样在安装过程中就不用这么麻烦
    或者将 Dism++ 等工具放在 Image.isovirtio-win.iso 里,这样可以在 Windows Setup 环境下解决问题
    ARM64 的 PE 或 Setup 可以运行 x64 的应用,无需额外支持(仅 Windows 11 及以上,Windows 10 仅支持运行 x86 应用)

  3. 缩短时间成本
    使用 VHD(X)(教程参阅管理虚拟硬盘 (VHD) | Microsoft Learn) 作为硬盘,在宿主机内往 VHD(X) 创建分区(教程参阅 UEFI 使用 DISM 命令安装系统章节中 #操作磁盘 的部分),再使用 Dism++ 释放映像到 VHD(X),再在 QEMU 中引导到 Windows 镜像后,使用 drvload 命令添加硬盘驱动,修复引导(教程参阅 UEFI 使用 DISM 命令安装系统章节中 #修复引导 的部分),完成后重启,即可解决安装过程过慢的问题

  4. PE 或 Setup 无驱动情况下加载驱动
    在 PE 或 Setup 下,可以使用 drvload 命令来加载驱动

更多关于 Devload 的命令,请参阅 Drvload 命令行选项 | Microsoft Learn

1
drvload "path\to\fileName.inf"

示例如下(可使用 tree 或 dir 命令来列出文件夹内容)

1
drvload "E:\viostor\w11\ARM64\viostor.inf"

参考文献

  1. BetaWorld Wiki(由此改编)
  2. 封面:BetaWorld Wiki
  3. FAQ | Windows on R
  4. 51CTO 博客 —— 党志强