OpenHarmony源码树解剖—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
编译命令还没敲先认路。今天把源码树摊开你改的文件会进哪张镜像。改错目录、刷错分区表现都是「我改了板上没反应」。改了一行设备树./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就是这次刚生成的那张板子启动时读的就是你刷的那张分层看失败通常停在其中一层你改的文件 ↓ 构建系统看见了吗GN sources / checkpoint out/ 里的中间拷贝 ↓ 真的重编了吗时间戳、hcb、.config packages/phone/images/*.img ↓ 打包脚本同步了吗pack_update 里可能是旧文件 你刷进板子的分区 ↓ 启动时读的是这块介质吗SD / eMMCresource vs boot_linux 板上正在跑的那份后面几篇分别写编译、打包、刷机、启动。这篇只回答一个问题源码树里每个目录默认会流进哪张镜像。认路比认命令值钱。2. 整棵树只需要记住这几块源码根目录下面东西很多。日常改板真正会进镜像的集中在这几处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 位 ELFhdc file send能送上去一执行No such file or directory——那是解释器路径不存在不是文件没送过去。3. 内核三份目录别改错那一份内核不是「一个 linux-5.10 目录」这么简单。构建时会拷、会打补丁、会另开 OBJ。三份目录职责不同。3.1kernel/linux/linux-5.10/上游 开源鸿蒙合入的那份这是 git 里的内核源。GN 的内核 action 把sources指到这里。你在这里改drivers/xxx.cninja看得到下次./build.sh会认为内核变了。不要在这里改板级设备树。板级 dts 不从这里出发从device/board/rk/rk3568_evb/kernel/出发构建脚本拷进来。你在linux-5.10/arch/arm64/boot/dts/rockchip/里直接改下次copy_and_patch一跑板级那份会盖过来或者反过来你的改动被当成「内核源改动」进了 git 脏状态两头都不干净。3.2kernel/linux/patches/linux-5.10/rk3568_patch/芯片补丁构建把 linux-5.10 拷到out/kernel/src_tmp/之后按清单把这里的 patch 打进去。RK3568 的 DRM、ISP、PCIE PHY、一些 staging 网卡经常以补丁形式存在而不是直接合进 git 源。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 网卡就报error: no member named rx_speed in struct usbnet这不是网卡没插是编译期。自己加补丁编号接在现有最大号后面让build_kernel.sh的循环能扫到。打补丁的代码大致是# 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 21 || { echo REJECT: $p exit 1 } patch -p1 --forward $p donesrc_tmp是打补丁后的工作树。下次构建若判定「内核没变」这份树会留着补丁不会重打。这就是为什么你改了 patch 目录有时镜像里还是旧内核——checkpoint 说没变拷贝和打补丁整段被跳过。3.3out/kernel/src_tmp和out/kernel/OBJ干活的地方路径是什么能手改吗out/kernel/src_tmp/linux-5.10拷贝 打过补丁 拷过板级 dts/驱动的工作树只为了「这一次增量 make」下次 copy 会盖out/kernel/OBJ/linux-5.10KBUILD_OUTPUT.config、vmlinux、Image、dtb、certs/不要当权威源。menuconfig 改它下次合成会丢out/kernel/checkpointlast_build.info 一类给 is_kernel_change 用删它 强制认为内核变了增量编内核、编单个.ko命令都在 src_tmp 上跑输出进 OBJROOT/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 LLVM1 LLVM_IAS1 CROSS_COMPILEaarch64-linux-gnu- ARCHarm64 \ Image -j$(nproc)编完Image 在 OBJ 里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 勾过了」和「下次全量还在」是两件事。四层从底到顶层 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_FOOy会被冲掉。只改层 4 不删 checkpoint脚本根本不跑OBJ 继续用旧.config。写入层 4 要幂等已经是y不要再 append 出两行# 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编完对三处缺一处就是没进# 层 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、只改板级 dtsninja 可能判定内核没变层 4 整段跳过。强制重跑rm -rf out/kernel/checkpoint ./build.sh --product-name rk3568_evb --ccache5. 板级目录一个产品真正和公版分道的地方device/board/rk/rk3568_evb/是你最常改的树。子目录和镜像的对应比记 GN target 名有用。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_imagesbuild_kernel.sh才是板级内核的总开关。它通常会做这些事具体行号按你的脚本逻辑一样# 伪代码对着你的 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_imagesohos_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.hardwarerk30board只认这个后缀设备树 cmdline 里有chosen { bootargs consolettyS2,1500000n8 androidboot.hardwarerk30board \ hardwarerk30board ...; };跑起来之后# param get ohos.boot.hardware rk30boardinit 用这个字符串拼文件名。system/etc/init.cfg里类似import /vendor/etc/init.${ohos.boot.hardware}.cfg mount_fstab /vendor/etc/fstab.${ohos.boot.hardware}展开就是/vendor/etc/init.rk30board.cfg /vendor/etc/fstab.rk30boardinit.rk3568.cfg、fstab.rk3568、init.rk3568_evb.cfg都可以在源码树里活得好好的开机不理它们。这不是文档写错是这颗产品从公版 SD 方案继承了rk30board这个 hardware 名一直没改 bootargs。改 console、改 chmod、改开机自启服务文件名必须带rk30board。验源码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验板上# 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 进 vendorvendor/rk/rk3568_evb/hdf_config/分成两棵树长得很像进的镜像完全不同。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编内核前应该无条件删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 -fuhdf 是另一对别删混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 真进去了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 | headHDF 的模型和 HCS 语法配置那篇写。这里只要记住分流。8. 改什么进哪张镜像这张表是这篇的中心。刷机之前对一下少刷一张没用的、少漏一张有用的。你改了什么权威路径进哪张镜像板上谁读还要刷板级 dtsdevice/board/rk/rk3568_evb/kernel/*.dtsresource.img 里的 rk-kernel.dtbboot_linux 里也有一份 toybrick.dtb开机不认它当主 dtbU-Boot 从 **resource** 取出 dtb 传给内核**resource boot_linux**SD 启动时 eMMC 的 p4/p5 也建议写内核 .c / Kconfig / defconfigkernel/linux/linux-5.10 或板级 kernel/ MERGED_CFGboot_linux.img内核boot_linux改显示相关 dts 仍要 resourcekhdf HCSvendor/rk/rk3568_evb/hdf_config/khdf/boot_linux.img链进 Image内核态 HDFboot_linuxuhdf HCS、vendor 脚本、相机 IQ、音频 jsonvendor/rk/...、device/board/.../camera audiovendor.img用户态 host / init 从 /vendor 读vendorfstab.requireddevice/board/rk/rk3568_evb/cfg/ramdisk.img也常被打进 boot_linux 的 extlinux/一阶段 initramdisk / 整包只刷 vendor 不够fstab.rk30board、init.rk30board.cfg同上 cfg/vendor.img二阶段 initvendor系统应用、foundation、powermgr jsonapplications/ foundation/ base/system.imgBMS / 各 SAsystem首启签名校验单刷有时跳过MiniLoader / DDR 固件device/board/rk/rk3568_evb/loader/MiniLoaderAll.bin在整包最前面BootROM整包SDDiskTool 会覆盖卡上 loader 区U-Boot板级 u-boot 或预置 uboot.imguboot.imgMiniLoader 之后uboot 分区或整包logo.bmp板级 kernel/resource.imgU-Bootresource不必动内核空分区 misc 等loader/prebuilt-images/对应 img打包时补齐U-Boot 看 misc 是否全零整包misc 非零可能进 recovery显示相关的 dts 为什么强制刷 resourceU-Boot 的bootrkp从resource 分区取出rk-kernel.dtb和 logo。boot_linux 是一个 ext2里面有 Image、extlinux.conf、有时还有一份 dtb那份 dtb 不是开机生效的那份。只刷 boot_linux/proc/device-tree可以一动不动。设备树那篇把缓存和反编译写完。这里先建立映射。9.out/.../images/才是打包的输入全量编完分区镜像落在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。验时间戳不要只信文件名IMGout/rk3568_evb/packages/phone/images ls -l --time-stylelong-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 目录却进不了板」的常见原因。# 板上 # 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内核和.koaarch64clang 的aarch64-linux-gnu或 LLVMARCHarm64。 用户态 bin / so / hap 里的.soarmv7musl动态链接器必须是板上那条路径。自己写一个丢/data的小工具# 错宿主机 gcc或 aarch64-linux-gnu-gcc 静态/动态混用 # 对 OHOS_SDK/path/to/OpenHarmony CC$OHOS_SDK/prebuilts/clang/ohos/linux-x86_64/llvm/bin/clang $CC --targetarm-linux-ohos -marcharmv7-a \ -fuse-ldlld \ -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.1file看到ARM aarch64或 interpreter 指向/lib/ld-linux-aarch64.so.1送上去必挂。这个工具本身不进任何官方镜像但你若把它写进device/board/...的 BUILD.gn 当ohos_executableGN 会按产品的用户态 abi 编那才省事。11. 一次对照改 dts 之后源码、out、镜像、板四份要一致假设你在板级 dts 里把hdmi { status disabled; };改成了 okay。期望板上/proc/device-tree里对应节点是 okay。对照顺序BOARDdevice/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。板上最后一问# cat /proc/device-tree/hdmife0a0000/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 0Image 里 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。对镜像里的 hapdebugfs -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 比。镜像里已经是新的、板上是旧的是刷机介质刷错镜像里就是旧的是构建没跟踪到应用源码系统应用很多是 prebuiltninja 只 COPY。改文件之前先问两句它进哪张 img板上启动时读哪张分区两句都有答案再动手。答案来自这张树不来自文件名看起来像不像「内核」。系列第 7 篇 · 芯片瑞芯微 RK3568 · OpenHarmony 4.1API 11 · Linux 5.10