AVB相关image(vbmeta.img/system.img)的生成
AVB相关image(vbmeta.img/system.img)的生成
vbmeta.img/vbmeta_system.img(chain partition)的生成
调用build-vbmetaimage-target生成vbmeta.img
3762 $(INSTALLED_VBMETAIMAGE_TARGET): \
3763 $(AVBTOOL) \
3764 $(INSTALLED_BOOTIMAGE_TARGET) \
3765 $(INSTALLED_VENDOR_BOOTIMAGE_TARGET) \
3766 $(INSTALLED_SYSTEMIMAGE_TARGET) \
3767 $(INSTALLED_VENDORIMAGE_TARGET) \
3768 $(INSTALLED_PRODUCTIMAGE_TARGET) \
3769 $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \
3770 $(INSTALLED_ODMIMAGE_TARGET) \
3771 $(INSTALLED_DTBOIMAGE_TARGET) \
3772 $(INSTALLED_CUSTOMIMAGES_TARGET) \
3773 $(INSTALLED_RECOVERYIMAGE_TARGET) \
3774 $(INSTALLED_VBMETA_SYSTEMIMAGE_TARGET) \
3775 $(INSTALLED_VBMETA_VENDORIMAGE_TARGET) \
3776 $(BOARD_AVB_VBMETA_SYSTEM_KEY_PATH) \
3777 $(BOARD_AVB_VBMETA_VENDOR_KEY_PATH) \
3778 $(BOARD_AVB_KEY_PATH)
3779 $(build-vbmetaimage-target)
3745 define build-vbmetaimage-target
3746 $(call pretty,"Target vbmeta image: $(INSTALLED_VBMETAIMAGE_TARGET)")
3747 $(hide) mkdir -p $(AVB_CHAIN_KEY_DIR)
3748 $(call extract-avb-chain-public-keys, $(AVB_CHAIN_KEY_DIR))
3749 $(hide) $(AVBTOOL) make_vbmeta_image \
3750 $(INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS) \
3751 $(PRIVATE_AVB_VBMETA_SIGNING_ARGS) \
3752 $(BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS) \
3753 --output $@
3754 $(hide) rm -rf $(AVB_CHAIN_KEY_DIR)
3755 endef
3666 # $(1): the directory to extract public keys to
3667 define extract-avb-chain-public-keys
3668 $(if $(BOARD_AVB_BOOT_KEY_PATH),\
3669 $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_BOOT_KEY_PATH) \
3670 --output $(1)/boot.avbpubkey)
3671 $(if $(BOARD_AVB_VENDOR_BOOT_KEY_PATH),\
3672 $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VENDOR_BOOT_KEY_PATH) \
3673 --output $(1)/vendor_boot.avbpubkey)
3674 $(if $(BOARD_AVB_SYSTEM_KEY_PATH),\
3675 $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_SYSTEM_KEY_PATH) \
3676 --output $(1)/system.avbpubkey)
3677 $(if $(BOARD_AVB_VENDOR_KEY_PATH),\
3678 $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VENDOR_KEY_PATH) \
3679 --output $(1)/vendor.avbpubkey)
3680 $(if $(BOARD_AVB_PRODUCT_KEY_PATH),\
3681 $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_PRODUCT_KEY_PATH) \
3682 --output $(1)/product.avbpubkey)
3683 $(if $(BOARD_AVB_SYSTEM_EXT_KEY_PATH),\
3684 $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_SYSTEM_EXT_KEY_PATH) \
3685 --output $(1)/system_ext.avbpubkey)
3686 $(if $(BOARD_AVB_ODM_KEY_PATH),\
3687 $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_ODM_KEY_PATH) \
3688 --output $(1)/odm.avbpubkey)
3689 $(if $(BOARD_AVB_DTBO_KEY_PATH),\
3690 $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_DTBO_KEY_PATH) \
3691 --output $(1)/dtbo.avbpubkey)
3692 $(if $(BOARD_AVB_RECOVERY_KEY_PATH),\
3693 $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_RECOVERY_KEY_PATH) \
3694 --output $(1)/recovery.avbpubkey)
3695 $(if $(BOARD_AVB_VBMETA_SYSTEM_KEY_PATH),\
3696 $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VBMETA_SYSTEM_KEY_PATH) \
3697 --output $(1)/vbmeta_system.avbpubkey)
3698 $(if $(BOARD_AVB_VBMETA_VENDOR_KEY_PATH),\
3699 $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VBMETA_VENDOR_KEY_PATH) \
3700 --output $(1)/vbmeta_vendor.avbpubkey)
3701 $(if $(BOARD_CUSTOMIMAGES_PARTITION_LIST),\
3702 $(hide) $(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
3703 $(AVBTOOL) extract_public_key --key $(BOARD_AVB_$(call to-upper,$(partition))_KEY_PATH) \
3704 --output $(1)/$(partition).avbpubkey;))
3705 endef
调用build-chained-vbmeta-image生成vbmeta_system.img
3725 ifdef BUILDING_SYSTEM_IMAGE
3726 ifdef BOARD_AVB_VBMETA_SYSTEM
3727 INSTALLED_VBMETA_SYSTEMIMAGE_TARGET := $(PRODUCT_OUT)/vbmeta_system.img
3728 $(INSTALLED_VBMETA_SYSTEMIMAGE_TARGET): \
3729 $(AVBTOOL) \
3730 $(call images-for-partitions,$(BOARD_AVB_VBMETA_SYSTEM)) \
3731 $(BOARD_AVB_VBMETA_SYSTEM_KEY_PATH)
3732 $(call build-chained-vbmeta-image,vbmeta_system)
3733 endif
3734 endif # BUILDING_SYSTEM_IMAGE
在enable了AVB的情况下system.img生成flow(system.img里将包含AVB hashtree)
(调用BuildImage之前的flow是怎样的参考blog:android related image generation - aspirs - 博客园 (cnblogs.com))
build/make/tools/releasetools/build_image.py
def BuildImage(in_dir, prop_dict, out_file, target_out=None): 410 verity_image_builder = verity_utils.CreateVerityImageBuilder(prop_dict) 412 if (prop_dict.get("use_dynamic_partition_size") == "true" and 413 "partition_size" not in prop_dict): 414 # If partition_size is not defined, use output of `du' + reserved_size. 415 size = GetDiskUsage(in_dir) 419 reserved_size = int(prop_dict.get("partition_reserved_size", BYTES_IN_MB * 16)) 423 size += reserved_size 434 BuildImageMkfs(in_dir, prop_dict, out_file, target_out, fs_config) 498 if verity_image_builder: 499 verity_image_builder.Build(out_file)
调用BuildImage来生成system.img,主要有4点:
1.调用CreateVerityImageBuilder生成verity_image_builder
2.对于system.img,因为在Android 10上开始使用super partition,所以use_dynamic_partition_size是true,同时在system_image_info.txt里没有指定system partition size,所以上述条件是成立的。如果system_image_info.txt里没有指定partition size,那生成的system.img(ext4)文件系统多大怎么设定的,这个是根据in_dir( $PRODUCT_OUT/system)目录的size加上system_image_info.txt里的system_reserved_size(在ImagePropFromGlobalDict被转成partition_reserved_size)来确定的
3.调用BuildImageMkfs生成指定文件系统格式(ext4)的system.img
4.调用verity_image_builder.Build(out_file) 构建system.img的hashtree、vbmeta、avb footer并依次将它们append到system.img
CreateVerityImageBuilder生成verity_image_builder
system_image_info.txt里没有指定verity和verity_block_device property,所以不是verified boot 1.0,而是verified boot 2.0
system_image_info.txt里指定了avb_hashtree_enable等于true,没有指定avb_hash_enable
143 def CreateVerityImageBuilder(prop_dict): 159 # Verified Boot 1.0 160 verity_supported = prop_dict.get("verity") == "true" 161 is_verity_partition = "verity_block_device" in prop_dict 162 if verity_supported and is_verity_partition: 176 # Verified Boot 2.0 177 if (prop_dict.get("avb_hash_enable") == "true" or 178 prop_dict.get("avb_hashtree_enable") == "true"): 195 # Image uses hashtree footer. 196 return VerifiedBootVersion2VerityImageBuilder( 197 prop_dict["partition_name"], 198 partition_size, 199 VerifiedBootVersion2VerityImageBuilder.AVB_HASHTREE_FOOTER, 200 prop_dict["avb_avbtool"], 201 key_path, 202 algorithm, 203 prop_dict.get("avb_salt"), 204 prop_dict["avb_add_hashtree_footer_args"])
verity_image_builder.Build(out_file) 构建system.img的hashtree、vbmeta、avb footer并依次将它们append到system.img
/build/make/tools/releasetools/verity_utils.py
调用avbtool add_hashtree_footer
这里self.partition_name为"system",self.partition_size前面也设置过了,self.key_path、self.algorithm均为空(system_image_info.txt里没有指定)
483 def Build(self, out_file): 484 """Adds dm-verity hashtree and AVB metadata to an image. 485 486 Args: 487 out_file: Path to image to modify. 488 """ 489 add_footer = ("add_hash_footer" if self.footer_type == self.AVB_HASH_FOOTER 490 else "add_hashtree_footer") 491 cmd = [self.avbtool, add_footer, 492 "--partition_size", str(self.partition_size), 493 "--partition_name", self.partition_name, 494 "--image", out_file] 495 if self.key_path and self.algorithm: 496 cmd.extend(["--key", self.key_path, "--algorithm", self.algorithm]) 497 if self.salt: 498 cmd.extend(["--salt", self.salt]) 499 cmd.extend(shlex.split(self.signing_args)) 500 501 proc = common.Run(cmd)
上面avbtool add_hashtree_footer会调用到如下方法:
def add_hashtree_footer(self, args): member in AvbTool
这个方法会调用到:
def add_hashtree_footer(self, image_filename, partition_size, partition_name, member in Avb
external/avb/avbtool.py
3352 def add_hashtree_footer(self, image_filename, partition_size, partition_name, 3353 generate_fec, fec_num_roots, hash_algorithm, 3354 block_size, salt, chain_partitions, algorithm_name, 3355 key_path, 3356 public_key_metadata_path, rollback_index, flags, 3357 props, props_from_file, kernel_cmdlines, 3358 setup_rootfs_from_kernel, 3359 setup_as_rootfs_from_kernel, 3360 include_descriptors_from_image, 3361 calc_max_image_size, signing_helper, 3362 signing_helper_with_files, 3363 release_string, append_to_release_string, 3364 output_vbmeta_image, do_not_append_vbmeta_image, 3365 print_required_libavb_version, 3366 use_persistent_root_digest, do_not_use_ab, 3367 no_hashtree):
add_hashtree_footer方法做了如下事情:
1.根据image size以及block size计算hash_level_offsets、tree_size,前者表示hash tree是有几层(level),tree size是hash tree的size(各层hash值block的size之和)
2.对image data以block size为单位计算hash值,并将hash值保存到hash tree中,即先以block size为单位计算image data的hash值,这些hash值构成hash tree的最低一层(第0层),之后根据这一层的hash值数据进行第1层hash值的计算,类似这样一层一层计算,直到某一层的hash值所占用的空间等于(有padding,会对齐到block size,所以只会是等于)block size时hash tree构建完成,此时对这等于block size的hash数据进行hash值计算,计算出的结果做为root digest返回,同时也会返回这里构建的hash tree
3.将2中计算出来的hash tree append到image
4.创建hashtree descriptor,然后设置它,如下,ht_desc.root_digest即是2中计算出来的root digest。之后将根据此hashtree descriptor创建vbmeta_blob,之后将创建的vbmeta_blob append到image
3532 ht_desc = AvbHashtreeDescriptor() 3533 ht_desc.dm_verity_version = 1 3534 ht_desc.image_size = image.image_size 3535 ht_desc.tree_offset = tree_offset 3536 ht_desc.tree_size = tree_size 3537 ht_desc.data_block_size = block_size 3538 ht_desc.hash_block_size = block_size 3539 ht_desc.hash_algorithm = hash_algorithm 3540 ht_desc.partition_name = partition_name 3541 ht_desc.salt = salt 3544 if not use_persistent_root_digest: 3545 ht_desc.root_digest = root_digest
3577 vbmeta_blob = self._generate_vbmeta_blob( 3578 algorithm_name, key_path, public_key_metadata_path, [ht_desc], 3579 chain_partitions, rollback_index, flags, props, props_from_file, 3580 kernel_cmdlines, setup_rootfs_from_kernel, ht_desc_to_setup, 3581 include_descriptors_from_image, signing_helper, 3582 signing_helper_with_files, release_string, 3583 append_to_release_string, required_libavb_version_minor)
5.创建avbfooter,并设置它的vbmeta_offset以及vbmeta_size(即是上面vbmeta_blob的size)成员,然后将avb footer写到image的最后一个block,注意avb footer位于这个block的最后,这个block前面没有占用的部分将用0填充:
3598 if partition_size > 0: 3599 image.append_dont_care(partition_size - image.image_size - 3600 1*image.block_size) #填充最后没有使用的空间(除了最后一个block,将最后一个block留出来给avb footer) 3601 3602 # Generate the Footer that tells where the VBMeta footer 3603 # is. Also put enough padding in the front of the footer since 3604 # we'll write out an entire block. 3605 footer = AvbFooter() 3606 footer.original_image_size = original_image_size 3607 footer.vbmeta_offset = vbmeta_offset 3608 footer.vbmeta_size = len(vbmeta_blob) 3609 footer_blob = footer.encode() 3610 footer_blob_with_padding = ('\0'*(image.block_size - AvbFooter.SIZE) + 3611 footer_blob) 3612 image.append_raw(footer_blob_with_padding)
注:
上面2中对一个block(4K)计算hash值,如果是采用的hash256算法,则计算出来的hash值有256bit,即32 byte,假设system.img size是1G,则hash tree layer0数据size为2048 block(4K)( (30 - 12) + 5 - 12 = 11),同样的方法后面计算layer 0、1等的hash值,最上面的layer只有一个block,最后这个hash tree一共有3个layer(layer0/1/2),这部分可以参考如下blog:
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
2021-05-16 内核reboot流程
2018-05-16 将二维数组名作为函数实参