Moto Edge 60 Pro OTA 升级保 Root 实录(刷回原版 init_boot + Android 16 重新 Root)
前言:
本文承接上一篇:Moto Edge 60 Pro Root & 隐藏方案(KSU-NEXT + Play Integrity FULL PASS)。
上一篇主要记录了 Moto Edge 60 Pro 在 Android 15 上如何通过 KSU-NEXT / LKM 获取 root,并通过 Play Integrity Strong。这次官方推送 Android 16 后,问题就从“怎么 root”变成了“怎么升级,而且尽量不丢数据,再把 root 平稳接回去”。
这次我没有直接拿完整包开刷,而是先把完整包结构、flashfile.xml、A/B OTA 的行为、分区刷写路径和 Windows 驱动问题重新捋了一遍。过程中也顺手让 Codex 帮我把步骤和判断拆清楚,最后走通了一条相对稳妥的路线。中间踩到的坑都挺典型,单独记一篇,后面自己翻也方便。
这篇主要记录:
- 为什么完整包不能直接原样线刷
- 为什么刷回旧版原版
init_boot之后,官方 OTA 又重新通过了 - OTA 完成后,如何从新版完整包重新提取、修补并刷回
init_boot - 过程中几个很容易浪费时间的坑
1. 我的环境与目标
我的环境如下:
- 机型:Moto Edge 60 Pro(RETCN)
- 旧系统版本:
V2VVC35.58-70-3 - 新系统版本:
W1VVC36H.7-73-6 - root 方式:
KernelSU NEXT修补init_boot.img,模式为LKM - 原有模块环境:
Zygisk Next + LSPosed + Shamiko + PIF + TrickyStore
这次升级的目标很简单:
- 尽量保留现有数据
- 优先走官方 OTA,而不是直接整包清刷
- OTA 完成后重新接回 root
- 后续继续沿用上一篇里的完整性隐藏方案
2. 为什么不能直接原样刷完整包
我下载的完整包是:
1 | |
实际上,这次折腾并不是从“我要手动刷完整包”开始的,而是先在系统里直接点了 OTA 更新。结果更新器给出的提示很明确:
1 | |
也正是这个报错,才让我开始认真怀疑:当前 root 状态下的系统,已经不再满足官方 OTA 所需的源版本校验条件。
接下来思路自然分成了两条:
- 一条是研究能不能绕过 OTA,直接用完整包保数据升级
- 另一条是想办法把当前系统尽量恢复到 OTA 能接受的状态,再走官方更新
前者在把 flashfile.xml 看完之后,基本就可以排除了;后者后来证明才是正路。
所以后面才会去研究完整包,而不是上来就直接开刷。
但把包里的 flashfile.xml 仔细看完之后,这条路基本也就可以放弃了。
原因很直接:这不是普通 OTA 包,而是完整 fastboot 固件包,官方 XML 里明确包含这些擦除项:
erase nvdataerase userdataerase metadataerase debug_token
也就是说,如果按 XML 原样整包刷:
- root 一定会被覆盖
- 用户数据会被清空
- 整个过程也不再属于“保数据升级”
这里其实要先统一一个认知:
Moto 的完整 CFC.xml.zip 固件包,不等于系统里的 OTA 更新包。
如果目标是保留数据,并继续沿用现有 root 路线,就不能把“完整包线刷”和“OTA 升级”看成同一件事。
3. 关键判断:先刷回旧版原版 init_boot,再试官方 OTA
我这台机器的 root 路线,就是上一篇里那套 KSU-NEXT + LKM:
- 从官方固件提取
init_boot.img - 在手机端修补
init_boot.img - 刷回当前活动槽位
所以从技术上讲,我主动改动过的 boot 链关键分区,核心就是 init_boot。
而 A/B OTA 的工作方式,可以简单理解成:
- 以当前活动槽位作为“源状态”
- 对当前系统做校验
- 再把新系统写到未使用槽位
那么这里就有一个比较自然的推论:
如果 OTA 过不了,很大概率是当前槽位里的 patched init_boot 让校验失败了。
所以这次我没有一上来乱刷,而是先做一个低风险验证:
- 从旧版官方包提取当前版本的原版
init_boot.img - 刷回当前活动槽位
- 再重新尝试官方 OTA
模块要不要先删?
这里我的结论是:
- 不需要卸载
LSPosed、Taichi或其它模块 - 但建议先全部停用,尤其是会作用于系统、设置、Play 服务、更新器的模块
原因也不复杂。这一步的目的不是“永久清环境”,而是尽量干净地验证:
到底是不是 patched init_boot 导致 OTA 过不去。
4. 提取并刷回旧版原版 init_boot
旧版完整包是:
1 | |
先确认当前系统确实还是旧版:
1 | |
然后先把当前 patched 的 init_boot 备份出来,这样如果 OTA 还是不通,可以快速恢复旧 root:
1 | |
如果当前槽位不是 a,就把上面命令里的 a 改掉。
接着从旧官方包里提取原版 init_boot.img:
1 | |
这里的第一个坑:不要进 fastbootd
一开始我习惯性用了:
1 | |
结果刷 init_boot_a 的时候直接报错,类似:
1 | |
后来排查才确认,这一步不能进 fastbootd,而要进 bootloader 模式。正确命令应该是:
1 | |
然后再确认槽位:
1 | |
这里要注意:
current-slot决定你该刷init_boot_a还是init_boot_bis-userspace应该返回no- 如果是
yes,说明你还在fastbootd
确认无误后,刷回原版 init_boot:
1 | |
如果当前槽位是 b,就改刷 init_boot_b。
刷回后重启,root 会临时消失,这是预期现象。
5. 刷回原版 init_boot 后,官方 OTA 重新通过
这一步是整条路线里最关键的验证点。
刷回原版 init_boot 之后,我再次点击系统里的 OTA 更新,结果很明确:
- 验证阶段通过
- 正式进入
apply 更新
这说明前面的判断基本是对的:
当前活动槽位里的 patched init_boot,确实是阻碍官方 OTA 的主要因素之一。
也正因为这里走的是官方正常 OTA 流程,所以数据安全性比完整包线刷高得多。只要是标准 A/B OTA,就不应该去碰 erase userdata 这种路径。
我的建议是:
- OTA 一旦进入
apply,就不要手动中断 - 不要强制重启
- 保证电量充足
- 等它完整结束,并成功启动一次新系统
6. OTA 完成后,Windows 下 fastboot 驱动又出了问题
OTA 完成后,我原本准备按计划重新 root,结果又遇到一个很别扭的问题:
- 系统开机状态下,
adb正常 - 进入
bootloader或fastbootd后,执行fastboot一直waiting for any device
后来发现这不是手机坏了,也不是 init_boot 有问题,而是 Windows 对 bootloader / fastboot 模式的驱动绑定丢了。
打开设备管理器后,可以看到一个带黄色感叹号的 Android 设备。
解决方法是:
- 保持手机停在
bootloader界面 - 打开设备管理器
- 找到带黄色感叹号的
Android - 右键 → 更新驱动程序
- 选择“浏览我的电脑以查找驱动程序”
- 再选“让我从计算机上的可用驱动程序列表中选取”
- 手动绑定到:
Android Bootloader Interface
这一点也值得单独记一下:
ADB 能用,不代表 fastboot 驱动就一定正常。
两者在 Windows 里对应的是不同的 USB 设备模式。
7. 从新版完整包提取 init_boot,再重新 root
OTA 成功进入新系统一次之后,后面的动作就回到了上一篇最熟悉的套路,只不过镜像必须换成新版。
先确认当前已经是新系统:
1 | |
然后从新版完整包提取 init_boot.img:
1 | |
把新版 init_boot 推到手机:
1 | |
然后在手机上打开 KernelSU NEXT:
- 选择修补镜像
- 选中新推送的新版
init_boot - 模式继续选
LKM
修补完成后,把 patched 镜像再拉回电脑:
1 | |
接着再次进入 bootloader:
1 | |
确认:
is-userspace = no- 再根据
current-slot判断刷a还是b
我这次 OTA 完成后的实际目标槽位是 b,所以最终刷的是:
1 | |
8. 第二个坑:Too many links 不是镜像问题,而是数据线问题
我在刷新版 patched init_boot 的时候,又遇到了一次报错:
1 | |
第一眼看确实有点唬人,因为这个错误完全不像普通 fastboot 报错。
但后来把分区名、槽位、驱动、模式都排查了一遍之后,结论反而很朴素:
不是镜像问题,也不是分区问题,而是数据线问题。
换了一根线之后,立刻正常刷入。
所以这里顺手记一个经验:
- 如果
sending成功,但writing阶段出现这种奇怪的 I/O 报错 - 而且分区名、驱动、模式都已经确认没问题
那就优先排查:
- 数据线
- USB 口
- 转接器 / Hub
不要第一时间怀疑镜像本身。
9. 刷入成功后,模块恢复建议
新版 root 恢复之后,不建议一上来把全部模块一次性打开。
我更推荐的顺序是:
- 先确认
KernelSU NEXT本体已经正常工作,模式仍为LKM - 再启用
Zygisk Next - 再启用
LSPosed - 再启用
Shamiko - 再检查
PIF - 再检查
TrickyStore - 最后再恢复其它零碎模块
至于 Play Integrity 的配置,这篇就不重复展开了,完全可以直接沿用上一篇里的方案:
PIFTrickyStoreTrickyStore AddonmomoSPICTBCheck
换句话说,这篇主要解决的是:
如何从“已经 root 的旧系统”安全升级到“新的已 root 系统”。
而完整性隐藏链路本身,仍然以前一篇为主。
10. 这次升级过程里最值得记住的几个结论
1. 完整包不等于 OTA 包
CFC.xml.zip 是完整 fastboot 固件包,不是普通 OTA 包。原样线刷通常会清数据,不能和系统里的 OTA 更新等同看待。
2. patched init_boot 确实可能阻断官方 OTA
如果你的 root 路线和我一样,是 KSU-NEXT + LKM 修补 init_boot,那 OTA 过不去时,优先尝试刷回当前版本的原版 init_boot,是一个非常高价值的验证步骤。
3. 刷 boot 链分区时,要进 bootloader,不要进 fastbootd
adb reboot fastboot 不一定是你想要的模式。对于 init_boot 这类分区,优先使用:
1 | |
4. Windows 下 ADB 正常,不代表 fastboot 驱动正常
开机能 adb,但 bootloader 下 fastboot waiting for any device,大概率是驱动绑定问题。设备管理器里出现黄色感叹号时,手动绑定 Android Bootloader Interface 往往就能解决。
5. Too many links 这种看起来离谱的 fastboot 报错,也可能只是线的问题
不要被报错文字吓到,排查顺序仍然应该从最基础的 USB 链路开始。
11. 总结
如果把这次过程压缩成一句话,那就是:
对已经用 KSU-NEXT root 的 Moto Edge 60 Pro 来说,最稳妥的升级路线,不是直接拿完整包原样线刷,而是先刷回旧版原版 init_boot 让官方 OTA 通过,升级完成后再从新版完整包重新提取并修补 init_boot,把 root 接回去。
这条路线的好处也很明确:
- 数据更安全
- root 路线不需要推倒重来
- Play Integrity 那套后续配置仍可承接上一篇
- 整个排错过程也更清楚
至此,这台 Moto Edge 60 Pro 的 root 方案基本就算完整了:
- 上一篇解决“如何在旧系统上获取 root 并通过完整性”
- 这一篇解决“如何在不粗暴清数据的前提下,跨版本升级并重新接回 root”
如果后面再遇到小版本 OTA,我大概率还是会优先沿用这条思路,而不是直接整包线刷。