• 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:

    dm-verity原理剖析_内核工匠的博客-CSDN博客

  • 相关阅读:
    静态初始化块的执行顺序
    Integer练习
    关于厦门电信访问不了中文域名的原因
    获得库每个表的记录数和容量,sp_msforeachtable是MS未公开的存储过程
    ASP.NET State Service服务的作用
    强烈后悔用VS2008
    sp_addextendedproc
    DataSet SELECT DISTINCT Helper Class in Visual C# .NET
    今天买了5个冰淇淋
    TSQL常用字符串函数
  • 原文地址:https://www.cnblogs.com/aspirs/p/16275360.html
Copyright © 2020-2023  润新知