diff --git a/core/Makefile b/core/Makefile index 23f4788e7..e0b501b28 100644 --- a/core/Makefile +++ b/core/Makefile @@ -2645,6 +2645,15 @@ BOARD_AVB_ALGORITHM := SHA256_RSA4096 BOARD_AVB_KEY_PATH := external/avb/test/data/testkey_rsa4096.pem endif +INTERNAL_AVB_PARTITIONS_IN_CHAINED_VBMETA_IMAGES := \ + $(BOARD_AVB_VBMETA_MAINLINE) \ + $(BOARD_AVB_VBMETA_VENDOR) + +# Not allowing the same partition to appear in multiple groups. +ifneq ($(words $(sort $(INTERNAL_AVB_PARTITIONS_IN_CHAINED_VBMETA_IMAGES))),$(words $(INTERNAL_AVB_PARTITIONS_IN_CHAINED_VBMETA_IMAGES))) + $(error BOARD_AVB_VBMETA_MAINLINE and BOARD_AVB_VBMETA_VENDOR cannot have duplicates) +endif + BOOT_FOOTER_ARGS := BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS DTBO_FOOTER_ARGS := BOARD_AVB_DTBO_ADD_HASH_FOOTER_ARGS SYSTEM_FOOTER_ARGS := BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS @@ -2655,7 +2664,7 @@ PRODUCT_SERVICES_FOOTER_ARGS := BOARD_AVB_PRODUCT_SERVICES_ADD_HASHTREE_FOOTER_A ODM_FOOTER_ARGS := BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS # Helper function that checks and sets required build variables for an AVB chained partition. -# $(1): the partition to enable AVB chain, e.g., boot or system. +# $(1): the partition to enable AVB chain, e.g., boot or system or vbmeta_mainline. define _check-and-set-avb-chain-args $(eval part := $(1)) $(eval PART=$(call to-upper,$(part))) @@ -2677,20 +2686,27 @@ $(eval $(_signing_args) := \ $(eval INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += \ --chain_partition $(part):$($(_rollback_index_location)):$(AVB_CHAIN_KEY_DIR)/$(part).avbpubkey) -# Set rollback_index via footer args -$(eval _footer_args := $(PART)_FOOTER_ARGS) -$(eval $($(_footer_args)) += --rollback_index $($(_rollback_index))) +# Set rollback_index via footer args for non-chained vbmeta image. Chained vbmeta image will pick up +# the index via a separate flag (e.g. BOARD_AVB_VBMETA_MAINLINE_ROLLBACK_INDEX). +$(if $(filter $(part),$(part:vbmeta_%=%)),\ + $(eval _footer_args := $(PART)_FOOTER_ARGS) \ + $(eval $($(_footer_args)) += --rollback_index $($(_rollback_index)))) endef # Checks and sets the required build variables for an AVB partition. The partition will be # configured as a chained partition, if BOARD_AVB__KEY_PATH is defined. Otherwise the -# image descriptor will be included into vbmeta.img. +# image descriptor will be included into vbmeta.img, unless it has been already added to any chained +# VBMeta image. # $(1): Partition name, e.g. boot or system. define check-and-set-avb-args +$(eval _in_chained_vbmeta := $(filter $(1),$(INTERNAL_AVB_PARTITIONS_IN_CHAINED_VBMETA_IMAGES))) $(if $(BOARD_AVB_$(call to-upper,$(1))_KEY_PATH),\ + $(if $(_in_chained_vbmeta),\ + $(error Chaining partition "$(1)" in chained VBMeta image is not supported)) \ $(call _check-and-set-avb-chain-args,$(1)),\ - $(eval INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += \ - --include_descriptors_from_image $(call images-for-partitions,$(1)))) + $(if $(_in_chained_vbmeta),,\ + $(eval INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += \ + --include_descriptors_from_image $(call images-for-partitions,$(1))))) endef ifdef INSTALLED_BOOTIMAGE_TARGET @@ -2723,6 +2739,15 @@ ifdef INSTALLED_RECOVERYIMAGE_TARGET $(eval $(call check-and-set-avb-args,recovery)) endif +# Not using INSTALLED_VBMETA_MAINLINEIMAGE_TARGET as it won't be set yet. +ifdef BOARD_AVB_VBMETA_MAINLINE +$(eval $(call check-and-set-avb-args,vbmeta_mainline)) +endif + +ifdef BOARD_AVB_VBMETA_VENDOR +$(eval $(call check-and-set-avb-args,vbmeta_vendor)) +endif + # Add kernel cmdline descriptor for kernel to mount system.img as root with # dm-verity. This works when system.img is either chained or not-chained: # - chained: The --setup_as_rootfs_from_kernel option will add dm-verity kernel @@ -2734,13 +2759,27 @@ BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS += --setup_as_rootfs_from_kernel endif BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --padding_size 4096 +BOARD_AVB_MAKE_VBMETA_MAINLINE_IMAGE_ARGS += --padding_size 4096 +BOARD_AVB_MAKE_VBMETA_VENDOR_IMAGE_ARGS += --padding_size 4096 + +ifeq (eng,$(filter eng, $(TARGET_BUILD_VARIANT))) +BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --set_hashtree_disabled_flag +BOARD_AVB_MAKE_VBMETA_MAINLINE_IMAGE_ARGS += --set_hashtree_disabled_flag +BOARD_AVB_MAKE_VBMETA_VENDOR_IMAGE_ARGS += --set_hashtree_disabled_flag +endif ifdef BOARD_AVB_ROLLBACK_INDEX BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --rollback_index $(BOARD_AVB_ROLLBACK_INDEX) endif -ifeq (eng,$(filter eng, $(TARGET_BUILD_VARIANT))) -BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --set_hashtree_disabled_flag +ifdef BOARD_AVB_VBMETA_MAINLINE_ROLLBACK_INDEX +BOARD_AVB_MAKE_VBMETA_MAINLINE_IMAGE_ARGS += \ + --rollback_index $(BOARD_AVB_VBMETA_MAINLINE_ROLLBACK_INDEX) +endif + +ifdef BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX +BOARD_AVB_MAKE_VBMETA_VENDOR_IMAGE_ARGS += \ + --rollback_index $(BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX) endif # $(1): the directory to extract public keys to @@ -2769,8 +2808,50 @@ define extract-avb-chain-public-keys $(if $(BOARD_AVB_RECOVERY_KEY_PATH),\ $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_RECOVERY_KEY_PATH) \ --output $(1)/recovery.avbpubkey) + $(if $(BOARD_AVB_VBMETA_MAINLINE_KEY_PATH),\ + $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VBMETA_MAINLINE_KEY_PATH) \ + --output $(1)/vbmeta_mainline.avbpubkey) + $(if $(BOARD_AVB_VBMETA_VENDOR_KEY_PATH),\ + $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VBMETA_VENDOR_KEY_PATH) \ + --output $(1)/vbmeta_vendor.avbpubkey) endef +# Builds a chained VBMeta image. This VBMeta image will contain the descriptors for the partitions +# specified in BOARD_AVB_VBMETA_. The built VBMeta image will be included into the top-level +# vbmeta image as a chained partition. For example, if a target defines `BOARD_AVB_VBMETA_MAINLINE +# := system product_services`, `vbmeta_mainline.img` will be created that includes the descriptors +# for `system.img` and `product_services.img`. `vbmeta_mainline.img` itself will be included into +# `vbmeta.img` as a chained partition. +# $(1): VBMeta image name, such as "vbmeta_mainline", "vbmeta_vendor" etc. +# $(2): Output filename. +define build-chained-vbmeta-image + $(call pretty,"Target chained vbmeta image: $@") + $(hide) $(AVBTOOL) make_vbmeta_image \ + $(INTERNAL_AVB_$(call to-upper,$(1))_SIGNING_ARGS) \ + $(BOARD_AVB_MAKE_$(call to-upper,$(1))_IMAGE_ARGS) \ + $(foreach image,$(BOARD_AVB_$(call to-upper,$(1))), \ + --include_descriptors_from_image $(call images-for-partitions,$(image))) \ + --output $@ +endef + +ifdef BOARD_AVB_VBMETA_MAINLINE +INSTALLED_VBMETA_MAINLINEIMAGE_TARGET := $(PRODUCT_OUT)/vbmeta_mainline.img +$(INSTALLED_VBMETA_MAINLINEIMAGE_TARGET): \ + $(AVBTOOL) \ + $(call images-for-partitions,$(BOARD_AVB_VBMETA_MAINLINE)) \ + $(BOARD_AVB_VBMETA_MAINLINE_KEY_PATH) + $(call build-chained-vbmeta-image,vbmeta_mainline) +endif + +ifdef BOARD_AVB_VBMETA_VENDOR +INSTALLED_VBMETA_VENDORIMAGE_TARGET := $(PRODUCT_OUT)/vbmeta_vendor.img +$(INSTALLED_VBMETA_VENDORIMAGE_TARGET): \ + $(AVBTOOL) \ + $(call images-for-partitions,$(BOARD_AVB_VBMETA_VENDOR)) \ + $(BOARD_AVB_VBMETA_VENDOR_KEY_PATH) + $(call build-chained-vbmeta-image,vbmeta_vendor) +endif + define build-vbmetaimage-target $(call pretty,"Target vbmeta image: $(INSTALLED_VBMETAIMAGE_TARGET)") $(hide) mkdir -p $(AVB_CHAIN_KEY_DIR) @@ -2797,6 +2878,10 @@ $(INSTALLED_VBMETAIMAGE_TARGET): \ $(INSTALLED_ODMIMAGE_TARGET) \ $(INSTALLED_DTBOIMAGE_TARGET) \ $(INSTALLED_RECOVERYIMAGE_TARGET) \ + $(INSTALLED_VBMETA_MAINLINEIMAGE_TARGET) \ + $(INSTALLED_VBMETA_VENDORIMAGE_TARGET) \ + $(BOARD_AVB_VBMETA_MAINLINE_KEY_PATH) \ + $(BOARD_AVB_VBMETA_VENDOR_KEY_PATH) \ $(BOARD_AVB_KEY_PATH) $(build-vbmetaimage-target) @@ -3372,6 +3457,20 @@ ifdef BOARD_AVB_RECOVERY_KEY_PATH $(hide) echo "avb_recovery_algorithm=$(BOARD_AVB_RECOVERY_ALGORITHM)" >> $(zip_root)/META/misc_info.txt $(hide) echo "avb_recovery_rollback_index_location=$(BOARD_AVB_RECOVERY_ROLLBACK_INDEX_LOCATION)" >> $(zip_root)/META/misc_info.txt endif # BOARD_AVB_RECOVERY_KEY_PATH +ifneq (,$(strip $(BOARD_AVB_VBMETA_MAINLINE))) + $(hide) echo "avb_vbmeta_mainline=$(BOARD_AVB_VBMETA_MAINLINE)" >> $(zip_root)/META/misc_info.txt + $(hide) echo "avb_vbmeta_mainline_args=$(BOARD_AVB_MAKE_VBMETA_MAINLINE_IMAGE_ARGS)" >> $(zip_root)/META/misc_info.txt + $(hide) echo "avb_vbmeta_mainline_key_path=$(BOARD_AVB_VBMETA_MAINLINE_KEY_PATH)" >> $(zip_root)/META/misc_info.txt + $(hide) echo "avb_vbmeta_mainline_algorithm=$(BOARD_AVB_VBMETA_MAINLINE_ALGORITHM)" >> $(zip_root)/META/misc_info.txt + $(hide) echo "avb_vbmeta_mainline_rollback_index_location=$(BOARD_AVB_VBMETA_MAINLINE_ROLLBACK_INDEX_LOCATION)" >> $(zip_root)/META/misc_info.txt +endif # BOARD_AVB_VBMETA_MAINLINE +ifneq (,$(strip $(BOARD_AVB_VBMETA_VENDOR))) + $(hide) echo "avb_vbmeta_vendor=$(BOARD_AVB_VBMETA_VENDOR)" >> $(zip_root)/META/misc_info.txt + $(hide) echo "avb_vbmeta_vendor_args=$(BOARD_AVB_MAKE_VBMETA_MAINLINE_IMAGE_ARGS)" >> $(zip_root)/META/misc_info.txt + $(hide) echo "avb_vbmeta_vendor_key_path=$(BOARD_AVB_VBMETA_VENDOR_KEY_PATH)" >> $(zip_root)/META/misc_info.txt + $(hide) echo "avb_vbmeta_vendor_algorithm=$(BOARD_AVB_VBMETA_VENDOR_ALGORITHM)" >> $(zip_root)/META/misc_info.txt + $(hide) echo "avb_vbmeta_vendor_rollback_index_location=$(BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX_LOCATION)" >> $(zip_root)/META/misc_info.txt +endif # BOARD_AVB_VBMETA_VENDOR_KEY_PATH endif # BOARD_AVB_ENABLE ifdef BOARD_BPT_INPUT_FILES $(hide) echo "board_bpt_enable=true" >> $(zip_root)/META/misc_info.txt diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py index 9e8b6987a..e9419feb5 100755 --- a/tools/releasetools/add_img_to_target_files.py +++ b/tools/releasetools/add_img_to_target_files.py @@ -393,32 +393,46 @@ def AppendVBMetaArgsForPartition(cmd, partition, image): cmd.extend(["--include_descriptors_from_image", image]) -def AddVBMeta(output_zip, partitions): - """Creates a VBMeta image and store it in output_zip. +def AddVBMeta(output_zip, partitions, name, needed_partitions): + """Creates a VBMeta image and stores it in output_zip. + + It generates the requested VBMeta image. The requested image could be for + top-level or chained VBMeta image, which is determined based on the name. Args: output_zip: The output zip file, which needs to be already open. partitions: A dict that's keyed by partition names with image paths as values. Only valid partition names are accepted, as listed in common.AVB_PARTITIONS. + name: Name of the VBMeta partition, e.g. 'vbmeta', 'vbmeta_mainline'. + needed_partitions: Partitions whose descriptors should be included into the + generated VBMeta image. + + Raises: + AssertionError: On invalid input args. """ - img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "vbmeta.img") + assert needed_partitions, "Needed partitions must be specified" + + img = OutputFile( + output_zip, OPTIONS.input_tmp, "IMAGES", "{}.img".format(name)) if os.path.exists(img.input_name): - print("vbmeta.img already exists; not rebuilding...") + print("{}.img already exists; not rebuilding...".format(name)) return img.input_name avbtool = os.getenv('AVBTOOL') or OPTIONS.info_dict["avb_avbtool"] cmd = [avbtool, "make_vbmeta_image", "--output", img.name] - common.AppendAVBSigningArgs(cmd, "vbmeta") + common.AppendAVBSigningArgs(cmd, name) for partition, path in partitions.items(): + if partition not in needed_partitions: + continue assert partition in common.AVB_PARTITIONS, \ 'Unknown partition: {}'.format(partition) assert os.path.exists(path), \ 'Failed to find {} for {}'.format(path, partition) AppendVBMetaArgsForPartition(cmd, partition, path) - args = OPTIONS.info_dict.get("avb_vbmeta_args") + args = OPTIONS.info_dict.get("avb_{}_args".format(name)) if args and args.strip(): split_args = shlex.split(args) for index, arg in enumerate(split_args[:-1]): @@ -439,7 +453,7 @@ def AddVBMeta(output_zip, partitions): split_args[index + 1] = alt_path found = True break - assert found, 'failed to find %s' % (image_path,) + assert found, 'Failed to find {}'.format(image_path) cmd.extend(split_args) p = common.Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) @@ -693,8 +707,8 @@ def AddImagesToTargetFiles(filename): os.path.exists(os.path.join(OPTIONS.input_tmp, "IMAGES", "vendor.img"))) has_odm = (os.path.isdir(os.path.join(OPTIONS.input_tmp, "ODM")) or - os.path.exists(os.path.join(OPTIONS.input_tmp, "IMAGES", - "odm.img"))) + os.path.exists(os.path.join(OPTIONS.input_tmp, "IMAGES", + "odm.img"))) has_product = (os.path.isdir(os.path.join(OPTIONS.input_tmp, "PRODUCT")) or os.path.exists(os.path.join(OPTIONS.input_tmp, "IMAGES", "product.img"))) @@ -806,8 +820,33 @@ def AddImagesToTargetFiles(filename): partitions['dtbo'] = AddDtbo(output_zip) if OPTIONS.info_dict.get("avb_enable") == "true": + # vbmeta_partitions includes the partitions that should be included into + # top-level vbmeta.img, which are the ones that are not included in any + # chained VBMeta image plus the chained VBMeta images themselves. + vbmeta_partitions = common.AVB_PARTITIONS[:] + + vbmeta_mainline = OPTIONS.info_dict.get("avb_vbmeta_mainline", "").strip() + if vbmeta_mainline: + banner("vbmeta_mainline") + AddVBMeta( + output_zip, partitions, "vbmeta_mainline", vbmeta_mainline.split()) + vbmeta_partitions = [ + item for item in vbmeta_partitions + if item not in vbmeta_mainline.split()] + vbmeta_partitions.append("vbmeta_mainline") + + vbmeta_vendor = OPTIONS.info_dict.get("avb_vbmeta_vendor", "").strip() + if vbmeta_vendor: + banner("vbmeta_vendor") + AddVBMeta( + output_zip, partitions, "vbmeta_vendor", vbmeta_vendor.split()) + vbmeta_partitions = [ + item for item in vbmeta_partitions + if item not in vbmeta_vendor.split()] + vbmeta_partitions.append("vbmeta_vendor") + banner("vbmeta") - AddVBMeta(output_zip, partitions) + AddVBMeta(output_zip, partitions, "vbmeta", vbmeta_partitions) if OPTIONS.info_dict.get("super_size"): banner("super_empty") diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py index 8d51df6b2..ee2c6f499 100644 --- a/tools/releasetools/common.py +++ b/tools/releasetools/common.py @@ -408,7 +408,7 @@ def AppendAVBSigningArgs(cmd, partition): cmd.extend(["--key", key_path, "--algorithm", algorithm]) avb_salt = OPTIONS.info_dict.get("avb_salt") # make_vbmeta_image doesn't like "--salt" (and it's not needed). - if avb_salt and partition != "vbmeta": + if avb_salt and not partition.startswith("vbmeta"): cmd.extend(["--salt", avb_salt])