在折腾上一篇文章的时候,发现了一条有趣的折腾分支,在这台老设备上运行 Windows 操作系统。
看起来应该蛮有趣的,那么就折腾一下吧。
写在前面
最早知道 WoA(Windows on ARM) 项目,是 2020 看到这篇报道:在 Lumia 950XL 上运行 Windows 10 ARM64 版。不过,当时的项目完善程度、和我的设备匹配度,都没有那么高。
在写完上篇文章《Docker 加持的 安卓手机:随身携带的知识库(一)》后,发现了 K20 Pro 芯片(Snapdragon 855)对应的 WoA 项目:woa-msmnile,这是一个聚集了将 “woa” 移植到 SM8150 和其他较新芯片的开源项目组织。
翻阅项目相关动态,发现项目的完善度还蛮高的,这不得试试看嘛!
本篇文章,有参考和改进社区另外一个项目 woa-raphael/woa-raphael中的文档(2024 年),当文章完全写完后,我会对项目发起“完善 PR”。
以及,参考了更早时候(2021 年)的 edk2-porting 开源项目的社区用户 Chr_ 的实践过程。
在这篇文章里,我会尽量将其中琐碎的、容易疏忽的坑一并记录下来,选择使用稳定可复现的环境来进行,明确每一步命令的因果联系,希望对喜欢折腾的你有用。
关于 WoA msmnile
项目组织中有非常多的仓库和文档,但是任何文档(包括文档站)都没有主要的项目 woa-msmnile/msmnilePkg 中更新的快。所以,在折腾的时候,我们可以始终以它为准。
在这个主要项目的文档中,我们可以发现它主要支持了四类芯片的手机,其中支持 DSDT、设备支持度好的有:
- 2019 年出品的 Qualcomm Snapdragon 855,代号:SM8150。
- 比如:ASUS ROG2、LG G8 和 V50 系列、Nubia Mini 5G、OnePlus 7 系列、OPPO Reno ACE、Realme X3、三星 S10 和 Fold、三星 Tab S6 系列、小米 9、小米 K20 Pro、小米 Mix3、小米 Pad 5,以及小米 Poco X3 Pro、高通 QRD 855。
- 2020 年出品的 Qualcomm Snapdragon 720G,代号:SM7125。
- 包含:小米 Note 9S、高通 QRD 778。
- 2021 年出品的 Qualcomm Snapdragon 888,代号:SM8350。
- 包含:三星 Z Fold 3 5G、ZTE A31 Pro、高通 MTP 888。
- 2021 和 2022 年出品的 Qualcomm Snapdragon 778G/778G+/782G, 代号:SM7325。
- 包含:高通 QRD 778。
本文验证设备 K20Pro 的相关开源项目的主要维护者,分别是来自摩洛哥的 @degdag (将适配硬件的 Linux 主线项目 degdag/sm8150-mainline 维护到了 6.0 版本)和来自福建的 @sunflower2333(woa-msmnile/msmnilePkg项目的主要维护者),感谢他们的无私付出。
准备工作
因为每个人的设备状况会有不同,如果你已经做了下面的一些工作,部分步骤就绪,可以选择性的略过。
在执行命令的时候,请胆大心细,勤做备份。我个人建议在折腾的时候,一条一条命令地执行,等待必要的执行结果返回,再执行下一条命令。
安卓开发工具和手机引导环境
我们所需要的安卓开发调试工具(ADB)和 Fastboot 相关的资源,可以在安卓开发者官方网站找到,platform-tools。
根据你的具体操作系统环境,下载对应的工具版本即可。本文中,我是在 macOS 上进行操作,选择的是 macOS 软件版本。
为手机刷入 TWRP 恢复环境
这次刷机的时候,当我再次查看 TWRP 的 K20 Pro 子项目页面时,发现这台设备的引导程序竟然还有新版本。
在 TWRP Raphael 的 GitHub 项目页面中,除了能够看到这台手机设备的硬件详情之外,能够发现目前这个引导程序已经能够支持 Android 12、13、14 啦。
不过,如果你的 K20 Pro 安装的是低于 Android 12 的操作系统,那么你需要使用下载页面中后缀是 9-0-raphael.img
的引导文件。
这里,我以高版本的引导文件为例:
引导对于折腾手机非常重要,所以建议在下载后,进行必要的 Hash 校验,确保下载文件是完整、有效的。
# 查看官方提供的校验值
# cat twrp-3.7.1_12-0-raphael.img.sha256
483a448620146aaa79c30ca1cdc4c2de2172c00401a5e93616d6f76c12bb2480 twrp-3.7.1_12-0-raphael.img
# 计算下载文件的校验值
# shasum -a 256 twrp-3.7.1_12-0-raphael.img
483a448620146aaa79c30ca1cdc4c2de2172c00401a5e93616d6f76c12bb2480 twrp-3.7.1_12-0-raphael.img
将手机和电脑使用数据线连在一起,先执行命令将手机切换到 fastboot
模式:
adb reboot bootloader
接着,将下载的引导镜像刷入手机:
# fastboot flash recovery twrp-3.7.1_12-0-raphael.img
Sending 'recovery' (65536 KB) OKAY [ 1.663s]
Writing 'recovery' OKAY [ 0.259s]
Finished. Total time: 1.944s
然后,重启手机即可开始验证 TWRP 是否刷写正确:
# fastboot reboot
Rebooting OKAY [ 0.002s]
Finished. Total time: 0.002s
最后,长按关机键盘和音量键上,我们就能够看到你刷入的指定版本的 TWRP 啦。
备份手机数据和固件数据
我个人不推荐使用正在使用的手机来折腾,如果你一定要这么做,请先妥善的备份这台手机上的数据,以免过程中出现意外,后悔莫及。
关闭手机,长按音量上键和电源键,进入手机的 TWRP 模式,然后点击备份,我个人建议至少备份 boot
、Modem
、EFS
目录。
当备份结束后,我们找到备份日志里的目录,将备份文件下载到本地电脑里以防万一,比如 TWRP 备份路径是这个:
/data/media/0/TWRP/BACKUPS/42cba029/2024-05-04--03-47-15_QQ3A200805001/
那么,我们可以用下面的命令,来一键从手机上拖下来各种备份文件:
# adb shell "ls /data/media/0/TWRP/BACKUPS/42cba029/2024-05-04--03-47-15_QQ3A200805001/" | xargs -I {} adb pull /data/media/0/TWRP/BACKUPS/42cba029/2024-05-04--03-47-15_QQ3A200805001/{} .
/data/media/0/TWRP/BACKUPS/42cba029/2024-05-04--03-47-15_QQ3A200805001/bluetooth.emmc.win: 1 file pulled, 0 skipped. 33.8 MB/s (1048576 bytes in 0.030s)
/data/media/0/TWRP/BACKUPS/42cba029/2024-05-04--03-47-15_QQ3A200805001/bluetooth.emmc.win.sha2: 1 file pulled, 0 skipped. 0.1 MB/s (85 bytes in 0.002s)
/data/media/0/TWRP/BACKUPS/42cba029/2024-05-04--03-47-15_QQ3A200805001/boot.emmc.win: 1 file pulled, 0 skipped. 41.1 MB/s (134217728 bytes in 3.112s)
...
备份完毕手机固件后,我们就可以甩开膀子折腾了。
下载适配手机的 UEFI 镜像
截止我这篇文章写完,目前 UEFI 项目最新的稳定版本是 releases/2402.86。这篇文章使用的 K20 Pro 对应的 UEFI 镜像非常小,只有 3MB:xiaomi-raphael_NOSB.img。
下载这个文件到本地,我们稍后使用。
下载一个用于初步验证的 ARM PE
今年一月份,远景上有一位网友出于 ARM 环境没有可以用于维护系统的 PE,开始发布并迭代 CNBYDJ PE,截止上个月,版本已经更新到了 v1.4,我们可以在 PE 网站下载到最新版本的 ISO 镜像文件。
下载“CNBYDJ PE-V1.4.iso
”到本地,同样稍后使用。
实践开始
接下来,我们首先来完成 Windows 安装环境的初始化准备,以及确保手机可以被引导至 Windows 环境(PE环境)。
第一步:调整分区表
我们首先需要使用 sgdisk(环境内置,无需下载),来调整分区表,来解锁默认分区的限制。
当然,任何时候,都不建议“摸黑”操作,先执行来了解下设备的分区表状况:
adb shell "sgdisk --print /dev/block/sda"
命令执行完毕,我们将看到类似下面的结果:
Disk /dev/block/sda: 123365376 sectors, 470.6 GiB
Logical sector size: 4096 bytes
Disk identifier (GUID): A5701557-F489-826C-FA44-357608497E4A
Partition table holds up to 32 entries
First usable sector is 6, last usable sector is 123365370
Partitions will be aligned on 2-sector boundaries
Total free space is 0 sectors (0 bytes)
Number Start (sector) End (sector) Size Code Name
1 6 7 8.0 KiB FFFF switch
2 8 15 32.0 KiB FFFF ssd
3 16 23 32.0 KiB FFFF dbg
4 24 31 32.0 KiB FFFF bk01
5 32 63 128.0 KiB FFFF bk02
6 64 127 256.0 KiB FFFF bk03
7 128 255 512.0 KiB FFFF bk04
8 256 383 512.0 KiB FFFF keystore
9 384 511 512.0 KiB FFFF frp
10 512 1023 2.0 MiB FFFF bk05
11 1024 2047 4.0 MiB FFFF misc
12 2048 3071 4.0 MiB FFFF vm-data
13 3072 4095 4.0 MiB FFFF bk06
14 4096 6143 8.0 MiB FFFF logfs
15 6144 8191 8.0 MiB FFFF bk07
16 8192 12287 16.0 MiB FFFF oops
17 12288 16383 16.0 MiB FFFF devinfo
18 16384 20479 16.0 MiB FFFF oem_misc1
19 20480 24575 16.0 MiB FFFF metadata
20 24576 32603 31.4 MiB FFFF bk08
21 32604 40959 32.6 MiB FFFF splash
22 40960 49151 32.0 MiB FFFF bk09
23 49152 65535 64.0 MiB FFFF persist
24 65536 81919 64.0 MiB FFFF persistbak
25 81920 98303 64.0 MiB FFFF logdump
26 98304 131071 128.0 MiB FFFF minidump
27 131072 163839 128.0 MiB FFFF rawdump
28 163840 180223 64.0 MiB FFFF recovery
29 180224 245759 256.0 MiB FFFF cache
30 245760 507903 1024.0 MiB FFFF cust
31 507904 123365370 468.7 GiB FFFF userdata
顺手做一个分区表备份,并将备份的结果保存到本地计算机:
# adb shell "sgdisk --backup=sgdisk-sda.bin /dev/block/sda"
The operation has completed successfully.
# adb pull sgdisk-sda.bin .
sgdisk-sda.bin: 1 file pulled, 0 skipped. 2.5 MB/s (5632 bytes in 0.002s)
我们可以先执行下面的命令,来扩大允许的分区表数量,避免后续执行过程中出现异常情况(比如允许 128 个分区项目存在):
adb shell sgdisk --resize-table=128 /dev/block/sda
命令执行完毕,我们将看到下面的日志结果:
# adb shell sgdisk --resize-table=128 /dev/block/sda
Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot.
The operation has completed successfully.
完成了分区表的调整和备份后,就可以开始对磁盘分区进行调整啦。
第二步:对手机进行分区调整
我们可以借助 Parted,来在手机上进行分区操作,来准备 Windows 的安装分区,raphael-partitioning/parted。
默认情况下,手机的 sbin
目录只有 bash
和 sh
:
# adb shell "ls /sbin/"
bash
sh
我们通过 adb push
将下载好的分区工具传到手机里:
# 上传工具到手机里
# adb push ./parted /sbin/
./parted: 1 file pushed, 0 skipped. 162.7 MB/s (922984 bytes in 0.005s)
# 赋予可执行权限
# adb shell "chmod +x /sbin/parted"
# 再次查看目录,就有 `parted` 工具啦
# adb shell "ls /sbin/"
bash
parted
sh
接下来,我们使用 parted
对现有的分区进行调整,先进入交互式命令行中:
adb shell parted /dev/block/sda
输入 print
,回车,我们能够得到磁盘的当前状况:
# print
Model: SAMSUNG KLUFG8R1EM-B0C1 (scsi)
Disk /dev/block/sda: 505GB
Sector size (logical/physical): 4096B/4096B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
1 24.6kB 32.8kB 8192B switch
2 32.8kB 65.5kB 32.8kB ssd
3 65.5kB 98.3kB 32.8kB dbg
4 98.3kB 131kB 32.8kB bk01
5 131kB 262kB 131kB bk02
6 262kB 524kB 262kB bk03
7 524kB 1049kB 524kB bk04
8 1049kB 1573kB 524kB keystore
9 1573kB 2097kB 524kB frp
10 2097kB 4194kB 2097kB bk05
11 4194kB 8389kB 4194kB misc
12 8389kB 12.6MB 4194kB vm-data
13 12.6MB 16.8MB 4194kB bk06
14 16.8MB 25.2MB 8389kB logfs
15 25.2MB 33.6MB 8389kB bk07
16 33.6MB 50.3MB 16.8MB oops
17 50.3MB 67.1MB 16.8MB devinfo
18 67.1MB 83.9MB 16.8MB oem_misc1
19 83.9MB 101MB 16.8MB ext4 metadata
20 101MB 134MB 32.9MB bk08
21 134MB 168MB 34.2MB splash
22 168MB 201MB 33.6MB bk09
23 201MB 268MB 67.1MB ext4 persist
24 268MB 336MB 67.1MB ext4 persistbak
25 336MB 403MB 67.1MB logdump
26 403MB 537MB 134MB minidump
27 537MB 671MB 134MB rawdump
28 671MB 738MB 67.1MB recovery
29 738MB 1007MB 268MB ext4 cache
30 1007MB 2080MB 1074MB ext4 cust
31 2080MB 505GB 503GB ext4 userdata
和上面使用 sgdisk 获取的数据类似,但是尺寸的计算方式有些差别,导致了展示大小有些差异。与此同时,我们也能够清晰的看到,我们这台设备使用的是一块 UFS 2.1 规格的三星硬盘:KLUFG8R1EM-B0C1,建议最高运行温度是不超过 85 度。未来实际使用的时候,我们需要尽量避免手机温度过高。
言归正传,通常情况,userdata
分区将会是列表中最后一个分区。我们需要短暂的记录下 userdata
分区的编号,稍后要使用,我这里展示的编号是 31
。
我们在手机中的 TWRP 界面选择“挂载”功能,确保没有挂载 Data 分区,然后执行命令,调整分区尺寸:
# 31 替换为你的 UserData 分区编号
resizepart 31
命令正确执行后,分区工具会询问想要调整的尺寸:
End? [505GB]?
如果你没有看到上面的对话提示,那么你需要在 TWRP 中卸载“Data”分区的挂载,或者手动输入命令,卸载分区,然后再次执行上面的命令:
adb shell umount /data/
因为我的不打算在这台设备上再深度使用 Android,就和社区文档推荐的保持一致,输入 32GB
并按下回车。当软件再次向我们确认的时候,输入 Yes
确认我们的选择即可。
#End? [505GB]? 32GB
32GB
Warning: Shrinking a partition can cause data loss, are you sure you want to
continue?
Yes/No? Yes
# Yes
我们再次输入 p free
查看分区大小,可以发现 userdata
就已经听话的缩容到 32GB 了。并且,在这个分区后,我们有了一个 473GB 空闲磁盘空间,可以用于安装 Windows 系统。
31 2080MB 32.0GB 29.9GB ext4 userdata
32.0GB 505GB 473GB Free Space
接下来,来创建一个紧贴着 userdata
分区的 esp
分区。因为 userdata
分区尺寸是 32GB(磁盘结束位置),所以,我们可以使用下面的命令,来创建一个尺寸为 500MB
的小巧 ESP 分区:
mkpart esp fat32 32GB 32.5GB
ESP 分区紧贴着的上一个分区 userdata
分区编号为 31,所以我们给 ESP 分区编号的时候,就需要设置为 32
:
set 32 esp on
再次使用 p feee
命令查看分区状况,能够看到我们上面命令的执行都生效了:
31 2080MB 32.0GB 29.9GB ext4 userdata
32.0GB 32.0GB 438kB Free Space
32 32.0GB 32.5GB 499MB fat32 esp boot, esp
32.5GB 505GB 473GB Free Space
我们继续操作,来创建存放 Windows 的磁盘。结合上面的 esp
分区的结束位置(32.5GB
)和整个磁盘大小505GB
:
mkpart win ntfs 32.5GB 485GB
这里我没有选择完整的占满整个磁盘,而是预留了 20GB 给后续 PE 维护系统使用(505GB-20GB=485GB
)。
当所有命令都执行就绪,输入 quit
或者按下 CTRL + D 组合键来退出 parted
交互环境。
接着,在手机上的 TWRP 中选择“清除”、“格式化 Data”分区。然后重启手机,等待手机“恢复出厂设置”完毕,进入手机将能看到一台容量只有 32GB 的手机。
至此,基础的分区调整就结束啦。
第三步:安装 ARM PE 环境
因为安装 Windows 系统,不可避免的要使用 Windows 环境下的程序,为了便宜行事,我们再次重启手机到 TWRP 环境,折腾 PE 系统使用的磁盘分区,来获得一个能够安装 Windows 使用的操作环境。
依旧是参考上文中的方法,展开对 /dev/block/sda
磁盘的攻势:
adb push ./parted /sbin/
adb shell "chmod +x /sbin/parted"
adb shell parted /dev/block/sda
输入 p free
能够看到分区状况如下:
31 2080MB 32.0GB 29.9GB ext4 userdata
32.0GB 32.0GB 438kB Free Space
32 32.0GB 32.5GB 499MB fat32 esp boot, esp
33 32.5GB 485GB 453GB ntfs win msftdata
485GB 505GB 20.3GB Free Space
执行命令,创建一个分区给 ARM PE 使用:
mkpart armpe fat32 485GB 505GB
再次使用 p free
查看,磁盘分区就都准备就绪啦:
32 32.0GB 32.5GB 499MB esp boot, esp
33 32.5GB 485GB 453GB win msftdata
34 485GB 505GB 20.3GB fat32 armpe msftdata
505GB 505GB 1028kB Free Space
重启手机,再次进入 TWRP 环境后,在 adb shell
环境中,我们将 ARM PE 分区初始化为 fat32
格式,将 PE 分区挂入手机系统。
# 格式化磁盘
# mkfs.fat -F32 -s1 /dev/block/by-name/armpe
mkfs.fat 3.0.28 (2015-05-16)
# 挂载到设备中
mkdir -p /armpe
mount /dev/block/by-name/armpe /armpe/
然后,将上文中我们下载好的 ARM PE 的 .iso
文件中的内容解压缩到本地计算机,并上传到这个分区内:
# 挂载 ISO 文件内容
# hdiutil attach CNBYDJ\ PE-V1.4.iso
/dev/disk4 /Volumes/CNBYDJ PE-V1.4
# 切换工作目录
# cd /Volumes/CNBYDJ\ PE-V1.4
# 查看光盘内容
# ls
CNBYDJ.ico autorun.inf boot bootmgr.efi efi sources
# 将光盘内容推送到 PE 分区
adb push boot /armpe/
adb push bootmgr.efi /armpe/
adb push efi /armpe/
adb push sources /armpe/
# 切换工作目录
cd -
# 弹出光盘
hdiutil detach disk4
将 PE 镜像中的内容上传到手机之后,PE 系统的安装就完成了一半啦。
第四步:更换手机启动引导方式为 UEFI
我们在手机的 TWRP 中选择“重启”,重启到 “Fastboot” 模式。或者手机关机状态下,选择长按“音量减”和“电源按键”,启动到 “Fastboot” 模式。
接着,执行 fastboot flash
命令,完成手机的“启动管理器”的更新:
# fastboot flash boot /Users/soulteary/Downloads/xiaomi-raphael_NOSB.img
Sending 'boot' (3088 KB) OKAY [ 0.077s]
Writing 'boot' OKAY [ 0.030s]
Finished. Total time: 0.131s
当刷新完毕,执行 fastboot reboot
或者手动重启手机,手机重新启动后,UEFI 引导开始工作,我们就能够看到熟悉的“Windows 启动界面”啦。
稍等片刻,系统将引导至 PE 环境,我们将能够看到 Windows PE 的桌面环境。
最后
3月份的时候,媒体上有报道《突发,Windows再也不能安装安卓应用了》,微软官方停止了“适用于 Android 的 Windows 子系统”的支持,虽然 Windows 不能再安装 Android 应用了,但是 Android 手机可以偷家呀(哈哈)。
好了,就先写到这里,下一篇相关的文章我们将继续,进行正式的 Windows 环境的安装。
–EOF