Ejemplo n.º 1
0
def AddImagesToTargetFiles(filename):
    """Creates and adds images (boot/recovery/system/...) to a target_files.zip.

  It works with either a zip file (zip mode), or a directory that contains the
  files to be packed into a target_files.zip (dir mode). The latter is used when
  being called from build/make/core/Makefile.

  The images will be created under IMAGES/ in the input target_files.zip.

  Args:
    filename: the target_files.zip, or the zip root directory.
  """
    if os.path.isdir(filename):
        OPTIONS.input_tmp = os.path.abspath(filename)
    else:
        OPTIONS.input_tmp = common.UnzipTemp(filename)

    if not OPTIONS.add_missing:
        if os.path.isdir(os.path.join(OPTIONS.input_tmp, "IMAGES")):
            logger.warning("target_files appears to already contain images.")
            sys.exit(1)

    OPTIONS.info_dict = common.LoadInfoDict(OPTIONS.input_tmp, repacking=True)

    has_recovery = OPTIONS.info_dict.get("no_recovery") != "true"
    has_boot = OPTIONS.info_dict.get("no_boot") != "true"
    has_vendor_boot = OPTIONS.info_dict.get("vendor_boot") == "true"

    # {vendor,odm,product,system_ext,vendor_dlkm,odm_dlkm, system, system_other}.img
    # can be built from source, or  dropped into target_files.zip as a prebuilt blob.
    has_vendor = HasPartition("vendor")
    has_odm = HasPartition("odm")
    has_vendor_dlkm = HasPartition("vendor_dlkm")
    has_odm_dlkm = HasPartition("odm_dlkm")
    has_product = HasPartition("product")
    has_system_ext = HasPartition("system_ext")
    has_system = HasPartition("system")
    has_system_other = HasPartition("system_other")
    has_userdata = OPTIONS.info_dict.get("building_userdata_image") == "true"
    has_cache = OPTIONS.info_dict.get("building_cache_image") == "true"

    # Set up the output destination. It writes to the given directory for dir
    # mode; otherwise appends to the given ZIP.
    if os.path.isdir(filename):
        output_zip = None
    else:
        output_zip = zipfile.ZipFile(filename,
                                     "a",
                                     compression=zipfile.ZIP_DEFLATED,
                                     allowZip64=True)

    # Always make input_tmp/IMAGES available, since we may stage boot / recovery
    # images there even under zip mode. The directory will be cleaned up as part
    # of OPTIONS.input_tmp.
    images_dir = os.path.join(OPTIONS.input_tmp, "IMAGES")
    if not os.path.isdir(images_dir):
        os.makedirs(images_dir)

    # A map between partition names and their paths, which could be used when
    # generating AVB vbmeta image.
    partitions = {}

    def banner(s):
        logger.info("\n\n++++ %s  ++++\n\n", s)

    boot_image = None
    if has_boot:
        banner("boot")
        boot_images = OPTIONS.info_dict.get("boot_images")
        if boot_images is None:
            boot_images = "boot.img"
        for index, b in enumerate(boot_images.split()):
            # common.GetBootableImage() returns the image directly if present.
            boot_image = common.GetBootableImage("IMAGES/" + b, b,
                                                 OPTIONS.input_tmp, "BOOT")
            # boot.img may be unavailable in some targets (e.g. aosp_arm64).
            if boot_image:
                boot_image_path = os.path.join(OPTIONS.input_tmp, "IMAGES", b)
                # Although multiple boot images can be generated, include the image
                # descriptor of only the first boot image in vbmeta
                if index == 0:
                    partitions['boot'] = boot_image_path
                if not os.path.exists(boot_image_path):
                    boot_image.WriteToDir(OPTIONS.input_tmp)
                    if output_zip:
                        boot_image.AddToZip(output_zip)

    if has_vendor_boot:
        banner("vendor_boot")
        vendor_boot_image = common.GetVendorBootImage("IMAGES/vendor_boot.img",
                                                      "vendor_boot.img",
                                                      OPTIONS.input_tmp,
                                                      "VENDOR_BOOT")
        if vendor_boot_image:
            partitions['vendor_boot'] = os.path.join(OPTIONS.input_tmp,
                                                     "IMAGES",
                                                     "vendor_boot.img")
            if not os.path.exists(partitions['vendor_boot']):
                vendor_boot_image.WriteToDir(OPTIONS.input_tmp)
                if output_zip:
                    vendor_boot_image.AddToZip(output_zip)

    recovery_image = None
    if has_recovery:
        banner("recovery")
        recovery_image = common.GetBootableImage("IMAGES/recovery.img",
                                                 "recovery.img",
                                                 OPTIONS.input_tmp, "RECOVERY")
        assert recovery_image, "Failed to create recovery.img."
        partitions['recovery'] = os.path.join(OPTIONS.input_tmp, "IMAGES",
                                              "recovery.img")
        if not os.path.exists(partitions['recovery']):
            recovery_image.WriteToDir(OPTIONS.input_tmp)
            if output_zip:
                recovery_image.AddToZip(output_zip)

            banner("recovery (two-step image)")
            # The special recovery.img for two-step package use.
            recovery_two_step_image = common.GetBootableImage(
                "OTA/recovery-two-step.img",
                "recovery-two-step.img",
                OPTIONS.input_tmp,
                "RECOVERY",
                two_step_image=True)
            assert recovery_two_step_image, "Failed to create recovery-two-step.img."
            recovery_two_step_image_path = os.path.join(
                OPTIONS.input_tmp, "OTA", "recovery-two-step.img")
            if not os.path.exists(recovery_two_step_image_path):
                recovery_two_step_image.WriteToDir(OPTIONS.input_tmp)
                if output_zip:
                    recovery_two_step_image.AddToZip(output_zip)

    if has_system:
        banner("system")
        partitions['system'] = AddSystem(output_zip,
                                         recovery_img=recovery_image,
                                         boot_img=boot_image)

    if has_vendor:
        banner("vendor")
        partitions['vendor'] = AddVendor(output_zip,
                                         recovery_img=recovery_image,
                                         boot_img=boot_image)

    if has_product:
        banner("product")
        partitions['product'] = AddProduct(output_zip)

    if has_system_ext:
        banner("system_ext")
        partitions['system_ext'] = AddSystemExt(output_zip)

    if has_odm:
        banner("odm")
        partitions['odm'] = AddOdm(output_zip)

    if has_vendor_dlkm:
        banner("vendor_dlkm")
        partitions['vendor_dlkm'] = AddVendorDlkm(output_zip)

    if has_odm_dlkm:
        banner("odm_dlkm")
        partitions['odm_dlkm'] = AddOdmDlkm(output_zip)

    if has_system_other:
        banner("system_other")
        AddSystemOther(output_zip)

    AddApexInfo(output_zip)

    if not OPTIONS.is_signing:
        banner("userdata")
        AddUserdata(output_zip)
        banner("cache")
        AddCache(output_zip)

    if OPTIONS.info_dict.get("board_bpt_enable") == "true":
        banner("partition-table")
        AddPartitionTable(output_zip)

    if OPTIONS.info_dict.get("has_dtbo") == "true":
        banner("dtbo")
        partitions['dtbo'] = AddDtbo(output_zip)

    if OPTIONS.info_dict.get("has_pvmfw") == "true":
        banner("pvmfw")
        partitions['pvmfw'] = AddPvmfw(output_zip)

    # Custom images.
    custom_partitions = OPTIONS.info_dict.get(
        "avb_custom_images_partition_list", "").strip().split()
    for partition_name in custom_partitions:
        partition_name = partition_name.strip()
        banner("custom images for " + partition_name)
        partitions[partition_name] = AddCustomImages(output_zip,
                                                     partition_name)

    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.
        # Currently custom_partitions are all chained to VBMeta image.
        vbmeta_partitions = common.AVB_PARTITIONS[:] + tuple(custom_partitions)

        vbmeta_system = OPTIONS.info_dict.get("avb_vbmeta_system", "").strip()
        if vbmeta_system:
            banner("vbmeta_system")
            partitions["vbmeta_system"] = AddVBMeta(output_zip, partitions,
                                                    "vbmeta_system",
                                                    vbmeta_system.split())
            vbmeta_partitions = [
                item for item in vbmeta_partitions
                if item not in vbmeta_system.split()
            ]
            vbmeta_partitions.append("vbmeta_system")

        vbmeta_vendor = OPTIONS.info_dict.get("avb_vbmeta_vendor", "").strip()
        if vbmeta_vendor:
            banner("vbmeta_vendor")
            partitions["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")

        if OPTIONS.info_dict.get("avb_building_vbmeta_image") == "true":
            banner("vbmeta")
            AddVBMeta(output_zip, partitions, "vbmeta", vbmeta_partitions)

    if OPTIONS.info_dict.get("use_dynamic_partitions") == "true":
        if OPTIONS.info_dict.get("build_super_empty_partition") == "true":
            banner("super_empty")
            AddSuperEmpty(output_zip)

    if OPTIONS.info_dict.get("build_super_partition") == "true":
        if OPTIONS.info_dict.get(
                "build_retrofit_dynamic_partitions_ota_package") == "true":
            banner("super split images")
            AddSuperSplit(output_zip)

    banner("radio")
    ab_partitions_txt = os.path.join(OPTIONS.input_tmp, "META",
                                     "ab_partitions.txt")
    if os.path.exists(ab_partitions_txt):
        with open(ab_partitions_txt) as f:
            ab_partitions = f.readlines()

        # For devices using A/B update, make sure we have all the needed images
        # ready under IMAGES/ or RADIO/.
        CheckAbOtaImages(output_zip, ab_partitions)

        # Generate care_map.pb for ab_partitions, then write this file to
        # target_files package.
        output_care_map = os.path.join(OPTIONS.input_tmp, "META",
                                       "care_map.pb")
        AddCareMapForAbOta(output_zip if output_zip else output_care_map,
                           ab_partitions, partitions)

    # Radio images that need to be packed into IMAGES/, and product-img.zip.
    pack_radioimages_txt = os.path.join(OPTIONS.input_tmp, "META",
                                        "pack_radioimages.txt")
    if os.path.exists(pack_radioimages_txt):
        with open(pack_radioimages_txt) as f:
            AddPackRadioImages(output_zip, f.readlines())

    # Calculate the vbmeta digest and put the result in to META/
    boot_images = OPTIONS.info_dict.get("boot_images")
    # Disable the digest calculation if the target_file is used as a container
    # for boot images.
    boot_container = boot_images and len(boot_images.split()) >= 2
    if (OPTIONS.info_dict.get("avb_enable") == "true" and not boot_container
            and OPTIONS.info_dict.get("avb_building_vbmeta_image") == "true"):
        avbtool = OPTIONS.info_dict["avb_avbtool"]
        digest = verity_utils.CalculateVbmetaDigest(OPTIONS.input_tmp, avbtool)
        vbmeta_digest_txt = os.path.join(OPTIONS.input_tmp, "META",
                                         "vbmeta_digest.txt")
        with open(vbmeta_digest_txt, 'w') as f:
            f.write(digest)

    if output_zip:
        common.ZipClose(output_zip)
        if OPTIONS.replace_updated_files_list:
            ReplaceUpdatedFiles(output_zip.filename,
                                OPTIONS.replace_updated_files_list)
def AddImagesToTargetFiles(filename):
    """Creates and adds images (boot/recovery/system/...) to a target_files.zip.

  It works with either a zip file (zip mode), or a directory that contains the
  files to be packed into a target_files.zip (dir mode). The latter is used when
  being called from build/make/core/Makefile.

  The images will be created under IMAGES/ in the input target_files.zip.

  Args:
    filename: the target_files.zip, or the zip root directory.
  """
    if os.path.isdir(filename):
        OPTIONS.input_tmp = os.path.abspath(filename)
    else:
        OPTIONS.input_tmp = common.UnzipTemp(filename)

    if not OPTIONS.add_missing:
        if os.path.isdir(os.path.join(OPTIONS.input_tmp, "IMAGES")):
            logger.warning("target_files appears to already contain images.")
            sys.exit(1)

    OPTIONS.info_dict = common.LoadInfoDict(OPTIONS.input_tmp, repacking=True)

    has_recovery = OPTIONS.info_dict.get("no_recovery") != "true"
    has_boot = OPTIONS.info_dict.get("no_boot") != "true"
    has_vendor_boot = OPTIONS.info_dict.get("vendor_boot") == "true"

    # {vendor,odm,product,system_ext}.img are unlike system.img or
    # system_other.img. Because it could be built from source, or dropped into
    # target_files.zip as a prebuilt blob. We consider either of them as
    # {vendor,product,system_ext}.img being available, which could be
    # used when generating vbmeta.img for AVB.
    has_vendor = (os.path.isdir(os.path.join(OPTIONS.input_tmp, "VENDOR"))
                  or 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")))
    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")))
    has_system_ext = (os.path.isdir(
        os.path.join(OPTIONS.input_tmp, "SYSTEM_EXT")) or os.path.exists(
            os.path.join(OPTIONS.input_tmp, "IMAGES", "system_ext.img")))
    has_system = os.path.isdir(os.path.join(OPTIONS.input_tmp, "SYSTEM"))
    has_system_other = os.path.isdir(
        os.path.join(OPTIONS.input_tmp, "SYSTEM_OTHER"))

    # Set up the output destination. It writes to the given directory for dir
    # mode; otherwise appends to the given ZIP.
    if os.path.isdir(filename):
        output_zip = None
    else:
        output_zip = zipfile.ZipFile(filename,
                                     "a",
                                     compression=zipfile.ZIP_DEFLATED,
                                     allowZip64=True)

    # Always make input_tmp/IMAGES available, since we may stage boot / recovery
    # images there even under zip mode. The directory will be cleaned up as part
    # of OPTIONS.input_tmp.
    images_dir = os.path.join(OPTIONS.input_tmp, "IMAGES")
    if not os.path.isdir(images_dir):
        os.makedirs(images_dir)

    # A map between partition names and their paths, which could be used when
    # generating AVB vbmeta image.
    partitions = {}

    def banner(s):
        logger.info("\n\n++++ %s  ++++\n\n", s)

    boot_image = None
    if has_boot:
        banner("boot")
        # common.GetBootableImage() returns the image directly if present.
        boot_image = common.GetBootableImage("IMAGES/boot.img", "boot.img",
                                             OPTIONS.input_tmp, "BOOT")
        # boot.img may be unavailable in some targets (e.g. aosp_arm64).
        if boot_image:
            partitions['boot'] = os.path.join(OPTIONS.input_tmp, "IMAGES",
                                              "boot.img")
            if not os.path.exists(partitions['boot']):
                boot_image.WriteToDir(OPTIONS.input_tmp)
                if output_zip:
                    boot_image.AddToZip(output_zip)

    if has_vendor_boot:
        banner("vendor_boot")
        vendor_boot_image = common.GetVendorBootImage("IMAGES/vendor_boot.img",
                                                      "vendor_boot.img",
                                                      OPTIONS.input_tmp,
                                                      "VENDOR_BOOT")
        if vendor_boot_image:
            partitions['vendor_boot'] = os.path.join(OPTIONS.input_tmp,
                                                     "IMAGES",
                                                     "vendor_boot.img")
            if not os.path.exists(partitions['vendor_boot']):
                vendor_boot_image.WriteToDir(OPTIONS.input_tmp)
                if output_zip:
                    vendor_boot_image.AddToZip(output_zip)

    recovery_image = None
    if has_recovery:
        banner("recovery")
        recovery_image = common.GetBootableImage("IMAGES/recovery.img",
                                                 "recovery.img",
                                                 OPTIONS.input_tmp, "RECOVERY")
        assert recovery_image, "Failed to create recovery.img."
        partitions['recovery'] = os.path.join(OPTIONS.input_tmp, "IMAGES",
                                              "recovery.img")
        if not os.path.exists(partitions['recovery']):
            recovery_image.WriteToDir(OPTIONS.input_tmp)
            if output_zip:
                recovery_image.AddToZip(output_zip)

            banner("recovery (two-step image)")
            # The special recovery.img for two-step package use.
            recovery_two_step_image = common.GetBootableImage(
                "OTA/recovery-two-step.img",
                "recovery-two-step.img",
                OPTIONS.input_tmp,
                "RECOVERY",
                two_step_image=True)
            assert recovery_two_step_image, "Failed to create recovery-two-step.img."
            recovery_two_step_image_path = os.path.join(
                OPTIONS.input_tmp, "OTA", "recovery-two-step.img")
            if not os.path.exists(recovery_two_step_image_path):
                recovery_two_step_image.WriteToDir(OPTIONS.input_tmp)
                if output_zip:
                    recovery_two_step_image.AddToZip(output_zip)

    if has_system:
        banner("system")
        partitions['system'] = AddSystem(output_zip,
                                         recovery_img=recovery_image,
                                         boot_img=boot_image)

    if has_vendor:
        banner("vendor")
        partitions['vendor'] = AddVendor(output_zip,
                                         recovery_img=recovery_image,
                                         boot_img=boot_image)

    if has_product:
        banner("product")
        partitions['product'] = AddProduct(output_zip)

    if has_system_ext:
        banner("system_ext")
        partitions['system_ext'] = AddSystemExt(output_zip)

    if has_odm:
        banner("odm")
        partitions['odm'] = AddOdm(output_zip)

    if has_system_other:
        banner("system_other")
        AddSystemOther(output_zip)

    if not OPTIONS.is_signing:
        banner("userdata")
        AddUserdata(output_zip)
        banner("cache")
        AddCache(output_zip)

    if OPTIONS.info_dict.get("board_bpt_enable") == "true":
        banner("partition-table")
        AddPartitionTable(output_zip)

    if OPTIONS.info_dict.get("has_dtbo") == "true":
        banner("dtbo")
        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_system = OPTIONS.info_dict.get("avb_vbmeta_system", "").strip()
        if vbmeta_system:
            banner("vbmeta_system")
            partitions["vbmeta_system"] = AddVBMeta(output_zip, partitions,
                                                    "vbmeta_system",
                                                    vbmeta_system.split())
            vbmeta_partitions = [
                item for item in vbmeta_partitions
                if item not in vbmeta_system.split()
            ]
            vbmeta_partitions.append("vbmeta_system")

        vbmeta_vendor = OPTIONS.info_dict.get("avb_vbmeta_vendor", "").strip()
        if vbmeta_vendor:
            banner("vbmeta_vendor")
            partitions["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, "vbmeta", vbmeta_partitions)

    if OPTIONS.info_dict.get("use_dynamic_partitions") == "true":
        banner("super_empty")
        AddSuperEmpty(output_zip)

    if OPTIONS.info_dict.get("build_super_partition") == "true":
        if OPTIONS.info_dict.get(
                "build_retrofit_dynamic_partitions_ota_package") == "true":
            banner("super split images")
            AddSuperSplit(output_zip)

    banner("radio")
    ab_partitions_txt = os.path.join(OPTIONS.input_tmp, "META",
                                     "ab_partitions.txt")
    if os.path.exists(ab_partitions_txt):
        with open(ab_partitions_txt) as f:
            ab_partitions = f.readlines()

        # For devices using A/B update, make sure we have all the needed images
        # ready under IMAGES/ or RADIO/.
        CheckAbOtaImages(output_zip, ab_partitions)

        # Generate care_map.pb for ab_partitions, then write this file to
        # target_files package.
        AddCareMapForAbOta(output_zip, ab_partitions, partitions)

    # Radio images that need to be packed into IMAGES/, and product-img.zip.
    pack_radioimages_txt = os.path.join(OPTIONS.input_tmp, "META",
                                        "pack_radioimages.txt")
    if os.path.exists(pack_radioimages_txt):
        with open(pack_radioimages_txt) as f:
            AddPackRadioImages(output_zip, f.readlines())

    if output_zip:
        common.ZipClose(output_zip)
        if OPTIONS.replace_updated_files_list:
            ReplaceUpdatedFiles(output_zip.filename,
                                OPTIONS.replace_updated_files_list)