尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

小米Mix2S移植EDK2-MS8998 UEFI固件实战:从启动到Windows 11 on ARM

小米Mix2S移植EDK2-MS8998 UEFI固件实战:从启动到Windows 11 on ARM 1. 为什么要在小米Mix2S上折腾UEFI手里这台小米Mix2S已经服役好几年了骁龙845放在今天跑个日常应用依然不卡但系统更新早就停了安卓这边的可玩性也越来越低。某天在技术社区闲逛看到有人讨论给老手机移植UEFI固件让ARM设备跑起Windows 11 on ARM我一下子来了兴趣。小米Mix2S这台机器在社区里的资料相对齐全骁龙845的芯片组文档也有不少公开内容可以参考于是决定拿它开刀。这个项目的核心目标很明确用EDK2-MS8998这个开源UEFI固件项目给小米Mix2S移植一套能启动的UEFI环境最终目标是让这台手机能够引导进入Windows 11 on ARM的安装界面。听起来很疯狂但技术上确实有路径可循。EDK2是Intel主导的开源UEFI开发框架MS8998则是针对骁龙845MSM8998平台的移植分支社区里已经有人在高通平台的其他设备上做过类似尝试。适合谁来参考这篇内容如果你对嵌入式开发、UEFI固件、ARM平台启动流程有一定了解或者单纯是个喜欢折腾老设备的玩家这篇分享应该能给你不少参考。我会尽量把每一步的操作意图和背后的原理讲清楚让不同基础的朋友都能跟上节奏。需要提前说明的是这个过程涉及底层固件操作有一定风险操作不当可能导致设备变砖请务必做好数据备份和心理准备。2. 项目整体设计与技术选型拆解2.1 为什么选EDK2-MS8998而不是其他方案给ARM设备移植UEFI市面上其实有几条路可以走。一条是使用现成的商业UEFI固件比如某些厂商提供的参考实现但这类固件通常不对外开放适配成本极高。另一条是自己从零写一个简单的引导程序但工作量巨大而且兼容性很难保证。EDK2-MS8998的优势在于它基于成熟的EDK2框架已经包含了UEFI规范要求的大部分基础设施同时针对MSM8998平台做了底层适配包括时钟初始化、内存控制器配置、串口调试输出等关键模块。我对比过几个社区项目EDK2-MS8998的代码结构最清晰提交记录也比较活跃。它的目录组织遵循EDK2的标准布局Platform目录下有针对不同设备的配置文件Silicon目录下是高通平台的芯片组驱动。这种分层设计让移植工作变得有章可循——你只需要关注Platform层的设备特定配置底层驱动大部分可以直接复用。另一个关键考量是社区支持。EDK2-MS8998在技术社区里有专门的讨论帖遇到问题可以搜索到相关的解决方案。相比之下一些个人维护的移植项目文档稀缺出了问题只能自己啃代码。对于我这种不是专业做固件开发的爱好者来说社区支持的重要性甚至超过了代码本身的质量。2.2 骁龙845平台的启动流程与UEFI的切入点理解骁龙845的启动流程是移植工作的前提。这颗芯片上电后首先运行的是芯片内部固化的一段引导代码然后加载外部存储中的引导程序。高通平台通常使用ABLApplication Bootloader作为二级引导程序它负责初始化关键硬件然后加载操作系统内核。我们的目标是用UEFI固件替换掉ABL或者作为ABL的下一级加载目标。具体来说骁龙845的启动链路大致是这样的PBLPrimary Bootloader从存储中加载XBLeXtensible BootloaderXBL完成DDR初始化和基本外设配置后加载ABLABL再根据配置加载bootloader或直接启动内核。EDK2-MS8998要做的就是把自己嵌入到这个链条中接管ABL之后的控制权提供一个符合UEFI规范的运行环境。这里有个技术难点UEFI规范要求固件在启动时完成一系列硬件初始化包括内存管理、中断控制器、定时器等。而高通平台的ABL已经做了部分初始化工作我们需要在EDK2中重新做一遍或者复用ABL的初始化结果。EDK2-MS8998的做法是尽量复用XBL和ABL已经完成的初始化只补充UEFI运行所需的最小硬件配置这样可以减少工作量也降低出错概率。2.3 目标设备小米Mix2S的硬件特性分析小米Mix2S搭载的骁龙845具体型号是MSM8998八核Kryo 385架构Adreno 630 GPU搭配6GB或8GB LPDDR4X内存存储为UFS 2.1。这些硬件参数决定了我们在EDK2中需要配置的内存控制器参数、存储驱动和显示输出方式。内存方面LPDDR4X的初始化参数需要根据具体的内存颗粒型号来调整。小米Mix2S使用的内存颗粒可能与其他骁龙845设备不同所以不能直接照搬其他设备的配置文件。我的做法是先从小米官方内核源码中提取内存时序参数然后对照EDK2-MS8998中现有的配置文件进行修改。这个过程需要反复调试因为内存参数不对的话设备连最基本的串口输出都不会有。存储方面UFS 2.1的驱动在EDK2-MS8998中已经有实现但需要确认小米Mix2S的UFS控制器配置是否匹配。显示输出是个麻烦事UEFI规范要求有图形输出协议但手机屏幕的MIPI DSI接口在EDK2中的驱动支持有限。我的方案是先用串口作为主要调试输出等系统基本跑通后再考虑显示适配。3. 开发环境搭建与核心工具链配置3.1 编译EDK2-MS8998所需的工具链安装编译EDK2需要一套完整的工具链包括交叉编译器、Python环境和EDK2自身的构建工具。我使用的是Ubuntu 20.04作为开发主机这个版本的系统库比较稳定社区里遇到的兼容性问题也少。首先安装基础依赖sudo apt update sudo apt install build-essential uuid-dev iasl git nasm python3-distutils gcc-aarch64-linux-gnu这里解释一下每个包的作用。build-essential提供基础的编译工具uuid-dev是EDK2构建系统需要的UUID库iasl是ACPI编译器EDK2在生成ACPI表时会用到nasm是汇编器gcc-aarch64-linux-gnu是ARM64交叉编译器用来编译目标平台的代码。python3-distutils是EDK2的构建脚本依赖的Python模块。安装完依赖后需要配置EDK2的构建环境。进入EDK2-MS8998的根目录执行source edksetup.sh这个脚本会设置环境变量包括WORKSPACE、EDK_TOOLS_PATH等。然后编译BaseToolsmake -C BaseToolsBaseTools是EDK2的构建工具集包括代码生成器、固件卷打包工具等。编译过程大概需要几分钟完成后就可以开始配置目标平台的构建参数了。3.2 目标平台配置文件的关键参数解读EDK2-MS8998的Platform目录下有针对不同设备的配置文件通常以.dsc平台描述文件和.fdf固件描述文件的形式存在。.dsc文件定义了平台包含哪些模块、使用哪些库、编译选项是什么。.fdf文件定义了固件卷的布局即各个模块在最终固件镜像中的位置和排列顺序。以MSM8998的参考配置为例关键参数包括PcdMsm8998MemoryBase和PcdMsm8998MemorySize定义内存的基地址和大小需要根据小米Mix2S的实际内存布局来设置。PcdMsm8998UartBase串口控制器的基地址用于调试输出。小米Mix2S的串口引脚可能没有引出但我们可以通过USB转串口工具或者利用设备的调试接口来获取输出。PcdMsm8998UfsBaseUFS控制器的基地址用于存储访问。这些PCDPlatform Configuration Database参数是EDK2中传递平台配置信息的主要方式。修改这些参数时需要参考高通提供的芯片组文档和小米Mix2S的硬件原理图。原理图在网上可以找到泄露版但使用时要注意甄别信息的准确性。3.3 串口调试环境的搭建与验证串口输出是固件开发中最重要的调试手段。在设备还没有显示输出的时候串口是唯一能告诉你固件运行到哪一步、哪里出了问题的通道。小米Mix2S的串口调试需要拆机找到主板上的TX、RX和GND测试点然后焊接细线引出。我使用的是CP2102 USB转串口模块波特率设置为1152008位数据位无校验1位停止位。连接时注意TX接RX、RX接TXGND对接。上电后如果串口有输出说明固件至少运行到了串口初始化阶段。注意焊接串口线时一定要断电操作焊接完成后先用万用表确认没有短路再上电。我第一次操作时因为焊锡渣导致TX和GND短路上电后设备直接保护关机幸好没有烧毁芯片。串口输出的内容需要仔细解读。EDK2在启动过程中会打印大量的调试信息包括PEI阶段的内存初始化、DXE阶段的驱动加载等。如果串口输出在某一步卡住就可以定位到对应的模块进行排查。4. 移植过程中的核心环节与实操记录4.1 内存初始化参数的提取与适配内存初始化是移植过程中最关键也最容易出问题的环节。骁龙845的内存控制器非常复杂涉及大量的时序参数包括tRCD、tRP、tRAS、tRFC等。这些参数如果设置错误轻则系统不稳定重则根本无法启动。我的做法是从小米官方发布的内核源码中提取内存参数。小米Mix2S的内核源码在GitHub上有公开仓库其中arch/arm64/boot/dts/qcom/目录下的设备树文件包含了内存控制器的配置信息。具体来说msm8998-mtp.dtsi和msm8998-mix2s.dtsi这两个文件里有内存时序相关的节点。提取到参数后需要将它们填入EDK2-MS8998的内存初始化代码中。这部分代码通常在Silicon/Qualcomm/Msm8998/Drivers/MemoryInit/目录下。代码中会有一个结构体数组每个元素对应一组内存参数。我需要根据小米Mix2S的实际配置修改这些参数值。这里有个经验不要一次性修改所有参数而是先保持大部分参数与参考配置一致只修改明显不同的部分比如内存大小和频率。每次修改后都要通过串口输出验证内存初始化是否成功。EDK2的内存初始化代码会在成功后打印内存大小和频率信息如果看到这些输出说明内存初始化基本正确。4.2 UFS存储驱动的适配与分区表处理UFS存储的适配相对内存来说要简单一些因为UFS协议是标准化的EDK2-MS8998中的UFS驱动已经实现了大部分功能。主要需要确认的是UFS控制器的基地址和时钟配置是否与小米Mix2S匹配。在设备树文件中UFS控制器的节点通常标记为ufshc里面包含了寄存器基地址、时钟频率、PHY配置等信息。我将这些信息与EDK2中的UFS驱动配置进行对照发现基地址是一致的但时钟配置有差异。小米Mix2S的UFS时钟频率与参考设备不同需要修改PcdMsm8998UfsClockFreq参数。分区表处理是另一个需要关注的点。UEFI规范要求固件能够识别FAT格式的分区以便加载EFI应用程序。小米Mix2S的原生分区表是GPT格式但分区内容都是安卓系统的镜像。我的做法是在UFS上单独划分一个FAT32分区用于存放UEFI应用程序和Windows安装镜像。提示修改分区表会清除设备上的所有数据操作前务必备份重要内容。我使用sgdisk工具在Linux下操作UFS设备命令是sgdisk --new1:0:512M --typecode1:ef00 /dev/sdX其中ef00是EFI系统分区的类型代码。4.3 显示输出的初步适配与串口回退方案显示输出是UEFI体验的重要组成部分但也是手机平台移植中最困难的部分之一。小米Mix2S的屏幕是MIPI DSI接口EDK2-MS8998中的显示驱动主要针对HDMI或DisplayPort对MIPI DSI的支持有限。我尝试了几种方案。第一种是直接使用EDK2的Graphics Output Protocol但发现没有对应的MIPI DSI驱动屏幕完全不亮。第二种是移植Linux内核中的MIPI DSI驱动到EDK2环境但工作量太大涉及中断处理、DMA等机制的适配短期内难以完成。最终我采用了串口回退方案在显示驱动没有调通之前所有调试信息都通过串口输出。UEFI应用程序可以通过串口进行交互虽然体验不如图形界面但足以完成基本的启动和安装操作。等系统基本稳定后再考虑显示适配的问题。4.4 构建固件镜像并刷入设备所有配置修改完成后就可以构建固件镜像了。在EDK2-MS8998根目录下执行build -p Platform/Qualcomm/Msm8998/Msm8998Pkg.dsc -a AARCH64 -t GCC5 -b DEBUG这个命令会编译平台描述文件中定义的所有模块生成一个.fd格式的固件镜像。-a AARCH64指定目标架构为ARM64-t GCC5指定使用GCC5工具链-b DEBUG表示构建调试版本包含详细的调试输出。生成的固件镜像位于Build/Msm8998Pkg/DEBUG_GCC5/FV/目录下文件名通常是MSM8998_EFI.fd。这个镜像需要刷入设备的引导分区。刷入方式有两种一种是通过高通的QPST工具在EDL模式下刷入另一种是通过fastboot刷入到boot分区。我使用的是fastboot方式因为小米Mix2S的bootloader支持fastboot刷写。命令是fastboot flash boot MSM8998_EFI.fd刷入完成后重启设备如果串口有输出说明固件已经开始运行。第一次启动时可能会遇到各种问题比如卡在某个初始化阶段、反复重启等这些都是正常的需要根据串口输出逐步排查。5. 常见问题排查与避坑经验实录5.1 串口无输出问题的排查思路串口无输出是最常见的问题可能的原因有很多。我的排查顺序是这样的首先确认硬件连接是否正确。TX和RX是否接反、GND是否共地、波特率是否匹配。我用示波器测量过TX引脚发现上电后有波形输出但串口工具收不到最后发现是波特率设置错误实际输出是460800而不是115200。如果硬件连接没问题那就是固件没有运行到串口初始化阶段。这时候需要检查固件的入口点是否正确、内存初始化是否成功。可以在EDK2的入口函数中添加一个简单的GPIO翻转操作用LED或示波器观察是否有执行。如果GPIO有翻转说明固件至少运行到了入口点问题出在后续的初始化流程。还有一种可能是固件镜像没有正确刷入。fastboot刷写时如果分区大小不匹配可能会截断镜像。我遇到过刷入后设备直接进入fastboot模式的情况后来发现是镜像大小超过了boot分区容量换用更大的分区后问题解决。5.2 内存初始化失败的典型表现与修复内存初始化失败的表现通常是串口输出在内存初始化阶段卡住或者输出乱码。乱码往往是因为内存参数错误导致数据读写不稳定。我遇到过一次内存初始化后串口输出随机字符的情况排查后发现是tRFC参数设置过小。tRFC是刷新周期时间设置过小会导致内存刷新不及时数据丢失。参考小米官方内核中的参数将tRFC从350ns调整到420ns后输出就稳定了。另一个常见问题是内存大小识别错误。EDK2的内存初始化代码会根据SPD信息或者硬件配置来识别内存大小如果识别错误后续的内存分配就会出问题。我建议在内存初始化完成后手动打印一段已知模式的数据到内存中再读回来验证确保内存读写正常。5.3 UEFI应用程序加载失败的调试方法UEFI应用程序加载失败通常表现为固件启动后找不到启动项或者加载EFI文件时出错。排查这类问题首先要确认FAT分区是否正确挂载。可以在UEFI Shell中使用map命令查看所有块设备用fs0:切换到FAT分区用ls查看文件列表。如果分区挂载正常但应用程序加载失败可能是EFI文件本身的问题。ARM64平台的EFI应用程序需要编译为AARCH64架构我遇到过用x86编译器编译的EFI文件在ARM64上无法加载的情况。确认编译目标架构正确后问题解决。还有一种情况是应用程序依赖的协议没有实现。比如Windows安装程序需要Graphics Output Protocol来显示界面如果固件没有实现这个协议安装程序会直接退出。这时候需要先在EDK2中实现缺失的协议或者使用串口版本的安装程序。5.4 常见问题速查表问题现象可能原因排查方法解决方案串口无输出硬件连接错误检查TX/RX/GND连接和波特率重新焊接或调整波特率串口输出乱码内存参数错误对照官方内核参数检查时序调整tRFC等关键参数固件卡在PEI阶段内存初始化失败查看串口最后输出的模块名修正内存配置或降低频率找不到启动项FAT分区未识别UEFI Shell中执行map命令检查分区类型和文件系统EFI应用加载失败架构不匹配用file命令查看EFI文件架构重新编译为AARCH64设备反复重启看门狗未处理检查看门狗定时器配置在EDK2中禁用或喂狗注意每次修改配置后建议先构建DEBUG版本通过串口确认基本功能正常后再构建RELEASE版本。DEBUG版本虽然体积大、速度慢但调试信息丰富能帮你快速定位问题。6. 从UEFI到Windows 11的引导链路打通6.1 Windows 11 on ARM的启动要求分析Windows 11 on ARM对固件有一系列要求包括UEFI 2.7以上版本、ACPI 6.0以上版本、安全启动支持可选但推荐、以及特定的硬件抽象层。EDK2-MS8998提供的UEFI环境基本满足这些要求但ACPI表的完整性需要额外关注。Windows安装程序在启动时会检查ACPI表特别是MADT多处理器描述表、GTDT通用定时器描述表和IORTI/O重映射表。这些表描述了系统的中断控制器、定时器和DMA重映射单元。如果这些表缺失或格式错误安装程序会直接蓝屏。我的做法是从Linux内核的ACPI实现中提取这些表的模板然后根据小米Mix2S的硬件配置填充具体参数。比如MADT表中需要描述GIC控制器的基地址和中断号范围这些信息可以从设备树中获取。6.2 引导Windows安装介质的制作与配置制作Windows 11 on ARM的安装介质需要一台Windows电脑和一张容量足够的U盘。首先从微软官网下载Windows 11 on ARM的ISO镜像然后用Rufus或者类似的工具写入U盘。注意选择GPT分区方案和FAT32文件系统因为UEFI固件通常只识别FAT格式的分区。写入完成后还需要在U盘上添加ARM64的引导文件。Windows安装镜像中自带的引导文件是x86架构的在ARM64设备上无法运行。需要从Windows on ARM的安装镜像中提取bootaa64.efi文件放到U盘的EFI/Boot/目录下并重命名为bootaa64.efi。提示如果找不到bootaa64.efi可以从Windows 11 on ARM的ISO镜像中的efi/boot/目录下提取。这个文件是ARM64架构的UEFI引导程序负责加载Windows安装环境。6.3 引导过程中的ACPI表适配与驱动注入引导Windows安装程序时最常见的失败原因是ACPI表不完整。安装程序在启动初期会解析ACPI表如果发现缺少必要的表或者表内容有误会显示错误代码并停止。我遇到过一个典型问题安装程序提示“ACPI BIOS Error”排查后发现是MADT表中缺少GIC CPU接口的描述。在ARM64系统中每个CPU核心都需要在MADT表中有一个对应的GIC结构体描述其中断控制器接口。我参照Linux内核的ACPI实现补全了这些结构体问题解决。另一个问题是存储驱动。Windows安装程序需要能够访问UFS存储才能继续安装但Windows自带的UFS驱动可能不兼容小米Mix2S的UFS控制器。解决方案是在安装介质中注入对应的UFS驱动或者使用Windows的通用UFS驱动。我尝试了后者发现Windows 11 on ARM自带的UFS驱动能够识别小米Mix2S的UFS控制器但需要手动指定驱动路径。6.4 安装后的系统优化与已知问题Windows 11 on ARM安装完成后还需要进行一系列优化才能日常使用。首先是显示驱动由于MIPI DSI驱动没有适配系统只能通过串口或者网络远程桌面进行操作。其次是电源管理ARM平台的电源管理比较复杂Windows的电源管理驱动可能无法完全适配导致电池续航不理想。已知的问题还包括触摸屏无法使用、摄像头无法使用、音频输出异常等。这些问题都需要对应的驱动程序才能解决而目前社区里还没有完整的驱动包。我的建议是如果只是想体验Windows on ARM可以尝试这个方案如果需要日常使用还是建议使用原生安卓系统或者购买官方支持Windows on ARM的设备。7. 个人实操体会与后续可扩展方向整个移植过程断断续续花了将近两个月中间踩了无数坑也学到了很多东西。最大的体会是固件开发真的需要耐心和细致一个参数的错误就可能导致完全无法启动而排查问题的唯一手段就是串口输出。我建议想尝试这个项目的朋友一定要先把串口调试环境搭好这是后续所有工作的基础。另一个体会是社区的力量很重要。EDK2-MS8998项目本身提供了很好的基础但针对具体设备的适配还是需要自己动手。我在技术社区里找到了不少有用的讨论帖有些问题别人已经踩过坑直接参考他们的解决方案可以节省大量时间。后续可以扩展的方向有几个。一是完善显示驱动让系统能够直接在手机屏幕上显示而不是依赖串口。二是适配更多外设比如触摸屏、音频、摄像头等提升系统的可用性。三是优化电源管理让设备在运行Windows时也能有合理的续航表现。这些工作都需要投入大量时间但每一步的进展都会让这个项目更有实用价值。最后分享一个小技巧在调试EDK2时善用DEBUG宏和ASSERT宏。DEBUG宏可以在关键路径上打印调试信息ASSERT宏可以在条件不满足时主动中断帮助你快速定位问题。我在内存初始化代码中加了大量的DEBUG输出虽然串口日志很长但每次出问题都能快速找到对应的模块。
返回列表