OnePlus Open (CPH2551) Root 记录
设备:OnePlus Open,型号 CPH2551EEA(欧洲/EEA 版),Android 16,芯片高通骁龙(Qualcomm,有 EDL 9008 硬件救砖模式)。
Root 完成时间:2026-07-19。当时系统版本 16.0.3.500(EX01)(OTA 日期码 202601202321),build BP2A.250605.015 / incremental T.R4T3.39d0968-17b17ea-17b17e8。
环境
- Mac 上
adb/fastboot在~/android-sdk/platform-tools/,不在 PATH 里,要写全路径或自己加 PATH。 payload-dumper-go(Go 二进制,从 GitHub release 下的预编译版):brew/go都没装的情况下解 OTApayload.bin用这个,比 Python 版payload_dumper(pip 装的那个)在 macOS 上更稳——Python 版在这台 Mac 上跑 multiprocessing 直接崩(TypeError: cannot pickle '_io.BufferedReader' object,py3.9 + macOS spawn 模式的已知坑)。
步骤
1. 开启开发者选项 + USB 调试
设置 → 关于手机 → 版本号连点 7 次 → 开发者选项 → USB 调试。连 Mac 后手机端会弹授权框,务必点确认。
2. Bootloader 解锁
- 开发者选项里打开 OEM 解锁 开关(需要手机联网,这个开关必须在手机上手动点,adb 远程写不了)。
adb reboot bootloader进 bootloader。- 关键坑:
fastboot devices经常识别不到刚进入 bootloader 的手机(USB 重新枚举失败),表现是命令一直卡在< waiting for any device >或者直接返回空。解法:把 USB 数据线拔了重插一次,几乎每次都能立刻解决,比等待或者重启 adb server 都管用。 fastboot flashing unlock,手机屏幕会弹确认框,音量键选、电源键确认。- 解锁会清空手机全部数据(相当于恢复出厂设置),确认前一定要跟用户对齐。
- 解锁后设备自动擦除数据 + 重启,过程可能要 1-2 分钟。
- 重新走一遍开机设置向导,重新开 USB 调试(数据清空后授权状态也没了)。
- 验证:
fastboot getvar unlocked应该返回yes。
3. 找 init_boot.img(这台机最大的坑)
Android 13+ 的 GKI(Generic Kernel Image)设备把可写的 ramdisk 独立成了 init_boot 分区,Magisk 要 patch 的是这个,不是传统的 boot.img。
死路 A —— 直接下载对应版本的独立 img:OnePlus Open 是小众机型,第三方固件站(firmwarefile/gsmmafia/firmwaredrive)镜像更新慢,经常没有当前最新版本。XDA 的机型 root 长帖是社区提前提取好 img 的地方,但不保证每个版本都有人传。
死路 B —— 用 OS Updater(Oxygen Updater 改名版)app 重新下载"当前版本"当完整包:
用 OS Updater(Play 商店有,包名 com.arjanvlek.oxygenupdater)开高级模式选当前版本下载,看起来是拿到了一个完整包,实际上很可能是差分包(用 payload.bin 里的 BROTLI_BSDIFF 操作类型编码,需要"旧分区原始数据"做基准才能算出新分区内容)。用 payload-dumper-go 解会直接报 Unhandled operation type: BROTLI_BSDIFF,输出文件是 0 字节。这是个死循环:解差分包需要当前分区的原始数据,而拿当前分区原始数据本来就需要 root——鸡生蛋蛋生鸡。
判断是不是差分包:解压 zip 后看 META-INF/com/android/metadata 里的 pre-build / from_version 字段,如果 pre-build 的 incremental 号和手机 getprop ro.build.version.incremental 一致(或者 from_version 对应的正是你当前跑的版本),这包大概率就是"从当前版本到某个目标版本"的差分包,不是独立完整镜像。
真正走通的路 —— 找完整 QFIL 刷机包:
第三方 ROM 站(比如 filewale.com、firmwaredrive.com)上如果有 ..._QFIL.zip 这种命名的包(几个 G 大小,官方售后/维修用的刷机格式),解压后目录结构是:
Firmware/IMAGES/init_boot.img ← 就是这个,独立完整镜像,直接能用
Firmware/IMAGES/boot.img
Firmware/IMAGES/vendor_boot.img
...(其余几十个分区各自独立 .img)
这种包是给 QFIL/MSM 烧录工具用的原厂物料,里面全是完整分区镜像,没有差分这一说。只要大版本相近(哪怕不是精确匹配你当前跑的那个小版本号),init_boot 这种偏底层、跟具体地区/业务功能关系不大的分区,跨一两个小版本通常直接能用——这次实测:手机当前版本是 16.0.3.500,用的是 16.0.2.400 这个 QFIL 包里的 init_boot.img,patch 完刷上去、开机、root 全部正常,系统版本号本身没有任何变化。
不需要解压整个几 G 的 zip,unzip -j 大包.zip "路径/init_boot.img" -d 目标目录 就能只抠这一个文件出来。
4. Magisk patch + 刷入
- 装 Magisk App(GitHub
topjohnwu/Magisk最新 release 的Magisk-vX.X.apk,Play 商店没有,得自己下 APKadb install)。 adb push init_boot.img /sdcard/Download/。- 手机上打开 Magisk → 安装 → 「选择并修补一个文件」→ 选刚推上去的 img → 等跑完,会在
/sdcard/Download/生成magisk_patched-<版本号>_<随机码>.img。 adb pull这个 patch 好的文件回 Mac。adb reboot bootloader(同样注意上面提到的"拔插数据线"坑)。fastboot flash init_boot 那个patch好的文件.img。fastboot reboot。- 验证:
adb shell su -c id应该返回uid=0(root)。
Root 之后的注意事项
- 别再点系统 OTA 更新:正常升级会整个覆盖
init_boot分区,root 直接失效(不会变砖,但要重新走一遍 patch+刷入流程)。 - Bootloader 解锁状态不影响日常使用,开机可能会有一条短暂的解锁提示。
- 如果 App 检测 root 报错,Magisk App 里配置隐藏/DenyList。
没走通、别浪费时间重试的路
fastboot fetch <partition>:这台机的 bootloader 不支持 fetch 命令,拿不到已刷入分区的原始数据。adb shell dd if=/dev/block/by-name/init_boot_a ...(非 root):权限不够,Permission denied,非 root 用户读不了块设备。- Python 版
payload_dumper(pip 装的vm03/payload_dumper):在这台 Mac(Python 3.9 + macOS)上 multiprocessing 直接崩,换payload-dumper-go的预编译二进制。 - 下载"当前版本"的完整包指望走差分 OTA 拿到完整镜像:见上面"死路 B",行不通。
关于降级刷机的风险(没走这条路,但调研过)
高通芯片有硬件级 anti-rollback(防降级)熔丝,一次性烧录、不可逆。如果直接整个刷入一个比手机已经跑过的版本更旧的完整固件(不只是抠一个分区,而是走 MSM/QFIL 全量刷),有可能触发防降级校验失败,卡在 bootloader/EDL 循环里进不去系统。这跟本文档"只抠 init_boot 单独刷"是完全不同风险等级的操作——后者不碰 anti-rollback 保护的早期启动分区(xbl/abl/vbmeta 等),前者才是真正有变砖风险的操作。高通芯片有 EDL(9008)硬件救砖模式,理论上救得回来,但需要官方 MSM 工具或第三方付费救砖服务,不是能免费/确定性 DIY 的路。这次全程没有整机刷过旧固件,只动过 init_boot 一个分区,跟这个风险不沾边。