rdk3 rdk-gen 源码和脚本:地平线官方不提供、也不支持客户直接修改 Bootloader 源码。

张开发
2026/4/10 4:04:23 15 分钟阅读

分享文章

rdk3 rdk-gen 源码和脚本:地平线官方不提供、也不支持客户直接修改 Bootloader 源码。
第一部分 架构设计原则这并非技术限制而是基于商业策略、系统安全性和软件工程成熟度的综合考量。1. 事实依据脚本中全是打包没有编译最关键的事实是Bootloader 的构建脚本 (source/bootloader/build/xbuild.sh) 内部没有任何编译动作也没有设置CROSS_COMPILE工具链。它只是一个打包脚本负责将以下预编译好的二进制文件拼装成最终的miniboot.imgspl_*.bin(Second Program Loader)bl31.bin(ARM Trusted Firmware)ddr_*.bin(DDR 初始化固件)cr5.bin(Cortex-R5 协处理器固件)客户能做的仅限于通过lunch菜单选择官方预置好的板级配置例如选择不同的 DDR 颗粒或启动介质 (eMMC/NAND)。2. 设计思想平台稳定者 vs 应用开发者地平线将开发者角色清晰地分成了两类地平线平台提供商负责维护 Bootloader、内核底层驱动、DDR 时序、安全启动等与硬件紧密耦合、极其复杂且要求高稳定性的底层代码。这些代码一旦出错板子就会变“砖”。客户应用开发者负责开发设备树 (DTS)、内核驱动模块、AI 算法和应用层业务逻辑。这些是产品的差异化所在也是客户的核心价值。这种分工模式是嵌入式行业的普遍做法与瑞芯微 (Rockchip)、恩智浦 (NXP) 等主流芯片厂商的策略一致。3. 核心考量安全性与稳定性安全性Bootloader 是安全启动链的信任根(Root of Trust)。地平线很可能在其中集成了签名验证、加密等安全特性。开放源码会暴露安全漏洞甚至导致设备被非法刷机。稳定性DDR 初始化、时钟配置等对硬件参数极度敏感错误的修改极大概率导致设备无法启动。将其作为“闭源核心”提供是保证产品质量、降低客户技术支持成本的最有效手段。4. 客户能做什么——定制边界在哪里虽然不能改 Bootloader但官方提供了充足的定制接口设备树 (Device Tree)这是最主要的定制方式。你可以在source/kernel/arch/arm64/boot/dts/hobot/下修改.dts文件来配置引脚复用、外设、时钟等Bootloader 会加载这个设备树。U-Boot 环境变量启动后可以通过setenv、saveenv命令修改启动参数、内核加载地址等。配置文件分区pack_image.sh脚本创建的FAT32 格式 CONFIG 分区允许用户在 Windows/Linux 下直接修改配置文件间接影响系统行为。技术点sdk整理总结“地平线 RDK 的 Bootloader 是不支持客户修改的。它的设计更像一个‘闭源的固件核心’客户通过lunch脚本从官方预置的配置中选择即可。核心原因有三点工程分工平台方保证底层硬件兼容性开发者聚焦应用。系统安全Bootloader 是安全启动的信任根源码不能轻易开放。降低风险避免客户因错误配置导致设备变砖减少技术支持负担。客户定制的边界在于可以深度定制设备树 (DTS) 和内核驱动。可以有限配置通过 U-Boot 环境变量。不能修改DDR 初始化、ATF、安全启动等底层固件。这种模式符合嵌入式行业的商业共识确保了平台健壮性也给了客户足够的自由度。”第二部分 xbuild.sh 完整分析Bootloader 镜像的装配工厂一、核心定位xbuild.sh是一个装配脚本而不是编译脚本。它不调用gcc/make编译任何源码而是将各种预编译好的二进制组件按照特定布局组装、打包成最终的miniboot.img启动固件。这与pack_image.sh的角色类似——pack_image.sh打包 Ubuntu 系统镜像而xbuild.sh打包 Bootloader 镜像。二、功能树形分析xbuild.sh 工作流程 │ ├── 1. 环境准备阶段 │ ├── source ./utils_funcs.sh工具函数 │ ├── 设置 HR_TOP_DIR、HR_LOCAL_DIR │ ├── check_board_config解析板级配置 │ │ ├── 读取配置文件如 board_ubuntu_nand_sdcard_config.mk │ │ └── 设置硬件参数DDR型号、频率、容量、启动介质等 │ └── 创建输出目录 deploy/miniboot │ ├── 2. Board ID 计算关键 │ ├── 根据以下参数计算 32 位 board_id │ │ ├── DDR 厂商hynix/micron/samsung→ bits 28-31 │ │ ├── DDR 类型LPDDR4/LPDDR4X→ bits 24-27 │ │ ├── DDR 频率667/1600/2133...→ bits 20-23 │ │ ├── DDR 容量1G/2G/4G→ bits 16-19 │ │ ├── SOM 类型x3som/j3som→ bits 8-15 │ │ └── 底板类型x3dvb/cvb→ bits 0-7 │ └── 最终输出 board_id如 0x12345678 │ └── 写入 Bootloader用于运行时识别硬件 │ ├── 3. DDR 固件生成 │ ├── cd ${MINIBOOT_SOURCE_DIR}/ddr │ ├── bash mk_ddr_bin.sh -o storage │ │ ├── 根据 DDR 参数生成 ddr_storage.bin │ │ └── 用于初始化 DDR 控制器 │ └── python2 ./efuse/pack_efuse_outside.py │ └── 生成 efuse.bin一次性可编程参数 │ ├── 4. 安全固件打包 │ ├── pack_efuse_tool.sh -b │ │ └── 打包 efuse 相关数据 │ ├── pack_keyset_tool.sh │ │ └── 打包密钥集key_set.bin │ └── 拷贝 bl31.binARM Trusted Firmware │ ├── 5. SPL 与 Warm SPL 处理 │ ├── 拷贝预编译的 SPL 二进制 │ │ └── spl_storage_secure.bin冷启动 │ ├── gen_warmspl生成 Warm SPL │ │ ├── 调用 x3-warm-spl.sh 添加头部 │ │ └── pack_cr5_warmspl合并 CR5 固件到 Warm SPL │ │ └── cr5.binCortex-R5 协处理器固件 │ └── 最终生成 spl_warm_storage_secure.bin │ ├── 6. 分区表与镜像组装 │ ├── build_miniboot_image 核心函数 │ │ ├── eval_gpt_conf解析分区配置文件 │ │ ├── miniboot_check校验分区配置合法性 │ │ ├── gen_miniboot_size_emmc计算 miniboot 分区大小 │ │ ├── 创建空白 miniboot.img │ │ ├── 生成 GPT/MBR 分区表 │ │ │ ├── gen_gpt.py生成 GPT 分区表 │ │ │ └── gen_miniboot_mbr.py生成 MBR │ │ └── miniboot_fill_partition填充各分区内容 │ │ ├── spl_storage_secure.bin │ │ ├── ddr_storage.bin │ │ ├── bl31.img │ │ ├── key_set.bin │ │ └── efuse.bin │ │ │ └── 输出 miniboot.img │ ├── 7. 工厂镜像生成可选 │ ├── 创建 factory_images 目录 │ ├── 拷贝关键二进制供 UART 烧录使用 │ └── 生成 uart_ddr_img用于串口烧录 DDR 初始化固件 │ └── 8. 清理与输出 ├── 复制分区配置文件到 deploy ├── 删除临时文件 └── 输出最终 miniboot.img三、关键证据无任何编译动作# 搜索整个脚本没有任何以下命令 # - gcc / g / clang # - make / cmake # - ld / ar / objcopy # - CROSS_COMPILE 设置 ​ # 全是这些操作 cp # 拷贝预编译二进制 dd # 写入数据到镜像 bash # 调用打包工具脚本 python2 # 运行 Python 打包工具四、Board ID 计算详解重要发现# Board ID 是一个 32 位整数各 bits 含义 # bits 31-28: DDR 厂商 (hynix1, micron2, samsung3) # bits 27-24: DDR 类型 (LPDDR41, LPDDR4X2, DDR43, DDR3L4) # bits 23-20: DDR 频率 (6671, 16002, 21333, 26664, 32005, 37336, 42667) # bits 19-16: DDR 容量 (1G1, 2G2, 4G4) # bits 15-8: SOM 类型 (x3som1, j3som2, x3sdb3) # bits 7-0: 底板类型 (x3dvb1, j3dvb2, cvb3, x3sdb4, customer5) ​ # 示例计算 # DDR厂商 hynix(1) 28 0x10000000 # DDR类型 LPDDR4(1) 24 0x01000000 # 最终 board_id 0x11000000 board_id$(echo obase16;$board_id|bc)意义Bootloader 启动时会读取这个 board_id根据其值配置 DDR 时序、引脚复用等硬件参数。这就是为什么必须通过lunch选择正确的板级配置。五、依赖的预编译组件清单组件路径说明能否修改spl_storage_secure.binminiboot/boot/spl/Secondary Program Loader❌ 预编译spl_warm_storage_secure.binminiboot/boot/spl/Warm SPL低功耗唤醒❌ 预编译bl31.binminiboot/boot/bl31/ARM Trusted Firmware❌ 预编译cr5.binminiboot/boot/cr5/Cortex-R5 协处理器固件❌ 预编译ddr_storage.binminiboot/ddr/DDR 初始化固件⚠️ 通过脚本生成efuse.bin动态生成一次性可编程参数⚠️ 通过脚本生成key_set.bin动态生成密钥集⚠️ 通过脚本生成六、执行流程图执行 ./xbuild.sh lunch 2选择配置 │ ├── [1/8] 解析板级配置 │ └── board_ubuntu_nand_sdcard_config.mk │ ├── HR_BOOT_MODEnand │ ├── HR_DDR_FREQ2666 │ ├── HR_DDR_CAPACITY4 │ └── HR_SOM_TYPEx3som │ ├── [2/8] 计算 Board ID │ └── 输出: VERSION:0.3, BOARD_ID:0x24110000 │ ├── [3/8] 生成 DDR 固件 │ └── mk_ddr_bin.sh → ddr_storage.bin │ ├── [4/8] 打包安全固件 │ ├── pack_efuse_tool.sh → efuse.bin │ └── pack_keyset_tool.sh → key_set.bin │ ├── [5/8] 处理 Warm SPL │ ├── x3-warm-spl.sh 添加头部 │ └── 合并 cr5.bin 到 Warm SPL │ ├── [6/8] 组装 miniboot.img │ ├── 解析分区表配置 │ ├── 创建空白 512 扇区镜像 │ ├── 生成 GPT/MBR 分区表 │ └── 填充各分区二进制 │ ├── [7/8] 生成工厂烧录文件 │ └── factory_images/*.bin │ └── [8/8] 完成 └── deploy/miniboot.img (约 2-4MB)七、与pack_image.sh的对比维度xbuild.shpack_image.sh产物miniboot.img(2-4MB)Ubuntu 系统镜像 (2-4GB)内容SPL、DDR、ATF、CR5 固件Ubuntu rootfs 配置文件启动阶段一级启动最先运行二级启动Bootloader 引导可定制性极低仅可选配置较高可增删 deb 包、配置文件编译无纯打包无纯打包关键依赖预编译二进制samplefs deb 包八、boot整理总结xbuild.sh是地平线 RDK 平台用于生成 Bootloader 镜像 (miniboot.img)的核心脚本。它不执行任何编译而是一个装配脚本负责将各种预编译好的底层固件组件打包成最终镜像。核心工作硬件识别根据lunch选择的板级配置计算board_id用于运行时识别 DDR 型号、频率、容量等固件组装将 SPL、DDR 初始化固件、ARM Trusted Firmware (BL31)、CR5 协处理器固件等预编译组件打包分区布局生成 GPT/MBR 分区表按规范布局各固件到指定偏移设计意义Bootloader 是闭源的所有组件都是预编译的二进制客户无法修改配置驱动通过选择不同的板级配置文件适配不同的 DDR 颗粒和启动介质Board ID 是关键运行时根据 board_id 动态配置硬件实现单一镜像支持多种硬件变体这种设计的优点避免客户因错误配置导致设备变砖简化客户开发流程无需搭建复杂的交叉编译环境保护地平线的核心知识产权DDR 调优、安全启动等这也解释了为什么之前找不到CROSS_COMPILE设置——因为这里根本不需要编译。

更多文章