我在 《Android 动态分区详解(二) 核心模块和相关工具介绍》 介绍lpmake 工具,这款工具用于将多个分区镜像打包生成一个 Android 专用的动态分区镜像,一般称为 super.img。Android 编译时,系统自动调用 lpmake 并传入相关参数生成 super.img,不需要我们手动操作。但难免还是有朋友想深入研究super.img,希望自己手动生成 super.img。所以这里专门开一篇详解介绍下 lpmake 工具

本文基于 android-13.0.0_r41 编译生成的 lpmake 介绍该工具使用,但也适用于 Android 10(Q) 开始的其它 Android 版本

《Android OTA 相关工具》系列,目前已有文章列表

本文为洛奇看世界(guyongqiangx)原创,转载请注明出处。

文章链接https://blog.csdn.net/guyongqiangx/article/details/132581720

1. lpmake编译

lpmake 工具从 Android Q 版代码开始引入源码位于 system/extras/partition_tools 目录下,默认编译 Android输出out/host/linux-x86/bin/lpmake ,第一次编译以后,通过 source 和 lunch 操作设置 Android 编译环境后就可以引用

例如:

$ source build/envsetup.sh 
$ lunch aosp_panther-userdebug
$ which lpmake
/local/public/users/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpmake
$ lpmake -h
lpmake: option requires an argument -- 'h'
Must specify --device OR --device-size.

当然,也可以out/host/linux-x86/bin 添加当前目录使用

$ echo $PATH
/home/rocky/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ export PATH=${PWD}/out/host/linux-x86/bin:$PATH
$ echo $PATH
/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin:/home/rocky/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ which lpmake
/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpmake
$ lpmake -h
lpmake: option requires an argument -- 'h'
Must specify --device OR --device-size.

两种方式都差不多,不过个人推荐前者。

2. lpmake 的帮助信息

关于一个工具,最好的文档就是自己的帮助手册,我这里顺手将 lpmake 的 help 命令输出贴在这里。

android-13.0.0_r41$ lpmake help
lpmake - command-line tool for creating Android Logical Partition images.

Usage:
  lpmake [options]

Required options:
  -d,--device-size=[SIZE|auto]  Size of the block device for logical partitions.
                                Can be set to auto to automatically calculate the
                                minimum size, the sum of partition sizes plus
                                metadata-size times the number of partitions.
  -m,--metadata-size=SIZE       Maximum size to reserve for partition metadata.
  -s,--metadata-slots=COUNT     Number of slots to store metadata copies.
  -p,--partition=DATA           Add a partition given the data, see below.
  -o,--output=FILE              Output file.

Optional:
  -b,--block-size=SIZE          Physical block size, defaults to 4096.
  -a,--alignment=N              Optimal partition alignment in bytes.
  -O,--alignment-offset=N       Alignment offset in bytes to device parent.
  -S,--sparse                   Output a sparse image for fastboot.
  -i,--image=PARTITION=FILE     If building a sparse image for fastboot, include
                                the given file (or sparse file) as initial data for
                                the named partition.
  -g,--group=GROUP:SIZE         Define a named partition group with the given
                                maximum size.
  -D,--device=DATA              Add a block device that the super partition
                                spans over. If specified, then -d/--device-size
                                and alignments must not be specified. The format
                                for DATA is listed below.
  -n,--super-name=NAME          Specify the name of the block device that will
                                house the super partition.
  -x,--auto-slot-suffixing      Mark the block device and partition names needing
                                slot suffixes before being used.
  -F,--force-full-image         Force a full image to be written even if no
                                partition images were specified. Normally, this
                                would produce a minimal super_empty.img which
                                cannot be flashed; force-full-image will produce
                                a flashable image.
  --virtual-ab                  Add the VIRTUAL_AB_DEVICE flag to the metadata
                                header. Note that the resulting super.img will
                                require a liblp capable of parsing a v1.2 header.

Partition data format:
  <name>:<attributes>:<size>[:group]
  Attrs must be 'none' or 'readonly'.

Device data format:
  <partition_name>:<size>[:<alignment>:<alignment_offset>]
  The partition name is the basename of the /dev/block/by-name/ path of the
  block device. The size is the device size in bytes. The alignment and
  alignment offset parameters are the same as -a/--alignment and 
  -O/--alignment-offset.

虽然上面的 help 信息包含了所有的选项说明,但我相信读到这里的小伙伴只有少部分真正去阅读了工具选项说明。主要有几点:

  1. 说明英文的,一看英文就反感。没说你,我自己就是这样。
  2. 选项很枯燥,看了也不知道怎么用
  3. 喜欢手把手的那种详细说明文档

但我还是十分建议你花 5 分钟去仔细阅读一下工具所有选项以及相应的说明,主要理由有以下几点:

  1. 不喜欢看英文的文档,那是因为你看得太少了,需要多看
  2. 选项很枯燥,看了也不知道怎么用,还是因为看得太少了
  3. 不要寄希望与别人的手把手文档,有当然好,没有就上帮助文档,这才是必由之路。

说到底,自带的帮助文档是第一手的资料阅读第一手的资料,有助于你提高自己学习能力。

3. lpmake 的用法

除了帮助文档,看看 Android 里具体如何使用 lpmake 工具,对学习理解也有很大帮助。实在理解不了帮助文档,那照着别人的用法依葫芦画瓢总比较容易一点。

3.1 示例 1

这里说说 Android 编译中对 lpmake 的调用

Android 编译时,build_super_image.py 脚本准备命令调用 lpmake 生成 super.img,直接在 Android 编译的 log搜索 lpmake 就可以看到详细的命令

这里以 Android 13 中编译参考设备 panther 为例,看看 build_super_image.py如何调用 lpmake 的:

$ source build/envsetup.sh 
$ lunch aosp_panther-userdebug
$ make dist -j80 2>&amp;1 | tee make-dist.log
$ grep -ni lpmake make-dist.log
56:2023-08-30 02:26:10 - common.py - INFO    :   Running: "/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpmake --metadata-size 65536 --super-name super --metadata-slots 3 --virtual-ab --device super:8531214336 --group google_dynamic_partitions_a:8527020032 --group google_dynamic_partitions_b:8527020032 --partition system_a:readonly:886816768:google_dynamic_partitions_a --image system_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/system.img --partition system_b:readonly:27312128:google_dynamic_partitions_b --image system_b=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/system_other.img --partition system_dlkm_a:readonly:348160:google_dynamic_partitions_a --image system_dlkm_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/system_dlkm.img --partition system_dlkm_b:readonly:0:google_dynamic_partitions_b --partition system_ext_a:readonly:301395968:google_dynamic_partitions_a --image system_ext_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/system_ext.img --partition system_ext_b:readonly:0:google_dynamic_partitions_b --partition product_a:readonly:368046080:google_dynamic_partitions_a --image product_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/product.img --partition product_b:readonly:0:google_dynamic_partitions_b --partition vendor_a:readonly:621752320:google_dynamic_partitions_a --image vendor_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/vendor.img --partition vendor_b:readonly:0:google_dynamic_partitions_b --partition vendor_dlkm_a:readonly:43040768:google_dynamic_partitions_a --image vendor_dlkm_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/vendor_dlkm.img --partition vendor_dlkm_b:readonly:0:google_dynamic_partitions_b --sparse --output out/target/product/panther/obj/PACKAGING/super.img_intermediates/super.img"

这里因为分区很多,所以 lpmake 的命令参数非常长,手动对这个 lpmake 命令整理下会清楚很多:

/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpmake 
	--metadata-size 65536 
	--super-name super 
	--metadata-slots 3 
	--virtual-ab 
	--device super:8531214336 
	--group google_dynamic_partitions_a:8527020032 
	--group google_dynamic_partitions_b:8527020032 
	--partition system_a:readonly:886816768:google_dynamic_partitions_a 
	--image system_a=out/target/product/panther/system.img 
	--partition system_b:readonly:27312128:google_dynamic_partitions_b 
	--image system_b=out/target/product/panther/system_other.img 
	--partition system_dlkm_a:readonly:348160:google_dynamic_partitions_a 
	--image system_dlkm_a=out/target/product/panther/system_dlkm.img 
	--partition system_dlkm_b:readonly:0:google_dynamic_partitions_b 
	--partition system_ext_a:readonly:301395968:google_dynamic_partitions_a 
	--image system_ext_a=out/target/product/panther/system_ext.img 
	--partition system_ext_b:readonly:0:google_dynamic_partitions_b 
	--partition product_a:readonly:368046080:google_dynamic_partitions_a 
	--image product_a=out/target/product/panther/product.img 
	--partition product_b:readonly:0:google_dynamic_partitions_b 
	--partition vendor_a:readonly:621752320:google_dynamic_partitions_a 
	--image vendor_a=out/target/product/panther/vendor.img 
	--partition vendor_b:readonly:0:google_dynamic_partitions_b 
	--partition vendor_dlkm_a:readonly:43040768:google_dynamic_partitions_a 
	--image vendor_dlkm_a=out/target/product/panther/vendor_dlkm.img 
	--partition vendor_dlkm_b:readonly:0:google_dynamic_partitions_b 
	--sparse 
	--output out/target/product/panther/super.img

这里我把 --image路径进行了简化,将类似下面这样的完整路径:

out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/system.img

使用另外一个比较简短的路径替代:

out/target/product/panther/system.img

上面这个 lpmake 命令的参数重点:

根据前面提示,以下参数是必须的:

--device-size=[SIZE|auto]
--metadata-size=SIZE
--metadata-slots=COUNT
--partition=DATA
--output=FILE

主要就是用于生成 super 头部的 metadata,缺少任何一个都会影响 metadata 数据的生成,所以是必须的。

上面的命令中,Android 参考设备 panther 上面的分区比较多,分区信息通过 --partition 指定,具体包含镜像通过 --image 指定。

至于 --group 以及 --image 参数都不是必须的。理论上你可以不用再 super 上创建分组,在制作 super 时也可以不用传入具体分区的镜像数据,这样生成的 super 就是一个只有 metadata 描述数据,而没有任何分区镜像数据的空的 super.img,相当于 Android 编译生成的 super_empty.img

3.2 示例 2

另外,文章《Android 动态分区详解(二) 核心模块和相关工具介绍》 中也介绍过 lpmake 工具的另外一个例子,可以参考上面的参数执行分析这个命令:

lpmake --metadata-size 65536 --super-name super --metadata-slots 3 
    --device super:3028287488 
	--group bcm_ref_a:1509949440 --group bcm_ref_b:1509949440 
	--partition system_a:readonly:1077702656:bcm_ref_a 
	--image system_a=out/target/product/inuvik/system.img 
	--partition system_b:readonly:0:bcm_ref_b 
	--partition vendor_a:readonly:104992768:bcm_ref_a 
	--image vendor_a=out/target/product/inuvik/vendor.img 
	--partition vendor_b:readonly:0:bcm_ref_b 
	--sparse --output out/target/product/inuvik/super.img

3.3 示例 3

这里再提供一个 Android 文档中介绍 lpmake 时使用的例子:

lpmake --device-size 10240000000 
       --metadata-size 65536     
       --metadata-slots 2        
       -o /tmp/super.img         
       -p "cache:2da85788-f0e1-4fda-9ee7-e5177eab184b:none:67108864" 
       -i "cache=out/target/hikey960/cache.img"

这个例子中,创建了一个 10GB 的 super 动态分区,里面包含了一个 64M 大小的 “cache” 分区。

现在,你可以手动自己使用 lpmake 来生成 super.img 了吗?

4. 几个思考题

到这里差不多应该结束了,给大家留三个思考题:

问题1system.imgsystem_other.img

仔细观察上面第 3 节生成参考设备 panther 的 super.img 的命令中,system_a 分区和 system_b 分区传入的镜像文件竟然不一样:

/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpmake 
	--metadata-size 65536 
	--super-name super 
	--metadata-slots 3 
	--virtual-ab 
	--device super:8531214336 
	--group google_dynamic_partitions_a:8527020032 
	--group google_dynamic_partitions_b:8527020032 
	--partition system_a:readonly:886816768:google_dynamic_partitions_a 
	--image system_a=out/target/product/panther/system.img 
	--partition system_b:readonly:27312128:google_dynamic_partitions_b 
	--image system_b=out/target/product/panther/system_other.img 
	...
	--sparse 
	--output out/target/product/panther/super.img

其中:

  • system_a 的 image 为: out/target/product/panther/system.img
  • system_b 的 image 为: out/target/product/panther/system_other.img

按照我的理解system_asystem_b 分区,制作镜像时可以提供一样的文件,或者像其他分区一样,system_b 不提供任何文件,仅保留一个空分区记录

为什么这里会传递 system_other.imgsystem_b 分区呢?

镜像文件 system_other.imgsystem.img什么区别

问题 2:按照我上面的方法,研究下 super_empty.img如何生成的?

问题 3为什么我 OTA 讨论群里的这位群友反馈他生成的 super.img 只有几十 K?
在这里插入图片描述
在这里插入图片描述

5. 其它

更多这些关于 Android OTA 升级相关文章内容,请参考《Android OTA 升级系列专栏文章导读》

如果您已经订阅动态分区和虚拟分区付费专栏,请务必加我微信备注订阅账号,拉您进“动态分区 &amp; 虚拟分区专栏 VIP 答疑群”。我会在方便的时候,回答大家关于 A/B 系统动态分区、虚拟分区、各种 OTA 升级签名问题,此群仅限专栏订阅者参与~

除此之外,我有一个 Android OTA 升级讨论群,里面现在有 400+ 朋友,主要讨论手机,车机,电视,机顶盒,平板等各种设备的 OTA 升级话题,如果您从事 OTA 升级工作,欢迎加群一起交流,请在加我微信时注明“Android OTA 讨论组”。此群仅限 Android OTA 开发者参与~

公众号“洛奇看世界”后台回复“wx获取个人微信

原文地址:https://blog.csdn.net/guyongqiangx/article/details/132581720

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_26208.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注