RK3128固件打包报错No space left?分区表与镜像大小排查指南

发布时间:2026/9/24 10:54:08
RK3128固件打包报错No space left?分区表与镜像大小排查指南 1. 从一次失败的刷机说起为什么RK3128的固件折腾起来这么费劲手里有块RK3128的板子可能是山寨投影仪拆出来的也可能是某个老式电视盒子的主板想改个开机画面、精简一下预装应用或者干脆换个桌面启动器。想法很美好但真正动手之后你会发现瑞芯微这套平台的固件处理流程跟常见的安卓手机完全不是一回事。手机上有现成的Recovery、有Fastboot、有各种一键工具而RK3128这类芯片的方案固件通常是一个后缀为.img的完整镜像包里面打包了引导程序、内核、根文件系统、参数分区等一大堆东西想动其中任何一个部分都得先把整个包拆开改完再合回去。我最初拿到的是一个山寨投影仪的固件包大概八百多兆文件名是一串看不出含义的字母数字组合。目标很简单把里面预装的几个推广APK删掉换掉开机第一屏的Logo。按照网上的教程第一步就是解包。工具用的是瑞芯微官方那套AFPTool和imgRePackerWindows下有对应的图形界面版本Linux下则是命令行。我选择在Linux环境下操作因为后续修改文件系统用Linux更方便。解包的过程本身不算复杂一条命令下去固件包被拆成了一个目录结构里面有boot.img、system.img、recovery.img、parameter.txt等等。看到这些文件的时候心里还挺踏实觉得接下来就是常规操作了。但问题恰恰出在后面——当你修改完system分区的内容准备重新打包的时候那个经典的报错出现了No space left on device。这个报错看起来像是磁盘满了但实际上磁盘空间充足得很。真正的原因是RK3128固件的分区表对每个分区的大小有严格限制你往system.img里塞进去的东西超过了它原本分配的空间打包工具在重建镜像时就写不进去了。更麻烦的是这个限制不是简单删几个文件就能绕过去的因为固件的分区布局在parameter.txt里定义得死死的你改了分区大小刷机工具那边可能又不认了。所以这篇内容就是把我从解包、修改、打包到最终成功刷入的完整过程梳理一遍重点讲清楚那个No space left到底是怎么回事、怎么排查、怎么解决以及在这个过程中还有哪些容易踩的坑。如果你手里正好有一台RK3128的设备想折腾或者你只是对瑞芯微平台的固件结构感兴趣下面的内容应该能帮你省下不少来回试错的时间。2. 解包之前必须搞清楚的几件事工具链、分区表和固件类型2.1 瑞芯微固件包的基本构成RK3128的固件包通常是一个统一的.img文件内部按照瑞芯微自己的格式打包了多个分区镜像。用AFPTool解包之后你会看到类似这样的结构output/ ├── boot.img ├── kernel.img ├── misc.img ├── recovery.img ├── resource.img ├── system.img ├── parameter.txt ├── package-file └── ...每个文件对应设备上的一个分区。parameter.txt是整个固件的分区布局定义文件里面用CMDLINE的方式描述了每个分区的起始扇区、大小和名称。package-file则告诉打包工具哪些文件需要被写入固件包以及它们对应的分区名。这里有一个关键点parameter.txt里的分区大小是固定的比如system分区可能被定义为0x00400000个扇区换算成字节就是大约2GB。但这个大小是上限不是实际使用量。当你解包出system.img之后它可能只占用了1.2GB剩下的空间是空闲的。问题在于重新打包时工具会根据parameter.txt里的定义来分配空间如果你的system.img内容超过了这个上限就会报No space left。2.2 工具链的选择与版本匹配瑞芯微的固件工具链有几个不同的来源官方SDK里带的、网上流传的独立版本、以及一些第三方修改版。我试过至少三个版本的imgRePacker发现不同版本对固件格式的兼容性有差异。有的版本能正常解包但打包时报错有的版本解包出来的文件结构都不对。最终我用的是从瑞芯微官方SDK里提取出来的AFPTool和imgRePacker版本号在工具运行时会打印出来。建议你在操作之前先确认工具版本尽量用较新的版本因为老版本可能不支持某些固件包的打包格式。在Linux下这两个工具都是命令行程序基本用法如下# 解包 ./AFPTool -unpack firmware.img output_dir # 打包 ./imgRePacker -pack output_dir new_firmware.imgWindows下也有对应的图形界面工具比如RKImageMaker和AndroidTool但图形界面工具在打包时往往隐藏了细节出了问题不好排查。如果你打算认真折腾建议还是在Linux下用命令行工具。2.3 确认固件类型Android还是LinuxRK3128可以跑Android也可以跑Linux比如Ubuntu Core或者Buildroot。两种系统的固件结构差异很大。Android固件通常有system.img、boot.img、recovery.img这些标准分区而Linux固件可能只有rootfs.img和boot.img。我手里这个山寨投影仪用的是Android 4.4所以分区结构是标准的Android那套。如果你不确定自己的固件是什么类型解包之后看文件结构就能判断有system.img的基本就是Android。另外要注意的是有些固件包是加密的解包时会提示格式错误。这种情况比较麻烦需要先找到对应的密钥或者用特殊工具处理。不过大多数山寨设备的固件都没有加密直接就能解开。3. No space left的根因定位从分区表到镜像格式的完整排查链路3.1 第一次遇到报错时的错误排查方向第一次看到No space left on device的时候我的第一反应是磁盘满了。df -h一看根分区还有几十个G的空闲显然不是这个问题。然后我以为是/tmp目录满了因为打包工具可能会在临时目录里生成中间文件。清理了/tmp之后重新打包还是同样的报错。接着我怀疑是输出目录所在的文件系统有问题换了一个分区重新操作依然报错。这时候我才意识到这个报错可能不是操作系统层面的而是打包工具自己抛出来的。用strace跟踪了一下imgRePacker的系统调用发现它在写入某个文件时返回了ENOSPC。但这个文件的大小并不大远没有达到文件系统的容量上限。这就说明工具在内部做了一层空间检查当它发现要写入的数据超过了某个预设值时就主动报错了。3.2 parameter.txt里的分区大小限制顺着这个思路我去看了parameter.txt的内容。里面有一行是这样的CMDLINE: mtdpartsrk29xxnand:0x000020000x00002000(uboot),0x000020000x00004000(trust),0x000080000x00006000(boot),0x000100000x0000E000(recovery),0x000200000x0001E000(backup),0x000200000x0003E000(logo),0x000200000x0005E000(misc),0x000200000x0007E000(metadata),0x000200000x0009E000(security),0x000200000x000BE000(verifiedboot),0x000200000x000DE000(resource),0x000200000x000FE000(kernel),0x000200000x0011E000(system),...这里每个分区后面的符号前面是分区大小以扇区为单位后面是起始扇区。system分区的大小是0x00020000个扇区也就是131072个扇区每个扇区512字节总共64MB。等等64MB的system分区这显然不对Android 4.4的system分区至少也得几百MB。再仔细看原来我数错了位数。0x00020000是十六进制换算成十进制是131072乘以512字节确实是64MB。但实际固件里的system分区不可能这么小。后来发现这个parameter.txt里的分区定义可能被修改过或者我看到的不是完整的定义。实际上RK3128的parameter.txt里system分区的大小通常是0x00400000或者更大也就是2GB左右。如果你解包出来的system.img实际大小接近这个值那说明分区已经被充分利用了没有多少余量。3.3 镜像文件的实际大小与分区上限的对比要确认是不是空间不够最直接的方法是对比system.img的实际大小和parameter.txt里定义的上限。用ls -l看一下system.img的大小比如是1.8GB。然后计算parameter.txt里system分区的上限0x00400000扇区乘以512字节等于2GB。1.8GB小于2GB理论上应该能放下。但问题在于system.img在打包时可能不是简单地按原样写入而是会经过某种转换或压缩。如果工具在打包时对镜像做了额外的处理比如添加了文件系统头、对齐填充等实际占用的空间可能会比原始文件大。另外如果你往system分区里添加了新的文件比如替换了开机动画、添加了新的APK这些都会增加system.img的大小。当增加后的体积超过了分区上限打包就会失败。3.4 用挂载和du命令精确计算实际占用为了精确知道system分区里到底用了多少空间可以把system.img挂载到本地目录然后用du命令统计。mkdir /mnt/system sudo mount -o loop system.img /mnt/system du -sh /mnt/system这样得到的是文件系统内部实际使用的空间。但要注意du统计的是文件占用的块数而镜像文件的大小还包含了文件系统的元数据、空闲块等。所以du的结果通常会小于system.img的文件大小。更准确的方法是看文件系统的超级块信息。对于ext4文件系统可以用dumpe2fssudo dumpe2fs -h system.img | grep -E Block count|Free blocks|Block size这样能算出文件系统的总块数、空闲块数和块大小从而精确知道已用空间和剩余空间。3.5 分区表修改的风险与限制既然空间不够最直接的想法就是改大system分区的上限。在parameter.txt里把system分区的大小从0x00400000改成0x00600000这样就有3GB的空间了。但这样做有几个风险第一分区大小改变后后面所有分区的起始扇区都要跟着调整否则会重叠。手动计算这些偏移量很容易出错。第二刷机工具在刷入固件时会按照parameter.txt里的定义来写入分区。如果分区大小超过了设备实际的存储容量刷机就会失败。第三有些设备的引导程序会校验分区表分区布局变了之后可能无法启动。所以改分区表是最后的手段优先考虑的还是精简system分区里的内容把空间腾出来。4. 精简与重新打包的实操细节从删文件到重建镜像4.1 安全删除预装应用的策略精简system分区的第一步是找出哪些文件可以删。对于Android系统/system/app和/system/priv-app目录下是预装应用/system/vendor下是厂商定制内容/system/media下是开机动画和音频。但删文件不能随便删。有些APK虽然看起来是独立的但实际上被其他系统组件依赖。删错了会导致系统启动后不断报错甚至无法进入桌面。我的做法是先把所有预装APK列出来然后逐个确认用途。对于明显是推广性质的APK比如名字里带“推荐”、“商城”、“游戏中心”之类的可以直接删。对于不确定的先保留等系统跑起来之后再通过pm disable禁用。另外要注意的是有些APK在/system/app下有对应的.odex文件如果是odex化的系统删APK的时候要把.odex一起删掉否则会残留无效的优化文件。4.2 替换开机Logo和开机动画的正确姿势开机第一屏的Logo通常存放在logo分区或者resource分区里是一个BMP格式的图片。替换的时候要注意分辨率必须和原图一致否则显示会异常。RK3128常见的Logo分辨率是1280x720或者1920x1080具体看设备。开机动画在/system/media/bootanimation.zip里面是一系列PNG图片和一个desc.txt描述文件。替换时要注意desc.txt里的帧率和分辨率设置以及图片的命名规则。我踩过的一个坑是替换了开机动画之后系统启动时黑屏了很久以为是自己改坏了。后来发现是新的bootanimation.zip里图片数量太多解码时间变长实际上系统还在正常启动只是动画没显示出来。等了一会儿就正常进入桌面了。4.3 重新打包时的文件权限与SELinux上下文Android系统对文件权限和SELinux上下文有严格要求。如果你在Linux下直接往system目录里复制文件文件的权限和属主可能不对导致系统启动后相关功能异常。正确的做法是在挂载system.img之后用chmod、chown设置正确的权限然后用chcon设置SELinux上下文。如果不知道正确的上下文是什么可以从同目录下的其他文件参考。对于Android 4.4SELinux还没有后来那么严格但基本的权限还是要注意。比如/system/app下的APK文件权限应该是644属主是root:root。4.4 打包命令的参数与输出验证修改完system目录后先卸载镜像sudo umount /mnt/system然后重新打包。imgRePacker的基本用法是./imgRePacker -pack output_dir new_firmware.img但有时候需要指定一些参数比如-rkimage或者-new具体看工具版本的帮助信息。打包完成后不要急着刷机先用AFPTool再解包一次新生成的固件确认里面的system.img确实包含了你的修改。这一步能避免很多“刷了没效果”的问题。5. 刷入环节的坑从驱动安装到刷机工具的选择5.1 RK3128进入刷机模式的方法RK3128设备进入刷机模式通常有两种方式一种是按住设备上的Recovery按键或者用牙签戳复位孔再上电另一种是通过ADB命令reboot loader。但山寨设备的按键定义往往不标准有的设备根本没有复位孔有的按键被隐藏在外壳内部。我遇到的一台投影仪复位键在镜头旁边的一个小孔里不仔细找根本看不到。如果按键方式不行可以尝试通过ADB进入。前提是设备能正常启动并且ADB调试是打开的。如果系统已经起不来了那就只能拆机短接Flash的特定引脚来强制进入刷机模式。5.2 刷机工具的版本兼容性问题瑞芯微的刷机工具主要有AndroidToolWindows和upgrade_toolLinux。不同版本的工具有不同的兼容性。我试过用较新版本的AndroidTool刷老固件结果工具识别不到设备。换成和固件同期的工具版本就正常了。在Linux下upgrade_tool的用法如下sudo ./upgrade_tool uf new_firmware.img但要注意Linux下需要先安装好USB驱动规则否则工具没有权限访问设备。通常需要添加一个udev规则文件把瑞芯微的USB设备权限放开。5.3 刷机失败后的恢复方法刷机失败是常有的事。如果刷到一半断了设备可能变成“砖头”无法启动。但RK3128有MaskROM模式只要硬件没坏基本上都能救回来。进入MaskROM模式的方法通常是按住设备上的MaskROM按键或者短接Flash的特定引脚再上电。这时候设备会以最低级别的模式启动刷机工具能识别到一个新的USB设备。然后重新刷入完整的固件即可。我遇到过一次刷机后设备完全没反应的情况后来发现是固件包本身有问题——打包时parameter.txt里的分区定义和实际镜像不匹配。重新打包后刷入就正常了。5.4 刷入后的首次启动与验证刷入成功后设备第一次启动会比较慢因为系统需要初始化各种缓存。如果等了很久还是黑屏可以接上串口调试线看内核日志。RK3128的调试串口通常是UART2波特率1500000。通过串口能看到内核启动的详细过程如果卡在某个阶段就能判断是哪个分区出了问题。比如卡在system分区挂载失败那说明system.img打包有问题。6. 几个容易被忽略的细节和我的个人经验6.1 固件包里的隐藏分区除了常见的boot、system、recovery之外RK3128固件里还有一些容易被忽略的分区比如misc、metadata、security等。这些分区虽然不大但删改时要注意。misc分区里存放的是启动模式标志如果被改坏了设备可能一直进入Recovery而不是正常启动。6.2 文件系统类型的选择重新打包system.img时文件系统类型要和原来一致。Android 4.4通常用ext4但有些设备可能用yaffs2或者ubifs。如果搞错了文件系统类型刷入后系统无法挂载。判断方法很简单解包后看system.img的文件头或者用file命令file system.img输出里会显示文件系统类型。6.3 打包时的对齐问题有些刷机工具对镜像文件的对齐有要求。如果打包时没有正确对齐刷入后可能会报校验错误。imgRePacker通常会自动处理对齐但如果你手动修改了parameter.txt里的分区大小对齐可能会乱掉。6.4 串口调试的实用技巧如果你打算长期折腾RK3128建议焊一个串口调试线出来。UART2的TX、RX、GND三个引脚引出来接一个USB转TTL模块就能看到完整的启动日志。这比盲猜问题原因高效得多。串口参数是波特率15000008位数据位1位停止位无校验。有些USB转TTL模块不支持这么高的波特率需要换一个支持高速率的模块。6.5 备份原厂固件的重要性在动手修改之前一定要先把原厂固件完整备份出来。备份的方法是用刷机工具读取设备的所有分区保存为一个完整的镜像文件。这样即使改坏了也能刷回原厂状态。我见过有人没有备份就直接改结果设备变砖之后找不到原厂固件只能去网上到处求人。山寨设备的固件往往没有公开下载渠道备份是唯一的保障。6.6 关于No space left的最终解决方案回到最初的问题。我最终的解决方案是先精简system分区里的内容把不必要的APK和资源文件删掉腾出足够的空间。然后重新打包确保system.img的大小不超过parameter.txt里定义的上限。如果实在腾不出空间再考虑调整分区表但调整之前一定要确认设备的总存储容量足够。具体操作上我删掉了大约200MB的预装应用和冗余资源然后重新打包system.img的大小从1.9GB降到了1.7GB打包顺利通过。刷入后设备正常启动开机Logo和预装应用都按照预期修改了。这个过程里最耗时的不是操作本身而是排查No space left的原因。希望上面的排查思路能帮你更快定位问题。如果你也在折腾RK3128或者其他瑞芯微平台的设备欢迎交流踩坑经验。