简介这是一份面向Android动态分区与超级镜像场景的lpmake/lpunpack完整源码资源包适合系统镜像定制、分区表生成、镜像解包调试等方向的工程师与进阶学习者。整包文件共1417个压缩后大小约24.23MB其中h、c、cpp、cc等C/C源文件数量明显占优另外还包含JSON/BP/MK构建配置、TXT/MD说明文档和Python/Perl辅助脚本可支撑源码阅读、构建复现与二次开发。内容围绕lpmake制作super镜像、lpunpack解包等核心流程展开覆盖内核配置、根文件系统构建、多场景系统映像集成、镜像验证与排错等知识点同时收录Android.bp、OWNERS、AIDL等关键工程文件以及x86/ARM汇编、加解密与哈希实现可帮助理解代码结构、编译约束、权限模型与镜像生成链路。已有1448人浏览学习适合需要掌握动态分区镜像原理、排查实际打包解包问题或定制私有镜像流程的读者深入参考使用。1. 从 super 镜像到 lpmake动态分区时代的打包工具很多从传统分区转向动态分区的开发者第一次看到 super.img 都会懵它不像 system、vendor 那样可以直接挂载而是一个把多个逻辑分区打包在一起的容器。lpmake 正是用来制作这个超级镜像的工具而配套的 lpunpack 可以把 super 解包还原。我最初做某跨平台系统适配时没有理解这两个工具的几何参数反复翻车。这篇笔记把 lpmake 制作 super 镜像的完整流程、参数含义和踩坑点整理出来适合刚从源码编译动态分区、准备刷写自定义系统的开发者。2. lpmake 与 lpunpack 是什么动态分区布局与工具选型2.1 动态分区与 super 镜像的关系动态分区是在传统固定分区基础上的一次大改动。在传统方案里system、vendor 这些分区直接在闪存上划分物理区域分区表写死之后就不能随意扩张。动态分区把这一层抽象成两个概念一个名为 super 的物理分区以及 super 内部若干逻辑分区。super 物理分区的大小在刷机时固定而内部逻辑分区可以灵活调整只要总和不超过 super 的可用空间。super 镜像的内部布局分为两个部分一部分是 metadata 区域另一部分是各逻辑分区镜像数据。metadata 区域存放分区表、分组信息、校验信息以及每个逻辑分区的起始偏移和大小。刷机时fastboot 把整个 super.img 写进 super 分区引导时内核通过 device-mapper 读取 metadata把逻辑分区动态映射成可用的块设备。metadata 还有一个关键设计叫 slots。为了支持 OTA 回滚动态分区会同时保留两组 metadata也就是 slot A 和 slot B。lpmake 用--metadata-slots指定保留几份 metadata一般取 2 或 3。多出来的那份用于临时或校验实际占用空间是 metadata-size 乘以 slots 数量。镜像里每个逻辑分区的大小不是随便写的必须按 alignment 对齐比如 4096 字节。如果对齐不正确dm 表解析时就会报错直接导致设备无法启动。一个典型的 super 镜像排列是这样的最前面是 slot 0 的 metadata紧接着是 slot 1 的 metadata然后是分配给某个分组group的逻辑分区数据区。每个逻辑分区按 alignment 对齐排列分区表记录的是相对 super 开头的偏移。所以你在做 lpmake 时--device-size必须同时覆盖 metadata 区与所有逻辑分区的总和否则 lpmake 算不过去。2.2 lpmake / lpunpack 在工具链中的位置构建动态分区镜像的工具链里常见的成员有 lpmake、lpunpack、simg2img 和 fastboot。它们分工不同但经常被混为一谈。lpmake 的作用是根据分区描述生成完整的 super.img。你可以把它理解成一个容器打包器输入是单个逻辑分区的镜像文件输出是一个带 metadata 的 super 容器。simg2img 是 sparse image 展开工具负责把稀疏格式的 ext4 镜像转成 raw 镜像。如果你用 lpmake 的输入镜像本身是 sparse 格式lpmake 会自己处理不需要先转成 raw。但为了保险我一般会先统一转成 raw 再打包这样输出的 super.img 体积更可控。lpunpack 是 lpmake 的逆操作。它从 super.img 中按 metadata 提取出各个逻辑分区输出到指定目录。很多开发者用 lpunpack 检查自己打包的镜像是否正确或者从刷机包里提取单个分区做修改。fastboot 负责把 super.img 写到设备上但它不理解 super 的内部结构。真正解析 super 内容的是引导阶段的 device-mapper 或 lpunpack。工具方向适用场景lpmake打包生成 super.imglpunpack解包从 super.img 提取分区simg2img转换把 sparse 转 raw供 lpmake 或挂载使用fastboot刷写把 super.img 写入设备简单总结simg2img 预处理分区镜像lpmake 合成 super.imgfastboot 刷入设备lpunpack 逆向解包验证。选型上如果你的目标是制作刷机包只用 lpmake 就够了如果要调试别人的 super 镜像lpunpack 是必备工具。有些开发者尝试用cat system.img vendor.img super.img直接拼接这种方式没有 metadata引导程序根本不认识完全是白费功夫。2.3 从源码编译这两个工具的步骤这份资源给的是源码包所以第一件事就是编译。我通常不会为了这两个小工具拉一整套完整源码而是把源码放进已有的系统源码树中用现成的构建系统编译。常见做法是source build/envsetup.sh lunch target make lpmake lpunpack -j$(nproc)这段命令初始化编译环境、选择目标设备然后编译两个工具。lunch后面需要填一个具体产品名比如某开发板自带的 target。如果你没有完整源码树也可以尝试单独编译但需要先把liblp、libsparse等头文件路径指对。我自己的经验是用源码树编译最省心因为构建系统会自动处理依赖。注意编出来的工具是 host 端可执行文件。如果需要放进 recovery 或 fastboot 环境要单独交叉编译静态版本避免缺少动态库。编译完成后检查一下./lpmake --version ./lpunpack --help如果第一个命令输出版本号第二个命令打印参数说明说明工具可用。我这里用到的 lpmake 版本支持--metadata-slots和--alignment这两个关键参数个别老版本不支持建议使用较新源码编译。我曾在某次适配中因为工具太老不支持--metadata-slots导致打出来的镜像只有一个 metadata slot设备无法回滚最后换了新版工具才解决。所以拿到源码包后先看下 README 或 Makefile 里的版本说明再决定要不要升级依赖。3. 用 lpmake 制作 super 镜像参数、布局与实操3.1 准备分区镜像与几何参数在制作 super 镜像之前需要先确定几个关键值super 分区在设备上的总大小。每个逻辑分区的实际镜像大小。对齐大小建议 4096部分设备用 2048。metadata 大小一般 65536 字节。准备镜像时我一般先把 ext4 镜像转为 raw因为 lpmake 虽然支持 sparse但 raw 格式更直观。转换命令如下simg2img system.img system_raw.img simg2img vendor.img vendor_raw.img simg2img product.img product_raw.img然后用 stat 取出每个镜像的字节数stat -c %s system_raw.img stat -c %s vendor_raw.img stat -c %s product_raw.img把这三个数字记下来作为 lpmake 的参数。很多翻车都发生在这里有人把分区大小取了十进制块数而 lpmake 预期的是字节数有人忽略对齐参数还有人把 super 分区总大小写小了导致打包失败。我踩过坑之后都会先把这些数值写在一个小本子上再动手。另一个容易忽略的是每个分区镜像末尾可能有稀疏空洞raw 镜像的真实大小以 stat 为准不要看文件占用块数。3.2 命令行参数逐个拆解lpmake 的参数非常多但最常用的就这几个参数含义典型值--metadata-size每组 metadata 的大小65536--metadata-slots保留几组 metadata2 或 3--super-namesuper 设备名super--device-sizesuper 分区总大小设备实际大小--device-block-size设备块大小4096--alignment对齐粒度4096--group创建分组并指定大小main:xxx--partition声明一个逻辑分区name:attrs:size:group--output输出镜像路径super.img一个典型的完整命令如下./lpmake --metadata-size 65536 --super-name super --metadata-slots 3 \ --device-size 511705088 --device-block-size 4096 --alignment 4096 \ --group main:383205376 \ --partition system:readonly:141043200:main \ --partition vendor:readonly:117571584:main \ --partition product:readonly:123731968:main \ --output super.img这段命令的含义是在 511705088 字节的 super 分区上用 64KB metadata、3 个 slots把 system、vendor、product 三个只读分区放入 main 分组。分区分组名不是乱写的引导程序会按表里的 group 名来查找分区如果你在设备树或 fstab 里引用了别的分组名就会找不到分区。--partition的参数格式是名称:属性:大小:分组。属性里readonly表示只读分区read-write表示可写。大小必须是字节数且需要是--alignment的整数倍。上面命令里三分区大小分别是 141043200、117571584、123731968三个加起来 382346752加上 metadata 占用仍然小于 device-size所以能正常生成。如果总和超过 device-sizelpmake 会直接报错并拒绝创建镜像。3.3 生成 super 镜像并验证直接执行上面的命令后当前目录会生成 super.img。用 ls 查看大小ls -l super.img这个大小通常会接近 device-size而不是正好相等因为 lpmake 会按 alignment 预留一些尾料。接下来用 lpunpack 验证mkdir out_super ./lpunpack super.img out_super/解包后out_super 里应该能看到 system.img、vendor.img、product.img。如果你的分区属性里带了 sparse 标志解出来的会是 sparse 镜像需要用 simg2img 转成 raw 再挂载检查。验证挂载mkdir /tmp/system_mnt mount -t ext4 out_super/system.img /tmp/system_mnt能挂载且文件正常说明打包没问题。我还会顺手检查一下解包出的镜像是否和原始镜像 MD5 一致md5sum system_raw.img out_super/system.img如果两个值一致说明打包过程没有数据损坏。这一步是后悔药能在刷机前发现问题而不是等设备变砖后才排查。4. lpunpack 解包与常见问题排查三个高频翻车现场4.1 lpunpack 的基本用法与恢复场景lpunpack 的用法非常直接./lpunpack super.img out_dir/它会把 super.img 中所有逻辑分区解到 out_dir 下命名与打包时的--partition名称一致。这个工具在恢复分区数据、修复刷机包、单独修改某个分区时特别有用。有人说 lpunpack 是“后悔药”因为当你只有设备里的 super 完整备份时可以用它把 system、vendor 等分区还原出来。解包后如果分区属性带有readonly解出的镜像默认是只读挂载的想修改需要重新创建可写镜像。常见做法是用simg2img转 raw 后直接mount -o rw。如果你发现解出的镜像一端有奇怪的填充数据那是为了 alignment 对齐加的填充字节不是损坏。4.2 解包失败现象、原因与解决现象lpunpack 报invalid metadata或could not find partition table。原因最常见的有三种。一是 super.img 文件被截断比如传输中断或磁盘满二是 metadata 版本不匹配lpunpack 太旧不认识新版 metadata三是镜像本身没有有效的 metadata比如用简单的 cat 命令拼接出的假 super 镜像。解决先检查文件大小和 MD5确认 super.img 完整。然后换用与 lpmake 同版本或更新版本的 lpunpack 再试。如果还不行用十六进制工具查看 super.img 开头是否有LP_HEADER之类的魔数没有魔数基本可以判定镜像无效只能重新打包。4.3 刷入后无法启动现象、原因与解决现象设备刷入 super.img 后停留在 bootloader 界面报dm table或cannot find partition错误反复重启。原因分组名不匹配。比如 lpmake 里用了--group main但引导程序或 fstab 引用的是--group system又或者--device-size比实际的 super 分区大刷入后 super 尾部越界再或者--alignment和设备的逻辑块大小不一致导致 dm 表解析失败。解决把你自己的 fstab、设备树中出现的分组名与 lpmake 命令里的--group逐一比对。--device-size要按设备实际的 super 分区大小填写可以通过 bootloader 的partition list查。--alignment建议设置为--device-block-size的倍数常见是 4096。我每次刷机前都会用 lpunpack 回解检查一遍确认分区名和大小都正确再执行刷写。4.4 分区大小不对齐现象、原因与解决现象lpmake 报requested size is not aligned或者size must align to 4096 bytes。原因--partition里给的大小不是--alignment的整数倍。比如对齐设置为 4096而分区大小是 141043201 字节差一个字节都不行。解决把分区大小向上取整到对齐粒度的倍数。用 shell 计算ALIGN4096 SIZE141043201 ALIGNED$(( (SIZE ALIGN - 1) / ALIGN * ALIGN )) echo $ALIGNED这里我一般会用 4096 对齐不会为了省几 KB 空间去用 512 或 2048因为很多设备的 storage 最小读写单位就是 4096。对齐出错时镜像能生成但刷入后 dm 表可能在边界处出错属于典型的“打包时没问题刷上后翻车”案例。5. 进阶把 lpmake 集成进自动化构建脚本5.1 一个通用的构建脚本模板手动敲 lpmake 命令总是容易出错尤其当分区数量多、大小经常变化时。我习惯把整个流程写成一个 bash 脚本自动读取镜像大小并计算对齐值最后调用 lpmake。#!/bin/bash ALIGN4096 DEVICE_SIZE511705088 GROUP_SIZE383205376 calc_align() { local size$1 local align$2 echo $(( (size align - 1) / align * align )) } SYSTEM_SIZE$(calc_align $(stat -c %s system_raw.img) $ALIGN) VENDOR_SIZE$(calc_align $(stat -c %s vendor_raw.img) $ALIGN) PRODUCT_SIZE$(calc_align $(stat -c %s product_raw.img) $ALIGN) ./lpmake \ --metadata-size 65536 \ --super-name super \ --metadata-slots 3 \ --device-size $DEVICE_SIZE \ --device-block-size $ALIGN \ --alignment $ALIGN \ --group main:$GROUP_SIZE \ --partition system:readonly:$SYSTEM_SIZE:main \ --partition vendor:readonly:$VENDOR_SIZE:main \ --partition product:readonly:$PRODUCT_SIZE:main \ --output super.img这个脚本先定义对齐粒度和 super 总大小然后用calc_align函数把每个分区大小自动对齐。这样即使某个镜像更新后大小变化脚本也能生成合法的 super 镜像不需要每次手动改数字。脚本里的GROUP_SIZE要确保大于三个分区大小之和否则 lpmake 会因分区组溢出而失败。5.2 验证镜像完整性的几个技巧生成 super.img 之后我习惯强制走一套验证流程先回解rm -rf out_super mkdir out_super ./lpunpack super.img out_super/然后比对原始镜像和解包镜像的哈希for img in system vendor product; do if md5sum -c (echo 原镜像哈希 out_super/$img.img); then echo $img OK else echo $img FAIL fi done最后再检查一次 super.img 尾部是否有 lpmake 写出的填充数据确认文件大小不超过设备分区ls -l super.img [ $(stat -c %s super.img) -le $DEVICE_SIZE ] echo size ok这套流程我已经实践过很多次。从那以后我每次做 super 镜像都会强制走一遍对齐自检、打包、回解、哈希比对这四步再直接省略刷机里的“赌一把”环节。希望帮到你。本文还有配套的精品资源点击获取