资讯动态

RK3588固件打包实战:从parameter.txt到update.img全流程解析

发布时间:2026/9/28 8:10:27 来源:尧图企业网站定制
1. 固件打包这件事到底在打什么搞RK3588板子的朋友迟早会碰到一个绕不开的环节把编译好的各个分区镜像合成一个可以整包烧录的update.img。不管你是做Ubuntu桌面、Android12还是跑YOLOv8的边缘盒子最后交付给产线或者客户的那一刻手里拿的往往就是这个update.img。我见过太多人卡在这一步。编译内核、编Buildroot、调设备树都挺顺一到打包就报错或者打出来的包烧进去起不来。问题往往不在打包脚本本身而在于没搞清楚这个包是怎么被“拼”出来的。RK3588的固件打包本质上是把boot.img、rootfs.img、parameter.txt、uboot.img、trust.img这些零散件按照分区表的位置关系塞进一个带头部描述信息的容器里最终生成瑞芯微平台能识别的update.img。这篇文章面向的是已经能在RK3588上跑通编译、但打包环节还不太有底的开发者。我会从脚本调用的入口讲起把mkupdate.sh、afptool、img_maker这几个关键工具串起来讲清楚每个参数为什么这么填分区表怎么对齐以及我实际踩过的那些坑。看完你应该能自己改打包脚本而不是只会敲一条命令然后祈祷。2. 打包前的准备工作与目录结构梳理2.1 先搞清楚你手里有哪些镜像RK3588的SDK编译完之后镜像不会散落在各处通常集中在rockdev/目录下。这个目录是SDK约定的输出汇总点不同版本的SDK可能叫rockdev也可能叫output但结构大同小异。以常见的Buildroot或Ubuntu SDK为例你会看到这些东西boot.img内核加设备树有些方案会把resource也并进来rootfs.img根文件系统Ubuntu的话可能是rootfs.ext4转过来的uboot.imgU-Boot引导程序trust.imgARM Trusted Firmware负责安全启动相关misc.img杂项分区恢复模式标志位放这儿parameter.txt分区表描述文件这是打包的灵魂MiniLoaderAll.bin一级加载器烧录工具最先写进去的东西注意parameter.txt不是可有可无的配置文件它直接决定了每个分区在存储介质上的起始扇区和大小。打包工具读的就是它烧录工具认的也是它。分区表错了包打得再漂亮也白搭。我建议在动手打包前先ls -l rockdev/看一眼文件时间戳确认这些镜像都是最近一次编译产出的。我遇到过有人拿半年前编译的boot.img配新编的rootfs.img烧进去内核和文件系统版本对不上驱动加载失败查了一整天才发现是镜像不同步。2.2 parameter.txt 分区表怎么读parameter.txt的内容长这样以eMMC方案为例FIRMWARE_VER: 8.1 MACHINE_MODEL: RK3588 MACHINE_ID: 007 MANUFACTURER: RK3588 MAGIC: 0x5041524B ATAG: 0x00200800 MACHINE: 0xffffffff CHECK_MASK: 0x80 PWR_HLD: 0,0,A,0,1 TYPE: GPT CMDLINE: mtdpartsrk29xxnand:0x000020000x00004000(uboot),0x000020000x00006000(trust),0x000020000x00008000(misc),0x000100000x0000a000(boot),0x000100000x0001a000(recovery),0x000200000x0002a000(backup),0x000400000x0004a000(oem),0x00c000000x0008a000(rootfs),-0x00caa000(userdata:grow)这里最关键的是CMDLINE那一行。mtdpartsrk29xxnand:后面跟的是一串分区定义格式是大小起始扇区(分区名)。扇区单位是512字节所以0x00002000就是 8192 个扇区等于 4MB。拿uboot分区举例0x000020000x00004000(uboot)意思是uboot从第0x4000个扇区开始占0x2000个扇区。换算成字节起始位置是0x4000 * 512 8MB大小是0x2000 * 512 4MB。为什么从8MB开始而不是0因为前面留给了一级加载器和GPT分区表本身。userdata那个-0x00caa000(userdata:grow)里的-表示“剩余全部空间”grow表示这个分区可以动态扩展。这是给用户数据留的弹性空间产线烧录后第一次启动会自动把剩余eMMC空间划给它。实操心得改分区大小的时候一定要保证前一个分区的“起始大小”等于后一个分区的“起始”中间不能有空洞也不能重叠。我习惯用计算器把每个分区的起止字节都算出来列个表比肉眼盯着十六进制靠谱得多。2.3 工具链从哪来打包用的工具不在系统PATH里而是SDK自带的。通常在tools/或者RKTools/目录下你会找到afptool负责把各个镜像按分区表打包成中间格式img_maker给中间格式加上RKFW头部生成最终的update.imgmkupdate.sh或mkupdate.bat封装好的调用脚本这些工具是预编译的二进制Linux下是ELFWindows下是exe。如果你在Ubuntu上打包直接用Linux版如果SDK只带了Windows版可以用wine跑但我更建议找对应SDK版本的Linux工具wine跑二进制有时候会有权限和路径问题。3. 打包脚本的调用链路拆解3.1 mkupdate.sh 到底做了什么很多人打包就是敲一句./mkupdate.sh然后看到输出update.img就完事了。但这个脚本内部其实做了好几件事理解它对排查问题至关重要。典型的mkupdate.sh逻辑是这样的#!/bin/bash # 进入rockdev目录 cd rockdev # 第一步用afptool打包成update.raw.img ../tools/afptool -pack ./ update.raw.img # 第二步用img_maker加头部 ../tools/img_maker -RK3588 update.raw.img update.img # 第三步清理中间文件 rm -f update.raw.imgafptool -pack ./ update.raw.img这个命令的意思是以当前目录./为根读取目录下的parameter.txt和各个镜像文件按照分区表把它们打包成update.raw.img。这个raw文件是纯数据没有RKFW头部。img_maker -RK3588 update.raw.img update.img则是给raw文件加上芯片平台标识和校验信息生成烧录工具能识别的update.img。-RK3588这个参数告诉工具目标芯片型号不同芯片的头部格式有细微差别。注意有些SDK的mkupdate.sh里芯片型号是写死的比如从RK3568的SDK改过来的可能还写着-RK3568。如果你拿RK3568的脚本打RK3588的包烧录工具可能认不出来或者烧进去起不来。一定要检查这一行。3.2 afptool 的参数细节afptool除了-pack还有-unpack和-check两个常用模式。-unpack可以把已有的update.img解包看看里面到底装了什么这在排查“为什么烧录后某个分区不对”时特别有用。# 解包update.img到unpack目录 ../tools/afptool -unpack update.img unpack/解包之后你会看到unpack/目录下按分区名建了子目录每个子目录里是对应的镜像文件还有一个parameter.txt。这样你就能对比打包前后的分区表是否一致镜像文件是否完整。-check模式用来校验update.img的完整性它会检查头部校验和和每个分区的数据校验。产线批量烧录前跑一遍-check能提前发现打包过程中文件损坏的问题。3.3 img_maker 的头部信息img_maker生成的头部包含这些关键字段字段含义典型值RKFW标识固定魔数0x57464B52芯片型号目标平台RK3588头部大小头部占用的字节数0x66数据偏移raw数据在文件中的起始位置0x66数据大小raw数据的字节数动态计算校验和头部和数据的CRC动态计算这个头部是瑞芯微烧录工具识别固件的依据。如果头部损坏或者芯片型号不对烧录工具会直接报“固件格式错误”或者“芯片不匹配”。实操心得如果你改了parameter.txt里的分区布局一定要重新跑完整的mkupdate.sh不能只替换update.img里的某个分区文件。因为头部里的数据大小和校验和是基于整个raw数据算的局部替换会导致校验失败。4. 完整打包流程实操记录4.1 从编译产物到rockdev目录假设你刚跑完./build.sh或者make编译产物散落在out/目录下。第一步是把它们汇总到rockdev/。有些SDK的编译脚本会自动做这一步有些需要手动拷贝。我习惯写一个简单的汇总脚本避免漏拷或者拷错版本#!/bin/bash ROCKDEVrockdev mkdir -p $ROCKDEV # 拷贝内核相关 cp out/kernel/boot.img $ROCKDEV/ cp out/kernel/resource.img $ROCKDEV/ 2/dev/null # 拷贝uboot和trust cp out/u-boot/uboot.img $ROCKDEV/ cp out/trust/trust.img $ROCKDEV/ # 拷贝根文件系统 cp out/rootfs/rootfs.img $ROCKDEV/ # 拷贝分区表和加载器 cp device/rockchip/rk3588/parameter.txt $ROCKDEV/ cp out/u-boot/MiniLoaderAll.bin $ROCKDEV/ echo 汇总完成检查文件 ls -lh $ROCKDEV/跑完之后ls -lh看一眼确认每个文件大小合理。boot.img一般几十MBrootfs.img看你的文件系统内容Ubuntu桌面版可能上GBBuildroot精简版可能就几十MB。如果某个文件只有几KB那多半是编译出错了别急着打包。4.2 修改分区表适配你的存储方案RK3588支持eMMC、SD卡、SPI Flash等多种启动介质不同介质的分区表不一样。eMMC通常用GPTSPI Flash可能用MTD。你拿到的SDK默认parameter.txt可能是针对某个参考板的直接用到自己的板子上可能分区大小不够或者浪费。假设你的板子eMMC是32GB想给rootfs分8GBuserdata留剩下的。计算过程如下eMMC总扇区数 32GB / 512B 67108864 扇区 0x4000000前面uboot到oem这些分区加起来按默认表uboot: 0x2000trust: 0x2000misc: 0x2000boot: 0x10000recovery: 0x10000backup: 0x20000oem: 0x40000合计 0x20000x20000x20000x100000x100000x200000x40000 0x8A000 扇区rootfs起始 0x4000 0x8A000 0x8E000注意uboot从0x4000开始前面0x4000是保留区rootfs大小8GB 8 * 1024 * 1024 * 1024 / 512 16777216 扇区 0x1000000所以rootfs定义是0x10000000x8E000(rootfs)userdata起始 0x8E000 0x1000000 0x18E000userdata用-0x18E000(userdata:grow)表示剩余全部。把这些填回parameter.txt的CMDLINE行保存。注意改完分区表后如果之前已经烧录过旧分区表的板子需要先擦除eMMC再烧新固件否则GPT分区表冲突会导致挂载失败。可以用烧录工具的“擦除”功能或者进maskrom模式全片擦除。4.3 执行打包并验证分区表改好镜像齐全就可以打包了cd rockdev ../tools/afptool -pack ./ update.raw.img ../tools/img_maker -RK3588 update.raw.img update.img如果一切正常你会看到类似输出Pack file: ./parameter.txt Pack file: ./uboot.img Pack file: ./trust.img ... Pack file: ./rootfs.img Total size: 0x1A2B3C4D bytes Make update.img success!打包完成后先别急着烧录跑一遍校验../tools/afptool -check update.img校验通过会输出Check update.img success!。如果报错通常是某个镜像文件在打包过程中读取失败或者分区表里有分区指向了不存在的文件。然后解包对比一下mkdir unpack_test ../tools/afptool -unpack update.img unpack_test/ diff unpack_test/parameter.txt parameter.txt如果diff没有输出说明分区表一致。再ls -l unpack_test/看看每个分区文件大小是否和原始镜像一致。4.4 烧录验证与启动日志检查用瑞芯微的烧录工具Windows下是RKDevToolLinux下是upgrade_tool加载update.img板子进maskrom或loader模式执行烧录。烧录完成后串口接上看启动日志。重点看这几个阶段U-Boot SPL或MiniLoader是否正常加载U-Boot是否识别到eMMC并读取分区表内核是否从boot分区加载成功rootfs是否挂载成功有没有报VFS: Cannot open root device如果卡在Starting kernel ...之后没输出多半是boot.img里的设备树和你的板子不匹配。如果内核起来了但挂载rootfs失败检查parameter.txt里rootfs的起始扇区和大小是否和实际烧录的一致。实操心得我习惯在打包前把parameter.txt备份一份命名成parameter_日期.txt。因为调试阶段经常要改分区大小改乱了可以随时回滚。另外每次打包后记录一下update.img的MD5产线反馈问题时先对MD5能快速判断是不是固件版本不对。5. 常见问题与排查技巧实录5.1 打包报错“parameter.txt not found”这个错误通常是因为afptool -pack的路径参数不对。-pack ./ update.raw.img里的./表示在当前目录找parameter.txt。如果你在rockdev目录外执行或者parameter.txt不在rockdev里就会报这个错。解决方法cd到rockdev目录再执行或者把路径参数改成rockdev/。但注意如果改成rockdev/afptool会去rockdev/下找镜像文件所以镜像也必须在那个目录里。5.2 烧录后卡在logo或者反复重启这种情况八成是分区表对不上。用afptool -unpack解包你烧录的update.img对比parameter.txt里的分区定义和实际镜像大小。常见问题有rootfs分区大小小于实际rootfs.img大小导致文件被截断boot分区起始扇区算错内核加载到了错误位置userdata分区和rootfs分区重叠文件系统互相覆盖排查方法在U-Boot命令行下用mmc part查看实际分区表和parameter.txt对比。如果U-Boot识别的分区和预期不一致说明GPT分区表没写对。5.3 update.img 体积异常大正常情况下update.img的大小约等于所有分区镜像之和加上头部。如果你发现它比预期大很多可能是userdata分区用了grow但打包时把整个剩余空间都填了0导致文件巨大某个镜像文件本身有问题比如rootfs.img是稀疏文件但打包时被展开了afptool打包时对grow分区的处理是只记录分区定义不实际填充数据。如果你看到update.img有几十GB检查一下是不是某个镜像文件本身就这么大。用du -h和ls -lh对比一下du显示的是实际磁盘占用ls显示的是表观大小稀疏文件两者会差很多。5.4 常见问题速查表现象可能原因排查方法解决打包报parameter.txt not found工作目录不对pwd确认当前位置cd到rockdev再打包烧录工具报固件格式错误img_maker芯片型号不对检查mkupdate.sh里的-RK参数改成-RK3588重新打包烧录后无法启动分区表与镜像不匹配afptool -unpack对比修正parameter.txt重新打包rootfs挂载失败rootfs分区大小不足对比rootfs.img和分区定义扩大rootfs分区update.img异常大grow分区被填充ls -lh和du -h对比检查afptool版本确认grow处理逻辑校验失败镜像文件损坏afptool -check重新编译镜像再打包5.5 独家避坑技巧第一个技巧在mkupdate.sh里加一行set -e。这样任何一步失败脚本都会立即退出不会带着错误继续往下跑。我见过有人afptool打包失败了但脚本没停接着img_maker拿旧的raw文件生成了update.img结果烧进去的是上一次的固件。第二个技巧打包完成后用md5sum update.img记录哈希值同时把parameter.txt和mkupdate.sh一起归档。产线出问题时先对哈希确认固件版本再对分区表确认配置能省掉大量沟通成本。第三个技巧如果你的SDK同时支持多个板型建议为每个板型建独立的rockdev目录比如rockdev_boardA/、rockdev_boardB/每个目录里放各自的parameter.txt和镜像。打包时切换目录避免不同板型的文件混在一起。我吃过这个亏把A板的boot.img打到B板的包里烧进去屏幕不亮查了半天才发现是文件拿错了。6. 自动化打包与产线适配6.1 写一个靠谱的打包脚本SDK自带的mkupdate.sh通常比较简陋我建议根据自己的产线需求重写一个。下面是我在用的版本加了错误检查、日志记录和版本标记#!/bin/bash set -e VERSION$(date %Y%m%d_%H%M%S) ROCKDEVrockdev TOOLStools LOGpack_${VERSION}.log echo 开始打包版本$VERSION | tee $LOG # 检查必要文件 for f in parameter.txt uboot.img trust.img boot.img rootfs.img; do if [ ! -f $ROCKDEV/$f ]; then echo 错误缺少 $ROCKDEV/$f | tee -a $LOG exit 1 fi done # 记录分区表 cp $ROCKDEV/parameter.txt parameter_${VERSION}.txt # 打包 cd $ROCKDEV ../$TOOLS/afptool -pack ./ update.raw.img 21 | tee -a ../$LOG ../$TOOLS/img_maker -RK3588 update.raw.img update_${VERSION}.img 21 | tee -a ../$LOG # 校验 ../$TOOLS/afptool -check update_${VERSION}.img 21 | tee -a ../$LOG # 记录哈希 md5sum update_${VERSION}.img | tee -a ../$LOG echo 打包完成update_${VERSION}.img | tee -a ../$LOG这个脚本的好处是每次打包都带时间戳不会覆盖旧版本日志和分区表一起归档出问题可追溯校验步骤强制通过才继续。6.2 产线批量烧录的注意事项产线烧录和研发调试不一样讲究的是稳定和效率。几个关键点固件统一用update.img整包烧录不要用分区单独烧录减少操作步骤烧录工具配置里勾选“烧录后重启”和“校验”确保每片板子都验证过如果产线用SD卡量产把update.img和烧录工具一起放到SD卡根目录工人只需插卡上电定期抽检烧录后的板子跑一遍启动日志检查防止烧录工具或固件在批量过程中出问题注意产线环境如果电压不稳烧录过程中断电可能导致eMMC分区表损坏。建议产线配UPS或者烧录工位单独稳压。我见过因为电压波动导致批量烧录后部分板子无法启动的情况返工成本很高。6.3 固件版本管理与回滚每次打包生成的update.img建议按产品名_版本号_日期.img命名比如RK3588_Box_V1.2_20250115.img。同时维护一个版本记录表版本号日期变更内容分区表版本MD5V1.020250101初始版本param_v1abc123...V1.120250110修复WiFi驱动param_v1def456...V1.220250115扩大rootfs到8GBparam_v2ghi789...回滚的时候如果分区表也变了需要同时回滚parameter.txt并重新烧录整包。不能只替换update.img里的某个分区因为分区布局变了旧镜像可能放不到新分区表对应的位置。7. 关于打包这件事的一些个人体会RK3588的固件打包表面上看就是跑两个命令但真正决定成败的是对分区表的理解和对手头镜像的掌控。我刚开始搞的时候觉得parameter.txt里那一串十六进制看着就头大后来强迫自己拿计算器把每个分区的起止字节都算了一遍画了张图贴在工位上之后改分区就再也没出过错。另一个体会是打包脚本一定要自己改一版。SDK自带的脚本是给参考板用的你的板子存储容量、分区需求、产线流程都可能不一样。花半小时写个带校验和日志的脚本后面能省下几十小时的排查时间。还有一点update.img打出来只是第一步烧录验证才是真正的考验。我现在的习惯是每次打包后至少在一台样机上完整走一遍烧录和启动看串口日志确认每个阶段都正常。样机验证通过的包才归档没验证的包一律标记为“未测试”绝不发给产线。最后分享一个小技巧如果你不确定某个分区改大之后会不会影响启动可以先不改parameter.txt而是用afptool -unpack把现有update.img解开手动替换里面的镜像文件再用afptool -pack重新打包。这样可以在不重新编译整个SDK的情况下快速验证分区调整的效果。等验证通过了再把改动同步回parameter.txt和编译配置里。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑