编译命令还没敲,先认路。今天把源码树摊开:你改的文件会进哪张镜像。改错目录、刷错分区,表现都是「我改了,板上没反应」。


改了一行设备树,./build.sh 退出码 0,镜像也刷进去了,板上 /proc/device-tree 还是昨天的内容。再改一份 init 脚本,这次连镜像时间戳都没动。第三回改触摸的 HCS,只刷了 vendor,坐标照样歪。
这三件事看起来像三只不同的虫子,其实是同一件事:你改的文件,和你刷的那张分区,不在一条管子上。 开源鸿蒙这棵树不是「一个 rootfs 打进去就算数」。内核、设备树、用户态驱动配置、系统应用、init、fstab,各自进不同的 img。编译系统还在中间做了一份拷贝。你改源码目录,不等于改到了那份拷贝,更不等于改到了板子正在读的分区。
产品名按源码写:rk3568_evb。板级路径 device/board/rk/rk3568_evb/。内核 Linux 5.10 aarch64,用户态 32 位 musl。你工程里产品名不同,对着换。
官方仓库布局可以对照:源码获取。下面按「改哪里 → 进哪张镜像 → 怎么验」摊开,不按仓库 README 的字母表走。

1. 先把现象钉死:exit 0 只说明构建脚本没崩
全量编完,日志最后一行经常是 build success 之类。它的意思是 ninja 认为该跑的 target 都跑完了。它不保证:
- 你改的那个
.dts被编进了 dtb - 你改的那个
.hcs被编进了内核 Image 或 vendor - 你刷进去的那张 img,就是这次刚生成的那张
- 板子启动时读的,就是你刷的那张
分层看,失败通常停在其中一层:
bash
你改的文件
↓ 构建系统看见了吗?(GN sources / checkpoint)
out/ 里的中间拷贝
↓ 真的重编了吗?(时间戳、hcb、.config)
packages/phone/images/*.img
↓ 打包脚本同步了吗?(pack_update 里可能是旧文件)
你刷进板子的分区
↓ 启动时读的是这块介质吗?(SD / eMMC,resource vs boot_linux)
板上正在跑的那份
后面几篇分别写编译、打包、刷机、启动。这篇只回答一个问题:源码树里每个目录,默认会流进哪张镜像。认路比认命令值钱。
2. 整棵树只需要记住这几块
源码根目录下面东西很多。日常改板,真正会进镜像的,集中在这几处:
bash
OpenHarmony/
├── kernel/linux/
│ ├── linux-5.10/ # 内核源,aarch64
│ ├── patches/linux-5.10/
│ │ └── rk3568_patch/ # 芯片补丁,构建时打进 linux-5.10
│ └── config/linux-5.10/ # 碎片 defconfig,不是你 menuconfig 的那份
├── device/board/rk/rk3568_evb/
│ ├── kernel/ # 板级 DTS、板级驱动、build_kernel.sh、logo
│ ├── cfg/ # init / fstab
│ ├── loader/ # MiniLoader、打包三件套、空分区占位
│ ├── camera/ # 相机 IQ / 板级 camera 部件
│ └── audio/ # 音频策略、板级 json
├── vendor/rk/rk3568_evb/
│ └── hdf_config/
│ ├── khdf/ # 编进内核 Image
│ └── uhdf/ # 打进 vendor.img
├── device/product/rk/rk3568_evb/ # 产品 json、要编哪些部件
├── drivers/hdf_core/ # HDF 框架,khdf 链进内核
├── drivers/peripheral/ # 显示 / 输入 / 音频 / 相机 HAL,多半进 vendor
├── base/ # 系统服务、部分系统应用,进 system.img
├── foundation/ # 窗口、图形、电话一类,进 system.img
├── applications/ # 桌面、设置、部分预装,进 system.img
└── out/
├── kernel/
│ ├── src_tmp/linux-5.10/ # 打过补丁的内核工作树
│ ├── OBJ/linux-5.10/ # KBUILD_OUTPUT,.config / Image / dtb
│ └── checkpoint/ # 「内核变没变」的判决书
└── rk3568_evb/packages/phone/images/ # 各分区镜像,打包的输入
还有 prebuilts/(clang、hap-sign-tool)、build/(GN 规则)、third_party/。那些你很少改。改了 third_party 里某个 so,产物进 system 还是 vendor,看那个部件的 install_images,不要猜。
用户态是 32 位 musl。板上动态链接器是 /system/lib/ld-musl-arm.so.1,没有 aarch64 的 ld-linux。你在内核目录里用 aarch64 clang 编 .ko 没问题;你在用户态目录里编一个「随便写的诊断程序」,必须走 armv7-unknown-linux-ohos-clang,并且 --dynamic-linker=/system/lib/ld-musl-arm.so.1。编成 64 位 ELF,hdc file send 能送上去,一执行 No such file or directory------那是解释器路径不存在,不是文件没送过去。
3. 内核三份目录,别改错那一份
内核不是「一个 linux-5.10 目录」这么简单。构建时会拷、会打补丁、会另开 OBJ。三份目录职责不同。
3.1 kernel/linux/linux-5.10/:上游 + 开源鸿蒙合入的那份
这是 git 里的内核源。GN 的内核 action 把 sources 指到这里。你在这里改 drivers/xxx.c,ninja 看得到 ,下次 ./build.sh 会认为内核变了。
不要在这里改板级设备树。板级 dts 不从这里出发,从 device/board/rk/rk3568_evb/kernel/ 出发,构建脚本拷进来。你在 linux-5.10/arch/arm64/boot/dts/rockchip/ 里直接改,下次 copy_and_patch 一跑,板级那份会盖过来,或者反过来你的改动被当成「内核源改动」进了 git 脏状态,两头都不干净。
3.2 kernel/linux/patches/linux-5.10/rk3568_patch/:芯片补丁
构建把 linux-5.10 拷到 out/kernel/src_tmp/ 之后,按清单把这里的 patch 打进去。RK3568 的 DRM、ISP、PCIE PHY、一些 staging 网卡,经常以补丁形式存在,而不是直接合进 git 源。
bash
ls kernel/linux/patches/linux-5.10/rk3568_patch | head
# 典型名字像:
# 0001-drm-rockchip-vop2-....patch
# 0012-net-usb-cdc_ncm-....patch
改补丁和改源码等效,但有两个坑。第一,补丁是对「拷贝后的树」打的,你若已经在 src_tmp 里手改过同一文件,patch 会 reject,构建停在 patch -p1。第二,cdc_ncm.c 这类文件,开源鸿蒙补丁从 struct usbnet 里删了 rx_speed / tx_speed,公版驱动还在访问这两个字段。板级 overlay 通常另给一份改过的 cdc_ncm.c 覆盖进去。补丁没打上、覆盖没做,内核编到 USB 网卡就报:
bash
error: no member named 'rx_speed' in 'struct usbnet'
这不是网卡没插,是编译期。
自己加补丁,编号接在现有最大号后面,让 build_kernel.sh 的循环能扫到。打补丁的代码大致是:
bash
# build_kernel.sh 里常见的形态,路径按你树里的为准
PATCH_DIR="$ROOT/kernel/linux/patches/linux-5.10/rk3568_patch"
cd "$SRC_TMP/linux-5.10"
for p in $(ls "$PATCH_DIR"/*.patch 2>/dev/null | sort); do
echo "apply $(basename $p)"
patch -p1 --forward --dry-run < "$p" >/dev/null 2>&1 || {
echo "REJECT: $p"
exit 1
}
patch -p1 --forward < "$p"
done
src_tmp 是打补丁后的工作树。下次构建若判定「内核没变」,这份树会留着,补丁不会重打。这就是为什么你改了 patch 目录,有时镜像里还是旧内核------checkpoint 说没变,拷贝和打补丁整段被跳过。
3.3 out/kernel/src_tmp 和 out/kernel/OBJ:干活的地方
| 路径 | 是什么 | 能手改吗 |
|---|---|---|
| `out/kernel/src_tmp/linux-5.10` | 拷贝 + 打过补丁 + 拷过板级 dts/驱动的工作树 | 只为了「这一次增量 make」,下次 copy 会盖 |
| `out/kernel/OBJ/linux-5.10` | `KBUILD_OUTPUT`,`.config`、`vmlinux`、`Image`、dtb、`certs/` | 不要当权威源。menuconfig 改它,下次合成会丢 |
| `out/kernel/checkpoint` | `last_build.info` 一类,给 `is_kernel_change` 用 | 删它 = 强制认为内核变了 |
增量编内核、编单个 .ko,命令都在 src_tmp 上跑,输出进 OBJ:
bash
ROOT=/path/to/OpenHarmony
export PATH=$ROOT/prebuilts/clang/ohos/linux-x86_64/llvm/bin:$PATH
export KBUILD_OUTPUT=$ROOT/out/kernel/OBJ/linux-5.10
cd $ROOT/out/kernel/src_tmp/linux-5.10
make LLVM=1 LLVM_IAS=1 CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 \
Image -j$(nproc)
编完,Image 在 OBJ 里:
bash
ls -l $KBUILD_OUTPUT/arch/arm64/boot/Image
# 再打进 boot_linux.img,不是到此就能刷
不要在 OBJ 里改源码。 OBJ 是 out-of-tree 编译目录,.c 不在这里。改 dts 要改板级那份,再拷进 src_tmp,或者改 src_tmp 里对应文件后立刻 make dtbs。src_tmp 里的 dts 是副本,权威在 device/board/rk/rk3568_evb/kernel/。
4. defconfig 有四层,menuconfig 只动最上面那层
「我 menuconfig 勾过了」和「下次全量还在」是两件事。四层从底到顶:
bash
层 1 kernel/linux/config/linux-5.10/.../arch/arm64_defconfig
git 里的产品碎片,copy 的起点
层 2 src_tmp 里合成出来的 rockchip_linux_defconfig
merge_config / 拷贝 / 补丁改过的那份「即将 make defconfig 的源」
层 3 OBJ/.config
这一次 make 真正读的。menuconfig 改的是它
层 4 device/board/rk/rk3568_evb/kernel/build_kernel.sh
MERGED_CFG 段。每次内核重建都会再跑一遍的幂等注入
这才是「下次合成还会在」的那一层
只改层 3,下次 make defconfig 或脚本重新 merge,勾掉的又回来,勾上的又没了。只改层 1 不改层 4,脚本若按自己的清单覆盖,你加的 CONFIG_FOO=y 会被冲掉。只改层 4 不删 checkpoint,脚本根本不跑,OBJ 继续用旧 .config。
写入层 4 要幂等,已经是 =y 不要再 append 出两行:
bash
# device/board/rk/rk3568_evb/kernel/build_kernel.sh MERGED_CFG
CFG="$KERNEL_SRC/arch/arm64/configs/rockchip_linux_defconfig"
set_y() {
local k="$1"
if grep -q "^${k}=y" "$CFG"; then
return 0
fi
if grep -q "^# ${k} is not set" "$CFG"; then
sed -i "s/^# ${k} is not set/${k}=y/" "$CFG"
else
echo "${k}=y" >> "$CFG"
fi
}
set_y CONFIG_GPIO_WATCHDOG
set_y CONFIG_CFI_PERMISSIVE
set_y CONFIG_I2C_CHARDEV
set_y CONFIG_USB_VIDEO_CLASS
编完对三处,缺一处就是没进:
bash
# 层 1 碎片
grep GPIO_WATCHDOG kernel/linux/config/linux-5.10/*/arch/arm64_defconfig
# 层 3 真正编译用
grep '^CONFIG_GPIO_WATCHDOG' out/kernel/OBJ/linux-5.10/.config
# 符号在不在 Image 里(=y 才有;=m 在 .ko 里)
strings out/kernel/OBJ/linux-5.10/vmlinux | grep -i gpio_wdt | head
.config 是 =y 而 vmlinux 里没有符号:合成了但没重链。删 checkpoint 再编。.config 仍是 is not set:层 4 没跑,或 Kconfig 本身 depends on 不允许 =y。
GN 的内核 action 不跟踪 device/board/。只改 build_kernel.sh、只改板级 dts,ninja 可能判定内核没变,层 4 整段跳过。强制重跑:
bash
rm -rf out/kernel/checkpoint
./build.sh --product-name rk3568_evb --ccache
5. 板级目录:一个产品真正和公版分道的地方
device/board/rk/rk3568_evb/ 是你最常改的树。子目录和镜像的对应,比记 GN target 名有用。
bash
device/board/rk/rk3568_evb/
├── kernel/
│ ├── rk3568-evb-linux.dts # 板级设备树(文件名按你树里的为准)
│ ├── *.c / *.h # 板级驱动,构建时拷进 src_tmp
│ ├── build_kernel.sh # 拷贝、打补丁、合成 defconfig、编 Image、打 boot_linux / resource
│ ├── logo.bmp / logo_kernel.bmp # 进 resource.img,不是进 boot_linux 才亮
│ └── certs/ # 模块签名永久钥匙
├── cfg/
│ ├── init.rk30board.cfg # 生效的 init,后缀必须是 rk30board
│ ├── init.rk30board.usb.cfg
│ ├── fstab.rk30board # 二阶段挂载,进 vendor
│ ├── fstab.required # 一阶段挂载,进 ramdisk
│ └── BUILD.gn
├── loader/
│ ├── MiniLoaderAll.bin
│ ├── parameter.txt # 有的树放 images 构建产物,有的放这里当源
│ ├── afptool / rkImageMaker / package-file
│ └── prebuilt-images/ # misc / bootctrl / chip_ckm / eng_chipset 空镜像
├── camera/ # IQ、module 信息,多半进 vendor
├── audio/ # 板级音频 json,多半进 vendor
└── BUILD.gn # part_name、install_images
build_kernel.sh 才是板级内核的总开关。它通常会做这些事(具体行号按你的脚本,逻辑一样):
bash
# 伪代码,对着你的 build_kernel.sh 看
copy_kernel_source # linux-5.10 → src_tmp
apply_rk3568_patch # patches/linux-5.10/rk3568_patch
copy_board_dts_and_drivers # device/board/.../kernel/* → src_tmp 对应位置
merge_and_inject_defconfig # 层 1 + MERGED_CFG → rockchip_linux_defconfig
make Image dtbs # 输出到 OBJ
pack_boot_linux_ext2 # Image + extlinux.conf + ramdisk → boot_linux.img
pack_resource # rk-kernel.dtb + logo*.bmp → resource.img
cp boot_linux.img resource.img MiniLoaderAll.bin uboot.img \
→ out/rk3568_evb/packages/phone/images/
板级驱动不要直接丢进 git 的 kernel/linux/linux-5.10/drivers/。放 device/board/rk/rk3568_evb/kernel/,让脚本拷。理由很具体:内核源每次 copy_and_patch 会从干净树重新来一份,你手改 linux-5.10 要么进了 git 变成「对所有产品生效」,要么下次 copy 被冲掉。
cfg/ 进哪张镜像看 BUILD.gn 的 install_images:
bash
ohos_prebuilt_etc("fstab_required") {
source = "fstab.required"
install_images = [ "ramdisk" ]
part_name = "rk3568_evb"
}
ohos_prebuilt_etc("fstab_rk30board") {
source = "fstab.rk30board"
install_images = [ "chipset_base_dir" ] # 即 vendor
part_name = "rk3568_evb"
}
ohos_prebuilt_etc("init_rk30board") {
source = "init.rk30board.cfg"
install_images = [ "chipset_base_dir" ]
part_name = "rk3568_evb"
}
part_name 必须是这个产品在 json 里登记过的部件名,乱写一个 product_rk3568_evb,构建期可能过,安装期文件不进 vendor。改完 init 不必清内核;ninja 跟踪 ohos_prebuilt_etc 的 source。
6. ohos.boot.hardware=rk30board,只认这个后缀
设备树 cmdline 里有:
bash
chosen {
bootargs = "console=ttyS2,1500000n8 androidboot.hardware=rk30board \
hardware=rk30board ...";
};
跑起来之后:
bash
# param get ohos.boot.hardware
rk30board
init 用这个字符串拼文件名。system/etc/init.cfg 里类似:
bash
import /vendor/etc/init.${ohos.boot.hardware}.cfg
mount_fstab /vendor/etc/fstab.${ohos.boot.hardware}
展开就是:
bash
/vendor/etc/init.rk30board.cfg
/vendor/etc/fstab.rk30board
init.rk3568.cfg、fstab.rk3568、init.rk3568_evb.cfg 都可以在源码树里活得好好的,开机不理它们 。这不是文档写错,是这颗产品从公版 SD 方案继承了 rk30board 这个 hardware 名,一直没改 bootargs。
改 console、改 chmod、改开机自启服务,文件名必须带 rk30board。验源码:
bash
grep -n 'rk30board' device/board/rk/rk3568_evb/cfg/*
grep -n 'ohos.boot.hardware' system/core/init/init.cfg \
device/board/rk/rk3568_evb/cfg/ -r
验板上:
bash
# ls /vendor/etc/init.rk30board.cfg /vendor/etc/fstab.rk30board
# grep start /vendor/etc/init.rk30board.cfg | head
你若在 init.rk3568.cfg 里加了 start console,串口能看 dmesg、敲回车没人理,就是这个后缀。
7. HDF 配置:khdf 进内核,uhdf 进 vendor
vendor/rk/rk3568_evb/hdf_config/ 分成两棵树,长得很像,进的镜像完全不同。
bash
vendor/rk/rk3568_evb/hdf_config/
├── khdf/
│ ├── hdf.hcs # 顶层,几乎全是 #include
│ ├── device_info/
│ ├── input/
│ ├── lcd/
│ ├── audio/
│ ├── camera/
│ └── platform/
└── uhdf/
├── device_info.hcs
└── ... # 用户态 host 读的
khdf 经 hc-gen 变成 C 数组,链进 vmlinux,最后进 boot_linux.img。触摸芯片驱动、部分音频、部分 panel 入口,开机读的是这份。
uhdf 变成 hdf_default.hcb,放进 /vendor/etc/hdfconfig/,进 vendor.img。composer、部分用户态 host 读这份。
改 khdf 只刷 vendor,等于没改。改 uhdf 只刷 boot_linux,同样没改。触摸分辨率写在 khdf 的 input_config.hcs 里,这是最常见的「我改了 HCS 怎么没反应」。
khdf 的 make 依赖只盯顶层 hdf.hcs。你改 input_config.hcs,顶层一行不动,make 认为没变,继续链上次的 hex。板级 build_kernel.sh 编内核前应该无条件删:
bash
rm -f vendor/rk/rk3568_evb/hdf_config/khdf/hdf.hcb
rm -f vendor/rk/rk3568_evb/hdf_config/khdf/hdf_hcs.hcb
find out/kernel -name 'hdf_hcs_hex.c' -o -name 'hdf_hcs_hex.o' \
| xargs --no-run-if-empty rm -f
uhdf 是另一对,别删混:
bash
rm -f out/rk3568_evb/gen/vendor/rk/rk3568_evb/hdf_config/uhdf/hdf_default.hcb
rm -f out/rk3568_evb/packages/phone/vendor/etc/hdfconfig/hdf_default.hcb
rm -f out/rk3568_evb/packages/phone/images/vendor.img
编完在 Image 里搜字符串,搜到才算 khdf 真进去了:
bash
grep -a "HDF_TOUCH_GT911" out/kernel/OBJ/linux-5.10/arch/arm64/boot/Image | head
grep -a "solutionX" out/kernel/OBJ/linux-5.10/arch/arm64/boot/Image | head
HDF 的模型和 HCS 语法,配置那篇写。这里只要记住分流。
8. 改什么,进哪张镜像
这张表是这篇的中心。刷机之前对一下,少刷一张没用的、少漏一张有用的。
| 你改了什么 | 权威路径 | 进哪张镜像 | 板上谁读 | 还要刷 |
|---|---|---|---|---|
| 板级 dts | `device/board/rk/rk3568_evb/kernel/*.dts` | resource.img 里的 `rk-kernel.dtb`;boot_linux 里也有一份 toybrick.dtb,开机不认它当主 dtb | U-Boot 从 **resource** 取出 dtb 传给内核 | **resource + boot_linux**,SD 启动时 eMMC 的 p4/p5 也建议写 |
| 内核 `.c` / Kconfig / defconfig | `kernel/linux/linux-5.10` 或板级 kernel/ + MERGED_CFG | boot_linux.img | 内核 | boot_linux;改显示相关 dts 仍要 resource |
| khdf HCS | `vendor/rk/rk3568_evb/hdf_config/khdf/` | boot_linux.img(链进 Image) | 内核态 HDF | boot_linux |
| uhdf HCS、vendor 脚本、相机 IQ、音频 json | `vendor/rk/...`、`device/board/.../camera` `audio` | vendor.img | 用户态 host / init 从 /vendor 读 | vendor |
| `fstab.required` | `device/board/rk/rk3568_evb/cfg/` | ramdisk.img(也常被打进 boot_linux 的 extlinux/) | 一阶段 init | ramdisk / 整包;只刷 vendor 不够 |
| `fstab.rk30board`、`init.rk30board.cfg` | 同上 cfg/ | vendor.img | 二阶段 init | vendor |
| 系统应用、foundation、powermgr json | `applications/` `foundation/` `base/` | system.img | BMS / 各 SA | system;首启签名校验,单刷有时跳过 |
| MiniLoader / DDR 固件 | `device/board/rk/rk3568_evb/loader/` | MiniLoaderAll.bin,在整包最前面 | BootROM | 整包;SDDiskTool 会覆盖卡上 loader 区 |
| U-Boot | 板级 u-boot 或预置 uboot.img | uboot.img | MiniLoader 之后 | uboot 分区或整包 |
| logo.bmp | 板级 kernel/ | resource.img | U-Boot | resource,不必动内核 |
| 空分区 misc 等 | loader/prebuilt-images/ | 对应 img,打包时补齐 | U-Boot 看 misc 是否全零 | 整包;misc 非零可能进 recovery |
显示相关的 dts 为什么强制刷 resource:U-Boot 的 bootrkp 从 resource 分区 取出 rk-kernel.dtb 和 logo。boot_linux 是一个 ext2,里面有 Image、extlinux.conf、有时还有一份 dtb,那份 dtb 不是开机生效的那份。只刷 boot_linux,/proc/device-tree 可以一动不动。设备树那篇把缓存和反编译写完。这里先建立映射。
9. out/.../images/ 才是打包的输入
全量编完,分区镜像落在:
bash
out/rk3568_evb/packages/phone/images/
├── boot_linux.img
├── resource.img
├── system.img
├── vendor.img
├── ramdisk.img
├── userdata.img
├── MiniLoaderAll.bin
├── uboot.img
├── parameter.txt
├── updater.img
├── sys_prod.img
├── chip_prod.img
├── eng_system.img
├── misc.img # 构建不一定生成,缺了从 loader/prebuilt-images 补
├── bootctrl.img
├── chip_ckm.img
└── eng_chipset.img
./build.sh 不 等于可刷整包已经躺在桌面上。它停在这些零散 img。pack_update_img.sh 再把它们合成 RKFW。打包脚本若从 images/ 拷到 pack_update/Image/,你只更新了 images/boot_linux.img、忘了拷,打出来的整包还是上一份 boot_linux。
验时间戳,不要只信文件名:
bash
IMG=out/rk3568_evb/packages/phone/images
ls -l --time-style=long-iso $IMG/boot_linux.img $IMG/resource.img \
$IMG/vendor.img $IMG/system.img $IMG/ramdisk.img
stat $IMG/boot_linux.img | grep Modify
时间是两小时前、你十分钟前才改完 dts,这份 boot_linux 就不是这次的。回去看 checkpoint 和 build_kernel.sh 有没有跑。
10. 用户态 32 位,内核 64 位,产物别混
这不是题外话,是「改了 native 目录却进不了板」的常见原因。
bash
# 板上
# uname -m
aarch64
# ls /system/lib/ld-musl-arm.so.1
/system/lib/ld-musl-arm.so.1
# ls /system/lib64 2>/dev/null | head
# file /system/bin/init
init: ELF 32-bit LSB ... ARM, ... interpreter /system/lib/ld-musl-arm.so.1
内核和 .ko:aarch64,clang 的 aarch64-linux-gnu 或 LLVM ARCH=arm64。 用户态 bin / so / hap 里的 .so:armv7,musl,动态链接器必须是板上那条路径。
自己写一个丢 /data 的小工具:
bash
# 错:宿主机 gcc,或 aarch64-linux-gnu-gcc 静态/动态混用
# 对:
OHOS_SDK=/path/to/OpenHarmony
CC=$OHOS_SDK/prebuilts/clang/ohos/linux-x86_64/llvm/bin/clang
$CC --target=arm-linux-ohos -march=armv7-a \
-fuse-ld=lld \
-Wl,--dynamic-linker=/system/lib/ld-musl-arm.so.1 \
-o gpio_dump gpio_dump.c
file gpio_dump
# ELF 32-bit LSB executable, ARM, EABI5 ... interpreter /system/lib/ld-musl-arm.so.1
file 看到 ARM aarch64 或 interpreter 指向 /lib/ld-linux-aarch64.so.1,送上去必挂。这个工具本身不进任何官方镜像,但你若把它写进 device/board/... 的 BUILD.gn 当 ohos_executable,GN 会按产品的用户态 abi 编,那才省事。
11. 一次对照:改 dts 之后,源码、out、镜像、板,四份要一致
假设你在板级 dts 里把 &hdmi { status = "disabled"; }; 改成了 okay。期望板上 /proc/device-tree 里对应节点是 okay。对照顺序:
bash
BOARD=device/board/rk/rk3568_evb/kernel
# 1) 权威源
grep -n -A2 '&hdmi' $BOARD/*.dts
# 2) src_tmp 副本,构建脚本应拷过来
grep -n -A2 '&hdmi' out/kernel/src_tmp/linux-5.10/arch/arm64/boot/dts/rockchip/*.dts
# 3) 编出来的 dtb,反编译看 status
DTB=$(find out/kernel/OBJ/linux-5.10 -name '*rk3568*evb*.dtb' | head -1)
dtc -I dtb -O dts "$DTB" 2>/dev/null | grep -A6 'hdmi@' | head -20
# 4) resource.img 里那份 rk-kernel.dtb 才是 U-Boot 交给内核的
mkdir -p /tmp/res && cd /tmp/res
# resource_tool 若在树里:
resource_tool --unpack --image=$OLDPWD/out/rk3568_evb/packages/phone/images/resource.img
dtc -I dtb -O dts rk-kernel.dtb 2>/dev/null | grep -A6 'hdmi@' | head -20
四份里只要有一份还是 disabled,刷进去也是 disabled。最常见的是 1 改了、2 没拷(checkpoint 跳过)、或者 2、3 对了,4 是旧 resource------你只把 boot_linux 刷进了 p5。
板上最后一问:
bash
# cat /proc/device-tree/hdmi@fe0a0000/status
# 或找实际节点名
# find /proc/device-tree -name status | xargs grep -l okay | grep -i hdmi
/proc/device-tree 是当前内核拿到的 dtb,不是源码,不是 out。它才是生效证据。
12. 失败判断:改了却没进镜像,按这张单子过
ninja 很快结束,images 时间戳旧。 GN 没看见你的文件。板级 dts / build_kernel.sh / khdf 子 hcs 都不在内核 action 的 sources 里。删 out/kernel/checkpoint,必要时 rm -rf out/kernel/src_tmp/linux-5.10/boot_linux。
exit 0,Image 里 grep 不到你加的字符串。 khdf 缓存,或 .c 没链进。strings vmlinux | grep 你的符号。没有就别刷。
Image 对了,板上 /proc/device-tree 不对。 刷了 boot_linux 没刷 resource,或刷了 SD 的 p4、U-Boot 从 eMMC 的 p4 取 dtb。
vendor 时间戳新,触摸还是旧分辨率。 分辨率在 khdf,不在 uhdf。刷错分区。
init 改了没反应。 改的是 init.rk3568.cfg。hardware 是 rk30board。
自己编的小工具 No such file or directory。 32/64 位或动态链接器。file 看 interpreter。
干净机 rm -rf out 之后打包缺 afptool / misc.img。 这三件套和空分区不在 ./build.sh 的产物里,在 device/board/rk/rk3568_evb/loader/。打包那篇写脚本怎么同步。
改了 applications/ 下某个系统应用,单刷 system 后桌面图标没变。 BMS 数据库还在 userdata。整包或清 data 才按新 hap 装。那是应用签名那条线,和源码树映射无关,但常被当成「system.img 没编进去」。先 debugfs 或 md5sum 对镜像里的 hap,再怀疑 BMS。
对镜像里的 hap:
bash
debugfs -R 'ls /app' out/rk3568_evb/packages/phone/images/system.img
# 或
debugfs -R 'dump /app/com.ohos.settings/Settings.hap /tmp/Settings.hap' \
out/rk3568_evb/packages/phone/images/system.img
md5sum /tmp/Settings.hap
和板上 /system/app/.../Settings.hap 的 md5 比。镜像里已经是新的、板上是旧的,是刷机介质刷错;镜像里就是旧的,是构建没跟踪到应用源码(系统应用很多是 prebuilt,ninja 只 COPY)。
改文件之前先问两句:它进哪张 img?板上启动时读哪张分区?两句都有答案,再动手。答案来自这张树,不来自文件名看起来像不像「内核」。
系列第 7 篇 · 芯片:瑞芯微 RK3568 · OpenHarmony 4.1(API 11) · Linux 5.10