安卓动态分区super.img解包打包全指南:从payload到lpmake
2026/8/27 16:21:18 网站建设 项目流程

简介:在Android系统定制与刷机领域,分区结构决定了第三方ROM的玩法。早期基于system.new.dat.br的包处理方式,随着Android 10引入动态分区机制而逐渐失效——system、vendor等分区被整合进super超级分区,配合metadata实现弹性分配。要定制现代安卓设备,就必须理解super.img的容器结构与payload.bin的封装逻辑。通过lpdump读取分区表、lpunpack解包镜像、修改后再用lpmake重新打包,配合fastboot刷入,就能实现系统精简、功能集成等深度定制。这套流程不仅适用于ROM开发者,普通用户也能借此打造专属系统。本文从动态分区原理出发,逐步演示super格式的完整处理流程,并解析常见问题与规避技巧,帮助你在新工具链下顺利完成第三方ROM的解包与打包。 如果你在2022年还抱着system.new.dat.br时代的老一套工具去做第三方ROM,大概率会撞上一堵新墙:新机型的刷机包里根本没有system.new.dat.br,取而代之的是一个叫super.img的大家伙,偶尔还会有人提到payload.bin。这段时间时不时有朋友来问“rom解包打包工具在哪下”“为什么我的 sdat2img 跑不动”,其实核心问题就一个:安卓动态分区普及之后,第三方ROM的工具链必须整体换一代了。

这篇文章就围绕“支持super格式解包打包”这条主线展开,从super格式的原理讲到实际动手解包、修改、重新打包、签名刷入的完整流程,再把我踩过的几个高频坑和排查思路一并放出来。适合三类人看:想给自用设备精简系统、想移植或集成功能、或者单纯想搞明白super.img到底是个什么结构的人。有一点先说明,刷机有风险,操作前把数据备份好,设备是自己的,责任也是自己的。

1. 从 system.new.dat.br 到 super:第三方ROM工具链为什么必须换一代

1.1 dat.br 时代的核心套路

在动态分区普及前,第三方ROM的做法相对简单粗暴。官方包或者第三方包里通常会带一个system.new.dat.br,这是用 brotli 压缩过的system.new.dat,而system.new.dat内部记录的是 system 分区的文件系统镜像数据,配合system.transfer.list这个转换清单,可以还原出完整的system.img

当时的经典命令套路长这样:

# 把 brotli 压缩的 dat.br 解成 dat brotli -d system.new.dat.br -o system.new.dat # 然后用 sdat2img 配合 transfer.list 还原 ext4 镜像 sdat2img system.transfer.list system.new.dat system.img # 修改完 system.img 之后,再用 img2sdat 打包回 dat # 需要先建好一个目录,把 system.img 解开放进去,改完再重新生成 python img2sdat.py output_dir -o new_system

这套流程在 Android 5 到 Android 9 之间非常成熟,网上能找到一堆system.new.dat.br解包打包工具,基本就是把 sdat2img、img2sdat、brotli 这些工具打包一下。老玩家玩得熟练的,闭着眼都能把system.img挂在 Ubuntu 下改 build.prop、删内置应用、塞应用进去再重新打包。

但到了 Android 10 之后的机型,这套东西基本就废了。

1.2 动态分区时代:super 变成了一个“分区容器”

Google 从 Android 10 开始强推动态分区(Dynamic Partitions),核心变化是:system、vendor、product、odm 这些原本各自占一块独立物理分区的镜像,现在全部被塞进了一个统一的超级分区super里。

可以这么理解:以前一台设备的分区布局像几个固定尺寸的抽屉,每个抽屉对应 system、vendor、product,出厂多大就是多大。动态分区之后,这些抽屉合并成一个大柜子,柜子内部再按照一份“清单”划出虚拟抽屉。这个清单就是 super 分区里的 metadata。系统启动时,内核和 init 进程根据 metadata 把虚拟分区映射出来,供后续挂载使用。

这样设计最大的好处是分区大小可以弹性调整。同一个硬件平台,低配版可能只需要较小的 system,高配版可以给 system 分配更多空间,不再受出厂物理分区表限制。OTA 升级时也只需要更新变化的部分,不用整个分区重刷。

对做第三方ROM的人来说,这意味着我们处理的对象从“独立分区镜像”变成了“一个大容器里的若干逻辑分区”。工具如果不能理解 super 分区内部的 metadata 结构,就完全无从下手。

1.3 旧工具失效的直接原因

为什么 sdat2img 那套在 super 上跑不动?因为现在的新机型根本没有system.new.dat.br,官方 OTA 包或者卡刷包里通常是一个payload.bin,线刷包则直接给一个super.img

payload.bin是OTA差分/全量镜像的封装格式,里面按顺序记录了 boot、system、vendor、product、super 等分区的数据,需要专门解析;而super.img也不是简单的 ext4 镜像,它的布局是:super 头部 + 一段protobuf序列化的metadata + 各逻辑分区的镜像数据块。旧工具不认识 protobuf metadata,直接把 super 当成 ext4 去解析,结果就是读出满屏乱码或者直接报错。

所以,2022年做第三方ROM,核心技能就变成了三件事:能从payload.bin里提取出super.img、能解析和修改 super 内的系统分区、能重新生成一份符合要求的super.img并让设备正常启动。

2. super 格式到底怎么拆:从 payload 到 metadata 再到可修改的镜像文件

2.1 先认清手上是哪种包

动手之前,先把手上的刷机包分个类,这决定了你接下来用哪套命令。我整理了一张表,基本覆盖常见情况:

包类型特征直接处理方式
OTA卡刷包里面有 payload.bin用 payload-dumper-go 提取 super.img 和 boot.img
线刷出厂包里面有 super.img 或多个分区img直接用 lpunpack 解 super
拆机备份/救砖包单个 super.img直接用 lpunpack 解
老机型包只有 system.new.dat.br走 sdat2img 老流程

判断方法很简单,下载完包先解压看一眼。没有system.new.dat.br,只有payload.binsuper.img,就进新工具链。

payload.bin的提取,我推荐用payload-dumper-go,速度快,跨平台,一条命令就能把 payload 里所有分区镜像全部导出来:

payload-dumper-go -o /path/to/output /path/to/payload.bin

跑完你会得到 boot.img、super.img、vbmeta.img 等一系列文件。如果只需要 super,也可以只提取它。

2.2 lpdump:先读 super 的“目录”

拿到 super.img 之后,第一件事不是急着解包,而是先读 metadata。这里要用到 lpdump 工具。命令很简单:

lpdump -s super.img

-s参数表示指定 super 镜像。输出会列出 metadata 版本、super 分区的物理大小、逻辑分区列表(system、vendor、product、odm 等)、每个分区的逻辑大小、分区组(group)信息以及槽位数。

别小看这一步输出的信息量大,后面用 lpmake 重新打包时,所有参数都要照着这里抄。我通常会把 lpdump 的输出存到文本文件里,作为本次修改的基线记录。

2.3 lpunpack:真正把 super 拆开

读取 metadata 之后,用 lpunpack 把各逻辑分区镜像导出来:

lpunpack --slot=0 super.img /tmp/extracted/

--slot=0表示提取当前槽位的数据。现在很多设备是 A/B 分区,super 里同一分区会存在两个槽位的数据,一般提取当前使用的 slot 0 即可。如果你不确定设备当前槽位,可以先用 fastboot 查:

fastboot getvar current-slot

执行完lpunpack之后,/tmp/extracted/下会出现 system.img、vendor.img、product.img、odm.img 等文件。

这里有一个非常容易踩的坑:这些 img 文件可能是稀疏镜像(sparse image),也有可能是 raw 镜像。如果你用file命令查看,出现Android sparse image字样,先转换成 raw ext4 再挂载:

simg2img system.img system_raw.img mkdir /mnt/system sudo mount -o loop system_raw.img /mnt/system

如果是普通的 ext4 镜像,直接挂载即可。现在部分新机型的 system/vendor 用的是 EROFS 只读文件系统,这种镜像在 Linux 下需要带 erofs 内核支持才能挂载,Windows 下处理起来会更麻烦。后面我会专门讲这个坑。

到这里,你就拿到了一份可以随意修改的系统分区镜像,接下来才是做第三方ROM的主菜。

3. 完整实操:把官方包改成你自己想要的第三方ROM

3.1 动手之前,先做好“最小改动”规划

我见过太多人一上来就删这个删那个,结果刷完开不了机,又回头到处问。做第三方ROM和做软件开发一个道理,先建立最小改动意识:每次只从官方包基础上做有限的几项修改,刷一次,确认能开机,再继续下一项。

建议把改动分成三层:

  • 安全层:只替换开机动画、字体、修改 build.prop 显示信息,不改分区结构,一般不会翻车。
  • 常规层:精简预装应用、加入自己的 apk、调整系统默认配置。
  • 高风险层:改动 SELinux 策略、删 vendor 下的驱动组件、修改 framework 层代码。

我自己的习惯是:先做安全层+常规层,验证整套工具链通了,再逐步尝试更深的定制。这样哪怕出了问题,也知道大概改到哪一步出的问题。

3.2 解开 system 分区,做常规定制

在 Linux 下挂载解包出来的 system.img:

sudo mkdir /mnt/system sudo mount -o loop system.img /mnt/system

常见定制操作有以下几种。

精简内置应用:删除/mnt/system/app/mnt/system/priv-app下的对应目录即可。但留意,有些应用带.odex.vdex.apk在同一个目录里,最好整个目录一起删,不要只删 apk 文件。

加入自己的应用:把 apk 复制到/mnt/system/app/应用名/应用名.apk,注意目录结构要正确,否则系统扫描不到。

替换开机动画:覆盖/mnt/system/media/bootanimation.zip。开机动画的压缩包打包格式有讲究,zip 内不能有顶层目录,图片要放在part0part1目录下,desc.txt 里写播放参数,建议用 store 方式存储,避免压缩问题。

修改系统属性:编辑/mnt/system/build.prop,比如调整屏幕密度:

ro.sf.lcd_density=440

改完不要忘记,product分区、odm分区里也可能存在属性文件,不同厂商拆分方式不同,如果改 system 里的没生效,去 product 分区里找找build.prop/product/etc下的相关配置。

这里要特别警告:不要动/mnt/system/etc/selinux下的安全策略文件。第三方ROM里最隐蔽的翻车点就是 SELinux 拒绝,而日志里报错往往又很笼统,新手根本看不出是策略问题。

3.3 用 lpmake 重新打包 super:所有参数都要有出处

改完各个分区镜像之后,需要把它们重新打包成 super.img。这里用 lpmake,参数必须严格按照 lpdump 查到的情况填。

一个典型的打包命令长这样:

lpmake \ --metadata-size 65536 \ --super-name super \ --metadata-slots 3 \ --device super:6434988032 \ --group main:6434988032 \ --partition system:readonly:2343706624:main \ --partition vendor:readonly:1054994432:main \ --partition product:readonly:1253687296:main \ --partition odm:readonly:234881024:main \ --sparse \ -o super_new.img

逐个解释这几个关键参数:

  • --metadata-size:metadata 区域预留大小,复制 lpdump 里看到的值即可。
  • --super-name super:固定写法,因为设备分区表里就叫 super。
  • --metadata-slots 3:metadata 槽位数量,A/B 设备一般是 2 或 3,同样照抄原值。
  • --device super:6434988032:物理 super 分区的大小,必须和原包一致,不能少于各分区总和,也不能超过设备真实分区大小。
  • --group main:6434988032:分区组名称和容量。系统所有逻辑分区都在 main 组里。
  • --partition system:readonly:2343706624:main:定义逻辑分区。readonly表示只读分区,2343706624是逻辑分区大小,main是所属组名。

大小是最容易出错的地方。如果你把一个分区的大小设得比原包小,lpmake 会因为数据放不下而报错;如果设得稍大,虽然能打包成功,但会导致 super 物理分区空间不足,刷入时同样会翻车。我的建议是:只精简--group main的总容量(如果需要缩小),每个逻辑分区的大小保留 lpdump 里的原值,不要随意更改。

3.4 vbmeta、AVB 验证和刷入

打包完 super.img,接下来要处理验证问题。Android 10 之后,设备普遍强制 AVB(Android Verified Boot)验证,如果刷入的 system 分区签名和 vbmeta 里的签名不一致,设备会直接拒绝启动,甚至进入bootloop。

对于第三方的自打包镜像,最通用的做法是刷入 vbmeta 时禁用验证:

fastboot flash vbmeta vbmeta.img --disable-verity --disable-verification

这动作会在 vbmeta 分区里写入一个标志位,告诉 bootloader 不要校验其他分区。之后刷入自己打包的 super:

fastboot wipe-super super_new.img fastboot flash super super_new.img

注意,fastboot wipe-super会清空整个 super 分区,然后再用fastboot flash super写入新镜像。如果你在旧系统上还保留着数据,这一操作会清掉所有系统逻辑分区内容,所以执行前备份好 data 分区。

如果你想保留 AVB 验证能力,那就要走重签名路线,常见做法是用 avbroot 之类的工具,给新的 system/vendor/boot 镜像全部重新签名,然后更新 vbmeta 里的公钥。这套流程复杂不少,对于普通第三方ROM需求来说,直接禁用验证最简单,代价是设备的安全性会下降,自己权衡。

4. 实测最常翻车的三个环节与完整排查链路

4.1 刷完无限重启?先别急着怀疑工具

“刷完卡在logo进不去系统”“开机动画转几圈又重启”,这是我在第三方ROM相关话题里见到最多的问题,也是当初我自己卡最久的地方。排查不要把锅甩给工具,按下面这个顺序来:

第一步,确认是不是 vbmeta/AVB 引起的。如果卡在 bootloader 阶段,手机连电脑后 fastboot 会显示类似ERROR: vbmeta: Invalid VBMeta header或者提示验证失败,那就是验证没关。重新刷一次带--disable-verification的 vbmeta 即可。

第二步,检查 super 里的分区大小。如果 lpmake 打包时把某个分区写小了,或者写大了导致超出 super 物理容量,系统在挂载阶段就会失败。重建 super,把 lpdump 里的原大小核对一遍。

第三步,看槽位一致。A/B 设备如果当前槽位是 B,而你只刷了 A 槽的 super,设备找不到完整系统就会反复重启。用fastboot getvar current-slot看当前槽位,刷入时注意对应:

fastboot flash super_a super_new.img

第四步,检查系统内部改动。如果前面都通过了,卡在开机动画阶段,多半是改动了关键系统组件,比如误删了 bootanimation 依赖的库,或者改坏了 build.prop 导致 zygote 起不来。回到 3.1 说的最小改动原则,先只做安全层验证,排除修改点。

4.2 精简系统后桌面崩溃、应用报错

这个问题通常不是“删太多”,而是“删错了对象”,我见过甚至有人把整个 priv-app 下的权限应用删掉,后果是桌面、设置全部闪退。

排查链路是这样的:先打开 logcat 看崩溃堆栈,命令是:

adb logcat -b crash

日志里会明确显示哪个包名崩溃、缺少哪个类或者哪个权限。如果是SecurityException,大概率是删掉了持有系统签名的关键应用;如果是ClassNotFoundException,说明你删掉了别的应用依赖的代码库;如果是FileNotFoundException,可能是应用还引用了 system/media 或者 /system/etc 下的资源,但相关文件被你连带删了。

这里给一个我总结的避坑原则:不要只凭“这个应用我用不上”就删。先查它的 AndroidManifest 里有没有systemUserprotectedBroadcast之类的权限声明;可以用 apktool 或者 JADX 看,这一步对排查有奇效。还有一个经验,厂商的priv-app目录里总有那么几个看似无关但其实承担“系统服务”的apk,宁愿留着,也不要图省事全删。

4.3 工具报错 invalid/sparse 解析失败

很多人在解包或者打包时报错,比如sparse image read failedInvalid sparse file formatCannot read metadata,出现在这一步,基本都是镜像格式识别问题。

依次排查这三个点:

第一,解包出来的镜像是不是 sparse 格式。前面说过,用file看,如果显示 sparse,必须先用 simg2img 转成 raw。直接把 sparse 镜像挂载会失败,直接把它传给 lpmake 也会报错。

第二,分区文件系统是不是 EROFS。现在不少新机的 system/vendor 使用 EROFS,这种只读文件系统在高版本 Linux 里的支持参数和 ext4 不同。下载时注意工具的说明,选支持 erofs 的版本。用挂载方式会麻烦一些。更稳的做法是用工具直接编辑分区镜像内的文件,比如erofs-utils里的fsck.erofsdump.erofs等。

第三,metadata 版本不匹配。lpmake 的版本尽量保持和系统官方包时代接近。版本太新打出来的 metadata,老手机可能不认;版本太旧,又不支持新分区布局。我一般会把 lpdump、lpmake 放到同一个工具包目录下,防止下载到的工具版本之间互相打架。

4.4 顺手提一句:源码编译和改包怎么选

经常有人问“lineageos源码编译rom和这种改包有什么区别”。我的理解是:源码编译适合长期维护、想深度定制、给特定机型从头做优化的人;但它的成本很高,需要拉代码、搭编译环境、适配设备树,每次 sync 代码都是几个小时,而且新手上手门槛不低。

改包则适合快速落地:官方包做底,改改精简、加加功能、调调配置,半天到一天就能出一个自用包。它的上限在于不能脱离官方内核和驱动,某些内核层面的行为改不了。如果是自用和轻度分享,改包完全够用了。如果想做长期更新、跟着 Android 大版本走,源码编译是正路。

5. 进阶建议:A/B槽位、自动化脚本与工具链搭建

5.1 A/B槽位下做ROM的注意事项

A/B 分区设备上,super 内会包含两个系统槽位的镜像。用 lpunpack 解包时,默认提取--slot=0的数据。如果你想把定制同时写到两个槽位,需要分别指定:

lpunpack --slot=0 super.img /tmp/slot0/ lpunpack --slot=1 super.img /tmp/slot1/

不过说实话,日常自用刷第三方ROM,我建议只改当前槽位,不要把两个槽位都刷成一样的定制内容,否则一旦新包有问题,给设备保留的原厂回滚路径就没了。A/B 设计其中一个重要价值就是“出现问题可以切换到另一个系统”,别把这个退路断了。

5.2 把重复劳动脚本化

解包打包流程熟练之后,完全可以写成一个脚本,极大降低重复工作和误操作风险。我自己的脚本大概长这样:

#!/bin/bash # 从 payload.bin 提取所需镜像 payload-dumper-go -o images payload.bin # 查看 super 结构 lpdump -s images/super.img > metadata_backup.txt # 解包当前槽位 lpunpack --slot=0 images/super.img extracted/ # 挂载修改部分 sudo mount -o loop extracted/system.img /mnt/system # ... 这里做你的定制操作 ... sudo umount /mnt/system # 重新打包 lpmake \ --metadata-size 65536 \ --super-name super \ --metadata-slots 3 \ --device super:6434988032 \ --group main:6434988032 \ --partition system:readonly:2343706624:main \ --partition vendor:readonly:1054994432:main \ --partition product:readonly:1253687296:main \ --partition odm:readonly:234881024:main \ --sparse \ -o super_new.img # 重新生成 vbmeta(禁用验证) fastboot flash vbmeta images/vbmeta.img --disable-verity --disable-verification fastboot wipe-super super_new.img fastboot flash super super_new.img

把 lpmake 的参数从 lpdump 输出里解析出来填进去,这步也可以做成半自动。脚本跑顺之后,从拿到官方包到刷入自制的第三方ROM,基本十几分钟搞定。

5.3 我个人的经验技巧

最后再分享几个实际经验。

第一,原始包永远留一份。打包过程中的任何一个操作失误,都可能导致最终镜像有问题。有了原始包,就能随时回到起点重新来,不用重新找、重新下载。

第二,每次修改都做记录。改到了哪个分区、删了哪个目录、改了什么属性,写在一个 Markdown 文件里,下次出问题时能快速定位。

第三,小步快跑。别指望一次把所有定制做完直接刷。先只改 system,刷完开机确认没事,再改 vendor,再改其他。尤其是第一次接触这套工具链的时候,这一步省不掉。

第四,检查文件系统一致性。打包前用 e2fsck 检查一下 ext4 镜像是否有损坏,错误太多就重新改一遍。刷一个文件系统损坏的镜像进去,和拿一张坏磁盘装机一个道理,各种诡异问题都会冒出来。

我能说的实操层面基本就是这些了。做第三方ROM这件事,看起来只是解决“系统精简、功能定制”的需求,但走一遍解包、改包、打包、验证的完整过程之后,你对安卓系统分区结构、启动链路、AVB 验证机制这些底层机制的理解,会明显比单纯刷别人做好的包深得多。工具链盯准payload-dumper-go + lpdump + lpunpack + lpmake + fastboot这套组合,足够应对绝大多数 super 格式解包打包的场景。遇到问题不要慌,按上面给的排查链路一步一步来,大多数坑都是能爬出来的。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询