小米平板 6S Pro Fastboot 循环:GPT 类型 GUID 修复记录

小米平板 6S Pro Fastboot 循环:GPT 类型 GUID 修复记录
misaka10843本文由GPT-6 Luna总结编写
前言
小米平板 6S Pro(sheng)之前一直卡在 Fastboot。开机时能看到小米 Logo,随后很快又掉回 Fastboot;进 Recovery 也会重启回 Fastboot。
中间试过重刷移植包,也试过刷入 OS3.0.303.0 底包里的部分启动镜像,Fastboot 命令都显示成功,但启动现象没有变化。后来又完整刷过一次官方线刷包,还是进 Fastboot。
折腾到这里,继续猜镜像已经没什么意义了。真正有用的线索来自 UEFI 启动日志:它不是报找不到系统,而是明确说 A/B 槽位的 GUID 校验失败。
先看启动日志
从 Fastboot 进入 EDL 后,读取了启动日志分区。进入 EDL 用的是:
fastboot devices |
第二条命令会让设备切换到 EDL 模式。确认设备确实进入 EDL 后,再用 Firehose 工具读取日志分区。日志中反复出现:
ValidateSlotGuids: BootableSlot _a does not have valid guids |
_b 槽也记录了相同的 ValidateSlotGuids 失败。也就是说,UEFI 在挑选启动槽位时就拒绝了 A、B 两边,之后才回到 Fastboot。
这条日志把排查方向从“系统镜像是不是没刷进去”带到了 GPT 分区项本身。
在一个 EDL 会话里读主备 GPT
读取日志后,在同一个 Firehose 会话里继续读取 UFS LUN4 的 GPT。主 GPT 从 LBA 0 开始读 6 个 4096 字节扇区;备 GPT 则读取 LBA 521209 到 521215。这样不必每读一段都重新连接设备:
LUN 4, LBA 0, 6 sectors -> primary GPT |
这次读取是通过自定义 Python 包装程序在一个 Firehose 会话里完成的。当前没有保留足以复现它的完整调用参数,所以这里记录实际读取的 LUN、LBA 和扇区数,不拼凑一个看起来完整但未经核实的 EDL 命令。
这台机器报告的 UFS 型号是 256 GB。注意,读回的 GPT 文件完整不代表分区表内容一定正确,所以还要分别校验主表、备表的表头 CRC、分区数组 CRC,并把两份数组逐字节比较。
本次结果:
- 主 GPT 表头 CRC 有效,分区数组 CRC 有效。
- 备 GPT 表头 CRC 有效,分区数组 CRC 有效。
- 主备分区数组逐字节一致。
- 分区起止位置与 OS3.0.303.0 模板的主要布局相同。
所以问题不是“主 GPT 坏了、备 GPT 好了”这种简单情况。两份表自身的 CRC 都正确,但其中一些分区项的类型 GUID 与启动程序要求的不一致。
找到错位的 26 个类型 GUID
将设备当前 GPT 与 OS3.0.303.0 包里的 GPT 模板对照后,发现 13 组 A/B 分区、共 26 个 Type GUID 不匹配:
aop_a / aop_b |
其中 boot_a、abl_a 等启动相关分区项被标成了通用 GUID:
77036CD4-03D5-42BB-8ED1-37E5A88BAA34 |
而 UEFI 日志正好显示它拿到的 Boot GUID 和 abl_a GUID 都是这个通用值,随后报 BootableSlot _a does not have valid guids。B 槽同理。
这里有个容易误判的地方:GPT 的 CRC 只检查数据和 CRC 是否匹配,并不理解某个分区应该使用哪种 Type GUID。因此,CRC 全绿仍然可能是语义错误的 GPT。
修复方式
没有把官方 GPT 文件整份覆盖到设备上,而是以设备当前 GPT 为底稿,只把上面 26 个分区项的 Type GUID 恢复成 OS3.0.303.0 模板对应的值,再重算 GPT CRC。
写回顺序是先备表,再主表:
| 内容 | LUN | 起始 LBA | 扇区数 |
|---|---|---|---|
| 备 GPT 分区数组 | 4 | 521209 | 3 |
| 备 GPT 表头 | 4 | 521215 | 1 |
| 主 GPT 分区数组 | 4 | 2 | 3 |
| 主 GPT 表头 | 4 | 1 | 1 |
写完后仍在同一个 Firehose 会话里把主、备 GPT 重新读回,重新计算 CRC,并确认两份分区数组一致。
这次只修改了 Type GUID 和相应 CRC,保留了:
- 分区起止位置与大小
- 分区属性和槽位状态
- 每个分区自己的唯一 GUID
- 设备磁盘 GUID
xbl_sc_logs等设备特有的尾部布局
之前线刷日志里出现过 metadata 擦除和 userdata 写入;本次 GPT 修复没有写 userdata。但此前的刷机操作是否影响过用户数据,不能只凭这次修复判断。
修复后怎么验证
读回确认主备 GPT CRC 都有效后,设备并没有立刻进入 Android,而是先从 Recovery 又回到了 Recovery。随后从 Recovery 进入 Fastboot,检查当前槽和槽位状态:
fastboot getvar current-slot |
当时读到当前槽是 a,A、B 都没有被标记为 unbootable。随后执行 Fastboot 的继续启动命令:
fastboot continue |
平板随后离开 Fastboot 并进入 Android 系统。设备屏幕显示系统已启动;USB 调试当时没有开启,因此没有用 ADB 读取 sys.boot_completed。
到这里可以确认:这次 GPT Type GUID 修复解除了 UEFI 对 A/B 槽的 GUID 校验阻断,Android 已经能够启动。Recovery 的一次普通重启仍回到 Recovery,Linux 启动路径也没有在本次修复后验证。
这次踩到的坑
Fastboot 显示 OKAY 不代表启动链完整
此前多次刷写都显示成功,但设备依旧回到 Fastboot。Fastboot 的 OKAY 只能说明对应写入命令完成了,不能证明 UEFI 后续会接受 GPT 元数据并成功引导。
GPT CRC 正确不代表分区定义正确
主备 GPT 完全一致且 CRC 正确,UEFI 仍然因为分区 Type GUID 不符拒绝 A/B 槽。需要同时看表结构、字段内容和启动日志。
不要盲目覆盖官方 GPT
官方 GPT 适合做布局和 Type GUID 的参考,不应该不加区分地整份覆盖。设备 GPT 里有唯一 GUID、槽位状态和设备自己的尾部布局;直接套模板可能把这些设备状态一起覆盖。本次只恢复了确认错误的 Type GUID。
qbootctl -s _a 不能直接认定是根因
本地检查的 qbootctl 源码只接受 a、b 或 0、1 这种槽位参数,字面量 _a 会被参数解析拒绝。不过,这不能证明设备上当时运行的二进制与检查的源码完全相同,也不足以单独证明故障由那条命令造成。最终定位依据是设备当前 GPT 与 UEFI 报错内容相互吻合。
总结
这次 Fastboot 循环的直接阻断点,是 GPT 中多组 A/B 分区 Type GUID 与 UEFI 槽位校验预期不一致。修复这些字段并重算 CRC 后,设备从 Fastboot 继续启动进入了 Android。
完整过程可以概括成:先读 UEFI 日志定位失败阶段,再在同一 EDL 会话中读回主备 GPT,对照设备对应版本的模板,只修确认错误的字段,最后读回验证并启动测试。
这篇记录只对应这台 sheng 和 OS3.0.303.0 分区模板。分区 LBA、GUID 和修复数据都具有设备与版本相关性,不能直接复制到其他平板上使用。





