适用设备: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 替换进去就能解决问题”。需要分别判断:
外层镜像是什么格式,能否直接 dd;
boot 镜像内部有哪些组成部分;
显示问题来自 kernel、DTB、ramdisk,还是 U-Boot/分区;
能正常显示的 SD boot 是否同时关闭了 GammaOS 需要的 eMMC 控制器;
修改 boot 内容之后,Android boot header 的校验信息是否仍然有效。
3. 第一步:先确认 GammaOS 镜像不是 raw 磁盘镜像
3.1 不能直接使用 dd
检查 GammaOS 文件头后发现它以 Rockchip 固件包头开头:
因此它不是可以直接写入 /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 替换不是完全失败,反而证明了两件事:
sd-boot.good.img 中的显示相关 kernel/DTB 配置确实能让 X35S 的 DSI/VOP 出图;
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 没有启动。
真正导致重启的日志是:
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 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 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 import structfrom 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 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.pyls -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-statuscat 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.baksha256sum 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 日志 最后一次重启原因
判断优先级:
kernel 是否启动;
DSI/VOP/panel 是否绑定;
eMMC 控制器是否枚举;
/sys/block 是否出现目标设备;
metadata/super 是否可见;
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
这会导致:
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”,而是通过实验和串口证据逐层定位:
确认 GammaOS 是 RKFW 外层升级包,不能直接当 raw 镜像写入;
用整 boot 混合实验验证 SD boot 的显示 kernel/DTB 有效;
根据 U-Boot、DRM、DSI 和 Linux 日志确认屏幕链路已经成功;
根据 metadata/super not found、boot_devices=fe310000.sdhci 和 MMC 超时,定位到 eMMC SDHCI 设备树状态不正确;
从 boot.img 中提取 DTB,用 dtc 反编译为 DTS,比较并修改 sdhci@fe310000;
将修改后的 boot 重新嵌回 GammaOS RKFW 包;
根据 U-Boot 的 Hash from header / Hash real 报错,更新 Android boot header id;
实机验证屏幕、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