<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>唐辫小二</title><description>文章、生活碎片与自己的小项目</description><link>https://larmaxharkerx.github.io/</link><language>zh_CN</language><item><title>AE 2026 + Red Giant Universe 中文参数乱码的修复记录</title><link>https://larmaxharkerx.github.io/posts/ae-2026-red-giant-universe-fix/</link><guid isPermaLink="true">https://larmaxharkerx.github.io/posts/ae-2026-red-giant-universe-fix/</guid><description>修复Maxon系列插件在AE2026的乱码问题</description><pubDate>Wed, 24 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;我原本只是开开心心重装了一下系统。&lt;/p&gt;
&lt;p&gt;系统干净了，软件重新装一遍，Adobe After Effects 2026 装上，Maxon App 装上，Red Giant / Universe 插件也重新装上。按理说这就是一套很常规的流程，没什么好写的。&lt;/p&gt;
&lt;p&gt;结果 AE 一打开，给我拉了一坨大的。 Red Giant Universe 的参数面板里，中文不是乱码，就是缺字，有些地方干脆只剩几个奇怪的符号。尤其是效果控件里的参数名，基本属于“看了也不知道自己在调什么”的状态。&lt;/p&gt;
&lt;p&gt;一开始我还以为是字体缺失、系统语言没装全、或者 AE 2026 哪个缓存坏了。后来才发现，Maxon 现在确实给 Red Giant / Universe 做了官方中文本地化，而且它会根据系统语言自动加载中文翻译文件。问题是，在 AE 这边，某些中文参数字符串会出现乱码、缺字或者显示异常。&lt;/p&gt;
&lt;p&gt;严格说，这件事不一定能完全甩锅给 Maxon。网上也有人反馈 AE 26.2 之后，第三方插件的非英文 UI 文本出现乱码，讨论里提到过 AE 对第三方插件字符串编码的处理变得更严格，可能导致旧编码、本地化文件、系统代码页之间互相打架。总之最后表现出来就是：官方中文是有了，但在我这里还不如纯英文能用。&lt;/p&gt;
&lt;p&gt;下面是我这次排查和修复的完整过程。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;先尝试：开启 Windows 的 UTF-8 Beta 支持&lt;/h2&gt;
&lt;p&gt;我最先想到的是 Windows 的编码设置。&lt;/p&gt;
&lt;p&gt;Windows 里有一个选项叫：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Beta 版：使用 Unicode UTF-8 提供全球语言支持&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这个选项以前主要是给一些非 Unicode 程序用的。既然现在的问题看起来像是中文编码炸了，那我就先试了一下。&lt;/p&gt;
&lt;p&gt;具体路径如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;按 Win + R&lt;/li&gt;
&lt;li&gt;输入：intl.cpl&lt;/li&gt;
&lt;li&gt;回车，打开“区域”窗口&lt;/li&gt;
&lt;li&gt;切到“管理”选项卡&lt;/li&gt;
&lt;li&gt;点击：  &lt;code&gt;更改系统区域设置(C)...&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;在弹出的窗口里勾选：&lt;code&gt;Beta 版：使用 Unicode UTF-8 提供全球语言支持&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;确定，然后重启电脑&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;注意，这里不是把系统区域改成英文，也不是把 Windows 显示语言改成英文。当前系统区域仍然可以保持：&lt;br /&gt;
&lt;code&gt;简体中文（中国大陆）&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;只是额外勾选 UTF-8 支持。&lt;/p&gt;
&lt;p&gt;但是实际测试下来，这个办法只恢复了一部分显示。比如某些按钮、某些插件面板看起来正常了一点，但 AE 效果控件里的参数名还是会乱码、缺字或者显示不完整。&lt;/p&gt;
&lt;p&gt;也就是说，UTF-8 这个开关在我的环境里不是最终解法。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;真正的思路：让 Universe 找不到中文翻译文件，自动回退英文&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;继续查资料后，我发现 Maxon 的 Red Giant 插件本地化并不是写死在插件本体里，而是通过一堆 JSON 翻译文件来加载的。&lt;/p&gt;
&lt;p&gt;也就是说，插件启动时会根据当前语言环境去找对应语言文件。例如简体中文就是：&lt;br /&gt;
&lt;code&gt;zh-CN.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;如果这个文件不存在，插件就会回退到英文。&lt;/p&gt;
&lt;p&gt;这就简单了：不用改系统语言，不用重装 AE，不用卸载 Red Giant，也不用动插件本体。只要把中文翻译 JSON 改名，让 Universe 找不到它，就能让参数面板回到英文。&lt;/p&gt;
&lt;p&gt;这里的关键是：不要乱删文件，直接改名就行。这样以后想恢复中文，也可以改回来。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;先定位 Red Giant / Universe 的翻译文件&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;我先用 PowerShell 查了一下 Maxon 的翻译目录。&lt;/p&gt;
&lt;p&gt;打开管理员 PowerShell，执行：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Get-ChildItem &quot;C:\ProgramData\Maxon&quot; -Recurse -Directory -Filter &quot;translations&quot; | ForEach-Object { &quot;`n==== $($_.FullName) ====&quot; Get-ChildItem $_.FullName -File | Select-Object Name }&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;一开始我看到：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;C:\ProgramData\Maxon\Universe\translations&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这个目录表面上是空的。&lt;/p&gt;
&lt;p&gt;但这其实有点误导，因为 Universe 的翻译文件不是直接放在这个根目录里，而是藏在更深的子目录里。&lt;/p&gt;
&lt;p&gt;于是我继续递归搜索，最后发现 Universe 的每个插件都有自己的翻译文件。以我出问题的 VHS 插件为例，它的路径是：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;C:\ProgramData\Maxon\Universe\translations\plugins\Universe_Stylize_VHS\ecw\zh-CN.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这个文件就是 VHS 在 AE 效果控件里显示中文参数名的来源。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;单独修复 VHS 插件&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;为了避免误伤，我没有一上来就批量改所有文件，而是先只改 VHS 这一个插件。&lt;/p&gt;
&lt;p&gt;管理员 PowerShell 执行：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$dir = &quot;C:\ProgramData\Maxon\Universe\translations\plugins\Universe_Stylize_VHS\ecw&quot; Get-ChildItem $dir -File | Sort-Object Name&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;正常情况下，里面会看到类似这些文件：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;de-DE.json en-US.json ja-JP.json ko-KR.json pt-BR.json zh-CN.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;其中：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;zh-CN.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;就是简体中文翻译文件。&lt;/p&gt;
&lt;p&gt;正式修改前，我先用 -WhatIf 预览了一下，确认它只会改这一个文件：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Rename-Item ` -LiteralPath &quot;C:\ProgramData\Maxon\Universe\translations\plugins\Universe_Stylize_VHS\ecw\zh-CN.json&quot; ` -NewName &quot;zh-CN.json.disabled&quot; ` -WhatIf&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;确认没问题后，执行正式改名：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Rename-Item ` -LiteralPath &quot;C:\ProgramData\Maxon\Universe\translations\plugins\Universe_Stylize_VHS\ecw\zh-CN.json&quot; ` -NewName &quot;zh-CN.json.disabled&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;再检查一下目录：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Get-ChildItem &quot;C:\ProgramData\Maxon\Universe\translations\plugins\Universe_Stylize_VHS\ecw&quot; -File | Sort-Object Name&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;修改后应该能看到：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;zh-CN.json.disabled&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;然后完全退出 AE，重新打开 AE，新建一个合成，重新给图层添加 uni.VHS。&lt;/p&gt;
&lt;p&gt;注意，最好不要只看旧工程里的旧效果实例。AE 有时候会缓存当前效果实例的状态，所以测试时最好新建合成、重新添加插件。&lt;/p&gt;
&lt;p&gt;这一步做完之后，我这里 VHS 的参数名就正常回到英文了。&lt;/p&gt;
&lt;p&gt;虽然最上面的“打开仪表板...”按钮仍然是中文，但下面真正影响使用的参数项，比如：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Choose a Preset... Save Preset... Enable Color Controls Color Controls Channel Controls Enable Tape Damage Tape Damage Enable Text Text Generator Frame Style Image Offset Tape Style (LUT) Post Noise Render Alpha Random Seed&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这些都恢复成英文了。&lt;/p&gt;
&lt;p&gt;这说明问题确实出在 Universe 插件自己的中文翻译 JSON 上。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;批量修复整个 Universe&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;确认单个插件修复有效后，就可以把整个 Universe 的简体中文翻译都禁用掉。&lt;/p&gt;
&lt;p&gt;这里一定要注意范围。&lt;/p&gt;
&lt;p&gt;我只处理这个目录：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;C:\ProgramData\Maxon\Universe\translations&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;不要碰这些目录：&lt;br /&gt;
&lt;code&gt;C:\ProgramData\Maxon\App Manager C:\ProgramData\Maxon\net.maxon.rg_common C:\Program Files&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;尤其不要用特别宽泛的关键词去批量匹配，比如：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cn&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;因为 cn 太容易误伤，很多无关文件名里也可能刚好出现这两个字母。&lt;/p&gt;
&lt;p&gt;我这里采用最保守的方式：只匹配文件名完全等于：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;zh-CN.json ccui_zh-CN.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;先预览目标文件：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$root = &quot;C:\ProgramData\Maxon\Universe\translations&quot; $targets = Get-ChildItem $root -Recurse -File | Where-Object { $_.Name -eq &quot;zh-CN.json&quot; -or $_.Name -eq &quot;ccui_zh-CN.json&quot; } $targets | Sort-Object FullName | Select-Object FullName &quot;Total targets: $($targets.Count)&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;看输出时，路径应该都在：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;C:\ProgramData\Maxon\Universe\translations&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;下面，例如：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;C:\ProgramData\Maxon\Universe\translations\customUI\zh-CN.json C:\ProgramData\Maxon\Universe\translations\dashboard\zh-CN.json C:\ProgramData\Maxon\Universe\translations\framework\zh-CN.json C:\ProgramData\Maxon\Universe\translations\ccui\ccui_zh-CN.json C:\ProgramData\Maxon\Universe\translations\plugins\某个插件\ecw\zh-CN.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;如果输出里出现了 App Manager、Program Files 或者其他非 Universe 路径，就不要继续执行。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;修改前保存一份清单&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;我建议正式改名前先导出一份清单到桌面，方便以后回看自己到底改过哪些文件。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$stamp = Get-Date -Format &quot;yyyyMMdd-HHmmss&quot; $report = &quot;$env:USERPROFILE\Desktop\Universe-zh-CN-disabled-$stamp.csv&quot; $targets | Sort-Object FullName | Select-Object FullName, Length, LastWriteTime | Export-Csv $report -NoTypeInformation -Encoding UTF8 &quot;Backup list saved to: $report&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这一步不是备份文件本体，只是保存一个修改清单。因为我们只是重命名文件，不是删除文件，所以一般已经足够安全。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;正式禁用 Universe 中文翻译&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;先用 -WhatIf 预演：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$targets | Rename-Item -NewName { $_.Name + &quot;.disabled&quot; } -WhatIf&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;确认输出全部都是 Universe 目录下的 zh-CN.json 或 ccui_zh-CN.json 后，再执行正式命令：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$targets | Rename-Item -NewName { $_.Name + &quot;.disabled&quot; }&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;完成后，关闭 AE，重新打开 AE，新建合成，重新添加 Universe 插件。&lt;/p&gt;
&lt;p&gt;如果一切正常，Universe 的参数名应该会回退到英文。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;如何恢复中文&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;如果以后 Maxon 或 Adobe 修好了这个问题，想恢复中文，也很简单，把 .disabled 去掉即可。&lt;br /&gt;
先预览：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$root = &quot;C:\ProgramData\Maxon\Universe\translations&quot; Get-ChildItem $root -Recurse -File | Where-Object { $_.Name -eq &quot;zh-CN.json.disabled&quot; -or $_.Name -eq &quot;ccui_zh-CN.json.disabled&quot; } | Rename-Item -NewName { $_.Name -replace &quot;\.disabled$&quot;,&quot;&quot; } -WhatIf&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;确认无误后，执行正式恢复：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$root = &quot;C:\ProgramData\Maxon\Universe\translations&quot; Get-ChildItem $root -Recurse -File | Where-Object { $_.Name -eq &quot;zh-CN.json.disabled&quot; -or $_.Name -eq &quot;ccui_zh-CN.json.disabled&quot; } | Rename-Item -NewName { $_.Name -replace &quot;\.disabled$&quot;,&quot;&quot; }&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;如果只想修某一个插件&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果不想让整个 Universe 都变英文，也可以只修出问题的插件。&lt;/p&gt;
&lt;p&gt;以 VHS 为例，只改：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;C:\ProgramData\Maxon\Universe\translations\plugins\Universe_Stylize_VHS\ecw\zh-CN.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;改成：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;zh-CN.json.disabled&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这样只有 VHS 回退英文，其他 Universe 插件仍然保持中文。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;这次问题本质上不是 AE 没装好，也不是系统语言没设对，而是 Red Giant / Universe 的官方中文本地化在 AE 里出现了显示兼容问题。&lt;/p&gt;
&lt;p&gt;我试过 Windows 的 UTF-8 Beta 开关，它能改善一部分显示，但没有彻底解决参数乱码和缺字。&lt;br /&gt;
最后真正有效的办法是：&lt;/p&gt;
&lt;p&gt;找到 Universe 的中文翻译 JSON；&lt;/p&gt;
&lt;p&gt;不删除，只重命名；&lt;/p&gt;
&lt;p&gt;让插件找不到中文翻译文件；&lt;/p&gt;
&lt;p&gt;Universe 自动回退英文；&lt;/p&gt;
&lt;p&gt;AE 里的参数名恢复正常可读。&lt;/p&gt;
&lt;p&gt;最关键的目录是：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;C:\ProgramData\Maxon\Universe\translations&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;最关键的文件名是：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;zh-CN.json ccui_zh-CN.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;最关键的原则是：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;只改 Universe 的翻译文件，不碰 App Manager，不碰 Program Files，不用模糊关键词乱匹配。&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;目前对我来说，这个方案比改系统语言、重装插件、重装 AE 都靠谱。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;参考来源&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Maxon 官方支持：After Effects 日文版中让 Red Giant 插件以英文版使用的方法&lt;br /&gt;
https://support.maxon.net/hc/ja-jp/articles/26087213462300-After-Effects%E6%97%A5%E6%9C%AC%E8%AA%9E%E7%89%88%E3%81%A7Red-Giant%E3%81%AE%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%82%92%E8%8B%B1%E8%AA%9E%E7%89%88%E3%81%A8%E3%81%97%E3%81%A6%E4%BD%BF%E3%81%86%E6%96%B9%E6%B3%95&lt;/p&gt;
&lt;p&gt;Maxon Note：How to use Red Giant plugins in English in the Japanese version of After Effects&lt;br /&gt;
https://note.com/maxonjapan/n/nb15318937ed1?hl=en&lt;/p&gt;
&lt;p&gt;Maxon Red Giant 2026.4.0 发行说明：提到 localized languages 下 Unicode error，以及 Studio 中 UTF-8 转换错误导致下拉菜单乱码或空白的问题&lt;br /&gt;
https://support.maxon.net/hc/en-us/articles/13764887933596-Red-Giant-2026-4-0-April-15-2026&lt;/p&gt;
&lt;p&gt;Adobe Community：After Effects 26.2 后第三方插件非英文 UI 文本乱码反馈&lt;br /&gt;
https://community.adobe.com/bug-reports-528/some-third-party-plug-ins-show-garbled-non-english-ui-text-in-after-effects-26-2-1557834&lt;/p&gt;
&lt;p&gt;Windows 11 UTF-8 设置说明：Enable or Disable Unicode UTF-8 for Worldwide Language Support in Windows 11&lt;br /&gt;
https://www.elevenforum.com/t/enable-or-disable-unicode-utf-8-for-worldwide-language-support-in-windows-11.38649/&lt;/p&gt;
</content:encoded></item><item><title>BNCF BPad Mini SE 刷入 crDroid GSI 记录</title><link>https://larmaxharkerx.github.io/posts/bpad-mini-se-crdroid-guide/</link><guid isPermaLink="true">https://larmaxharkerx.github.io/posts/bpad-mini-se-crdroid-guide/</guid><description>从贴牌平板到可用小板 - Unisoc UMS9230 UFS 机型的 BootROM 漏洞解锁和 GSI 刷入完整记录</description><pubDate>Wed, 27 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;BNCF BPad Mini SE 刷入 crDroid GSI 记录：从贴牌平板到可用小板&lt;/h1&gt;
&lt;p&gt;这篇是我自己折腾一台 Philips 牌平板的完整记录。它名义上是 Philips，实际更像一台贴牌机，系统里能看到的真实身份是 &lt;strong&gt;BNCF BPad Mini SE&lt;/strong&gt;。我爸当时只是想要一块屏幕大一点的平板，买回来以后才发现，这类机器硬件不算差，但原厂系统和 Google 套件这件事会让人很头疼。&lt;/p&gt;
&lt;p&gt;我最后走的是 Unisoc UMS9230 UFS 机型的 BootROM 漏洞解锁路线，完整备份后刷入 Doze-off 的 crDroid 11.6 Android 15 GSI。现在 Wi-Fi、蓝牙、触摸、相机预览、麦克风输入、Play 商店登录页这些基础项目都能工作，但这不是万能教程，也不是保砖教程。&lt;/p&gt;
&lt;p&gt;如果你手里不是 &lt;strong&gt;BNCF BPad Mini SE，Unisoc T615 / UMS9230，UFS 存储，动态分区，virtual A/B&lt;/strong&gt; 这一路设备，请不要照抄。&lt;/p&gt;
&lt;h2&gt;先把风险说清楚&lt;/h2&gt;
&lt;p&gt;刷这台机之前，我建议先读完全文，再决定要不要动手。&lt;/p&gt;
&lt;p&gt;这篇文章只是我的个人经验记录，不是官方教程，也不对任何结果承担法律责任。包括但不限于系统破解、解锁、修改带来的风险，设备变砖、功能异常、保修问题，以及数据丢失，都需要你自己判断和承担。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这些操作有真实风险：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;解锁、刷 GSI、&lt;code&gt;fastboot -w&lt;/code&gt; 都会清数据。&lt;/li&gt;
&lt;li&gt;写错 FDL、写错分区、用错镜像，有可能直接不开机。&lt;/li&gt;
&lt;li&gt;这台是 &lt;strong&gt;UFS&lt;/strong&gt;，不是 EMMC。不要把 EMMC 包拿来用在这台 UFS 设备上。&lt;/li&gt;
&lt;li&gt;本文只针对我这台 BNCF BPad Mini SE 和同类 UMS9230 UFS 变体，不保证别的 Unisoc 设备可用。&lt;/li&gt;
&lt;li&gt;我有完整只读备份，所以敢继续。没有备份就刷，出事只能靠运气。&lt;/li&gt;
&lt;li&gt;回滚不是万能的。特别是 NV、persist、modem、miscdata、super、boot 链相关分区，如果你之前没备份，后面很难凭空恢复。&lt;/li&gt;
&lt;li&gt;GSI 下某些属性或界面可能显示 green、locked 之类状态，这不一定等同于真实 BootROM 或 fastbootd 解锁状态。我的解锁验证以 fastbootd 和原厂系统阶段的启动属性为准。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;这台机器的基本情况&lt;/h2&gt;
&lt;p&gt;我手上这台的关键信息如下：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;项目&lt;/th&gt;
&lt;th&gt;信息&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;外壳品牌&lt;/td&gt;
&lt;td&gt;Philips&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;实际设备&lt;/td&gt;
&lt;td&gt;BNCF BPad Mini SE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;原厂系统&lt;/td&gt;
&lt;td&gt;Android 15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SoC&lt;/td&gt;
&lt;td&gt;Unisoc T615 / UMS9230&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ABI&lt;/td&gt;
&lt;td&gt;arm64-v8a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Treble&lt;/td&gt;
&lt;td&gt;已启用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;分区&lt;/td&gt;
&lt;td&gt;dynamic partitions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A/B&lt;/td&gt;
&lt;td&gt;virtual A/B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;当前槽位&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_b&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;存储&lt;/td&gt;
&lt;td&gt;UFS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;下载模式识别&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SPRD U2S Diag (COM3)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VID/PID&lt;/td&gt;
&lt;td&gt;&lt;code&gt;VID_1782&amp;amp;PID_4D00&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;我后来在解锁日志里也看到过这些确认信息：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Storage is ufs
Device is using slot b
Total number of partitions: 75
userdata 112202MB
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;为什么我没有继续折腾原厂 ROM&lt;/h2&gt;
&lt;p&gt;原厂 Android 15 看起来有点像准 AOSP，但实际体验很别扭。&lt;/p&gt;
&lt;p&gt;预装应用不少，权限提示也比较绕。系统没有干净的 Google 套件，想自己补 GMS、Play Services、Play Store，结果一直不顺。更麻烦的是，开发者选项里的 OEM unlock 被厂商和 &lt;code&gt;OemLock HAL&lt;/code&gt; 相关行为压住了，开关处于强制关闭状态。&lt;/p&gt;
&lt;p&gt;我还试过以前 Android 12 那类 Google Account Manager 强行注入账号的旧思路，但 Android 15 已经挡住了这条路。最后我的判断是，继续在原厂 ROM 上补 Google 套件不划算。它不干净，不稳定，也不好复现给别人。&lt;/p&gt;
&lt;p&gt;所以我改走另一条路：先完整备份，再通过 UMS9230 UFS 解锁包打开 bootloader，然后刷 Treble GSI。&lt;/p&gt;
&lt;h2&gt;先确认你的设备是不是同一路&lt;/h2&gt;
&lt;p&gt;不要只看外壳品牌。贴牌机最怕同名不同料。&lt;/p&gt;
&lt;p&gt;我会先确认这些点：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;adb shell getprop ro.product.cpu.abi
adb shell getprop ro.treble.enabled
adb shell getprop ro.boot.slot_suffix
adb shell getprop ro.boot.dynamic_partitions
adb shell getprop ro.virtual_ab.enabled
adb shell getprop ro.boot.hardware
adb reboot fastboot
fastboot getvar current-slot
fastboot getvar is-userspace
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我这台应该对应：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;arm64-v8a
Treble enabled
slot _b / current-slot: b
dynamic partitions
virtual A/B
fastbootd userspace mode 可用
UFS storage
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;UFS 这一点尤其重要。TomKing062 的包里有 UFS 和 EMMC 差异，&lt;strong&gt;我用的是 &lt;code&gt;ums9230_universal_unlock_UFS.dangerous.zip&lt;/code&gt;，不是 EMMC 包&lt;/strong&gt;。&lt;/p&gt;
&lt;h2&gt;我准备的目录和文件&lt;/h2&gt;
&lt;p&gt;我的工具目录是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;F:\project\pad\unisoc_unlock\ums9230_universal_unlock_UFS.dangerous
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;用到的正确包是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ums9230_universal_unlock_UFS.dangerous.zip
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;备份输出目录是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;E:\ufs\backup-full-readonly-20260527-202422
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个目录里包含 75 个分区信息和关键文件。对我来说，最重要的是这些：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;super.bin
splloader.bin
uboot_a.bin
uboot_b.bin
boot_a.bin
boot_b.bin
init_boot_a.bin
init_boot_b.bin
vendor_boot_a.bin
vendor_boot_b.bin
dtb_a.bin
dtb_b.bin
dtbo_a.bin
dtbo_b.bin
vbmeta_a.bin
vbmeta_b.bin
vbmeta_system_a.bin
vbmeta_system_b.bin
vbmeta_vendor_a.bin
vbmeta_vendor_b.bin
vbmeta_system_ext_a.bin
vbmeta_system_ext_b.bin
vbmeta_product_a.bin
vbmeta_product_b.bin
vbmeta_odm_a.bin
vbmeta_odm_b.bin
prodnv
persist
misc
miscdata
modem / NV 相关分区
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;几个我实际记录下来的文件大小：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;super.bin       5,872,025,600 bytes
splloader.bin   262,144 bytes
uboot_b.bin     3,145,728 bytes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我尝试过完整 &lt;code&gt;userdata&lt;/code&gt; 备份，但它很大，日志里显示 &lt;code&gt;userdata 112202MB&lt;/code&gt;。这次最终回滚并不依赖完整 userdata，所以我不建议普通读者为了保险无脑长时间 dump userdata。你如果有非常重要的个人数据，应该先在 Android 里用正常方式导出。分区级 userdata dump 又慢又占空间，而且恢复时还可能碰上加密问题。&lt;/p&gt;
&lt;h2&gt;下载模式和驱动识别&lt;/h2&gt;
&lt;p&gt;设备进下载模式后，Windows 这边识别为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SPRD U2S Diag (COM3)
VID_1782&amp;amp;PID_4D00
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这里还有个容易忽略的点：这台机的 EDL / SPRD 下载模式有超时机制。如果进模式以后一直不操作，过一会儿它可能会自己退出下载模式，然后直接开机进系统。遇到这种情况不用慌，重新按住 &lt;strong&gt;Power + 音量下&lt;/strong&gt; 不放，直到电脑这边再次断开又重新识别到设备，再继续后面的步骤。&lt;/p&gt;
&lt;p&gt;备份脚本里就是靠这个 VID/PID 等设备出现。我的脚本常量是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;VID/PID:   VID_1782&amp;amp;PID_4D00
exec addr: 0x65015f08
FDL1 addr: 0x65000800
FDL2 addr: 0x9efffe00
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;第一步，只读完整备份&lt;/h2&gt;
&lt;p&gt;我先做的是只读备份。这个阶段不写、不擦、不解锁，只用 &lt;code&gt;spd_dump&lt;/code&gt; 读取分区，最后 reset。&lt;/p&gt;
&lt;p&gt;下面是我使用的 &lt;code&gt;backup_full_readonly_wait_sprd.ps1&lt;/code&gt;。路径在工具目录下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;F:\project\pad\unisoc_unlock\ums9230_universal_unlock_UFS.dangerous\backup_full_readonly_wait_sprd.ps1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;脚本内容如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;param(
    [int]$TimeoutSeconds = 900,
    [string]$OutputRoot = &apos;E:\ufs&apos;,
    [int]$SpdWaitSeconds = 300,
    [int]$MinimumFreeGB = 140,
    [switch]$NoHash
)

$ErrorActionPreference = &apos;Stop&apos;

$ToolDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$VidPidPattern = &apos;VID_1782&amp;amp;PID_4D00&apos;
$ExecAddr = &apos;0x65015f08&apos;
$Fdl1Addr = &apos;0x65000800&apos;
$Fdl2Addr = &apos;0x9efffe00&apos;

# Full partition list captured from this BPad Mini SE / UMS9230 UFS device.
# READ ONLY: this script uses only spd_dump &apos;r &amp;lt;partition&amp;gt;&apos; commands plus final reset.
$Partitions = @(
    &apos;splloader&apos;,
    &apos;prodnv&apos;,&apos;items&apos;,&apos;miscdata&apos;,&apos;misc&apos;,
    &apos;trustos_a&apos;,&apos;trustos_b&apos;,&apos;sml_a&apos;,&apos;sml_b&apos;,&apos;uboot_a&apos;,&apos;uboot_b&apos;,&apos;uboot_log&apos;,
    &apos;logo&apos;,&apos;fbootlogo&apos;,
    &apos;l_fixnv1_a&apos;,&apos;l_fixnv2_a&apos;,&apos;l_fixnv1_b&apos;,&apos;l_fixnv2_b&apos;,&apos;l_runtimenv1&apos;,&apos;l_runtimenv2&apos;,&apos;persist&apos;,
    &apos;l_modem_a&apos;,&apos;l_modem_b&apos;,&apos;l_deltanv_a&apos;,&apos;l_deltanv_b&apos;,&apos;l_gdsp_a&apos;,&apos;l_gdsp_b&apos;,&apos;l_ldsp_a&apos;,&apos;l_ldsp_b&apos;,&apos;l_agdsp_a&apos;,&apos;l_agdsp_b&apos;,
    &apos;pm_sys_a&apos;,&apos;pm_sys_b&apos;,&apos;teecfg_a&apos;,&apos;teecfg_b&apos;,&apos;hypervsior_a&apos;,&apos;hypervsior_b&apos;,
    &apos;boot_a&apos;,&apos;boot_b&apos;,&apos;vendor_boot_a&apos;,&apos;vendor_boot_b&apos;,&apos;init_boot_a&apos;,&apos;init_boot_b&apos;,&apos;dtb_a&apos;,&apos;dtb_b&apos;,&apos;dtbo_a&apos;,&apos;dtbo_b&apos;,
    &apos;super&apos;,&apos;cache&apos;,&apos;blackbox&apos;,&apos;vbmeta_a&apos;,&apos;vbmeta_b&apos;,&apos;metadata&apos;,&apos;sysdumpdb&apos;,
    &apos;vbmeta_system_a&apos;,&apos;vbmeta_system_b&apos;,&apos;vbmeta_vendor_a&apos;,&apos;vbmeta_vendor_b&apos;,&apos;vbmeta_system_ext_a&apos;,&apos;vbmeta_system_ext_b&apos;,&apos;vbmeta_product_a&apos;,&apos;vbmeta_product_b&apos;,&apos;vbmeta_odm_a&apos;,&apos;vbmeta_odm_b&apos;,
    &apos;avbmeta_rs_a&apos;,&apos;avbmeta_rs_b&apos;,&apos;common_rs1_a&apos;,&apos;common_rs1_b&apos;,&apos;common_rs2_a&apos;,&apos;common_rs2_b&apos;,&apos;common_rs3_a&apos;,&apos;common_rs3_b&apos;,
    &apos;reserve1&apos;,&apos;reserve2&apos;,&apos;calinv&apos;,&apos;userdata&apos;
)

function Get-SprdDiagDevice {
    Get-CimInstance Win32_PnPEntity |
        Where-Object { $_.DeviceID -like &quot;*$VidPidPattern*&quot; -and $_.Status -eq &apos;OK&apos; }
}

function Get-DriveFreeGB([string]$Path) {
    $item = Get-Item -LiteralPath $Path
    $driveName = $item.PSDrive.Name
    $drive = Get-PSDrive -Name $driveName
    [math]::Round($drive.Free / 1GB, 2)
}

foreach ($required in @(&apos;spd_dump.exe&apos;,&apos;Channel.ini&apos;,&apos;Channel9.dll&apos;,&apos;custom_exec_no_verify_65015f08.bin&apos;,&apos;fdl1-dl.bin&apos;,&apos;fdl2-dl.bin&apos;)) {
    if (-not (Test-Path -LiteralPath (Join-Path $ToolDir $required))) {
        throw &quot;Missing required file in tool directory: $required&quot;
    }
}

if (-not (Test-Path -LiteralPath $OutputRoot)) {
    New-Item -ItemType Directory -Path $OutputRoot | Out-Null
}

$freeGB = Get-DriveFreeGB $OutputRoot
Write-Host &quot;Output root: $OutputRoot&quot;
Write-Host &quot;Free space on output drive: $freeGB GB&quot;
if ($freeGB -lt $MinimumFreeGB) {
    throw &quot;Not enough free space. Need at least $MinimumFreeGB GB for full backup with userdata.&quot;
}

$stamp = Get-Date -Format &apos;yyyyMMdd-HHmmss&apos;
$BackupDir = Join-Path $OutputRoot &quot;backup-full-readonly-$stamp&quot;
New-Item -ItemType Directory -Path $BackupDir | Out-Null

foreach ($required in @(&apos;spd_dump.exe&apos;,&apos;Channel.ini&apos;,&apos;Channel9.dll&apos;,&apos;custom_exec_no_verify_65015f08.bin&apos;,&apos;fdl1-dl.bin&apos;,&apos;fdl2-dl.bin&apos;)) {
    Copy-Item -LiteralPath (Join-Path $ToolDir $required) -Destination (Join-Path $BackupDir $required) -Force
}

$partListPath = Join-Path $BackupDir &apos;PARTITIONS_REQUESTED.txt&apos;
$Partitions | Set-Content -LiteralPath $partListPath -Encoding ASCII
$LogPath = Join-Path $BackupDir &apos;spd_dump-full-readonly.log&apos;

Write-Host &quot;Waiting for SPRD U2S Diag ($VidPidPattern) for up to $TimeoutSeconds seconds...&quot;
$deadline = (Get-Date).AddSeconds($TimeoutSeconds)
$device = $null
while ((Get-Date) -lt $deadline) {
    $device = Get-SprdDiagDevice | Select-Object -First 1
    if ($device) { break }
    Start-Sleep -Seconds 1
}
if (-not $device) {
    throw &quot;SPRD U2S Diag device not found. Re-enter download mode and retry.&quot;
}
Write-Host &quot;Found: $($device.Name) [$($device.DeviceID)]&quot;
Write-Host &quot;Backup directory: $BackupDir&quot;
Write-Host &quot;Partitions to read: $($Partitions.Count)&quot;
Write-Host &quot;This is READ ONLY: no erase/write/unlock payload commands are used.&quot;

$argsList = @(
    &apos;--wait&apos;, &quot;$SpdWaitSeconds&quot;,
    &apos;exec_addr&apos;, $ExecAddr,
    &apos;fdl&apos;, &apos;fdl1-dl.bin&apos;, $Fdl1Addr,
    &apos;fdl&apos;, &apos;fdl2-dl.bin&apos;, $Fdl2Addr,
    &apos;exec&apos;
)
foreach ($partition in $Partitions) {
    if ($partition -match &apos;^(e|w|write|erase|reset|exec|fdl)$&apos;) {
        throw &quot;Refusing suspicious partition token: $partition&quot;
    }
    $argsList += @(&apos;r&apos;, $partition)
}
$argsList += &apos;reset&apos;

Push-Location $BackupDir
try {
    &amp;amp; .\spd_dump.exe @argsList 2&amp;gt;&amp;amp;1 | Tee-Object -FilePath $LogPath
} finally {
    Pop-Location
}

Get-ChildItem -LiteralPath $BackupDir -File |
    Where-Object { $_.Name -notin @(&apos;spd_dump.exe&apos;,&apos;Channel.ini&apos;,&apos;Channel9.dll&apos;,&apos;custom_exec_no_verify_65015f08.bin&apos;,&apos;fdl1-dl.bin&apos;,&apos;fdl2-dl.bin&apos;) } |
    Select-Object Name,Length,LastWriteTime |
    Format-Table -AutoSize |
    Out-String |
    Set-Content -LiteralPath (Join-Path $BackupDir &apos;FILES.txt&apos;) -Encoding ASCII

if (-not $NoHash) {
    Write-Host &quot;Computing SHA256 manifest. This can take a long time for userdata...&quot;
    $hashLines = foreach ($file in Get-ChildItem -LiteralPath $BackupDir -File | Where-Object { $_.Name -notin @(&apos;spd_dump.exe&apos;,&apos;Channel.ini&apos;,&apos;Channel9.dll&apos;,&apos;custom_exec_no_verify_65015f08.bin&apos;,&apos;fdl1-dl.bin&apos;,&apos;fdl2-dl.bin&apos;) }) {
        $h = Get-FileHash -Algorithm SHA256 -LiteralPath $file.FullName
        &quot;$($h.Hash)  $($file.Name)&quot;
    }
    $hashLines | Set-Content -LiteralPath (Join-Path $BackupDir &apos;SHA256SUMS.txt&apos;) -Encoding ASCII
}

Write-Host &quot;Full read-only backup complete.&quot;
Write-Host &quot;Backup directory: $BackupDir&quot;
Get-Content -LiteralPath (Join-Path $BackupDir &apos;FILES.txt&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;运行方式大概是这样：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd F:\project\pad\unisoc_unlock\ums9230_universal_unlock_UFS.dangerous
powershell -ExecutionPolicy Bypass -File .\backup_full_readonly_wait_sprd.ps1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果你不想等超大的 userdata 算 SHA256，可以自己评估是否加 &lt;code&gt;-NoHash&lt;/code&gt;。我仍然建议至少把关键启动链、super、NV、persist、misc、miscdata 相关分区保存好，并把 &lt;code&gt;FILES.txt&lt;/code&gt;、&lt;code&gt;SHA256SUMS.txt&lt;/code&gt;、日志一起留着。&lt;/p&gt;
&lt;h2&gt;第二步，分阶段解锁&lt;/h2&gt;
&lt;p&gt;这里开始就是危险区了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;再次提醒：这一步不是只读。它会擦写 &lt;code&gt;splloader&lt;/code&gt;、&lt;code&gt;splloader_bak&lt;/code&gt;、临时写入 active &lt;code&gt;uboot&lt;/code&gt;，运行 unlock payload，然后恢复 &lt;code&gt;splloader&lt;/code&gt; 和 &lt;code&gt;uboot&lt;/code&gt; 并 wipe &lt;code&gt;misc&lt;/code&gt;。如果你的设备不是同款 UFS 变体，或者包不是 UFS 包，不要继续。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我用到的脚本路径是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;F:\project\pad\unisoc_unlock\ums9230_universal_unlock_UFS.dangerous\unlock_staged_no_pause.bat
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这次脚本中生成或使用过的文件包括：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;spl-unlock.bin
u-boot-spl-16k-sign.bin
uboot_bak.bin
fdl2-cboot.bin
misc-wipe.bin
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;unlock_staged_no_pause.bat&lt;/code&gt; 内容如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@echo off
setlocal enabledelayedexpansion
cd /d &quot;%~dp0&quot;
echo === STAGED UMS9230 UFS UNLOCK START ===
echo This script uses pre-generated backup-derived files.
echo It WILL erase splloader/splloader_bak, write temporary uboot, run unlock payload, then restore splloader/uboot and wipe misc.
echo.

echo [1/5] Erase splloader and splloader_bak for fallback path
spd_dump --wait 300 exec_addr 0x65015f08 fdl fdl1-dl.bin 0x65000800 fdl fdl2-dl.bin 0x9efffe00 exec e splloader e splloader_bak reset
if errorlevel 1 goto fail

timeout /t 10 /nobreak

echo [2/5] Write temporary fdl2-cboot into active uboot
spd_dump --wait 300 exec_addr 0x65015f08 fdl fdl1-dl.bin 0x65000800 fdl fdl2-dl.bin 0x9efffe00 exec w uboot fdl2-cboot.bin reset
if errorlevel 1 goto fail

timeout /t 10 /nobreak

echo [3/5] Run unlock payload, may need twice on some devices
spd_dump --wait 300 exec_addr 0x65015f08 fdl spl-unlock.bin 0x65000800
if errorlevel 1 echo unlock payload returned non-zero; continuing to check/restore

timeout /t 10 /nobreak

echo [4/5] Check unlock data in miscdata. Locked: 64 zeros. Unlocked: 32 string + 16 hash + 16 hash.
spd_dump --wait 300 exec_addr 0x65015f08 fdl fdl1-dl.bin 0x65000800 fdl fdl2-dl.bin 0x9efffe00 exec verbose 2 read_part miscdata 8192 64 m.bin reset
if errorlevel 1 echo miscdata check failed; continuing to restore

timeout /t 10 /nobreak

echo [5/5] Restore splloader and active uboot, wipe misc, reset
spd_dump --wait 300 exec_addr 0x65015f08 fdl fdl1-dl.bin 0x65000800 fdl fdl2-dl.bin 0x9efffe00 exec r boot w splloader u-boot-spl-16k-sign.bin w uboot uboot_bak.bin w misc misc-wipe.bin reset
if errorlevel 1 goto restore_fail

echo === STAGED UMS9230 UFS UNLOCK COMPLETE ===
exit /b 0

:restore_fail
echo === RESTORE FAILED. DO NOT PANIC, KEEP DEVICE CONNECTED/IN DIAG IF POSSIBLE. ===
exit /b 2

:fail
echo === UNLOCK SCRIPT FAILED BEFORE RESTORE STAGE ===
exit /b 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;运行前，我会确认当前目录里这些文件都在，尤其是 &lt;code&gt;spd_dump.exe&lt;/code&gt;、&lt;code&gt;fdl1-dl.bin&lt;/code&gt;、&lt;code&gt;fdl2-dl.bin&lt;/code&gt;、&lt;code&gt;spl-unlock.bin&lt;/code&gt;、&lt;code&gt;fdl2-cboot.bin&lt;/code&gt;、&lt;code&gt;u-boot-spl-16k-sign.bin&lt;/code&gt;、&lt;code&gt;uboot_bak.bin&lt;/code&gt;、&lt;code&gt;misc-wipe.bin&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;运行方式：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd /d F:\project\pad\unisoc_unlock\ums9230_universal_unlock_UFS.dangerous
unlock_staged_no_pause.bat
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我的成功验证不是只看脚本最后一句，而是后面进 fastbootd 看状态。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;adb reboot fastboot
fastboot getvar is-userspace
fastboot getvar current-slot
fastboot getvar unlocked
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我看到的关键信息是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;is-userspace: yes
current-slot: b
unlocked: yes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在原厂系统阶段，也出现过这些属性：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ro.boot.flash.locked=0
ro.boot.vbmeta.device_state=unlocked
ro.boot.verifiedbootstate=orange
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;刷入 GSI 之后，用户空间里有时会出现 green 或 locked 的显示和叠层提示。我把它当作 GSI 属性映射或显示层面的 caveat，没有拿它推翻 fastbootd 的 &lt;code&gt;unlocked: yes&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;第三步，选择 crDroid GSI&lt;/h2&gt;
&lt;p&gt;我选的是 Doze-off 的 crDroid 11.6 Android 15 QPR2 Treble GSI：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;E:\ufs\gsi\crDroid-11.6_treble_arm64_bgN-ab.img.xz
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;文件信息：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;压缩包大小: 1,213,953,860 bytes
SHA256: 0DC22B143F4390BE8D44FC5641FA42DEE1A2935DF21C13521F3D34A68D5EE24D
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解压后镜像：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;E:\ufs\gsi\crDroid-11.6_treble_arm64_bgN-ab.img
大小: 3,730,255,872 bytes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个文件名里的几个点很关键：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;arm64
bgN
ab
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我的理解是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;arm64&lt;/code&gt; 对应这台机的 &lt;code&gt;arm64-v8a&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ab&lt;/code&gt; 对应 A/B 或 virtual A/B 设备。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bgN&lt;/code&gt; 是带 GApps、无 root 风格的构建。&lt;/li&gt;
&lt;li&gt;这是 Doze-off 的 crDroid 11.6，基于 Android 15 QPR2。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我没有选 root 版，也没有自己补 Google 套件，因为这次目标就是让它变成一台能正常登录 Play 的轻度可用平板。crDroid 本来就是从 LineageOS / AOSP 这一路延伸出来的系统，很多日常会用到的功能已经集成好了，对我来说，比从一个很裸的 GSI 开始重新搭一遍更省事，也更容易复现。&lt;/p&gt;
&lt;h2&gt;第四步，通过 fastbootd 刷 system&lt;/h2&gt;
&lt;p&gt;这里刷的是动态分区里的 &lt;code&gt;system&lt;/code&gt;，所以要进 userspace fastboot，也就是 fastbootd。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;adb reboot fastboot
fastboot getvar is-userspace
fastboot getvar current-slot
fastboot getvar unlocked
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;确认：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;is-userspace: yes
current-slot: b
unlocked: yes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后刷入 GSI：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fastboot flash system E:\ufs\gsi\crDroid-11.6_treble_arm64_bgN-ab.img
fastboot -w
fastboot reboot
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我这里 &lt;code&gt;fastboot -w&lt;/code&gt; 擦 userdata 成功，擦 cache 报错失败，但最后系统还是正常启动了。这个现象我只按实记录，不把它当成所有设备都可以忽略的通用结论。&lt;/p&gt;
&lt;p&gt;启动以后，我确认到的 crDroid 信息包括：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ro.crdroid.build.version=11.6
ro.crdroid.display.version=v11.6-20250618
ro.crdroid.device=tdgsi_arm64_ab
Android 15
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;GApps 相关包存在：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;com.google.android.gms
com.google.android.gsf
com.android.vending
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Play 商店能打开到登录页。这一点对我来说已经比原厂 ROM 上硬补 GMS 干净很多。&lt;/p&gt;
&lt;h2&gt;Wi-Fi 网络验证和 captive portal 修复&lt;/h2&gt;
&lt;p&gt;刷完后，我遇到过网络验证相关问题。最后用 Android 全局设置把 captive portal 检测地址换成国内可访问地址，Wi-Fi 验证恢复正常。&lt;/p&gt;
&lt;p&gt;我用的命令如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;adb shell settings put global captive_portal_mode 1
adb shell settings put global captive_portal_http_url http://connect.rom.miui.com/generate_204
adb shell settings put global captive_portal_https_url https://connect.rom.miui.com/generate_204
adb shell settings put global captive_portal_fallback_url http://connectivitycheck.platform.hicloud.com/generate_204
adb shell settings put global captive_portal_other_fallback_urls http://www.google.cn/generate_204
adb shell settings put global captive_portal_use_https 1
adb shell svc wifi disable
adb shell svc wifi enable
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行后网络状态验证通过。&lt;/p&gt;
&lt;p&gt;如果你用的是代理工具，比如 Clash 一类，只需要按自己的网络环境配置。这里我不会放任何订阅链接、token、账号或密钥。公开教程里不要贴这些东西。&lt;/p&gt;
&lt;h2&gt;相机方向修复：前摄 270°、后摄 90°&lt;/h2&gt;
&lt;p&gt;GSI 刷完后，前后摄像头预览方向都是反的，而且画面有明显拉伸。用 &lt;code&gt;dumpsys media.camera&lt;/code&gt; 一看，前后摄都报 &lt;code&gt;Orientation: 0&lt;/code&gt;，这显然不对。&lt;/p&gt;
&lt;p&gt;PHH/Treble 设置里没有现成的相机方向修复开关。我又去翻了 vendor 底层配置 &lt;code&gt;/vendor/odm/etc/sensor_config.xml&lt;/code&gt;，发现传感器配置本身是对的：前摄 &lt;code&gt;Orientation=270&lt;/code&gt;，后摄 &lt;code&gt;Orientation=90&lt;/code&gt;。问题不在配置文件。&lt;/p&gt;
&lt;p&gt;顺着线索查下去，定位到 Unisoc 的 camera HAL（&lt;code&gt;camera.unisoc.so&lt;/code&gt;）。这个 HAL 在往 framework 上报 &lt;code&gt;android.sensor.orientation&lt;/code&gt; 静态元数据的时候，把方向值统一抹成了 0。不管底层配置写的是什么，HAL 传上去的永远是 0。&lt;/p&gt;
&lt;p&gt;试过一堆常规手段：&lt;code&gt;persist.vendor.camera.HAL3.enabled=0&lt;/code&gt;、&lt;code&gt;vendor.camera.hal1.packagelist&lt;/code&gt;、&lt;code&gt;OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT&lt;/code&gt; compat change、&lt;code&gt;device_config camera enable_landscape_to_portrait=true&lt;/code&gt;，全没用。这些开关要么不被这台机子的 HAL 读取，要么只对特定 fixed-orientation app 生效，解决不了根本问题。&lt;/p&gt;
&lt;p&gt;最终走的是二进制级 patch。定位到 &lt;code&gt;camera.unisoc.so&lt;/code&gt; 里的 &lt;code&gt;SprdCamera3Setting::initStaticMetadataforSensorInfo()&lt;/code&gt; 函数。该函数在写入 &lt;code&gt;android.sensor.orientation&lt;/code&gt;（tag &lt;code&gt;0xE000E&lt;/code&gt;）时，从结构体偏移 &lt;code&gt;+0x5528&lt;/code&gt; 读取一个值，但该值始终为 0。&lt;/p&gt;
&lt;p&gt;通过反汇编（pyelftools + capstone）找到了写入点的精确指令窗口，地址 &lt;code&gt;0x643dc&lt;/code&gt;。用 keystone-engine 生成了一个 32 字节的 ARM64 trampoline，放在函数体内的一个 UDF 代码洞（地址 &lt;code&gt;0x80030&lt;/code&gt;）。trampoline 逻辑很简单：根据 camera ID（&lt;code&gt;w19&lt;/code&gt;）计算 &lt;code&gt;90 + 180 × camera_id&lt;/code&gt;，即 camera 0 → 90，camera 1 → 270，然后写入正确的元数据槽位。原始写入点改为跳转指令 &lt;code&gt;b #0x80030&lt;/code&gt;，跳到 trampoline 执行完再跳回原函数继续。&lt;/p&gt;
&lt;p&gt;patch 好的 &lt;code&gt;camera.unisoc.so&lt;/code&gt; 通过 Magisk 模块做 systemless 覆盖，路径 &lt;code&gt;/system/vendor/lib64/hw/camera.unisoc.so&lt;/code&gt;。重启后 &lt;code&gt;dumpsys media.camera&lt;/code&gt; 确认：Back Orientation = 90，Front Orientation = 270。前后摄预览方向和拉伸问题都修复了，对所有 app 生效。&lt;/p&gt;
&lt;p&gt;Magisk 模块结构：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/data/adb/modules/camera_orientation_patch/
├── module.prop
└── system/
    └── vendor/
        └── lib64/
            └── hw/
                └── camera.unisoc.so
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;回退方法：删除 &lt;code&gt;/data/adb/modules/camera_orientation_patch&lt;/code&gt; 目录并重启即可恢复原始 HAL。&lt;/p&gt;
&lt;h2&gt;我做过的基础静默 QA&lt;/h2&gt;
&lt;p&gt;这台机刷完 crDroid 后，我做了一轮基础检查。结果如下：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;项目&lt;/th&gt;
&lt;th&gt;结果&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Wi-Fi&lt;/td&gt;
&lt;td&gt;可用，captive portal 修复后网络验证通过&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VPN / Clash 类工具&lt;/td&gt;
&lt;td&gt;可安装并运行，不包含任何订阅信息&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;蓝牙&lt;/td&gt;
&lt;td&gt;可打开&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;屏幕&lt;/td&gt;
&lt;td&gt;800x1340，164dpi，支持 90Hz / 60Hz&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;触摸&lt;/td&gt;
&lt;td&gt;&lt;code&gt;himax-touchscreen&lt;/code&gt; 可用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;传感器&lt;/td&gt;
&lt;td&gt;有 accelerometer / device orientation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;相机&lt;/td&gt;
&lt;td&gt;camera service 看到 2 个摄像头，预览能打开&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;麦克风&lt;/td&gt;
&lt;td&gt;输入设备存在&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Play Store&lt;/td&gt;
&lt;td&gt;能打开到登录页&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;也有一些我没有充分测试的地方：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;扬声器没有完整测试。&lt;/li&gt;
&lt;li&gt;GPS 没有完整测试。&lt;/li&gt;
&lt;li&gt;SIM 或蜂窝网络没有完整测试。&lt;/li&gt;
&lt;li&gt;长待机、深睡、耗电没有长期观察。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;YouTube 闪退和替代方案&lt;/h3&gt;
&lt;p&gt;YouTube 在这台 4GB 内存的板子上会闪退。我抓过 crash log，原因是 Glide 图片库的 Bitmap 被系统提前回收：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;FATAL EXCEPTION: glide-active-resources
Process: com.google.android.youtube
java.lang.IllegalStateException: Cannot obtain size for recycled Bitmap
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这是 YouTube 自身的 bug，在低内存设备上更容易触发。我试过开 &lt;code&gt;ro.config.low_ram=true&lt;/code&gt;，没用。降级 YouTube 版本也没用，因为 Play 会自动更新回来。&lt;/p&gt;
&lt;p&gt;最后我换成了 &lt;strong&gt;SmartTube&lt;/strong&gt;，不需要 GMS，自带广告过滤，对低内存设备也更友好。直接从 GitHub 下载 arm64-v8a 的 APK 安装就行：&lt;a href=&quot;https://github.com/yuliskov/SmartTube&quot;&gt;https://github.com/yuliskov/SmartTube&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;所以我不会说它已经完美，也不会说它适合所有人当主力机。对我来说，它已经从一台原厂系统很别扭的贴牌平板，变成了一台基本可用的 Android 15 crDroid 小板。&lt;/p&gt;
&lt;h2&gt;回滚策略&lt;/h2&gt;
&lt;p&gt;我做完整备份的最大意义，就是保留回滚路径。&lt;/p&gt;
&lt;p&gt;如果只是 GSI 不合适，优先考虑回 fastbootd，用原备份里的 &lt;code&gt;super.bin&lt;/code&gt; 恢复动态分区内容。因为我当前槽位是 &lt;code&gt;b&lt;/code&gt;，所以启动链相关文件也要按槽位匹配，不要把 a、b 混着写。&lt;/p&gt;
&lt;p&gt;我会重点保留这些文件：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;super.bin
boot_b.bin
vendor_boot_b.bin
init_boot_b.bin
dtb_b.bin
dtbo_b.bin
vbmeta_b.bin
vbmeta_system_b.bin
vbmeta_vendor_b.bin
vbmeta_system_ext_b.bin
vbmeta_product_b.bin
vbmeta_odm_b.bin
uboot_b.bin
splloader.bin
prodnv
persist
misc
miscdata
modem / NV 相关分区
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果当前槽位变成 a，就要换成对应的 &lt;code&gt;_a&lt;/code&gt; 文件。不要在没确认槽位时乱刷。&lt;/p&gt;
&lt;p&gt;概念上，fastbootd 回滚 &lt;code&gt;super&lt;/code&gt; 会像这样：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;adb reboot fastboot
fastboot getvar is-userspace
fastboot getvar current-slot
fastboot flash super E:\ufs\backup-full-readonly-20260527-202422\super.bin
fastboot -w
fastboot reboot
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启动链回滚要更谨慎。比如槽位 b 对应的是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fastboot flash boot_b E:\ufs\backup-full-readonly-20260527-202422\boot_b.bin
fastboot flash vendor_boot_b E:\ufs\backup-full-readonly-20260527-202422\vendor_boot_b.bin
fastboot flash init_boot_b E:\ufs\backup-full-readonly-20260527-202422\init_boot_b.bin
fastboot flash dtb_b E:\ufs\backup-full-readonly-20260527-202422\dtb_b.bin
fastboot flash dtbo_b E:\ufs\backup-full-readonly-20260527-202422\dtbo_b.bin
fastboot flash vbmeta_b E:\ufs\backup-full-readonly-20260527-202422\vbmeta_b.bin
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;是否能直接用 fastboot 写某个分区，取决于设备当前能进入的模式、分区暴露情况和 fastbootd 支持情况。进不了 fastbootd 时，就可能要回到 Unisoc 下载模式和 &lt;code&gt;spd_dump&lt;/code&gt; 这条线。那时更不能乱试，应该先确认分区名、槽位、镜像来源和命令含义。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;我不会承诺一定能 unbrick。&lt;/strong&gt; 我能做的是把备份、槽位、分区文件、日志都留好，让自己在出问题时有东西可回。&lt;/p&gt;
&lt;h2&gt;常见坑和我的建议&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;不要用 EMMC 包刷 UFS 设备。这是本文最重要的警告之一。&lt;/li&gt;
&lt;li&gt;不要跳过备份。至少把 &lt;code&gt;super&lt;/code&gt;、启动链、vbmeta、NV、persist、miscdata 留好。&lt;/li&gt;
&lt;li&gt;不要只看品牌名。Philips 外壳不代表内部方案一致。&lt;/li&gt;
&lt;li&gt;不要在 GSI 里看到 locked 字样就立刻慌。先回 fastbootd 看 &lt;code&gt;fastboot getvar unlocked&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;不要把自己的代理订阅、账号、token 写进教程、截图或日志。&lt;/li&gt;
&lt;li&gt;不要在没确认当前槽位时刷 &lt;code&gt;_a&lt;/code&gt; 或 &lt;code&gt;_b&lt;/code&gt; 镜像。&lt;/li&gt;
&lt;li&gt;不要把 &lt;code&gt;userdata&lt;/code&gt; 当作最可靠的个人数据备份方式。能在系统里导出的，先用正常方法导出。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;参考和致谢&lt;/h2&gt;
&lt;p&gt;这次能完成，主要靠这些项目和资料：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;TomKing062 的 Unisoc CVE 解锁项目：&lt;a href=&quot;https://github.com/TomKing062/CVE-2022-38694_unlock_bootloader&quot;&gt;https://github.com/TomKing062/CVE-2022-38694_unlock_bootloader&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;TomKing062 的 spreadtrum_flash releases：&lt;a href=&quot;https://github.com/TomKing062/spreadtrum_flash/releases/latest&quot;&gt;https://github.com/TomKing062/spreadtrum_flash/releases/latest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;NCC Group 关于 Unisoc ROM 漏洞的文章：&lt;a href=&quot;https://www.nccgroup.com/research/there-s-another-hole-in-your-soc-unisoc-rom-vulnerabilities/&quot;&gt;https://www.nccgroup.com/research/there-s-another-hole-in-your-soc-unisoc-rom-vulnerabilities/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Doze-off crDroid GSI 2025-06-18 发布页：&lt;a href=&quot;https://github.com/Doze-off/android_crdroid/releases/tag/2025-06-18&quot;&gt;https://github.com/Doze-off/android_crdroid/releases/tag/2025-06-18&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Doze-off crDroid GSI 仓库和 releases：&lt;a href=&quot;https://github.com/Doze-off/android_crdroid&quot;&gt;https://github.com/Doze-off/android_crdroid&lt;/a&gt;，&lt;a href=&quot;https://github.com/Doze-off/crdroid_gsi_treble/releases&quot;&gt;https://github.com/Doze-off/crdroid_gsi_treble/releases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;crDroid 官方网站和源码组织：&lt;a href=&quot;https://crdroid.net&quot;&gt;https://crdroid.net&lt;/a&gt;，&lt;a href=&quot;https://github.com/crdroidandroid&quot;&gt;https://github.com/crdroidandroid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;TrebleDroid：&lt;a href=&quot;https://github.com/TrebleDroid/treble_experimentations&quot;&gt;https://github.com/TrebleDroid/treble_experimentations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Android GSI 官方文档：&lt;a href=&quot;https://developer.android.google.cn/topic/generic-system-image&quot;&gt;https://developer.android.google.cn/topic/generic-system-image&lt;/a&gt;，&lt;a href=&quot;https://source.android.com/docs/core/tests/vts/gsi?hl=en&quot;&gt;https://source.android.com/docs/core/tests/vts/gsi?hl=en&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OpenCode：&lt;a href=&quot;https://opencode.ai&quot;&gt;https://opencode.ai&lt;/a&gt;，&lt;a href=&quot;https://github.com/anomalyco/opencode&quot;&gt;https://github.com/anomalyco/opencode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;LineageOS：&lt;a href=&quot;https://lineageos.org&quot;&gt;https://lineageos.org&lt;/a&gt;，&lt;a href=&quot;https://github.com/LineageOS/android&quot;&gt;https://github.com/LineageOS/android&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;SmartTube：&lt;a href=&quot;https://github.com/yuliskov/SmartTube&quot;&gt;https://github.com/yuliskov/SmartTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;pyelftools：&lt;a href=&quot;https://github.com/eliben/pyelftools&quot;&gt;https://github.com/eliben/pyelftools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;capstone：&lt;a href=&quot;https://github.com/capstone-engine/capstone&quot;&gt;https://github.com/capstone-engine/capstone&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;keystone-engine：&lt;a href=&quot;https://github.com/keystone-engine/keystone&quot;&gt;https://github.com/keystone-engine/keystone&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AOSP CameraUtils 源码（sensor_orientation 用法参考）：&lt;a href=&quot;https://android.googlesource.com/platform/frameworks/av/+/69e86ab47181f93fce4c119d0f293a147c2e687f/camera/CameraUtils.cpp&quot;&gt;https://android.googlesource.com/platform/frameworks/av/+/69e86ab47181f93fce4c119d0f293a147c2e687f/camera/CameraUtils.cpp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ChatGPT 5.5，协助整理步骤、风险提示和文章结构。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;最后再重复一次：这是一篇我自己的 BNCF BPad Mini SE / UMS9230 UFS 折腾记录，不是通用刷机包说明书。你可以参考我的路径，但每一步都要先确认自己的设备、槽位、存储类型和备份是否可靠。&lt;/p&gt;
</content:encoded></item><item><title>华为平板 M3 刷机记录：扩容 System、刷第三方系统与 Google 服务</title><link>https://larmaxharkerx.github.io/posts/huawei-m3-flashing-guide/</link><guid isPermaLink="true">https://larmaxharkerx.github.io/posts/huawei-m3-flashing-guide/</guid><description>以 BTV-DL09 64GB 为例，整理一次华为平板 M3 的刷机记录，并明确区分官方恢复路径与社区方案</description><pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;华为平板 M3 刷机记录：扩容 System、刷第三方系统与 Google 服务&lt;/h1&gt;
&lt;p&gt;这篇文章不是“包你一次成功”的万能教程，而是我自己折腾 &lt;strong&gt;华为平板 M3（BTV-DL09 64GB）&lt;/strong&gt; 的一次整理版记录。之所以重写，是因为这类老设备现在已经不在官方支持周期内，很多资料散落在论坛、旧帖子和镜像包说明里。如果把“官方还支持什么”和“社区现在只能怎么凑合”混在一起写，很容易把读者带沟里。&lt;/p&gt;
&lt;p&gt;我下面会把三件事分清楚：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Huawei 现在仍然承认的官方恢复路径&lt;/strong&gt; 是什么；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bootloader 解锁、TWRP、第三方系统、Google 服务&lt;/strong&gt; 哪些属于社区方案；&lt;/li&gt;
&lt;li&gt;我这台机器上哪些步骤是我实际做过、确认过的。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果你手上的不是 &lt;strong&gt;MediaPad M3 / BTV 系列&lt;/strong&gt;，或者容量、地区版本、系统版本不一致，请不要直接照抄分区参数。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;先把边界说清楚&lt;/h2&gt;
&lt;h3&gt;1. 华为官方现在能提供的，主要是恢复，不是解锁&lt;/h3&gt;
&lt;p&gt;Huawei 目前公开还能查到的资料，主要集中在 &lt;code&gt;HiSuite&lt;/code&gt;、&lt;code&gt;eRecovery&lt;/code&gt;、系统修复和更新失败处理上。例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rooted 设备如何通过 &lt;code&gt;HiSuite&lt;/code&gt; / &lt;code&gt;eRecovery&lt;/code&gt; 恢复系统；&lt;/li&gt;
&lt;li&gt;更新失败后如何进入恢复；&lt;/li&gt;
&lt;li&gt;进入 Fastboot / eRecovery 的按键方式；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eRecovery&lt;/code&gt; 需要 Wi‑Fi，电量最好高于 30%。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这部分能作为&lt;strong&gt;官方恢复依据&lt;/strong&gt;，但它不等于“华为仍然支持 Bootloader 解锁”。&lt;/p&gt;
&lt;h3&gt;2. Bootloader 官方通道已经停了，但老设备还有第三方算号路线&lt;/h3&gt;
&lt;p&gt;华为在 2018 年停止了官方 Bootloader 解锁码服务。对今天还在折腾 MediaPad M3 这种老设备的人来说，真正常见的现实不是“去华为官网申请”，而是去 &lt;strong&gt;某宝 / 某鱼&lt;/strong&gt; 找还在做老华为解锁的人。&lt;/p&gt;
&lt;p&gt;他们通常会给你两样东西：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一个专用的解锁程序；&lt;/li&gt;
&lt;li&gt;一个远程 USB 软件或加密狗式的授权环境。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;说白了，本质就是：&lt;strong&gt;对方通过老设备还能用的第三方算号方式，给你算出这台机器的解锁码，然后你自己在本地完成解锁。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这条路有几个边界必须说清楚：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;只适用于一部分 &lt;strong&gt;老华为 / 老荣耀设备&lt;/strong&gt;，不是所有 Huawei 机器都还能这么做；&lt;/li&gt;
&lt;li&gt;不同卖家的工具、驱动、远控方式可能不一样；&lt;/li&gt;
&lt;li&gt;这完全不是 Huawei 官方支持路径；&lt;/li&gt;
&lt;li&gt;你买到的是“算号和授权能力”，不是一份对所有机型通用的公开方法。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我这台 M3 走的就是这类路子，不是自己凭空把 Bootloader 解开的。&lt;/p&gt;
&lt;p&gt;所以这篇文章里只要提到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fastboot oem unlock&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;TWRP；&lt;/li&gt;
&lt;li&gt;分区调整；&lt;/li&gt;
&lt;li&gt;刷第三方 ROM；&lt;/li&gt;
&lt;li&gt;手动装 Google 服务；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;都应该理解为 &lt;strong&gt;社区方案&lt;/strong&gt;。&lt;/p&gt;
&lt;h3&gt;3. 这台设备官方支持也已经结束&lt;/h3&gt;
&lt;p&gt;MediaPad M3 的官方支持页已经显示支持结束，而且公开页面上也没有继续提供完整固件下载。换句话说，折腾这台设备本来就是“旧设备维护”，不要再把它当成还在主线支持里的产品。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;风险提示&lt;/h2&gt;
&lt;p&gt;这部分不写成模板化“免责声明”，只说实际风险：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;会清数据。&lt;/strong&gt; 进 Fastboot、刷 TWRP、格式化 Data、改分区、刷第三方系统，都可能让数据直接归零。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分区步骤最危险。&lt;/strong&gt; &lt;code&gt;parted&lt;/code&gt; 这一段不是“高级一点的普通操作”，而是真正会把 GPT 改掉的步骤。数字抄错一位就可能把机器送进救砖流程。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;官方恢复不等于第三方刷机兜底。&lt;/strong&gt; &lt;code&gt;eRecovery&lt;/code&gt; 和 &lt;code&gt;HiSuite&lt;/code&gt; 能救一部分系统问题，但不保证你改过分区以后还能轻松回到原厂状态。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Google 服务不是官方支持功能。&lt;/strong&gt; 这部分更多是兼容性折腾，不是 Huawei 给旧平板留下的标准安装路线。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你只是想要一台“稳定可用的老平板”，最稳妥的做法并不是刷最狠，而是先评估：你到底是为了完整 GMS、为了更大的 System 分区，还是只是为了把机器救活。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;我的设备信息&lt;/h2&gt;
&lt;p&gt;我这次记录对应的是下面这台机器：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;项目&lt;/th&gt;
&lt;th&gt;信息&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;型号&lt;/td&gt;
&lt;td&gt;BTV-DL09&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;容量&lt;/td&gt;
&lt;td&gt;64GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;芯片&lt;/td&gt;
&lt;td&gt;麒麟 950&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;目标&lt;/td&gt;
&lt;td&gt;刷入第三方系统并给 System 留出更大的空间&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;重点问题&lt;/td&gt;
&lt;td&gt;原厂系统老旧、Google 服务不完整、System 空间不够&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这也是为什么本文会出现“扩容 System 分区”这一步。对同系列但不同容量的设备来说，&lt;strong&gt;分区终点值不能照搬&lt;/strong&gt;。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;开始前我准备了什么&lt;/h2&gt;
&lt;p&gt;我实际准备的是这几类东西：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;确认 Bootloader 已经处于可解锁/已解锁状态&lt;/strong&gt;
我这里不是走官方申请通道，而是找第三方远程算号解锁。对方会让你装驱动、远程 USB 软件或者配套程序，最后给出这台机器对应的解锁码。做完以后，我会进 Fastboot 看底部状态，确认不是完全锁死状态。没有这个前提，后面步骤都没法谈。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ADB / Fastboot 工具&lt;/strong&gt;
我最后用的是较老版本的 platform-tools。原因不是“网上都说旧版神”，而是我在这台设备上碰到过新版工具写 recovery 后仍然表现异常的情况，回退工具版本后反而稳定了。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;TWRP 镜像&lt;/strong&gt;
这里最重要的不是“找个 TWRP 就行”，而是确认它确实对应 M3 / BTV 这一路机器。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;底层分区工具&lt;/strong&gt;
我准备了 &lt;code&gt;parted&lt;/code&gt;、&lt;code&gt;mkfs.ext4&lt;/code&gt;、&lt;code&gt;e2fsck&lt;/code&gt;、&lt;code&gt;resize2fs&lt;/code&gt;。后面会通过 &lt;code&gt;adb push&lt;/code&gt; 临时送进恢复环境使用。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ROM 和 GApps&lt;/strong&gt;
这部分我直接放在 MicroSD 卡里，而不是指望改完分区以后再慢慢往平板内部传。对老设备来说，外置卡能省很多麻烦。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;先说官方可接受的退路&lt;/h2&gt;
&lt;p&gt;即使你最终要刷第三方系统，也建议先知道官方还能提供什么恢复路径：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;HiSuite&lt;/code&gt;：适合系统层面的修复和回刷；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eRecovery&lt;/code&gt;：适合系统损坏或升级失败后从网络恢复；&lt;/li&gt;
&lt;li&gt;进入恢复前先保证电量和网络条件；&lt;/li&gt;
&lt;li&gt;rooted / 改过系统的设备也不代表完全没有恢复路径，但官方只会支持它自己的恢复方式。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我之所以把这个提前讲，是因为很多教程一上来就进入刷机命令，却不告诉你：&lt;strong&gt;一旦改了分区，官方工具未必还能像原机那样顺手兜底。&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;实际操作记录&lt;/h2&gt;
&lt;p&gt;下面这一段是我的真实流程，但我会尽量写成“你需要确认什么”，而不是“照着抄就一定行”。&lt;/p&gt;
&lt;h3&gt;第一步：先把“解锁这件事”说明白&lt;/h3&gt;
&lt;p&gt;这一步我不想继续写得很含蓄，因为现实里很多人就是卡在这里。&lt;/p&gt;
&lt;p&gt;像 MediaPad M3 这种老华为设备，现在常见做法就是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;去某宝或某鱼找还在做老设备解锁的人；&lt;/li&gt;
&lt;li&gt;对方发你一个解锁程序，以及配套的远程 USB 软件 / 加密狗环境；&lt;/li&gt;
&lt;li&gt;你把平板接到电脑，对方远程跑一遍识别和算号流程；&lt;/li&gt;
&lt;li&gt;算出解锁码后，再由你自己本地执行解锁。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这个流程我没有办法写成“所有人都能直接离线复现”的公开教程，因为第三方工具链和授权本身就不公开。但有一点我可以明确说：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;如果你的设备还在这条老华为算号支持范围里，解锁不是玄学，更多是有没有对应渠道和工具。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我建议你至少确认两件事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;卖家明确说支持 &lt;strong&gt;MediaPad M3 / BTV 系列&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;解锁完成后，Fastboot 里能看到已解锁状态，而不是只听卖家说“已经好了”。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;第二步：刷入 TWRP，但不要把 Fastboot 的“成功”提示当作全部真相&lt;/h3&gt;
&lt;p&gt;我做法很简单：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;关机；&lt;/li&gt;
&lt;li&gt;按住音量下接 USB，进 Fastboot；&lt;/li&gt;
&lt;li&gt;执行：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;fastboot flash recovery twrp.img
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;真正要注意的是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;命令返回 &lt;code&gt;OKAY&lt;/code&gt; 不代表后续一定能正常进恢复；&lt;/li&gt;
&lt;li&gt;如果工具链或镜像不匹配，Fastboot 的提示有时会过于乐观；&lt;/li&gt;
&lt;li&gt;我这台机器上，刷完以后&lt;strong&gt;不要直接 &lt;code&gt;fastboot reboot&lt;/code&gt;&lt;/strong&gt;，而是拔线、长按电源彻底关机，再手动按 &lt;strong&gt;音量上 + 电源&lt;/strong&gt; 进入恢复。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这是我自己踩过坑以后留下来的操作习惯，不是华为官方步骤。&lt;/p&gt;
&lt;h3&gt;第三步：把底层工具推到 &lt;code&gt;/sbin&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;进入 TWRP 后，我没有往 &lt;code&gt;/data&lt;/code&gt; 或其他分区里塞这些工具，而是直接推到内存中的 &lt;code&gt;/sbin&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;adb push parted /sbin/
adb push mkfs.ext4 /sbin/
adb push e2fsck /sbin/
adb push resize2fs /sbin/

adb shell
chmod 0777 /sbin/parted
chmod 0777 /sbin/mkfs.ext4
chmod 0777 /sbin/e2fsck
chmod 0777 /sbin/resize2fs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这么做的好处是简单直接，坏处也很明显：你已经彻底进入“恢复环境里的手工操作”了，后面没有任何图形向导会替你检查参数。&lt;/p&gt;
&lt;h3&gt;第四步：调整分区&lt;/h3&gt;
&lt;p&gt;这是最不适合写成“傻瓜照抄”的一段。&lt;/p&gt;
&lt;p&gt;我在 &lt;code&gt;parted /dev/block/mmcblk0&lt;/code&gt; 里确认过当前分区表，并且&lt;strong&gt;先看序号，再决定是否动手&lt;/strong&gt;。本文里那组 &lt;code&gt;43-49&lt;/code&gt; 的分区操作，是我这台 &lt;strong&gt;64GB BTV-DL09&lt;/strong&gt; 上的记录，不应该被理解成“所有 MediaPad M3 都是这样”。&lt;/p&gt;
&lt;p&gt;我实际遵循的是这个原则：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;先 &lt;code&gt;print&lt;/code&gt; 确认分区表；&lt;/li&gt;
&lt;li&gt;确认 &lt;code&gt;system&lt;/code&gt;、&lt;code&gt;cust&lt;/code&gt;、&lt;code&gt;vendor&lt;/code&gt;、&lt;code&gt;userdata&lt;/code&gt; 的位置和顺序；&lt;/li&gt;
&lt;li&gt;只在明确知道自己要扩大 &lt;code&gt;system&lt;/code&gt; 并且知道后续要如何重建其他分区时才继续；&lt;/li&gt;
&lt;li&gt;退出前再次确认新分区表没有把后面的链条打乱。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你对 GPT 和分区边界没有把握，&lt;strong&gt;到这里就应该停下&lt;/strong&gt;，而不是继续跟着敲命令。&lt;/p&gt;
&lt;p&gt;下面这组命令，是我这台 &lt;strong&gt;BTV-DL09 64GB&lt;/strong&gt; 机器上实际执行过的记录，我把它完整放回来，方便以后自己查，也方便同机型的人核对。再说一遍：&lt;strong&gt;只能拿来参考，不能默认适用于所有 M3。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;先进入分区工具：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/sbin/parted /dev/block/mmcblk0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后在 &lt;code&gt;(parted)&lt;/code&gt; 里先 &lt;code&gt;print&lt;/code&gt; 看当前分区，再确认：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;43&lt;/code&gt; 是 &lt;code&gt;system&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;49&lt;/code&gt; 是 &lt;code&gt;userdata&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我当时实际删掉旧分区的命令是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rm 49
rm 48
rm 47
rm 46
rm 45
rm 44
rm 43
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接着重建分区，我这台 &lt;strong&gt;64GB&lt;/strong&gt; 机器当时用的是下面这一组：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkpart system ext2 1174 6501
name 43 system
set 43 msftdata on

mkpart cust ext4 6501 6702
name 44 cust
set 44 msftdata on

mkpart version ext4 6702 6736
name 45 version
set 45 msftdata on

mkpart vendor ext2 6736 7374
name 46 vendor
set 46 msftdata on

mkpart product ext4 7374 7575
name 47 product
set 47 msftdata on

mkpart hisitest2 7575 7579
name 48 hisitest2
set 48 msftdata on

mkpart userdata 7579 62.5GB
name 49 userdata
set 49 msftdata on
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果你不是 64GB 版本，尤其是 32GB / 16GB，就不要直接照搬最后这个容量终点值，而是先看 &lt;code&gt;print&lt;/code&gt; 里磁盘总容量是多少。&lt;/p&gt;
&lt;p&gt;最后退出：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;quit
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;第五步：格式化并让 TWRP 重新识别新分区&lt;/h3&gt;
&lt;p&gt;分区表改完不等于系统已经会用。我的做法是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用 &lt;code&gt;mkfs.ext4&lt;/code&gt; 格式化新建分区；&lt;/li&gt;
&lt;li&gt;完全重启一次 TWRP，让内核重新读取分区表；&lt;/li&gt;
&lt;li&gt;在 TWRP 里对 &lt;code&gt;Data&lt;/code&gt;、&lt;code&gt;System&lt;/code&gt;、&lt;code&gt;Vendor&lt;/code&gt; 做文件系统修复或重新指定为 &lt;code&gt;ext4&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;去挂载菜单确认这些分区可以正常挂载。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我当时 shell 里实际跑过的基础格式化命令是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/sbin/mkfs.ext4 /dev/block/mmcblk0p43
/sbin/mkfs.ext4 /dev/block/mmcblk0p44
/sbin/mkfs.ext4 /dev/block/mmcblk0p45
/sbin/mkfs.ext4 /dev/block/mmcblk0p46
/sbin/mkfs.ext4 /dev/block/mmcblk0p47
/sbin/mkfs.ext4 /dev/block/mmcblk0p49
exit
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这一步做完以后，我是 &lt;strong&gt;彻底断开 USB，长按电源关机，再重新按音量上 + 电源回到 TWRP&lt;/strong&gt;，不是在原地图方便点个重启系统。&lt;/p&gt;
&lt;p&gt;这一步的重要性比很多教程写得高。因为分区表刚变更时，恢复环境里的挂载状态经常还停留在旧认知上。&lt;/p&gt;
&lt;h3&gt;第六步：刷 ROM 后把 System 真正“撑开”&lt;/h3&gt;
&lt;p&gt;扩完 System 分区以后，ROM 自己的镜像大小未必会自动占满新空间。这也是我保留 &lt;code&gt;e2fsck&lt;/code&gt; 和 &lt;code&gt;resize2fs&lt;/code&gt; 的原因。&lt;/p&gt;
&lt;p&gt;我的做法是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在 TWRP 里先刷目标 ROM；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不要急着重启系统&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;重新连电脑后执行：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;adb shell
/sbin/e2fsck -f /dev/block/mmcblk0p43
/sbin/resize2fs /dev/block/mmcblk0p43
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果 &lt;code&gt;resize2fs&lt;/code&gt; 能顺利把文件系统扩到新的上限，这一步才算完整闭环。&lt;/p&gt;
&lt;p&gt;至于 GApps，我当时的思路也很直白：既然都把 System 分区扩出来了，那就别再装最瘦的包，而是直接刷自己需要的完整包。刷完以后再顺手 &lt;code&gt;Wipe Cache/Dalvik&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;第七步：第一次开机要有耐心&lt;/h3&gt;
&lt;p&gt;这一步没什么技术含量，但很容易被误判：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一次开机时间会明显变长；&lt;/li&gt;
&lt;li&gt;改过分区和 Data 以后，系统重建缓存就是会慢；&lt;/li&gt;
&lt;li&gt;没必要在第一次 logo 多转几分钟时就立刻判断“变砖”。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我自己的经验是，先给它足够时间，再判断是不是卡死。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Google 服务这件事，最好说人话&lt;/h2&gt;
&lt;p&gt;这部分最容易被写成“刷完 ROM 一切顺利，尽享全量 GApps”，但真实情况没有这么干脆。&lt;/p&gt;
&lt;h3&gt;1. 官方并没有给这台设备留下标准的 GMS 安装路线&lt;/h3&gt;
&lt;p&gt;尤其是中国市场机器，Google 服务本来就不是 Huawei 给出的官方预期路径。&lt;/p&gt;
&lt;h3&gt;2. M3 上能找到的方案，本质上还是社区 workaround&lt;/h3&gt;
&lt;p&gt;社区常见思路有两类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;直接刷 OpenGApps / MindTheGapps 这类包；&lt;/li&gt;
&lt;li&gt;对部分版本使用 &lt;code&gt;gsminstaller&lt;/code&gt;、手动装 Play Services / Play Store。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这两条路都不是 Huawei 文档会教你的做法，也都不保证“以后重置、换版本、换系统以后还一样稳定”。&lt;/p&gt;
&lt;h3&gt;3. 我的建议比“装什么包”更重要&lt;/h3&gt;
&lt;p&gt;如果你的目标是给老设备补上基础 Google 服务，优先级应该是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先让系统稳定启动；&lt;/li&gt;
&lt;li&gt;先确认 System 和 Data 都正常；&lt;/li&gt;
&lt;li&gt;再决定是刷完整 GApps 还是只补必须组件；&lt;/li&gt;
&lt;li&gt;遇到认证或兼容性问题，按 ROM 社区的实际反馈处理，而不是把责任推给 Huawei 官方。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;Wi‑Fi 显示“已连接但网络受限”时，我是怎么处理的&lt;/h2&gt;
&lt;p&gt;这部分我保留，因为它确实是老设备刷第三方系统以后很常见的问题。&lt;/p&gt;
&lt;p&gt;原因通常不是 Wi‑Fi 真坏了，而是系统默认拿 Google 的探测地址去做 captive portal 验证，国内环境下容易超时，于是图标上出现 &lt;code&gt;×&lt;/code&gt; 或“网络受限”提示。&lt;/p&gt;
&lt;p&gt;我最后是用 ADB 改掉验证地址，比如：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;adb shell settings put global captive_portal_http_url http://connect.rom.miui.com/generate_204
adb shell settings put global captive_portal_https_url https://connect.rom.miui.com/generate_204
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果你不想用小米的地址，也可以换成别的可达 &lt;code&gt;generate_204&lt;/code&gt; 目标，例如 Cloudflare 的 &lt;code&gt;https://cp.cloudflare.com/generate_204&lt;/code&gt;。核心思路不是“某家服务器最神”，而是：&lt;strong&gt;让系统别再去访问当前环境下不可达的默认探测地址。&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;这篇记录真正能帮你的地方&lt;/h2&gt;
&lt;p&gt;如果只看一句话，我希望你记住的是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;这台设备现在还能折腾，但“官方支持的恢复路径”和“社区自己拼出来的刷机路径”已经不是一回事了。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;把这件事看明白，后面的决策才不会乱。&lt;/p&gt;
&lt;p&gt;对我来说，这次折腾最大的经验不是“命令怎么敲”，而是三点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先确认这台机器现在还有没有官方兜底；&lt;/li&gt;
&lt;li&gt;再确认社区方法到底适配哪一批机型；&lt;/li&gt;
&lt;li&gt;最后才是你要不要真的去动分区。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果这三点没搞清楚，写得再像“终极教程”，也只是把风险包装得更好看。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;参考依据&lt;/h2&gt;
&lt;h3&gt;官方资料&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Huawei：rooted 设备的系统恢复说明&lt;br /&gt;
&lt;a href=&quot;https://consumer.huawei.com/ca/support/content/en-us00406898/&quot;&gt;https://consumer.huawei.com/ca/support/content/en-us00406898/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Huawei：系统更新失败后的恢复说明&lt;br /&gt;
&lt;a href=&quot;https://consumer.huawei.com/ca/support/content/en-us00416970/&quot;&gt;https://consumer.huawei.com/ca/support/content/en-us00416970/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Huawei：HiSuite / 恢复相关 FAQ&lt;br /&gt;
&lt;a href=&quot;https://consumer.huawei.com/ca/support/content/en-us00698630/&quot;&gt;https://consumer.huawei.com/ca/support/content/en-us00698630/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Huawei eRecovery 说明页&lt;br /&gt;
&lt;a href=&quot;https://consumer-tkbdownload.huawei.com/ctkbfm/applet/simulator/en-gb00739873/erecovery.html&quot;&gt;https://consumer-tkbdownload.huawei.com/ctkbfm/applet/simulator/en-gb00739873/erecovery.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MediaPad M3 官方支持页（可见支持结束状态）&lt;br /&gt;
&lt;a href=&quot;https://consumer.huawei.com/jp/support/tablets/mediapad-m3-8/&quot;&gt;https://consumer.huawei.com/jp/support/tablets/mediapad-m3-8/&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;政策与社区资料&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Huawei 社区：Bootloader 解锁政策停止说明&lt;br /&gt;
&lt;a href=&quot;https://consumer.huawei.com/en/community/details/topicId-41529/&quot;&gt;https://consumer.huawei.com/en/community/details/topicId-41529/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Android Police：Huawei 停止官方 Bootloader 解锁计划&lt;br /&gt;
&lt;a href=&quot;https://www.androidpolice.com/2018/05/24/huawei-halts-bootloader-unlock-program-indefinitely/&quot;&gt;https://www.androidpolice.com/2018/05/24/huawei-halts-bootloader-unlock-program-indefinitely/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;XDA：MediaPad M3 解锁 / TWRP / root 讨论&lt;br /&gt;
&lt;a href=&quot;https://xdaforums.com/t/guide-unlock-bootloader-twrp-root-huawei-mediapad-m3-8-4-btv-w09-btv-dl09.4085383/&quot;&gt;https://xdaforums.com/t/guide-unlock-bootloader-twrp-root-huawei-mediapad-m3-8-4-btv-w09-btv-dl09.4085383/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;XDA：MediaPad M3 添加 Google 服务讨论&lt;br /&gt;
&lt;a href=&quot;https://xdaforums.com/t/media-pad-m3-8-add-google-services-install-core-gsm-core-package-solved.3768089/&quot;&gt;https://xdaforums.com/t/media-pad-m3-8-add-google-services-install-core-gsm-core-package-solved.3768089/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;XDA：M3 BTV 机型 unbrick / rollback / rescue 讨论&lt;br /&gt;
&lt;a href=&quot;https://xdaforums.com/t/mediapad-m3-un-brick-restore-rollback-and-rescue-for-btv-variants.4212953/&quot;&gt;https://xdaforums.com/t/mediapad-m3-un-brick-restore-rollback-and-rescue-for-btv-variants.4212953/&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item></channel></rss>