Beispiel #1
0
def main(argv):
    def option_handler():
        return True

    args = common.ParseOptions(argv,
                               __doc__,
                               extra_opts="",
                               extra_long_opts=[],
                               extra_option_handler=option_handler)

    if len(args) != 1:
        common.Usage(__doc__)
        sys.exit(1)

    logging_format = '%(asctime)s - %(filename)s - %(levelname)-8s: %(message)s'
    date_format = '%Y/%m/%d %H:%M:%S'
    logging.basicConfig(level=logging.INFO,
                        format=logging_format,
                        datefmt=date_format)

    logging.info("Unzipping the input target_files.zip: %s", args[0])
    input_tmp, input_zip = common.UnzipTemp(args[0])

    ValidateFileConsistency(input_zip, input_tmp)

    info_dict = common.LoadInfoDict(input_tmp)
    ValidateInstallRecoveryScript(input_tmp, info_dict)

    # TODO: Check if the OTA keys have been properly updated (the ones on /system,
    # in recovery image).

    logging.info("Done.")
def main(argv):
    # def option_handler(o, a):
    #   return False

    args = common.ParseOptions(argv, __doc__)
    input_dir, output_dir = args

    OPTIONS.info_dict = common.LoadInfoDict(input_dir)

    # SPRD: add for secure boot
    OPTIONS.secure_boot = OPTIONS.info_dict.get("secure_boot", False)
    OPTIONS.secure_boot_tool = OPTIONS.info_dict.get("secure_boot_tool", None)
    OPTIONS.single_key = OPTIONS.info_dict.get("single_key", True)

    recovery_img = common.GetBootableImage("recovery.img", "recovery.img",
                                           input_dir, "RECOVERY")
    boot_img = common.GetBootableImage("boot.img", "boot.img", input_dir,
                                       "BOOT")

    if not recovery_img or not boot_img:
        sys.exit(0)

    def output_sink(fn, data):
        with open(os.path.join(output_dir, "SYSTEM", *fn.split("/")),
                  "wb") as f:
            f.write(data)

    common.MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img)
Beispiel #3
0
def main(argv):
    args = common.ParseOptions(argv, __doc__)
    input_dir, output_dir = args

    common.InitLogging()

    OPTIONS.info_dict = common.LoadInfoDict(input_dir)

    recovery_img = common.GetBootableImage("recovery.img", "recovery.img",
                                           input_dir, "RECOVERY")
    boot_img = common.GetBootableImage("boot.img", "boot.img", input_dir,
                                       "BOOT")

    if not recovery_img or not boot_img:
        sys.exit(0)

    board_uses_vendorimage = OPTIONS.info_dict.get(
        "board_uses_vendorimage") == "true"
    board_builds_vendorimage = OPTIONS.info_dict.get(
        "board_builds_vendorimage") == "true"
    target_files_dir = None

    if board_builds_vendorimage:
        target_files_dir = "VENDOR"
    elif not board_uses_vendorimage:
        target_files_dir = "SYSTEM/vendor"

    def output_sink(fn, data):
        if target_files_dir is None:
            return

        with open(os.path.join(output_dir, target_files_dir, *fn.split("/")),
                  "wb") as f:
            f.write(data)
Beispiel #4
0
 def test_LoadInfoDict_dirInput_legacyRecoveryFstabPath(self):
     target_files = self._test_LoadInfoDict_createTargetFiles(
         self.INFO_DICT_DEFAULT, 'BOOT/RAMDISK/system/etc/recovery.fstab')
     unzipped = common.UnzipTemp(target_files)
     loaded_dict = common.LoadInfoDict(unzipped)
     self.assertEqual(3, loaded_dict['recovery_api_version'])
     self.assertEqual(2, loaded_dict['fstab_version'])
     self.assertIn('/', loaded_dict['fstab'])
     self.assertIn('/system', loaded_dict['fstab'])
Beispiel #5
0
 def test_LoadInfoDict_legacyRecoveryFstabPath(self):
     target_files = self._test_LoadInfoDict_createTargetFiles(
         self.INFO_DICT_DEFAULT, 'BOOT/RAMDISK/etc/recovery.fstab')
     with zipfile.ZipFile(target_files, 'r') as target_files_zip:
         loaded_dict = common.LoadInfoDict(target_files_zip)
         self.assertEqual(3, loaded_dict['recovery_api_version'])
         self.assertEqual(2, loaded_dict['fstab_version'])
         self.assertIn('/', loaded_dict['fstab'])
         self.assertIn('/system', loaded_dict['fstab'])
Beispiel #6
0
def main(argv):
    def option_handler(o, a):
        if o in ("-I", "--ifwi-directory"):
            OPTIONS.ifwi_directory = a
        elif o in ("-A", "--avb-key"):
            OPTIONS.avb_key = a
            OPTIONS.all_keys.add(a)
        elif o in ("-K", "--oem-key"):
            OPTIONS.oem_key = a
            OPTIONS.all_keys.add(a)
        elif o in ("-V", "--variant"):
            OPTIONS.variant = a
        else:
            return False
        return True

    args = common.ParseOptions(argv,
                               __doc__,
                               extra_opts="I:A:K:V:",
                               extra_long_opts=[
                                   "ifwi-directory=", "avb-key=", "oem-key=",
                                   "variant="
                               ],
                               extra_option_handler=option_handler)

    if len(args) != 2:
        common.Usage(__doc__)
        sys.exit(1)

    output_fastboot_fn = args[1]

    print("Extracting the provdata.zip")
    prov_file = "provdata_" + OPTIONS.variant + ".zip"
    unpack_dir = common.UnzipTemp(args[0])
    input_zip = zipfile.ZipFile(args[0], "r")
    input_provzip = zipfile.ZipFile(
        os.path.join(unpack_dir, "RADIO", prov_file), "r")

    print("Parsing build.prop for target_product")
    d = {}
    try:
        with open(os.path.join(unpack_dir, "SYSTEM", "build.prop")) as f:
            d = common.LoadDictionaryFromLines(f.read().split("\n"))
    except IOError as e:
        if e.errno == errno.ENOENT:
            raise KeyError(f)
    OPTIONS.target_product = d["ro.product.system.name"]

    print("Processing private keys")
    OPTIONS.info_dict = common.LoadInfoDict(input_zip)
    passwords = common.GetKeyPasswords(OPTIONS.all_keys)

    #process the provdata.zip to generate resigned one
    process_provzip(input_provzip, output_fastboot_fn)

    common.ZipClose(input_zip)
    print("Extract done.")
def CheckVintfFromExtractedTargetFiles(input_tmp, info_dict=None):
    """
  Checks VINTF metadata of an extracted target files directory.

  Args:
    inp: path to the directory that contains the extracted target files archive.
    info_dict: The build-time info dict. If None, it will be loaded from inp.

  Returns:
    True if VINTF check is skipped or compatible, False if incompatible. Raise
    a RuntimeError if any error occurs.
  """

    if info_dict is None:
        info_dict = common.LoadInfoDict(input_tmp)

    if info_dict.get('vintf_enforce') != 'true':
        logger.warning(
            'PRODUCT_ENFORCE_VINTF_MANIFEST is not set, skipping checks')
        return True

    dirmap = GetDirmap(input_tmp)
    args_for_skus = GetArgsForSkus(info_dict)
    shipping_api_level_args = GetArgsForShippingApiLevel(info_dict)
    kernel_args = GetArgsForKernel(input_tmp)

    common_command = [
        'checkvintf',
        '--check-compat',
    ]
    for device_path, real_path in dirmap.items():
        common_command += ['--dirmap', '{}:{}'.format(device_path, real_path)]
    common_command += kernel_args
    common_command += shipping_api_level_args

    success = True
    for sku_args in args_for_skus:
        command = common_command + sku_args
        proc = common.Run(command,
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE)
        out, err = proc.communicate()
        if proc.returncode == 0:
            logger.info("Command `%s` returns 'compatible'", ' '.join(command))
        elif out.strip() == "INCOMPATIBLE":
            logger.info("Command `%s` returns 'incompatible'",
                        ' '.join(command))
            success = False
        else:
            raise common.ExternalError(
                "Failed to run command '{}' (exit code {}):\nstdout:{}\nstderr:{}"
                .format(' '.join(command), proc.returncode, out, err))
        logger.info("stdout: %s", out)
        logger.info("stderr: %s", err)

    return success
Beispiel #8
0
 def test_LoadInfoDict_noRecoveryTrue(self):
     # Device doesn't have a recovery partition at all.
     info_dict = copy.copy(self.INFO_DICT_DEFAULT)
     del info_dict['recovery_as_boot']
     target_files = self._test_LoadInfoDict_createTargetFiles(
         info_dict, 'RECOVERY/RAMDISK/system/etc/recovery.fstab')
     with zipfile.ZipFile(target_files, 'r') as target_files_zip:
         loaded_dict = common.LoadInfoDict(target_files_zip)
         self.assertEqual(3, loaded_dict['recovery_api_version'])
         self.assertEqual(2, loaded_dict['fstab_version'])
         self.assertIsNone(loaded_dict['fstab'])
Beispiel #9
0
def AddImagesToTargetFiles(filename):
    OPTIONS.input_tmp, input_zip = common.UnzipTemp(filename)

    for n in input_zip.namelist():
        if n.startswith("IMAGES/"):
            print "target_files appears to already contain images."
            sys.exit(1)

    try:
        input_zip.getinfo("VENDOR/")
        has_vendor = True
    except KeyError:
        has_vendor = False

    OPTIONS.info_dict = common.LoadInfoDict(input_zip)
    if "selinux_fc" in OPTIONS.info_dict:
        OPTIONS.info_dict["selinux_fc"] = os.path.join(OPTIONS.input_tmp,
                                                       "BOOT", "RAMDISK",
                                                       "file_contexts")

    input_zip.close()
    output_zip = zipfile.ZipFile(filename,
                                 "a",
                                 compression=zipfile.ZIP_DEFLATED)

    def banner(s):
        print "\n\n++++ " + s + " ++++\n\n"

    banner("boot")
    boot_image = common.GetBootableImage("IMAGES/boot.img", "boot.img",
                                         OPTIONS.input_tmp, "BOOT")
    if boot_image:
        boot_image.AddToZip(output_zip)

    banner("recovery")
    recovery_image = common.GetBootableImage("IMAGES/recovery.img",
                                             "recovery.img", OPTIONS.input_tmp,
                                             "RECOVERY")
    if recovery_image:
        recovery_image.AddToZip(output_zip)

    banner("system")
    AddSystem(output_zip)
    if has_vendor:
        banner("vendor")
        AddVendor(output_zip)
    banner("userdata")
    AddUserdata(output_zip)
    banner("userdata_extra")
    AddUserdataExtra(output_zip)
    banner("cache")
    AddCache(output_zip)

    output_zip.close()
Beispiel #10
0
 def test_LoadInfoDict_repacking(self):
     target_files = self._test_LoadInfoDict_createTargetFiles(
         self.INFO_DICT_DEFAULT, 'BOOT/RAMDISK/system/etc/recovery.fstab')
     unzipped = common.UnzipTemp(target_files)
     loaded_dict = common.LoadInfoDict(unzipped, True)
     self.assertEqual(3, loaded_dict['recovery_api_version'])
     self.assertEqual(2, loaded_dict['fstab_version'])
     self.assertIn('/', loaded_dict['fstab'])
     self.assertIn('/system', loaded_dict['fstab'])
     self.assertEqual(os.path.join(unzipped, 'ROOT'),
                      loaded_dict['root_dir'])
     self.assertEqual(
         os.path.join(unzipped, 'META', 'root_filesystem_config.txt'),
         loaded_dict['root_fs_config'])
Beispiel #11
0
 def test_LoadInfoDict_recoveryAsBootFalse(self):
     # Devices using system-as-root, but with standalone recovery image. Non-A/B
     # devices launched since P will likely have this config.
     info_dict = copy.copy(self.INFO_DICT_DEFAULT)
     del info_dict['no_recovery']
     del info_dict['recovery_as_boot']
     target_files = self._test_LoadInfoDict_createTargetFiles(
         info_dict, 'RECOVERY/RAMDISK/system/etc/recovery.fstab')
     with zipfile.ZipFile(target_files, 'r') as target_files_zip:
         loaded_dict = common.LoadInfoDict(target_files_zip)
         self.assertEqual(3, loaded_dict['recovery_api_version'])
         self.assertEqual(2, loaded_dict['fstab_version'])
         self.assertIn('/', loaded_dict['fstab'])
         self.assertIn('/system', loaded_dict['fstab'])
Beispiel #12
0
 def test_LoadInfoDict_systemRootImageFalse(self):
     # Devices not using system-as-root nor recovery-as-boot. Non-A/B devices
     # launched prior to P will likely have this config.
     info_dict = copy.copy(self.INFO_DICT_DEFAULT)
     del info_dict['no_recovery']
     del info_dict['system_root_image']
     del info_dict['recovery_as_boot']
     target_files = self._test_LoadInfoDict_createTargetFiles(
         info_dict, 'RECOVERY/RAMDISK/system/etc/recovery.fstab')
     with zipfile.ZipFile(target_files, 'r') as target_files_zip:
         loaded_dict = common.LoadInfoDict(target_files_zip)
         self.assertEqual(3, loaded_dict['recovery_api_version'])
         self.assertEqual(2, loaded_dict['fstab_version'])
         self.assertNotIn('/', loaded_dict['fstab'])
         self.assertIn('/system', loaded_dict['fstab'])
Beispiel #13
0
def main():
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('target_files',
                        help='the input target_files.zip to be validated')
    parser.add_argument(
        '--verity_key',
        help='the verity public key to verify the bootable images (Verified '
        'Boot 1.0), or the vbmeta image (Verified Boot 2.0, aka AVB), where '
        'applicable')
    for partition in common.AVB_PARTITIONS + common.AVB_VBMETA_PARTITIONS:
        parser.add_argument(
            '--avb_' + partition + '_key_path',
            help='the public or private key in PEM format to verify AVB chained '
            'partition of {}'.format(partition))
    parser.add_argument(
        '--verity_key_mincrypt',
        help='the verity public key in mincrypt format to verify the system '
        'images, if target using Verified Boot 1.0')
    args = parser.parse_args()

    # Unprovided args will have 'None' as the value.
    options = vars(args)

    logging_format = '%(asctime)s - %(filename)s - %(levelname)-8s: %(message)s'
    date_format = '%Y/%m/%d %H:%M:%S'
    logging.basicConfig(level=logging.INFO,
                        format=logging_format,
                        datefmt=date_format)

    logging.info("Unzipping the input target_files.zip: %s", args.target_files)
    input_tmp = common.UnzipTemp(args.target_files)

    info_dict = common.LoadInfoDict(input_tmp)
    with zipfile.ZipFile(args.target_files, 'r', allowZip64=True) as input_zip:
        ValidateFileConsistency(input_zip, input_tmp, info_dict)

    CheckBuildPropDuplicity(input_tmp)

    ValidateInstallRecoveryScript(input_tmp, info_dict)

    ValidateVerifiedBootImages(input_tmp, info_dict, options)

    # TODO: Check if the OTA keys have been properly updated (the ones on /system,
    # in recovery image).

    logging.info("Done.")
def LoadOptions(input_file):
    """Loads information from input_file to OPTIONS.

  Args:
    input_file: Path to the root dir of an extracted target_files zip.
  """
    info = OPTIONS.info_dict = common.LoadInfoDict(input_file)

    OPTIONS.put_super = info.get("super_image_in_update_package") == "true"
    OPTIONS.dynamic_partition_list = info.get("dynamic_partition_list",
                                              "").strip().split()
    OPTIONS.super_device_list = info.get("super_block_devices",
                                         "").strip().split()
    OPTIONS.retrofit_dap = info.get("dynamic_partition_retrofit") == "true"
    OPTIONS.build_super = info.get("build_super_partition") == "true"
    OPTIONS.sparse_userimages = bool(info.get("extfs_sparse_flag"))
Beispiel #15
0
def LoadOptions(input_file):
    """Loads information from input_file to OPTIONS.

  Args:
    input_file: Path to the input target_files zip file.
  """
    with zipfile.ZipFile(input_file) as input_zip:
        info = OPTIONS.info_dict = common.LoadInfoDict(input_zip)

    OPTIONS.put_super = info.get('super_image_in_update_package') == 'true'
    OPTIONS.dynamic_partition_list = info.get('dynamic_partition_list',
                                              '').strip().split()
    OPTIONS.super_device_list = info.get('super_block_devices',
                                         '').strip().split()
    OPTIONS.retrofit_dap = info.get('dynamic_partition_retrofit') == 'true'
    OPTIONS.build_super = info.get('build_super_partition') == 'true'
    OPTIONS.sparse_userimages = bool(info.get('extfs_sparse_flag'))
Beispiel #16
0
def BuildSuperImageFromExtractedTargetFiles(inp, out):
    info_dict = common.LoadInfoDict(inp)
    partition_list = shlex.split(
        info_dict.get("dynamic_partition_list", "").strip())
    missing_images = []
    for partition in partition_list:
        image_path = os.path.join(inp, "IMAGES", "{}.img".format(partition))
        if not os.path.isfile(image_path):
            missing_images.append(image_path)
        else:
            info_dict["{}_image".format(partition)] = image_path
    if missing_images:
        logger.warning(
            "Skip building super image because the following "
            "images are missing from target files:\n%s",
            "\n".join(missing_images))
        return False
    return BuildSuperImageFromDict(info_dict, out)
Beispiel #17
0
def IncrementalOTA_InstallEnd(self):
    script = self.script
    source_zip = self.source_zip
    source_version = self.source_version
    target_zip = self.target_zip
    target_version = self.target_version
    output_zip = self.output_zip
    script = self.script
    metadata = self.metadata
    info_dict = self.info_dict

    tgt_info_dict = common.LoadInfoDict(target_zip)

    # add OTA information
    AddOTA_Items(target_zip, output_zip, 0)

    # add extra images to upgrade
    AddOTAImage_Items(target_zip, output_zip, tgt_info_dict, script)
def main(argv):
    args = common.ParseOptions(argv, __doc__)
    input_dir, output_dir = args

    common.InitLogging()

    OPTIONS.info_dict = common.LoadInfoDict(input_dir)

    recovery_img = common.GetBootableImage("recovery.img", "recovery.img",
                                           input_dir, "RECOVERY")
    boot_img = common.GetBootableImage("boot.img", "boot.img", input_dir,
                                       "BOOT")

    if not recovery_img or not boot_img:
        sys.exit(0)

    def output_sink(fn, data):
        with open(os.path.join(output_dir, "SYSTEM", *fn.split("/")),
                  "wb") as f:
            f.write(data)
Beispiel #19
0
def main(argv):

  key_mapping_options = []

  def option_handler(o, a):
    if o in ("-e", "--extra_apks"):
      names, key = a.split("=")
      names = names.split(",")
      for n in names:
        OPTIONS.extra_apks[n] = key
    elif o in ("-d", "--default_key_mappings"):
      key_mapping_options.append((None, a))
    elif o in ("-k", "--key_mapping"):
      key_mapping_options.append(a.split("=", 1))
    elif o in ("-o", "--replace_ota_keys"):
      OPTIONS.replace_ota_keys = True
    elif o in ("-t", "--tag_changes"):
      new = []
      for i in a.split(","):
        i = i.strip()
        if not i or i[0] not in "-+":
          raise ValueError("Bad tag change '%s'" % (i,))
        new.append(i[0] + i[1:].strip())
      OPTIONS.tag_changes = tuple(new)
    elif o == "--replace_verity_public_key":
      OPTIONS.replace_verity_public_key = (True, a)
    elif o == "--replace_verity_private_key":
      OPTIONS.replace_verity_private_key = (True, a)
    elif o == "--replace_verity_keyid":
      OPTIONS.replace_verity_keyid = (True, a)
    else:
      return False
    return True

  args = common.ParseOptions(argv, __doc__,
                             extra_opts="e:d:k:ot:",
                             extra_long_opts=["extra_apks=",
                                              "default_key_mappings=",
                                              "key_mapping=",
                                              "replace_ota_keys",
                                              "tag_changes=",
                                              "replace_verity_public_key=",
                                              "replace_verity_private_key=",
                                              "replace_verity_keyid="],
                             extra_option_handler=option_handler)

  if len(args) != 2:
    common.Usage(__doc__)
    sys.exit(1)

  input_zip = zipfile.ZipFile(args[0], "r")
  output_zip = zipfile.ZipFile(args[1], "w")

  misc_info = common.LoadInfoDict(input_zip)

  BuildKeyMap(misc_info, key_mapping_options)

  apk_key_map = GetApkCerts(input_zip)
  CheckAllApksSigned(input_zip, apk_key_map)

  key_passwords = common.GetKeyPasswords(set(apk_key_map.values()))
  platform_api_level, platform_codename = GetApiLevelAndCodename(input_zip)
  codename_to_api_level_map = GetCodenameToApiLevelMap(input_zip)
  # Android N will be API Level 24, but isn't yet.
  # TODO: Remove this workaround once Android N is officially API Level 24.
  if platform_api_level == 23 and platform_codename == "N":
    platform_api_level = 24

  ProcessTargetFiles(input_zip, output_zip, misc_info,
                     apk_key_map, key_passwords,
                     platform_api_level,
                     codename_to_api_level_map)

  common.ZipClose(input_zip)
  common.ZipClose(output_zip)

  add_img_to_target_files.AddImagesToTargetFiles(args[1])

  print "done."
Beispiel #20
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)
Beispiel #21
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"

    # {vendor,odm,product,product_services}.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,product_services}.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_product_services = (os.path.isdir(
        os.path.join(OPTIONS.input_tmp, "PRODUCT_SERVICES")) or os.path.exists(
            os.path.join(OPTIONS.input_tmp, "IMAGES", "product_services.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 = dict()

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

    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)

    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(
                "IMAGES/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, "IMAGES", "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)

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

    if has_product_services:
        banner("product_services")
        partitions['product_services'] = AddProductServices(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("build_super_partition") == "true":
        banner("super_empty")
        AddSuperEmpty(output_zip)

        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, 'r') 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, 'r') 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)
Beispiel #22
0
def AddImagesToTargetFiles(filename):
    OPTIONS.input_tmp, input_zip = common.UnzipTemp(filename)

    if not OPTIONS.add_missing:
        for n in input_zip.namelist():
            if n.startswith("IMAGES/"):
                print("target_files appears to already contain images.")
                sys.exit(1)

    try:
        input_zip.getinfo("VENDOR/")
        has_vendor = True
    except KeyError:
        has_vendor = False

    try:
        input_zip.getinfo("OEM/")
        has_oem = True
    except KeyError:
        has_oem = False

    has_system_other = "SYSTEM_OTHER/" in input_zip.namelist()

    OPTIONS.info_dict = common.LoadInfoDict(input_zip, OPTIONS.input_tmp)

    common.ZipClose(input_zip)
    output_zip = zipfile.ZipFile(filename,
                                 "a",
                                 compression=zipfile.ZIP_DEFLATED)

    has_recovery = (OPTIONS.info_dict.get("no_recovery") != "true")

    def banner(s):
        print("\n\n++++ " + s + " ++++\n\n")

    banner("boot")
    prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", "boot.img")
    boot_image = None
    if os.path.exists(prebuilt_path):
        print("boot.img already exists in IMAGES/, no need to rebuild...")
        if OPTIONS.rebuild_recovery:
            boot_image = common.GetBootableImage("IMAGES/boot.img", "boot.img",
                                                 OPTIONS.input_tmp, "BOOT")
    else:
        boot_image = common.GetBootableImage("IMAGES/boot.img", "boot.img",
                                             OPTIONS.input_tmp, "BOOT")
        if boot_image:
            boot_image.AddToZip(output_zip)

    recovery_image = None
    if has_recovery:
        banner("recovery")
        prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES",
                                     "recovery.img")
        if os.path.exists(prebuilt_path):
            print(
                "recovery.img already exists in IMAGES/, no need to rebuild..."
            )
            if OPTIONS.rebuild_recovery:
                recovery_image = common.GetBootableImage(
                    "IMAGES/recovery.img", "recovery.img", OPTIONS.input_tmp,
                    "RECOVERY")
        else:
            recovery_image = common.GetBootableImage("IMAGES/recovery.img",
                                                     "recovery.img",
                                                     OPTIONS.input_tmp,
                                                     "RECOVERY")
            if recovery_image:
                recovery_image.AddToZip(output_zip)

    banner("system")
    system_imgname = AddSystem(output_zip,
                               recovery_img=recovery_image,
                               boot_img=boot_image)
    vendor_imgname = None
    if has_vendor:
        banner("vendor")
        AddVendor(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", None) == "true":
        banner("partition-table")
        AddPartitionTable(output_zip)

    # For devices using A/B update, copy over images from RADIO/ and/or
    # VENDOR_IMAGES/ to IMAGES/ and make sure we have all the needed
    # images ready under IMAGES/. All images should have '.img' as extension.
    banner("radio")
    ab_partitions = os.path.join(OPTIONS.input_tmp, "META",
                                 "ab_partitions.txt")
    if os.path.exists(ab_partitions):
        with open(ab_partitions, 'r') as f:
            lines = f.readlines()
        # For devices using A/B update, generate care_map for system and vendor
        # partitions (if present), then write this file to target_files package.
        care_map_list = []
        for line in lines:
            if line.strip() == "system" and OPTIONS.info_dict.get(
                    "system_verity_block_device", None) is not None:
                assert os.path.exists(system_imgname)
                care_map_list += GetCareMap("system", system_imgname)
            if line.strip() == "vendor" and OPTIONS.info_dict.get(
                    "vendor_verity_block_device", None) is not None:
                assert os.path.exists(vendor_imgname)
                care_map_list += GetCareMap("vendor", vendor_imgname)

            img_name = line.strip() + ".img"
            img_radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
            if os.path.exists(img_radio_path):
                common.ZipWrite(output_zip, img_radio_path,
                                os.path.join("IMAGES", img_name))

            # Zip spec says: All slashes MUST be forward slashes.
            img_path = 'IMAGES/' + img_name
            assert img_path in output_zip.namelist(), "cannot find " + img_name

        if care_map_list:
            file_path = "META/care_map.txt"
            common.ZipWriteStr(output_zip, file_path, '\n'.join(care_map_list))

    common.ZipClose(output_zip)
Beispiel #23
0
def main(argv):
    bootable_only = [False]

    def option_handler(o, _):
        if o in ("-z", "--bootable_zip"):
            bootable_only[0] = True
        else:
            return False
        return True

    args = common.ParseOptions(argv,
                               __doc__,
                               extra_opts="z",
                               extra_long_opts=["bootable_zip"],
                               extra_option_handler=option_handler)

    bootable_only = bootable_only[0]

    if len(args) != 2:
        common.Usage(__doc__)
        sys.exit(1)

    OPTIONS.input_tmp, input_zip = common.UnzipTemp(args[0])
    output_zip = zipfile.ZipFile(args[1],
                                 "w",
                                 compression=zipfile.ZIP_DEFLATED)
    CopyInfo(output_zip)
    AddRadio(output_zip)

    try:
        done = False
        images_path = os.path.join(OPTIONS.input_tmp, "IMAGES")
        if os.path.exists(images_path):
            # If this is a new target-files, it already contains the images,
            # and all we have to do is copy them to the output zip.
            # Skip oem.img files since they are not needed in fastboot images.
            images = os.listdir(images_path)
            if images:
                for image in images:
                    if bootable_only and image not in ("boot.img",
                                                       "recovery.img"):
                        continue
                    if not image.endswith(".img"):
                        continue
                    if image == "oem.img" or image == "recovery-two-step.img":
                        continue
                    common.ZipWrite(output_zip,
                                    os.path.join(images_path, image), image)
                done = True

        if not done:
            # We have an old target-files that doesn't already contain the
            # images, so build them.
            import add_img_to_target_files

            OPTIONS.info_dict = common.LoadInfoDict(input_zip,
                                                    OPTIONS.input_tmp)

            boot_image = common.GetBootableImage("boot.img", "boot.img",
                                                 OPTIONS.input_tmp, "BOOT")
            if boot_image:
                boot_image.AddToZip(output_zip)

            if OPTIONS.info_dict.get("no_recovery") != "true":
                recovery_image = common.GetBootableImage(
                    "recovery.img", "recovery.img", OPTIONS.input_tmp,
                    "RECOVERY")
                if recovery_image:
                    recovery_image.AddToZip(output_zip)

            def banner(s):
                print("\n\n++++ " + s + " ++++\n\n")

            if not bootable_only:
                banner("AddSystem")
                add_img_to_target_files.AddSystem(output_zip, prefix="")
                try:
                    input_zip.getinfo("VENDOR/")
                    banner("AddVendor")
                    add_img_to_target_files.AddVendor(output_zip, prefix="")
                except KeyError:
                    pass  # no vendor partition for this device
                banner("AddUserdata")
                add_img_to_target_files.AddUserdata(output_zip, prefix="")
                banner("AddUserdataExtra")
                add_img_to_target_files.AddUserdataExtra(output_zip, prefix="")
                banner("AddCache")
                add_img_to_target_files.AddCache(output_zip, prefix="")

    finally:
        print("cleaning up...")
        common.ZipClose(output_zip)
        shutil.rmtree(OPTIONS.input_tmp)

    print("done.")
Beispiel #24
0
def main(argv):

  key_mapping_options = []

  def option_handler(o, a):
    if o in ("-e", "--extra_apks"):
      names, key = a.split("=")
      names = names.split(",")
      for n in names:
        OPTIONS.extra_apks[n] = key
    elif o in ("-d", "--default_key_mappings"):
      key_mapping_options.append((None, a))
    elif o in ("-k", "--key_mapping"):
      key_mapping_options.append(a.split("=", 1))
    elif o in ("-o", "--replace_ota_keys"):
      OPTIONS.replace_ota_keys = True
    elif o in ("-t", "--tag_changes"):
      new = []
      for i in a.split(","):
        i = i.strip()
        if not i or i[0] not in "-+":
          raise ValueError("Bad tag change '%s'" % (i,))
        new.append(i[0] + i[1:].strip())
      OPTIONS.tag_changes = tuple(new)
    elif o == "--replace_verity_public_key":
      OPTIONS.replace_verity_public_key = (True, a)
    elif o == "--replace_verity_private_key":
      OPTIONS.replace_verity_private_key = (True, a)
    elif o == "--replace_verity_keyid":
      OPTIONS.replace_verity_keyid = (True, a)
    elif o == "--avb_vbmeta_key":
      OPTIONS.avb_keys['vbmeta'] = a
    elif o == "--avb_vbmeta_algorithm":
      OPTIONS.avb_algorithms['vbmeta'] = a
    elif o == "--avb_vbmeta_extra_args":
      OPTIONS.avb_extra_args['vbmeta'] = a
    elif o == "--avb_boot_key":
      OPTIONS.avb_keys['boot'] = a
    elif o == "--avb_boot_algorithm":
      OPTIONS.avb_algorithms['boot'] = a
    elif o == "--avb_boot_extra_args":
      OPTIONS.avb_extra_args['boot'] = a
    elif o == "--avb_dtbo_key":
      OPTIONS.avb_keys['dtbo'] = a
    elif o == "--avb_dtbo_algorithm":
      OPTIONS.avb_algorithms['dtbo'] = a
    elif o == "--avb_dtbo_extra_args":
      OPTIONS.avb_extra_args['dtbo'] = a
    elif o == "--avb_system_key":
      OPTIONS.avb_keys['system'] = a
    elif o == "--avb_system_algorithm":
      OPTIONS.avb_algorithms['system'] = a
    elif o == "--avb_system_extra_args":
      OPTIONS.avb_extra_args['system'] = a
    elif o == "--avb_vendor_key":
      OPTIONS.avb_keys['vendor'] = a
    elif o == "--avb_vendor_algorithm":
      OPTIONS.avb_algorithms['vendor'] = a
    elif o == "--avb_vendor_extra_args":
      OPTIONS.avb_extra_args['vendor'] = a
    else:
      return False
    return True

  args = common.ParseOptions(
      argv, __doc__,
      extra_opts="e:d:k:ot:",
      extra_long_opts=[
        "extra_apks=",
        "default_key_mappings=",
        "key_mapping=",
        "replace_ota_keys",
        "tag_changes=",
        "replace_verity_public_key=",
        "replace_verity_private_key=",
        "replace_verity_keyid=",
        "avb_vbmeta_algorithm=",
        "avb_vbmeta_key=",
        "avb_vbmeta_extra_args=",
        "avb_boot_algorithm=",
        "avb_boot_key=",
        "avb_boot_extra_args=",
        "avb_dtbo_algorithm=",
        "avb_dtbo_key=",
        "avb_dtbo_extra_args=",
        "avb_system_algorithm=",
        "avb_system_key=",
        "avb_system_extra_args=",
        "avb_vendor_algorithm=",
        "avb_vendor_key=",
        "avb_vendor_extra_args=",
      ],
      extra_option_handler=option_handler)

  if len(args) != 2:
    common.Usage(__doc__)
    sys.exit(1)

  input_zip = zipfile.ZipFile(args[0], "r")
  output_zip = zipfile.ZipFile(args[1], "w")

  misc_info = common.LoadInfoDict(input_zip)

  BuildKeyMap(misc_info, key_mapping_options)

  apk_key_map = GetApkCerts(input_zip)
  CheckAllApksSigned(input_zip, apk_key_map)

  key_passwords = common.GetKeyPasswords(set(apk_key_map.values()))
  platform_api_level, _ = GetApiLevelAndCodename(input_zip)
  codename_to_api_level_map = GetCodenameToApiLevelMap(input_zip)

  ProcessTargetFiles(input_zip, output_zip, misc_info,
                     apk_key_map, key_passwords,
                     platform_api_level,
                     codename_to_api_level_map)

  common.ZipClose(input_zip)
  common.ZipClose(output_zip)

  # Skip building userdata.img and cache.img when signing the target files.
  new_args = ["--is_signing"]
  # add_img_to_target_files builds the system image from scratch, so the
  # recovery patch is guaranteed to be regenerated there.
  if OPTIONS.rebuild_recovery:
    new_args.append("--rebuild_recovery")
  new_args.append(args[1])
  add_img_to_target_files.main(new_args)

  print "done."
Beispiel #25
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")):
            print("target_files appears to already contain images.")
            sys.exit(1)

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

    has_recovery = OPTIONS.info_dict.get("no_recovery") != "true"

    # {vendor,product}.img is 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}.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")))
        and OPTIONS.info_dict.get("vendor_prebuilt_installed") != "true")
    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_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 = dict()

    def banner(s):
        print("\n\n++++ " + s + " ++++\n\n")

    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)

    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(
                "IMAGES/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, "IMAGES", "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)

    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)

    if has_product:
        banner("product")
        partitions['product'] = AddProduct(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":
        banner("vbmeta")
        AddVBMeta(output_zip, partitions)

    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, 'r') as f:
            ab_partitions = f.readlines()

        # For devices using A/B update, copy over images from RADIO/ and/or
        # VENDOR_IMAGES/ to IMAGES/ and make sure we have all the needed
        # images ready under IMAGES/. All images should have '.img' as extension.
        AddRadioImagesForAbOta(output_zip, ab_partitions)

        # Generate care_map.txt for system and vendor partitions (if present), then
        # write this file to target_files package.
        AddCareMapTxtForAbOta(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, 'r') 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)
Beispiel #26
0
def main(argv):

  key_mapping_options = []

  def option_handler(o, a):
    if o in ("-e", "--extra_apks"):
      names, key = a.split("=")
      names = names.split(",")
      for n in names:
        OPTIONS.extra_apks[n] = key
    elif o == "--extra_apex_payload_key":
      apex_name, key = a.split("=")
      OPTIONS.extra_apex_payload_keys[apex_name] = key
    elif o == "--skip_apks_with_path_prefix":
      # Sanity check the prefix, which must be in all upper case.
      prefix = a.split('/')[0]
      if not prefix or prefix != prefix.upper():
        raise ValueError("Invalid path prefix '%s'" % (a,))
      OPTIONS.skip_apks_with_path_prefix.add(a)
    elif o in ("-d", "--default_key_mappings"):
      key_mapping_options.append((None, a))
    elif o in ("-k", "--key_mapping"):
      key_mapping_options.append(a.split("=", 1))
    elif o in ("-o", "--replace_ota_keys"):
      OPTIONS.replace_ota_keys = True
    elif o in ("-t", "--tag_changes"):
      new = []
      for i in a.split(","):
        i = i.strip()
        if not i or i[0] not in "-+":
          raise ValueError("Bad tag change '%s'" % (i,))
        new.append(i[0] + i[1:].strip())
      OPTIONS.tag_changes = tuple(new)
    elif o == "--replace_verity_public_key":
      OPTIONS.replace_verity_public_key = (True, a)
    elif o == "--replace_verity_private_key":
      OPTIONS.replace_verity_private_key = (True, a)
    elif o == "--replace_verity_keyid":
      OPTIONS.replace_verity_keyid = (True, a)
    elif o == "--avb_vbmeta_key":
      OPTIONS.avb_keys['vbmeta'] = a
    elif o == "--avb_vbmeta_algorithm":
      OPTIONS.avb_algorithms['vbmeta'] = a
    elif o == "--avb_vbmeta_extra_args":
      OPTIONS.avb_extra_args['vbmeta'] = a
    elif o == "--avb_boot_key":
      OPTIONS.avb_keys['boot'] = a
    elif o == "--avb_boot_algorithm":
      OPTIONS.avb_algorithms['boot'] = a
    elif o == "--avb_boot_extra_args":
      OPTIONS.avb_extra_args['boot'] = a
    elif o == "--avb_dtbo_key":
      OPTIONS.avb_keys['dtbo'] = a
    elif o == "--avb_dtbo_algorithm":
      OPTIONS.avb_algorithms['dtbo'] = a
    elif o == "--avb_dtbo_extra_args":
      OPTIONS.avb_extra_args['dtbo'] = a
    elif o == "--avb_system_key":
      OPTIONS.avb_keys['system'] = a
    elif o == "--avb_system_algorithm":
      OPTIONS.avb_algorithms['system'] = a
    elif o == "--avb_system_extra_args":
      OPTIONS.avb_extra_args['system'] = a
    elif o == "--avb_system_other_key":
      OPTIONS.avb_keys['system_other'] = a
    elif o == "--avb_system_other_algorithm":
      OPTIONS.avb_algorithms['system_other'] = a
    elif o == "--avb_system_other_extra_args":
      OPTIONS.avb_extra_args['system_other'] = a
    elif o == "--avb_vendor_key":
      OPTIONS.avb_keys['vendor'] = a
    elif o == "--avb_vendor_algorithm":
      OPTIONS.avb_algorithms['vendor'] = a
    elif o == "--avb_vendor_extra_args":
      OPTIONS.avb_extra_args['vendor'] = a
    elif o == "--avb_vbmeta_system_key":
      OPTIONS.avb_keys['vbmeta_system'] = a
    elif o == "--avb_vbmeta_system_algorithm":
      OPTIONS.avb_algorithms['vbmeta_system'] = a
    elif o == "--avb_vbmeta_system_extra_args":
      OPTIONS.avb_extra_args['vbmeta_system'] = a
    elif o == "--avb_vbmeta_vendor_key":
      OPTIONS.avb_keys['vbmeta_vendor'] = a
    elif o == "--avb_vbmeta_vendor_algorithm":
      OPTIONS.avb_algorithms['vbmeta_vendor'] = a
    elif o == "--avb_vbmeta_vendor_extra_args":
      OPTIONS.avb_extra_args['vbmeta_vendor'] = a
    elif o == "--avb_apex_extra_args":
      OPTIONS.avb_extra_args['apex'] = a
    else:
      return False
    return True

  args = common.ParseOptions(
      argv, __doc__,
      extra_opts="e:d:k:ot:",
      extra_long_opts=[
          "extra_apks=",
          "extra_apex_payload_key=",
          "skip_apks_with_path_prefix=",
          "default_key_mappings=",
          "key_mapping=",
          "replace_ota_keys",
          "tag_changes=",
          "replace_verity_public_key=",
          "replace_verity_private_key=",
          "replace_verity_keyid=",
          "avb_apex_extra_args=",
          "avb_vbmeta_algorithm=",
          "avb_vbmeta_key=",
          "avb_vbmeta_extra_args=",
          "avb_boot_algorithm=",
          "avb_boot_key=",
          "avb_boot_extra_args=",
          "avb_dtbo_algorithm=",
          "avb_dtbo_key=",
          "avb_dtbo_extra_args=",
          "avb_system_algorithm=",
          "avb_system_key=",
          "avb_system_extra_args=",
          "avb_system_other_algorithm=",
          "avb_system_other_key=",
          "avb_system_other_extra_args=",
          "avb_vendor_algorithm=",
          "avb_vendor_key=",
          "avb_vendor_extra_args=",
          "avb_vbmeta_system_algorithm=",
          "avb_vbmeta_system_key=",
          "avb_vbmeta_system_extra_args=",
          "avb_vbmeta_vendor_algorithm=",
          "avb_vbmeta_vendor_key=",
          "avb_vbmeta_vendor_extra_args=",
      ],
      extra_option_handler=option_handler)

  if len(args) != 2:
    common.Usage(__doc__)
    sys.exit(1)

  common.InitLogging()

  input_zip = zipfile.ZipFile(args[0], "r")
  output_zip = zipfile.ZipFile(args[1], "w",
                               compression=zipfile.ZIP_DEFLATED,
                               allowZip64=True)

  misc_info = common.LoadInfoDict(input_zip)

  BuildKeyMap(misc_info, key_mapping_options)

  apk_keys_info, compressed_extension = common.ReadApkCerts(input_zip)
  apk_keys = GetApkCerts(apk_keys_info)

  apex_keys_info = ReadApexKeysInfo(input_zip)
  apex_keys = GetApexKeys(apex_keys_info, apk_keys)

  CheckApkAndApexKeysAvailable(
      input_zip,
      set(apk_keys.keys()) | set(apex_keys.keys()),
      compressed_extension,
      apex_keys)

  key_passwords = common.GetKeyPasswords(
      set(apk_keys.values()) | set(itertools.chain(*apex_keys.values())))
  platform_api_level, _ = GetApiLevelAndCodename(input_zip)
  codename_to_api_level_map = GetCodenameToApiLevelMap(input_zip)

  ProcessTargetFiles(input_zip, output_zip, misc_info,
                     apk_keys, apex_keys, key_passwords,
                     platform_api_level, codename_to_api_level_map,
                     compressed_extension)

  common.ZipClose(input_zip)
  common.ZipClose(output_zip)

  # Skip building userdata.img and cache.img when signing the target files.
  new_args = ["--is_signing"]
  # add_img_to_target_files builds the system image from scratch, so the
  # recovery patch is guaranteed to be regenerated there.
  if OPTIONS.rebuild_recovery:
    new_args.append("--rebuild_recovery")
  new_args.append(args[1])
  add_img_to_target_files.main(new_args)

  print("done.")
def AddImagesToTargetFiles(filename):
    if os.path.isdir(filename):
        OPTIONS.input_tmp = os.path.abspath(filename)
        input_zip = None
    else:
        OPTIONS.input_tmp, input_zip = common.UnzipTemp(filename)

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

    has_vendor = os.path.isdir(os.path.join(OPTIONS.input_tmp, "VENDOR"))
    has_system_other = os.path.isdir(
        os.path.join(OPTIONS.input_tmp, "SYSTEM_OTHER"))

    if input_zip:
        OPTIONS.info_dict = common.LoadInfoDict(input_zip, OPTIONS.input_tmp)

        common.ZipClose(input_zip)
        output_zip = zipfile.ZipFile(filename,
                                     "a",
                                     compression=zipfile.ZIP_DEFLATED,
                                     allowZip64=True)
    else:
        OPTIONS.info_dict = common.LoadInfoDict(filename, filename)
        output_zip = None
        images_dir = os.path.join(OPTIONS.input_tmp, "IMAGES")
        if not os.path.isdir(images_dir):
            os.makedirs(images_dir)
        images_dir = None

    has_recovery = (OPTIONS.info_dict.get("no_recovery") != "true")

    def banner(s):
        print("\n\n++++ " + s + " ++++\n\n")

    prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", "boot.img")
    boot_image = None
    if os.path.exists(prebuilt_path):
        banner("boot")
        print("boot.img already exists in IMAGES/, no need to rebuild...")
        if OPTIONS.rebuild_recovery:
            boot_image = common.GetBootableImage("IMAGES/boot.img", "boot.img",
                                                 OPTIONS.input_tmp, "BOOT")
    else:
        banner("boot")
        boot_image = common.GetBootableImage("IMAGES/boot.img", "boot.img",
                                             OPTIONS.input_tmp, "BOOT")
        if boot_image:
            if output_zip:
                boot_image.AddToZip(output_zip)
            else:
                boot_image.WriteToDir(OPTIONS.input_tmp)

    recovery_image = None
    if has_recovery:
        banner("recovery")
        prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES",
                                     "recovery.img")
        if os.path.exists(prebuilt_path):
            print(
                "recovery.img already exists in IMAGES/, no need to rebuild..."
            )
            if OPTIONS.rebuild_recovery:
                recovery_image = common.GetBootableImage(
                    "IMAGES/recovery.img", "recovery.img", OPTIONS.input_tmp,
                    "RECOVERY")
        else:
            recovery_image = common.GetBootableImage("IMAGES/recovery.img",
                                                     "recovery.img",
                                                     OPTIONS.input_tmp,
                                                     "RECOVERY")
            if recovery_image:
                if output_zip:
                    recovery_image.AddToZip(output_zip)
                else:
                    recovery_image.WriteToDir(OPTIONS.input_tmp)

            banner("recovery (two-step image)")
            # The special recovery.img for two-step package use.
            recovery_two_step_image = common.GetBootableImage(
                "IMAGES/recovery-two-step.img",
                "recovery-two-step.img",
                OPTIONS.input_tmp,
                "RECOVERY",
                two_step_image=True)
            if recovery_two_step_image:
                if output_zip:
                    recovery_two_step_image.AddToZip(output_zip)
                else:
                    recovery_two_step_image.WriteToDir(OPTIONS.input_tmp)

    banner("system")
    system_img_path = AddSystem(output_zip,
                                recovery_img=recovery_image,
                                boot_img=boot_image)
    vendor_img_path = None
    if has_vendor:
        banner("vendor")
        vendor_img_path = AddVendor(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)

    dtbo_img_path = None
    if OPTIONS.info_dict.get("has_dtbo") == "true":
        banner("dtbo")
        dtbo_img_path = AddDtbo(output_zip)

    if OPTIONS.info_dict.get("avb_enable") == "true":
        banner("vbmeta")
        boot_contents = boot_image.WriteToTemp()
        AddVBMeta(output_zip, boot_contents.name, system_img_path,
                  vendor_img_path, dtbo_img_path)

    # For devices using A/B update, copy over images from RADIO/ and/or
    # VENDOR_IMAGES/ to IMAGES/ and make sure we have all the needed
    # images ready under IMAGES/. All images should have '.img' as extension.
    banner("radio")
    ab_partitions = os.path.join(OPTIONS.input_tmp, "META",
                                 "ab_partitions.txt")
    if os.path.exists(ab_partitions):
        with open(ab_partitions, 'r') as f:
            lines = f.readlines()
        # For devices using A/B update, generate care_map for system and vendor
        # partitions (if present), then write this file to target_files package.
        care_map_list = []
        for line in lines:
            if line.strip() == "system" and (
                    "system_verity_block_device" in OPTIONS.info_dict
                    or OPTIONS.info_dict.get("avb_system_hashtree_enable")
                    == "true"):
                assert os.path.exists(system_img_path)
                care_map_list += GetCareMap("system", system_img_path)
            if line.strip() == "vendor" and (
                    "vendor_verity_block_device" in OPTIONS.info_dict
                    or OPTIONS.info_dict.get("avb_vendor_hashtree_enable")
                    == "true"):
                assert os.path.exists(vendor_img_path)
                care_map_list += GetCareMap("vendor", vendor_img_path)

            img_name = line.strip() + ".img"
            prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
            if os.path.exists(prebuilt_path):
                print("%s already exists, no need to overwrite..." %
                      (img_name, ))
                continue

            img_radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
            img_vendor_dir = os.path.join(OPTIONS.input_tmp, "VENDOR_IMAGES")
            if os.path.exists(img_radio_path):
                if output_zip:
                    common.ZipWrite(output_zip, img_radio_path,
                                    os.path.join("IMAGES", img_name))
                else:
                    shutil.copy(img_radio_path, prebuilt_path)
            else:
                for root, _, files in os.walk(img_vendor_dir):
                    if img_name in files:
                        if output_zip:
                            common.ZipWrite(output_zip,
                                            os.path.join(root, img_name),
                                            os.path.join("IMAGES", img_name))
                        else:
                            shutil.copy(os.path.join(root, img_name),
                                        prebuilt_path)
                        break

            if output_zip:
                # Zip spec says: All slashes MUST be forward slashes.
                img_path = 'IMAGES/' + img_name
                assert img_path in output_zip.namelist(
                ), "cannot find " + img_name
            else:
                img_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
                assert os.path.exists(img_path), "cannot find " + img_name

        if care_map_list:
            care_map_path = "META/care_map.txt"
            if output_zip and care_map_path not in output_zip.namelist():
                common.ZipWriteStr(output_zip, care_map_path,
                                   '\n'.join(care_map_list))
            else:
                with open(os.path.join(OPTIONS.input_tmp, care_map_path),
                          'w') as fp:
                    fp.write('\n'.join(care_map_list))
                if output_zip:
                    OPTIONS.replace_updated_files_list.append(care_map_path)

    # Radio images that need to be packed into IMAGES/, and product-img.zip.
    pack_radioimages = os.path.join(OPTIONS.input_tmp, "META",
                                    "pack_radioimages.txt")
    if os.path.exists(pack_radioimages):
        with open(pack_radioimages, 'r') as f:
            lines = f.readlines()
        for line in lines:
            img_name = line.strip()
            _, ext = os.path.splitext(img_name)
            if not ext:
                img_name += ".img"
            prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
            if os.path.exists(prebuilt_path):
                print("%s already exists, no need to overwrite..." %
                      (img_name, ))
                continue

            img_radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
            assert os.path.exists(img_radio_path), \
                "Failed to find %s at %s" % (img_name, img_radio_path)
            if output_zip:
                common.ZipWrite(output_zip, img_radio_path,
                                os.path.join("IMAGES", img_name))
            else:
                shutil.copy(img_radio_path, prebuilt_path)

    if output_zip:
        common.ZipClose(output_zip)
        if OPTIONS.replace_updated_files_list:
            ReplaceUpdatedFiles(output_zip.filename,
                                OPTIONS.replace_updated_files_list)
def main(argv):
    bootable_only = [False]

    def option_handler(o, a):
        if o in ("-z", "--bootable_zip"):
            bootable_only[0] = True
        else:
            return False
        return True

    args = common.ParseOptions(argv,
                               __doc__,
                               extra_opts="z",
                               extra_long_opts=["bootable_zip"],
                               extra_option_handler=option_handler)

    bootable_only = bootable_only[0]

    if len(args) != 2:
        common.Usage(__doc__)
        sys.exit(1)

    OPTIONS.input_tmp, input_zip = common.UnzipTemp(args[0])
    output_zip = zipfile.ZipFile(args[1],
                                 "w",
                                 compression=zipfile.ZIP_DEFLATED,
                                 allowZip64=True)
    CopyInfo(output_zip)

    try:
        done = False
        images_path = os.path.join(OPTIONS.input_tmp, "IMAGES")
        if os.path.exists(images_path):
            # If this is a new target-files, it already contains the images,
            # and all we have to do is copy them to the output zip.
            images = os.listdir(images_path)
            if images:
                for i in images:
                    if bootable_only and i not in ("boot.img", "recovery.img"):
                        continue
                    if not i.endswith(".img"): continue
                    with open(os.path.join(images_path, i), "r") as f:
                        common.ZipWriteStr(output_zip, i, f.read())
                done = True

        if not done:
            # We have an old target-files that doesn't already contain the
            # images, so build them.
            import add_img_to_target_files

            OPTIONS.info_dict = common.LoadInfoDict(input_zip)

            # If this image was originally labelled with SELinux contexts,
            # make sure we also apply the labels in our new image. During
            # building, the "file_contexts" is in the out/ directory tree,
            # but for repacking from target-files.zip it's in the root
            # directory of the ramdisk.
            if "selinux_fc" in OPTIONS.info_dict:
                OPTIONS.info_dict["selinux_fc"] = os.path.join(
                    OPTIONS.input_tmp, "BOOT", "RAMDISK", "file_contexts")

            boot_image = common.GetBootableImage("boot.img", "boot.img",
                                                 OPTIONS.input_tmp, "BOOT")
            if boot_image:
                boot_image.AddToZip(output_zip)
            recovery_image = common.GetBootableImage("recovery.img",
                                                     "recovery.img",
                                                     OPTIONS.input_tmp,
                                                     "RECOVERY")
            if recovery_image:
                recovery_image.AddToZip(output_zip)

            def banner(s):
                print "\n\n++++ " + s + " ++++\n\n"

            if not bootable_only:
                banner("AddSystem")
                add_img_to_target_files.AddSystem(output_zip, prefix="")
                try:
                    input_zip.getinfo("VENDOR/")
                    banner("AddVendor")
                    add_img_to_target_files.AddVendor(output_zip, prefix="")
                except KeyError:
                    pass  # no vendor partition for this device
                try:
                    input_zip.getinfo("CUSTOM/")
                    banner("AddCustom")
                    add_img_to_target_files.AddCustom(output_zip, prefix="")
                except KeyError:
                    pass  # no custom partition for this device
                banner("AddUserdata")
                add_img_to_target_files.AddUserdata(output_zip, prefix="")
                banner("AddCache")
                add_img_to_target_files.AddCache(output_zip, prefix="")

    finally:
        print "cleaning up..."
        output_zip.close()
        shutil.rmtree(OPTIONS.input_tmp)

    print "done."
Beispiel #29
0
def main(argv):

    key_mapping_options = []

    def option_handler(o, a):
        if o in ("-e", "--extra_apks"):
            names, key = a.split("=")
            names = names.split(",")
            for n in names:
                OPTIONS.extra_apks[n] = key
        elif o in ("-d", "--default_key_mappings"):
            key_mapping_options.append((None, a))
        elif o in ("-k", "--key_mapping"):
            key_mapping_options.append(a.split("=", 1))
        elif o in ("-o", "--replace_ota_keys"):
            OPTIONS.replace_ota_keys = True
        elif o in ("-t", "--tag_changes"):
            new = []
            for i in a.split(","):
                i = i.strip()
                if not i or i[0] not in "-+":
                    raise ValueError("Bad tag change '%s'" % (i, ))
                new.append(i[0] + i[1:].strip())
            OPTIONS.tag_changes = tuple(new)
        elif o == "--replace_verity_public_key":
            OPTIONS.replace_verity_public_key = (True, a)
        elif o == "--replace_verity_private_key":
            OPTIONS.replace_verity_private_key = (True, a)
        else:
            return False
        return True

    args = common.ParseOptions(argv,
                               __doc__,
                               extra_opts="e:d:k:ot:",
                               extra_long_opts=[
                                   "extra_apks=", "default_key_mappings=",
                                   "key_mapping=", "replace_ota_keys",
                                   "tag_changes=",
                                   "replace_verity_public_key=",
                                   "replace_verity_private_key="
                               ],
                               extra_option_handler=option_handler)

    if len(args) != 2:
        common.Usage(__doc__)
        sys.exit(1)

    input_zip = zipfile.ZipFile(args[0], "r")
    output_zip = zipfile.ZipFile(args[1], "w")

    misc_info = common.LoadInfoDict(input_zip)

    BuildKeyMap(misc_info, key_mapping_options)

    apk_key_map = GetApkCerts(input_zip)
    CheckAllApksSigned(input_zip, apk_key_map)

    key_passwords = common.GetKeyPasswords(set(apk_key_map.values()))
    ProcessTargetFiles(input_zip, output_zip, misc_info, apk_key_map,
                       key_passwords)

    common.ZipClose(input_zip)
    common.ZipClose(output_zip)

    add_img_to_target_files.AddImagesToTargetFiles(args[1],
                                                   rebuild_recovery=True)

    print("done.")
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)
        input_zip = None
    else:
        OPTIONS.input_tmp, input_zip = common.UnzipTemp(filename)

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

    # vendor.img is 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.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_system_other = os.path.isdir(
        os.path.join(OPTIONS.input_tmp, "SYSTEM_OTHER"))

    if input_zip:
        OPTIONS.info_dict = common.LoadInfoDict(input_zip, OPTIONS.input_tmp)

        common.ZipClose(input_zip)
        output_zip = zipfile.ZipFile(filename,
                                     "a",
                                     compression=zipfile.ZIP_DEFLATED,
                                     allowZip64=True)
    else:
        OPTIONS.info_dict = common.LoadInfoDict(filename, filename)
        output_zip = None

    # 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)

    has_recovery = (OPTIONS.info_dict.get("no_recovery") != "true")

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

    def banner(s):
        print("\n\n++++ " + s + " ++++\n\n")

    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)

    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(
                "IMAGES/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, "IMAGES", "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)

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

    if has_vendor:
        banner("vendor")
        partitions['vendor'] = vendor_img_path = AddVendor(output_zip)

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

    if not OPTIONS.is_signing:
        banner("userdata")
        AddUserdata(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":
        banner("vbmeta")
        AddVBMeta(output_zip, partitions)

    if OPTIONS.info_dict.get("avb_disabled_vbmeta") == "true":
        banner("vbmeta")
        AddDisabledVBMeta(output_zip)

    # For devices using A/B update, copy over images from RADIO/ and/or
    # VENDOR_IMAGES/ to IMAGES/ and make sure we have all the needed
    # images ready under IMAGES/. All images should have '.img' as extension.
    banner("radio")
    ab_partitions = os.path.join(OPTIONS.input_tmp, "META",
                                 "ab_partitions.txt")
    if os.path.exists(ab_partitions):
        with open(ab_partitions, 'r') as f:
            lines = f.readlines()
        # For devices using A/B update, generate care_map for system and vendor
        # partitions (if present), then write this file to target_files package.
        care_map_list = []
        for line in lines:
            if line.strip() == "system" and (
                    "system_verity_block_device" in OPTIONS.info_dict
                    or OPTIONS.info_dict.get("avb_system_hashtree_enable")
                    == "true"):
                assert os.path.exists(system_img_path)
                care_map_list += GetCareMap("system", system_img_path)
            if line.strip() == "vendor" and (
                    "vendor_verity_block_device" in OPTIONS.info_dict
                    or OPTIONS.info_dict.get("avb_vendor_hashtree_enable")
                    == "true"):
                assert os.path.exists(vendor_img_path)
                care_map_list += GetCareMap("vendor", vendor_img_path)

            img_name = line.strip() + ".img"
            prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
            if os.path.exists(prebuilt_path):
                print("%s already exists, no need to overwrite..." %
                      (img_name, ))
                continue

            img_radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
            img_vendor_dir = os.path.join(OPTIONS.input_tmp, "VENDOR_IMAGES")
            if os.path.exists(img_radio_path):
                if output_zip:
                    common.ZipWrite(output_zip, img_radio_path,
                                    os.path.join("IMAGES", img_name))
                else:
                    shutil.copy(img_radio_path, prebuilt_path)
            else:
                for root, _, files in os.walk(img_vendor_dir):
                    if img_name in files:
                        if output_zip:
                            common.ZipWrite(output_zip,
                                            os.path.join(root, img_name),
                                            os.path.join("IMAGES", img_name))
                        else:
                            shutil.copy(os.path.join(root, img_name),
                                        prebuilt_path)
                        break

            if output_zip:
                # Zip spec says: All slashes MUST be forward slashes.
                img_path = 'IMAGES/' + img_name
                assert img_path in output_zip.namelist(
                ), "cannot find " + img_name
            else:
                img_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
                assert os.path.exists(img_path), "cannot find " + img_name

        if care_map_list:
            care_map_path = "META/care_map.txt"
            if output_zip and care_map_path not in output_zip.namelist():
                common.ZipWriteStr(output_zip, care_map_path,
                                   '\n'.join(care_map_list))
            else:
                with open(os.path.join(OPTIONS.input_tmp, care_map_path),
                          'w') as fp:
                    fp.write('\n'.join(care_map_list))
                if output_zip:
                    OPTIONS.replace_updated_files_list.append(care_map_path)

    # Radio images that need to be packed into IMAGES/, and product-img.zip.
    pack_radioimages = os.path.join(OPTIONS.input_tmp, "META",
                                    "pack_radioimages.txt")
    if os.path.exists(pack_radioimages):
        with open(pack_radioimages, 'r') as f:
            lines = f.readlines()
        for line in lines:
            img_name = line.strip()
            _, ext = os.path.splitext(img_name)
            if not ext:
                img_name += ".img"
            prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
            if os.path.exists(prebuilt_path):
                print("%s already exists, no need to overwrite..." %
                      (img_name, ))
                continue

            img_radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
            assert os.path.exists(img_radio_path), \
                "Failed to find %s at %s" % (img_name, img_radio_path)
            if output_zip:
                common.ZipWrite(output_zip, img_radio_path,
                                os.path.join("IMAGES", img_name))
            else:
                shutil.copy(img_radio_path, prebuilt_path)

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