Android P 如何挂载system镜像到根目录
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镜像。
Android P 如何挂载system镜像到根目录相关推荐
- android 挂载system 读写,android使用mount挂载/system/app为读写权限,删除或替换系统应用...
注意:以下代码中#开头的则为需要执行的shell命令,其他的为打印的结果.#代表需要使用ROOT权限(su)执行,所以想要修改您android手机某个目录挂载为读写,首先需要有ROOT权限! 先要得到 ...
- Android:重新挂载system分区
用命令 adb root adb remount 可以将system分区挂载成rw模式,但是在写入数据时变成了ro模式. 需要用下面的命令来解锁system分区: adb root adb disab ...
- android系统system镜像解包打包制作过程
** android系统system镜像解包打包制作过程 首先确认你的system是哪种类型镜像:yaffs2 ? 还是sparse? 这两种镜像使用的解包工具也不一样,下面以sparse类型镜像描述 ...
- android root 挂载分区,adb — adb disable-verity, adb remount 实现重新挂载system分区为可读写分区...
关键词:adb; disable-verity; adb remount; android 7.1; 如果你的安卓版本是android7.1之前的版本,请参考该文章< 1.android 在版本 ...
- 安卓system镜像分区_如何完全备份android系统上的system分区和data分区
安卓的系统备份在很多场合下可能会用到,下面这个python的脚本,可以用来备份整个的data分区:将所有data分区的文件和目录打包到data.zip,并生成recovery的专用edify脚本到up ...
- 详解使用fastboot为Android刷入原厂镜像
如果你的手机有一个解锁的 bootloader 的话,你可以用 fastboot 命令来刷入原厂镜像.听起来这好像是外行弄不懂的东西,但是当你需要升级被 root 过的设备,修理坏掉的手机,恢复到原生 ...
- android提权system,Android push app to /system/app/
背景 个人想要了解一下关于系统权限方面的知识,而我又天真地以为只要把app push到/system/app/目录下,app就有系统签名了,也就能获取到系统权限了.但是其实这样是不行的...算了,学一 ...
- [IMX6Q][Android5.1]移植笔记 --- 无法挂载system文件系统
platform: imx6q os: Android5.1 branch: l5.1.1_2.1.0-ga 编译好system image之后开机提示如下log,注意红色部分: Freeing un ...
- centos7 nbd 挂在qcow2或qcow,raw,虚机镜像,virsh,virt,使用qemu-nbd挂载qcow2镜像文件
基本原理 nbd(网络块设备: Network Block Device),利用qemu-nbd将qemu虚拟机镜像挂载到Linux上. 展开来讲,nbd可以将一个远程主机的磁盘空间,当作一个块设备来 ...
最新文章
- 纪念数学家、系统与控制学家关肇直院士《泛函分析》
- 解决Docker容器内访问宿主机MySQL数据库服务器的问题
- 8.腾讯微博Android客户端开发——自动获取验证码(2)
- tp5 if 如果有html判断,tp5条件判断,in,notin,between,if等
- js_jQuery【下拉菜单联动dom操作】
- 图论--一般带花树匹配
- 如何在开源社区贡献代码_如何在15分钟内从浏览器获得您的第一个开源贡献
- 决策树编程python_Python如何制定决策:编程中的控制流简介
- android 拖动缩放窗口大小,Android小应用----图片的拖动、缩放
- 【每日算法Day 74】经典面试题:约瑟夫环,我敢打赌你一定不会最后一种方法!...
- php超链接怎么写,怎么给一个PHP密码访问页面加超链接
- 智慧食堂项目策划书(商业计划书/立项计划)
- app架构师实践指南pdf,分享一些行业经验,看完这一篇你就懂了
- python量化策略—— alpha 三因子策略(1)
- 41岁职场中年人深度劝告:一定要从小公司往大公司走
- matlab C++ 实现对手机拍摄的机读卡结果识别
- mysql prefix_mysql改变innodb_large_prefix
- 下C语言做的五子棋,20年没输过
- unity绘制管道_在Unity里写一个纯手动的渲染管线(一)
- JOHNSON计数器,环形计数器,普通计数器
热门文章
- 计算机单片机实训报告,计算器单片机实训报告.doc
- Windows下的gotoxy 函数
- 学生信息管理系统之用户登录:用户登录流程
- PHP招聘:如何面试应届生求职者
- 编程之美 笔记之——24点游戏
- oracle数据库运维一般做什么,数据库运维都做些什么呢?
- 蓝牙技术基础知识总结笔记1 - 蓝牙版本及 4.0 和 BLE 的关系等
- SQL面试题 (一)
- 深度学习(4):NCHW和NHWC
- uvalive 6528(DAG,递推,想法/bitset, 好题)