GammaOS Core Beta3 X35S sdboot_sdhci 修复过程

适用设备:Powkiddy X35S / RK3566 + RK817

目标镜像:GammaOS_Core_Beta3_X35_x35sdtb_v9_sdboot_sdhci.img

本文记录一次从现象分析、镜像混合、串口定位、设备树反编译,到 Android boot header 哈希修复的完整过程。重点不是某一条命令,而是如何用串口证据把问题从“屏幕不亮”逐步收敛到“显示设备树与 eMMC 设备树互相冲突”。


1. 最终结果

最终生成的版本是:

1
/home/openclaw/Share/GammaOS_Core_Beta3_X35_x35sdtb_v9_sdboot_sdhci.img

之后发现 Android boot header 中的 id 没有随着 DTB 修改而更新,又生成了哈希修正版:

1
/home/openclaw/Share/GammaOS_Core_Beta3_X35_x35sdtb_v9_sdboot_sdhci_hashfix.img

可单独刷入的最终 boot:

1
/home/openclaw/.openclaw/workspace-rk3566-dev/tmp/sdboot-sdhci/sd-boot.good.sdhci-okay.hashfix.img

关键验证结果:

1
2
3
4
DTB 中 sdhci@fe310000/status = "okay"
Android boot header id = 2ae4fa77a566a0382e43646a29368737a47c4952
boot sha256 = ebabd79fd6b4c03cb7810afff9ebd2f149550bd33d4960f3c03ff19fcad8b37e
完整升级包 sha256 = 728873846593712628950f0769956f16cad237bc21b9bd1f19732693025b7174

训练家实机刷入后确认:

1
2
3
系统成功启动
屏幕正常
eMMC / metadata / super 能够正常使用

2. 原始问题和分析目标

最初的目标是让 GammaOS Core Beta3 在 X35S 上正常启动并正常显示。已有两个重要输入:

1
2
GammaOS_Core_Beta3_X35_x35sdtb_v9.img
./bootfix/bootfix/sd-boot.good.img

其中:

  • GammaOS 镜像包含完整 Android 系统、分区和 ramdisk 配置,但显示链路存在问题。
  • sd-boot.good.img 能够正常显示,说明其中的 kernel/DTB 至少包含一套可工作的 X35S 显示配置,但它并不一定与 GammaOS 的 eMMC、dynamic partition 和 ramdisk 配置兼容。

因此不能一开始就假设“把整个 SD boot 替换进去就能解决问题”。需要分别判断:

  1. 外层镜像是什么格式,能否直接 dd
  2. boot 镜像内部有哪些组成部分;
  3. 显示问题来自 kernel、DTB、ramdisk,还是 U-Boot/分区;
  4. 能正常显示的 SD boot 是否同时关闭了 GammaOS 需要的 eMMC 控制器;
  5. 修改 boot 内容之后,Android boot header 的校验信息是否仍然有效。

3. 第一步:先确认 GammaOS 镜像不是 raw 磁盘镜像

3.1 不能直接使用 dd

检查 GammaOS 文件头后发现它以 Rockchip 固件包头开头:

1
RKFW

因此它不是可以直接写入 /dev/mmcblkX 的 raw 磁盘镜像,而是 Rockchip update.img / RKFW 升级包。它内部包含多个带名称的镜像条目,例如:

1
2
3
4
5
6
7
8
9
MiniLoaderAll
uboot
trust
misc
boot
recovery
super
vbmeta
...

正确思路是:

1
2
3
4
解读 RKFW 包
定位 boot 条目
只替换 boot 条目内容
保持外层包结构、其他分区和原始文件不变

刷写时应使用 Rockchip Loader/Maskrom 工具,例如:

1
2
sudo ./tools/upgrade_tool/upgrade_tool uf \
/home/openclaw/Share/GammaOS_Core_Beta3_X35_x35sdtb_v9_sdboot_sdhci_hashfix.img

或者使用已经验证可用的 rkdeveloptool 流程。不要把整个 RKFW 文件直接当作普通 SD 卡盘镜像执行 dd

3.2 定位 RKFW 中的 boot 条目

第一次直接混合时,确认 GammaOS 包中 boot 条目的位置和长度为:

1
2
offset = 0x4eb226
length = 0x2130d50 = 34803024 bytes

这个信息很重要:它说明外层包并不是简单的“文件头 + 固定分区”,而是由内部 package metadata 描述各个文件。替换时必须:

  • 从原 GammaOS 包复制一份副本;
  • 找到 boot 条目的实际数据区;
  • 写入与条目长度相同的 boot 内容;
  • 不改变外层文件尺寸和其他条目;
  • 替换后重新验证外层包头、内嵌 boot 头和长度。

第一次混合版本验证到:

1
2
3
4
外层镜像头:RKFW
内嵌 boot 头:ANDROID!
输出镜像大小与原包一致:True
embedded boot 等于 sd-boot.good.img 前 34803024 bytes:True

4. 第二步:先做整 boot 混合,利用实机结果建立因果关系

训练家要求先直接把 sd-boot.good.img 混入 GammaOS。这个版本没有立刻假设它是最终方案,而是作为一次有价值的实验。

生成的中间版本:

1
/home/openclaw/Share/GammaOS_Core_Beta3_X35_x35sdtb_v9_sdbootmix.img

做法是:

1
2
GammaOS 外层 RKFW 包
└── 原 boot 条目替换为 sd-boot.good.img 对应内容

该版本的意义是验证“显示问题是否确实位于 SD boot 的 kernel/DTB 路径”。

4.1 实机结果

刷入后出现了非常关键的现象:

1
2
3
屏幕正常
但 Android 无法进入系统
随后重新进入 fastboot

这说明整 boot 替换不是完全失败,反而证明了两件事:

  1. sd-boot.good.img 中的显示相关 kernel/DTB 配置确实能让 X35S 的 DSI/VOP 出图;
  2. SD boot 的其他内容不能直接用于 GammaOS,尤其可能破坏 eMMC、fstab、dynamic partition 或 ramdisk 之间的配合。

这一步把问题从“GammaOS 显示不正常”缩小成了“需要移植显示部分,但必须保留 GammaOS 的存储和启动配置”。


5. 第三步:通过串口日志判断失败点

整 boot 混合版的串口日志是定位核心。不能只看最后一句“进入 fastboot”,而要看 Linux 启动过程中的前后关系。

5.1 显示链路已经成功

日志中有以下证据:

1
2
vp0, plane_mask:0x2a, primary-id:5
vp1, plane_mask:0x15, primary-id:4

U-Boot/DRM 还显示:

1
2
3
VOP VP1 enable Smart0[640x480->640x480@0x0] fmt[1]
final DSI-Link bandwidth: 198 Mbps x 4
dw_mipi_dsi_connector_enable....

Linux DRM 继续绑定了:

1
2
3
4
rockchip-vop2 fe040000.vop
rockchip-drm display-subsystem
rockchip-drm display-subsystem: bound fe060000.dsi
panel-simple-dsi fe060000.dsi.0

这些信息说明:

  • VOP 已经分配了可用 plane;
  • DSI0 fe060000 被识别;
  • panel 被探测;
  • U-Boot 和 Linux 都进入了显示初始化;
  • 实机也确认屏幕正常。

所以这次失败不是“屏幕仍然不亮”,也不是“kernel 没启动”。

5.2 Linux kernel 已经正常启动

日志中可以看到:

1
2
3
4
5
Linux version 4.19.219
Machine model: Rockchip RK3566 RK817 TABLET LP4X Board
Memory: 7852680K/8108032K available
Run /init as init process
init: init first stage started!

这排除了以下错误方向:

  • DDR 初始化失败;
  • kernel 无法解压或无法运行;
  • DTB 完全损坏;
  • init 没有启动。

5.3 真正的致命错误是 metadata/super 找不到

真正导致重启的日志是:

1
2
3
4
5
6
7
8
init: [libfs_mgr]ReadFstabFromDt(): failed to read fstab from dt
init: ... partition(s) not found in /sys, waiting for their uevent(s): metadata, super
...
init: Wait for partitions returned after 10001ms
init: ... partition(s) not found after polling timeout: metadata, super
init: Failed to mount required partitions early ...
init: InitFatalReboot: signal 6
reboot: Restarting system with command 'bootloader'

与此同时,eMMC/SDHCI 相关日志出现:

1
mmc1 mmc_send_io_op_cond err: -110

而 kernel command line 明确写着:

1
2
androidboot.storagemedia=emmc
androidboot.boot_devices=fe310000.sdhci

把这些证据连起来,结论是:

1
2
3
4
5
GammaOS 期望从 fe310000.sdhci 访问 eMMC
但混入的 SD boot DTB 没有把这个控制器保持为可用状态
内核无法枚举 eMMC
metadata 和 super 自然不会出现在 /sys/block 或 by-name 路径
Android first-stage init 等待超时后主动重启到 bootloader

这里的关键不是“super 分区损坏”,而是“承载 super 的 eMMC 控制器没有被正确启用”。


6. 设备树反编译:从 boot.img 找出 DTB

设备树在 boot 流程中承担了硬件描述作用,包括:

  • VOP、DSI、panel 和 backlight;
  • eMMC/SD 控制器;
  • GPIO、pinctrl、regulator;
  • Android fstab 节点;
  • Wi-Fi、蓝牙、按键等外设;
  • reserved-memory 和 CMA。

设备树在编译后不是文本,而是 DTB(Flattened Device Tree Binary)。反编译过程就是:

1
2
3
4
5
6
7
8
boot/update 包
→ boot.img
→ 找到 DTB/FDT 二进制
→ dtc -I dtb -O dts
→ 得到可读的 DTS
→ 对比并修改目标节点
→ dtc -I dts -O dtb
→ 嵌回 boot.img

6.1 先识别 boot.img

可以先检查文件类型和 Android boot magic:

1
2
file boot.img
xxd -l 64 boot.img

标准 Android boot image 的开头通常是:

1
ANDROID!

也可以搜索:

1
grep -aob 'ANDROID!' boot.img

Rockchip Android 11 的 boot 镜像通常由以下部分按 header 参数排列:

1
2
3
4
5
6
boot header
kernel
ramdisk
second(某些版本存在)
dtb / device tree
padding

不能盲目假设 DTB 一定在固定偏移;应先读取 boot header 中的 kernel size、ramdisk size、second size、page size 等字段,或者使用系统中可用的 unpackbootimg 工具解析。

6.2 使用 unpackbootimg 拆分 boot.img

如果系统安装了 Android bootimg 工具:

1
2
3
mkdir -p boot-unpacked
unpackbootimg -i boot.img -o boot-unpacked
find boot-unpacked -maxdepth 2 -type f -ls

不同版本工具输出文件名可能不同,常见内容包括:

1
2
3
4
5
6
7
8
9
10
boot.img-kernel
boot.img-ramdisk.gz
boot.img-second
boot.img-dtb
boot.img-header_version
boot.img-base
boot.img-pagesize
boot.img-kernel_offset
boot.img-ramdisk_offset
boot.img-tags_offset

如果工具已经输出 boot.img-dtb,可以直接处理:

1
2
3
dtc -I dtb -O dts \
-o boot-unpacked/gamma.dts \
boot-unpacked/boot.img-dtb

6.3 没有现成 DTB 文件时,搜索 FDT magic

DTB 的 magic 是 0xd00dfeed,在文件中的字节序列通常是:

1
d0 0d fe ed

可以先搜索候选位置:

1
grep -aob $'\xd0\x0d\xfe\xed' boot.img

更稳妥的做法是用 Python 根据 FDT header 中的 totalsize 截取完整 DTB。下面的脚本会扫描文件中所有 FDT magic,并依据大端 totalsize 导出候选 DTB:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/usr/bin/env python3
import struct
from pathlib import Path

src = Path("boot.img")
data = src.read_bytes()
out = Path("dtb-candidates")
out.mkdir(exist_ok=True)

magic = b"\xd0\x0d\xfe\xed"
index = 0
pos = 0
while True:
pos = data.find(magic, pos)
if pos < 0:
break

# struct fdt_header:
# magic, totalsize, off_dt_struct, off_dt_strings, off_mem_rsvmap,
# version, last_comp_version, boot_cpuid_phys, size_dt_strings,
# size_dt_struct
if pos + 40 <= len(data):
totalsize = struct.unpack_from(">I", data, pos + 4)[0]
end = pos + totalsize
if 0 < totalsize <= 16 * 1024 * 1024 and end <= len(data):
path = out / f"candidate-{index:02d}-off-{pos:x}-size-{totalsize:x}.dtb"
path.write_bytes(data[pos:end])
print(f"{path}: offset=0x{pos:x}, size=0x{totalsize:x}")
index += 1
pos += 4

执行:

1
2
python3 extract-fdt.py
ls -lh dtb-candidates/

然后逐个反编译:

1
2
3
4
for f in dtb-candidates/*.dtb; do
base=${f%.dtb}
dtc -I dtb -O dts -o "$base.dts" "$f"
done

6.4 dtc 反编译命令

最基本的命令是:

1
dtc -I dtb -O dts -o gamma.dts gamma.dtb

如果只想看关键节点,可以直接搜索:

1
grep -nE 'fe310000|sdhci|fe060000|dsi|panel|vop|route-dsi|firmware/android|fstab' gamma.dts

还可以先确认设备树中的节点状态:

1
2
3
grep -n -A12 -B4 'sdhci@fe310000' gamma.dts
grep -n -A20 -B4 'dsi@fe060000' gamma.dts
grep -n -A20 -B4 'panel@0' gamma.dts

本次最关键的对比就是:

1
2
3
4
sdhci@fe310000 {
...
status = "disabled";
};

和修复后的:

1
2
3
4
sdhci@fe310000 {
...
status = "okay";
};

6.5 用 live DT 验证反编译结果

如果设备还能通过 ADB 启动,内核实际使用的设备树还可以从 /proc/device-tree 读取:

1
2
3
adb shell 'cat /proc/device-tree/model'
adb shell 'cat /proc/device-tree/sdhci@fe310000/status'
adb shell 'find /proc/device-tree -maxdepth 2 -iname "*dsi*" -o -iname "*vop*"'

二进制属性需要转换:

1
adb shell 'tr -d "\000" < /proc/device-tree/sdhci@fe310000/status'

或拉回主机后查看:

1
2
adb pull /proc/device-tree/sdhci@fe310000/status live-sdhci-status
cat live-sdhci-status

还可以把整棵 live DT 导出后再反编译:

1
2
adb shell 'dtc -I fs -O dts -o /data/local/tmp/live.dts /proc/device-tree'
adb pull /data/local/tmp/live.dts .

如果目标系统没有 dtc,可以在主机上使用 fdtdump 或把设备树节点逐个从 /proc/device-tree 拉回。实际诊断时,boot 内 DTB 和 /proc/device-tree 的 live DT 应互相验证,避免只分析了没有真正生效的候选 DTB。


7. 设备树对比的重点:不要只比较整个文件

两份 DTS 通常会有大量无关差异。有效方法是先围绕硬件功能做定向对比:

1
diff -u gamma.dts sd-good.dts > gamma-vs-sd.diff

再重点检查以下节点:

7.1 显示链路

1
2
3
4
5
6
7
fe040000.vop
fe060000.dsi
panel@0
pwm-backlight
route-dsi0
pinctrl
regulator

本设备的显示特征为:

1
2
3
4
分辨率:640 x 480
pixel clock:约 30 MHz
DSI:4 lane
最终链路:198 Mbps x 4

7.2 存储链路

1
2
3
4
5
6
sdhci@fe310000
mmc / eMMC pinctrl
vcc / vccio-sd regulator
non-removable
bus-width
status

7.3 Android 分区挂载

1
2
3
4
5
firmware/android/fstab
vendor、system、product
metadata
super
boot_devices

整 boot 替换时,ramdisk 与 DT 中的 fstab 可能不匹配。即使显示正常,只要 eMMC 或 fstab 配置不兼容,Android first-stage init 仍会因为 metadata/super 挂载失败而重启。


8. 修复策略:只移植显示能力,同时恢复 eMMC

8.1 为什么不继续整 boot 替换

第一次整 boot 混合已经证明显示配置有效,但也证明它会带来存储启动兼容性问题。因此最终策略是:

1
2
3
保留能正常显示的 SD good boot/kernel/DTB 基础
恢复 eMMC 控制器 fe310000.sdhci
尽量保留 GammaOS 的 ramdisk、cmdline 和分区逻辑

实际修复的最小硬件差异是:

1
sdhci@fe310000: disabled → okay

这不是随便把所有存储控制器都打开,而是根据 kernel command line 和 U-Boot 的 boot device 定位到 GammaOS 真正依赖的控制器:

1
androidboot.boot_devices=fe310000.sdhci

8.2 生成第三版 boot

第三版的逻辑可以概括为:

1
2
3
4
5
6
7
8
9
SD good boot
+ 正常的 VOP/DSI/panel 配置
+ sdhci@fe310000 改为 okay

重新生成 boot.img

替换 GammaOS RKFW 包中的 boot 条目

重新计算 Android boot header id

中间版名称:

1
GammaOS_Core_Beta3_X35_x35sdtb_v9_sdboot_sdhci.img

初步验证:

1
2
3
4
boot 条目头部 = ANDROID!
sdhci@fe310000/status = okay
完整包大小与原包一致
屏幕显示链路仍然存在

9. 第四步:发现并修复 Android boot header hash mismatch

第三版第一次刷写时,U-Boot 报告:

1
2
3
4
Hash from header:
0x6fd8dfd740fd24253e27d922982ac43c3a8d2378
Hash real:
0x2ae4fa77a566a0382e43646a29368737a47c4952

这不是 DTB 修改错误,而是 boot 镜像内容变更后,Android boot header 中的 id 仍然是旧值。

9.1 为什么修改 DTB 会影响 hash

Android boot image header 保存了用于校验的标识。boot 内容由以下部分组成:

1
2
3
4
kernel
ramdisk
second(如果有)
dtb

只要其中任何一部分变化,镜像内容的 SHA-1 就可能变化。我们虽然只改变了 DTB 里的一个 status 属性,但整个 boot 的实际内容已经不同;如果 header 仍然保留旧 id,U-Boot 就会算出:

1
header 中记录的 hash ≠ 实际内容 hash

9.2 修复方式

重新计算修改后 boot 内容的 hash,并将正确值写回 Android boot header:

1
2
旧 header id:6fd8dfd740fd24253e27d922982ac43c3a8d2378
新 real hash:2ae4fa77a566a0382e43646a29368737a47c4952

同时要注意:

  • standalone boot 要修;
  • RKFW 包中的 embedded boot 条目也要修;
  • 修改后需要再次验证 DTB 没有被破坏;
  • 不能只修外层升级包的 SHA-256,因为 U-Boot 检查的是 Android boot header 内部的 hash。

9.3 最终验证

最终版本确认:

1
2
3
4
header id = 2ae4fa77a566a0382e43646a29368737a47c4952
sdhci@fe310000/status = okay
boot sha256 = ebabd79fd6b4c03cb7810afff9ebd2f149550bd33d4960f3c03ff19fcad8b37e
package sha256 = 728873846593712628950f0769956f16cad237bc21b9bd1f19732693025b7174

训练家实机刷入后成功启动,证明:

1
2
3
4
显示 DTB 修复有效
sdhci/eMMC 修复有效
boot header hash 修复有效
RKFW 外层包可被正常刷写

10. 为什么最终方案能同时解决两个问题

可以把整个故障链条表示为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
原始 GammaOS boot/DTB

├── 显示配置不适合当前 X35S
│ └── 屏幕异常/不出图

└── GammaOS 存储和分区逻辑本身是可用的

直接换成 SD good boot

├── 显示配置正确
│ └── 屏幕正常

└── sdhci@fe310000 被关闭或不匹配
└── eMMC 不枚举
└── metadata/super 不存在
└── init 超时
└── 重启到 fastboot

最终方案

├── 保留 SD good 的显示配置
├── sdhci@fe310000 改回 okay
├── 保留与 GammaOS 配套的启动/分区逻辑
└── 更新 Android boot header hash
└── 屏幕正常 + eMMC 正常 + Android 正常启动

11. 推荐的完整复现流程

下面是以后处理类似 RK3566 Android boot/DTB 问题时可以复用的流程。

11.1 备份和校验

1
2
cp original.img original.img.bak
sha256sum original.img original.img.bak

所有修改都写到新文件,原始镜像不覆盖。

11.2 判断镜像层级

1
2
file image.img
xxd -l 32 image.img

根据文件头区分:

1
2
3
RKFW      → Rockchip update.img 外层包
ANDROID! → Android boot.img
d00dfeed → DTB

11.3 先用串口证明故障位置

至少采集:

1
2
3
4
5
6
U-Boot 输出
kernel 启动前 2 秒
init first-stage 日志
mmc/sdhci 日志
DRM/VOP/DSI/panel 日志
最后一次重启原因

判断优先级:

  1. kernel 是否启动;
  2. DSI/VOP/panel 是否绑定;
  3. eMMC 控制器是否枚举;
  4. /sys/block 是否出现目标设备;
  5. metadata/super 是否可见;
  6. init 是否因为挂载失败主动重启。

11.4 反编译并对比 DTB

1
2
3
dtc -I dtb -O dts -o gamma.dts gamma.dtb
dtc -I dtb -O dts -o sd-good.dts sd-good.dtb
diff -u gamma.dts sd-good.dts > dtb.diff

优先搜索:

1
grep -nE 'sdhci@fe310000|dsi@fe060000|panel@0|route-dsi0|firmware/android|status' *.dts

11.5 最小修改

不要把两份 DTS 整体无选择地合并。优先只改已经被串口证据证实的节点,例如:

1
2
3
&sdhci {
status = "okay";
};

显示链路则尽量从已知可工作的 boot/DTB 中移植,避免破坏:

  • Android fstab;
  • boot_devices
  • eMMC pinctrl;
  • PMIC/regulator;
  • reserved-memory;
  • ramdisk 与 dynamic partition 配置。

11.6 重新打包后做三层验证

第一层:格式验证

1
2
3
boot.img 开头是否仍是 ANDROID!
RKFW 包头是否仍是 RKFW
输出文件大小是否符合预期

第二层:内容验证

1
2
3
反编译回 boot 中的 DTB
确认 sdhci@fe310000/status = okay
确认 DSI/VOP/panel 节点仍存在

第三层:启动验证

1
2
3
4
5
U-Boot 不再报告 hash mismatch
屏幕出图
mmc/eMMC 枚举
metadata/super 出现
Android first-stage mount 通过

12. 常见错误和经验总结

12.1 把 RKFW 当作 raw 镜像

错误:

1
dd if=GammaOS...img of=/dev/mmcblkX

问题:RKFW 是升级包,不是磁盘布局。应使用 Rockchip 工具,或者仅修改包内对应条目。

12.2 直接替换整个 boot 就停止分析

整 boot 替换可以快速验证显示问题,但它可能同时替换:

  • kernel;
  • ramdisk;
  • DTB;
  • cmdline;
  • fstab;
  • Android boot 参数。

所以“屏幕亮了”不等于“启动方案正确”。本次就是屏幕正常但 metadata/super 找不到。

12.3 只看最后一行 fastboot

“重启到 fastboot”只是结果,不是根因。真正的根因在前面:

1
2
3
partition(s) not found: metadata, super
Failed to mount required partitions early
InitFatalReboot

12.4 改了 DTB 却忘记更新 boot header id

这会导致:

1
Hash from header != Hash real

每次修改 kernel、ramdisk、second 或 DTB 后,都必须重新生成或更新 Android boot header 中的校验字段。

12.5 用字符串搜索代替结构化验证

strings 可以用来快速确认某些字符串存在,但不能证明:

  • 节点真的处于生效路径;
  • status 的值正确;
  • phandle、offset、长度没有损坏;
  • 当前启动使用的是这份 DTB。

最终应使用 dtc 反编译验证,并配合 /proc/device-tree、串口和实机结果交叉确认。


13. 结论

这次修复不是简单“换一个 boot.img”,而是通过实验和串口证据逐层定位:

  1. 确认 GammaOS 是 RKFW 外层升级包,不能直接当 raw 镜像写入;
  2. 用整 boot 混合实验验证 SD boot 的显示 kernel/DTB 有效;
  3. 根据 U-Boot、DRM、DSI 和 Linux 日志确认屏幕链路已经成功;
  4. 根据 metadata/super not foundboot_devices=fe310000.sdhci 和 MMC 超时,定位到 eMMC SDHCI 设备树状态不正确;
  5. 从 boot.img 中提取 DTB,用 dtc 反编译为 DTS,比较并修改 sdhci@fe310000
  6. 将修改后的 boot 重新嵌回 GammaOS RKFW 包;
  7. 根据 U-Boot 的 Hash from header / Hash real 报错,更新 Android boot header id
  8. 实机验证屏幕、eMMC、dynamic partition 和 Android 启动全部恢复。

最终可复用的核心原则是:

1
2
3
4
先确认镜像层级,再做最小实验;
先用串口确定失败阶段,再改 DTB;
显示和存储必须分别验证;
修改 boot 内容后,必须同步更新 Android boot header 校验值。

附录:本次重要文件和版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
原始 GammaOS:
/home/openclaw/Share/GammaOS_Core_Beta3_X35_x35sdtb_v9.img

SD good boot 来源:
./bootfix/bootfix/sd-boot.good.img

第一次整 boot 混合版:
/home/openclaw/Share/GammaOS_Core_Beta3_X35_x35sdtb_v9_sdbootmix.img

第三版:恢复 sdhci@fe310000:
/home/openclaw/Share/GammaOS_Core_Beta3_X35_x35sdtb_v9_sdboot_sdhci.img

最终哈希修正版:
/home/openclaw/Share/GammaOS_Core_Beta3_X35_x35sdtb_v9_sdboot_sdhci_hashfix.img

最终 standalone boot:
/home/openclaw/.openclaw/workspace-rk3566-dev/tmp/sdboot-sdhci/sd-boot.good.sdhci-okay.hashfix.img