Android P 如何挂载system镜像到根目录

news/2024/11/29 19:59:21/

Android O/P 版本以来,谷歌加入了A/B system的特性,此时ramdisk和system是一起放在同一个system.img镜像中的。而系统起来之后也就不存在system分区了,而是直接把system镜像挂载到/根目录上。那么这个操作是怎么进行的呢?
system.img默认是需要使能dm-verity来挂载的,那么这就涉及到如何使能dm-verity来挂载/根分区。还有一个重要的点,如果我们想要禁用dm-verity功能又要如何操作,这又涉及更深的层次,如果可配置/根分区的挂载方式为dm-verity或者非dm-verity方式。带着这些问题,我们进行逐步的深入研究。

vbmeta

Android P 中有一个vbmeta分区,这是一个主要起检验作用的分区,存放有各个分区的校验数据以及签名和其他信息。主要分三个部分:Vbmeta Header(头部)/Authentication Data(校验数据)/Auxiliary Data(其他附加信息)。我们可以使用android在带的avbtool对vbmeta.img进行解析:

avbtool info_image --image vbmeta.img > vbmeta.img.info

解析出来的结果实例如下:

 Minimum libavb version:   1.0Header Block:             256 bytesAuthentication Block:     576 bytesAuxiliary Block:          3456 bytesAlgorithm:                SHA256_RSA4096Rollback Index:           0Flags:                    0Release String:           'avbtool 1.1.0'Descriptors:Chain Partition descriptor:Partition Name:          systemRollback Index Location: 2Public key (sha1):       cdbb77177f731920bbe0a0f94f84d9038ae0617dChain Partition descriptor:Partition Name:          recoveryRollback Index Location: 1Public key (sha1):       2597c218aae470a130f61162feaae70afd97f011Hash descriptor:Image Size:            35553280 bytesHash Algorithm:        sha256Partition Name:        bootSalt:                  baa1ce5d7db69d1b3943a78b5b142ae4d77b4ed60b9885c8661e845172b29a13Digest:                ec7cb1ad89fed3104a03191434d5487b5b4acc78e6bfeb84d7178af40df7db75Flags:                 0Hashtree descriptor:Version of dm-verity:  1Image Size:            1056714752 bytesTree Offset:           1056714752Tree Size:             8327168 bytesData Block Size:       4096 bytesHash Block Size:       4096 bytesFEC num roots:         2FEC offset:            1065041920FEC size:              8421376 bytesHash Algorithm:        sha1Partition Name:        vendorSalt:                  abbf0829ed7bc08913b83f9a994a37ad2a85b5e9Root Digest:           39a22a035ebff2d339dc682603adedb91da01374Flags:                 0Hash descriptor:Image Size:            176641 bytesHash Algorithm:        sha256Partition Name:        dtboSalt:                  386837807aa5a7d9cbe51e7f768009f4e5fca5190af4b3e856a7c96a96c33e0aDigest:                dabdbe5be19c38a3428efd046182d215f8522ab7cd3804e84f196fe73e9052f7Flags:                 0
  • Vbmeta Header

在Android自带的Library/avb/libavb/avb_vbmeta_image.h中可以找到该结构体的定义:

typedef struct AvbVBMetaImageHeader {...
/* 120: Flags from the AvbVBMetaImageFlags enumeration. This must be* set to zero if the vbmeta image is not a top-level image.*/
uint32_t flags;...
}AVB_ATTR_PACKED AvbVBMetaImageHeader;

这里我们仅仅截取关键的部分 flags,这个成员标志着是否要使能dm-verity或者verification。

 typedef enum {AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED = (1 << 0),AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED = (1 << 1)} AvbVBMetaImageFlags;

这个也就是今天要解说的重点了,刚刚我们提到system image使用dm-verity挂载应该是一个可配置选项,那这个可配置功能就是利用这个flag中的AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED位。如果我们利用adb disable-verity命令操作了设备,设备就会去重写vbmeta分区中对应的该bit位为1,这样在后续的bootloader加载时就会做这个flag的判断,由此确定是否使能dm-verity去挂载system镜像。

  • Authentication Data

校验数据主要包含了hash摘要和签名,这是为了AVB启动准备的,不再本文讨论范围内,不做深入讲解。

  • Auxiliary Data

附加数据在system挂载时是需要讲解的,附加数据包含了三类信息:描述符/公钥/公钥元数据。主要介绍描述符,上面的实例可以看到,在Descriptors:一项的后面有很多内容,描述符包括很多类型的描述符,其中有一个与system挂载有关,那就是cmdline descriptor,当然这个并不在vbmeta.img中有体现,因为vbmeta并不需要挂载,这个描述符只会存在于需要被kernel挂载的分区中。

cmdline

这里需要提到一些背景,我们知道system.img现在已经和ramdisk打包在一起了,那么system.img就不是挂载到/system的地方了,而是需要直接挂载在/根目录上,以往的版本,对于system的挂载都是由init来完成的,我们只需要修改fstab即可完成对system的挂载,但是现在不同了,根目录的挂载必须要由kernel去完成了。因为根目录挂载是先于init的运行的,没有根目录就不会有init。那么如何由kernel去挂载system.img镜像呢?
首先我们解析出来system.img中的vbmeta校验数据:

avbtool info_image --image system.img > system.img.info

解析出来的结果实例如下:

Footer version:           1.0
Image size:               3221225472 bytes
Original image size:      3170316288 bytes
VBMeta offset:            3220549632
VBMeta size:              1856 bytes
--
Minimum libavb version:   1.0 (Sparse)
Header Block:             256 bytes
Authentication Block:     320 bytes
Auxiliary Block:          1280 bytes
Algorithm:                SHA256_RSA2048
Rollback Index:           0
Flags:                    0
Release String:           'avbtool 1.1.0'
Descriptors:Hashtree descriptor:Version of dm-verity:  1Image Size:            3170316288 bytesTree Offset:           3170316288Tree Size:             24969216 bytesData Block Size:       4096 bytesHash Block Size:       4096 bytesFEC num roots:         2FEC offset:            3195285504FEC size:              25264128 bytesHash Algorithm:        sha1Partition Name:        systemSalt:                  1215bb10e3488f3f030d9f412c29dd5f3ca07d5aRoot Digest:           ac8d587b82748d9128e84e8cfd2c004889ba3fd4Flags:                 0Kernel Cmdline descriptor:Flags:                 1Kernel Cmdline:        'dm="1 vroot none ro 1,0 6192024 verity 1 PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) 4096 4096 774003 774003 sha1 ac8d587b82748d9128e84e8cfd2c0
04889ba3fd4 1215bb10e3488f3f030d9f412c29dd5f3ca07d5a 10 $(ANDROID_VERITY_MODE) ignore_zero_blocks use_fec_from_device PARTUUID=$(ANDROID_SYSTEM_PARTUUID) fec_roots 2 fec_blocks 780099 fec_start 780099"root=/dev/dm-0'Kernel Cmdline descriptor:Flags:                 2Kernel Cmdline:        'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'

这里我们终于可以看到前文提到的Kernel Cmdline descriptor,但是很奇怪,这里为什么会有两个描述符呢?
还记得前面说的可配置功能吗?原来如此,这里第一个cmdline描述符,是使能dm-verity要使用的cmdline,而第二个cmdline描述符,则是禁止掉dm-verity要使用的cmdline。bootloader中需要根据我们前面vbmeta分区中的flag值来确定使用哪一个描述符。然后把cmdline添加到最终的cmdline中并写回到dtb(内存中的dtb),然后把dtb在ram中的存放地址传递给kernel去启动。

关键的处理流程也是需要libavb的依赖,在avb_slot_verify.c中:

typedef enum {AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED = (1 << 0),AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED = (1 << 1)
} AvbKernelCmdlineFlags;
 /* Compare the flags for top-level VBMeta struct with flags in* the command-line descriptor so command-line snippets only* intended for a certain mode (dm-verity enabled/disabled)* are skipped if applicable.*/apply_cmdline = true;if (toplevel_vbmeta_flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {if (kernel_cmdline_desc.flags &AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) {apply_cmdline = false;}} else {if (kernel_cmdline_desc.flags &AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) {apply_cmdline = false;}}

上面是轮询描述符的操作,其中的toplevel_vbmeta_flags就是vbmeta.img中header保存的flags,如果其中AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED被设置为1,那么代表了dm-verity是禁止的,那么会选择cmdline descriptor中的flags为2的作为cmdline,反之选择cmdline descriptor中的flags为1的作为cmdline。

由此我们就通过传入不同的cmdline的方式来启动kernel,进而挂载根目录,也就是system.img镜像。


http://www.ppmy.cn/news/382813.html

相关文章

[转载型] Neutron 系列 (17): Neutron 分布式虚拟路由【上】

http://www.aboutyun.com/forum.php?modviewthread&tid16860&highlightneutron%2B%2B%CF%B5%C1%D0 1.路由的相关知识有哪些&#xff1f; 2.Neutron 的传统和 DVR Router是什么&#xff1f; 3.DVR的功能有哪些&#xff1f; Neutron 作为 OpenStack 一个基础性关键服务&…

[连载型] Neutron 系列 (17): Neutron 分布式虚拟路由【上】

问题导读&#xff1a; 1.路由的相关知识有哪些&#xff1f; 2.Neutron 的传统和 DVR Router是什么&#xff1f; 3.DVR的功能有哪些&#xff1f; Neutron 作为 OpenStack 一个基础性关键服务&#xff0c;高可用性&#xff08;HA&#xff09;和扩展性是它的基本需求之一。对 neut…

DVR

eutron 系列 (17): Neutron 分布式虚拟路由【上】 [复制链接] 电梯直达 楼主 发表于 2016-1-4 14:56:36 | 只看该作者 |只看大图 大数据系列零基础由入门到实战视频大优惠 本帖最后由 eying 于 2016-1-13 16:59 编辑 问题导读&#xff1a; 1.路由的相关知识有哪些&#x…

Neutron 分布式虚拟路由(Neutron Distributed Virtual Routing)

本系列会分析OpenStack 的高可用性&#xff08;HA&#xff09;概念和解决方案&#xff1a; &#xff08;1&#xff09;OpenStack 高可用方案概述 &#xff08;2&#xff09;Neutron L3 Agent HA - VRRP &#xff08;虚拟路由冗余协议&#xff09; &#xff08;3&#xff09;…

错误 解决“Unknown class in Interface Builder file”

1. 在任意一个源文件中使用一下这个class&#xff0c;比如NSLog(”%”, classA); 2. 在project的Info里面的Link Flag处&#xff0c;增加-all_load 转载于:https://www.cnblogs.com/bandy/archive/2012/04/20/2459326.html

华云数据携首款通用型云操作系统安超OS™正式发布

当前数字化和智能化正在不断改变企业的发展方式&#xff0c;云计算已成为企业数字化转型的必然选择&#xff0c;而系统云化是个复杂的系统工程&#xff0c;涉及到繁多场景需求&#xff0c;务必需要构建一个软硬件资源统一管理、调度实现数据中心资源整合、智能调性、业务优化的…

VC++编译错误信息

VC编译错误信息总结 0、 error C2180: controlling expression has type void 定义方式不应该为void类型&#xff1b; 1、fatal error C1010: unexpected end of file while looking for precompiled header directive。 寻找预编译头文件路径时遇到了不该遇到的文件尾。(一般…

118、杨辉三角

杨辉三角 题目描述 给定一个非负整数 numRows&#xff0c;生成杨辉三角的前 numRows 行。 在杨辉三角中&#xff0c;每个数是它左上方和右上方的数的和。 示例: 输入: 5 输出: [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ] 思路分析 建立两个数组分别为上一个数组跟…