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)
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)
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'])
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'])
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
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'])
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()
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'])
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'])
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'])
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"))
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'))
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)
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)
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."
def AddImagesToTargetFiles(filename): """Creates and adds images (boot/recovery/system/...) to a target_files.zip. It works with either a zip file (zip mode), or a directory that contains the files to be packed into a target_files.zip (dir mode). The latter is used when being called from build/make/core/Makefile. The images will be created under IMAGES/ in the input target_files.zip. Args: filename: the target_files.zip, or the zip root directory. """ if os.path.isdir(filename): OPTIONS.input_tmp = os.path.abspath(filename) else: OPTIONS.input_tmp = common.UnzipTemp(filename) if not OPTIONS.add_missing: if os.path.isdir(os.path.join(OPTIONS.input_tmp, "IMAGES")): logger.warning("target_files appears to already contain images.") sys.exit(1) OPTIONS.info_dict = common.LoadInfoDict(OPTIONS.input_tmp, repacking=True) has_recovery = OPTIONS.info_dict.get("no_recovery") != "true" has_boot = OPTIONS.info_dict.get("no_boot") != "true" has_vendor_boot = OPTIONS.info_dict.get("vendor_boot") == "true" # {vendor,odm,product,system_ext,vendor_dlkm,odm_dlkm, system, system_other}.img # can be built from source, or dropped into target_files.zip as a prebuilt blob. has_vendor = HasPartition("vendor") has_odm = HasPartition("odm") has_vendor_dlkm = HasPartition("vendor_dlkm") has_odm_dlkm = HasPartition("odm_dlkm") has_product = HasPartition("product") has_system_ext = HasPartition("system_ext") has_system = HasPartition("system") has_system_other = HasPartition("system_other") has_userdata = OPTIONS.info_dict.get("building_userdata_image") == "true" has_cache = OPTIONS.info_dict.get("building_cache_image") == "true" # Set up the output destination. It writes to the given directory for dir # mode; otherwise appends to the given ZIP. if os.path.isdir(filename): output_zip = None else: output_zip = zipfile.ZipFile(filename, "a", compression=zipfile.ZIP_DEFLATED, allowZip64=True) # Always make input_tmp/IMAGES available, since we may stage boot / recovery # images there even under zip mode. The directory will be cleaned up as part # of OPTIONS.input_tmp. images_dir = os.path.join(OPTIONS.input_tmp, "IMAGES") if not os.path.isdir(images_dir): os.makedirs(images_dir) # A map between partition names and their paths, which could be used when # generating AVB vbmeta image. partitions = {} def banner(s): logger.info("\n\n++++ %s ++++\n\n", s) boot_image = None if has_boot: banner("boot") boot_images = OPTIONS.info_dict.get("boot_images") if boot_images is None: boot_images = "boot.img" for index, b in enumerate(boot_images.split()): # common.GetBootableImage() returns the image directly if present. boot_image = common.GetBootableImage("IMAGES/" + b, b, OPTIONS.input_tmp, "BOOT") # boot.img may be unavailable in some targets (e.g. aosp_arm64). if boot_image: boot_image_path = os.path.join(OPTIONS.input_tmp, "IMAGES", b) # Although multiple boot images can be generated, include the image # descriptor of only the first boot image in vbmeta if index == 0: partitions['boot'] = boot_image_path if not os.path.exists(boot_image_path): boot_image.WriteToDir(OPTIONS.input_tmp) if output_zip: boot_image.AddToZip(output_zip) if has_vendor_boot: banner("vendor_boot") vendor_boot_image = common.GetVendorBootImage("IMAGES/vendor_boot.img", "vendor_boot.img", OPTIONS.input_tmp, "VENDOR_BOOT") if vendor_boot_image: partitions['vendor_boot'] = os.path.join(OPTIONS.input_tmp, "IMAGES", "vendor_boot.img") if not os.path.exists(partitions['vendor_boot']): vendor_boot_image.WriteToDir(OPTIONS.input_tmp) if output_zip: vendor_boot_image.AddToZip(output_zip) recovery_image = None if has_recovery: banner("recovery") recovery_image = common.GetBootableImage("IMAGES/recovery.img", "recovery.img", OPTIONS.input_tmp, "RECOVERY") assert recovery_image, "Failed to create recovery.img." partitions['recovery'] = os.path.join(OPTIONS.input_tmp, "IMAGES", "recovery.img") if not os.path.exists(partitions['recovery']): recovery_image.WriteToDir(OPTIONS.input_tmp) if output_zip: recovery_image.AddToZip(output_zip) banner("recovery (two-step image)") # The special recovery.img for two-step package use. recovery_two_step_image = common.GetBootableImage( "OTA/recovery-two-step.img", "recovery-two-step.img", OPTIONS.input_tmp, "RECOVERY", two_step_image=True) assert recovery_two_step_image, "Failed to create recovery-two-step.img." recovery_two_step_image_path = os.path.join( OPTIONS.input_tmp, "OTA", "recovery-two-step.img") if not os.path.exists(recovery_two_step_image_path): recovery_two_step_image.WriteToDir(OPTIONS.input_tmp) if output_zip: recovery_two_step_image.AddToZip(output_zip) if has_system: banner("system") partitions['system'] = AddSystem(output_zip, recovery_img=recovery_image, boot_img=boot_image) if has_vendor: banner("vendor") partitions['vendor'] = AddVendor(output_zip, recovery_img=recovery_image, boot_img=boot_image) if has_product: banner("product") partitions['product'] = AddProduct(output_zip) if has_system_ext: banner("system_ext") partitions['system_ext'] = AddSystemExt(output_zip) if has_odm: banner("odm") partitions['odm'] = AddOdm(output_zip) if has_vendor_dlkm: banner("vendor_dlkm") partitions['vendor_dlkm'] = AddVendorDlkm(output_zip) if has_odm_dlkm: banner("odm_dlkm") partitions['odm_dlkm'] = AddOdmDlkm(output_zip) if has_system_other: banner("system_other") AddSystemOther(output_zip) AddApexInfo(output_zip) if not OPTIONS.is_signing: banner("userdata") AddUserdata(output_zip) banner("cache") AddCache(output_zip) if OPTIONS.info_dict.get("board_bpt_enable") == "true": banner("partition-table") AddPartitionTable(output_zip) if OPTIONS.info_dict.get("has_dtbo") == "true": banner("dtbo") partitions['dtbo'] = AddDtbo(output_zip) if OPTIONS.info_dict.get("has_pvmfw") == "true": banner("pvmfw") partitions['pvmfw'] = AddPvmfw(output_zip) # Custom images. custom_partitions = OPTIONS.info_dict.get( "avb_custom_images_partition_list", "").strip().split() for partition_name in custom_partitions: partition_name = partition_name.strip() banner("custom images for " + partition_name) partitions[partition_name] = AddCustomImages(output_zip, partition_name) if OPTIONS.info_dict.get("avb_enable") == "true": # vbmeta_partitions includes the partitions that should be included into # top-level vbmeta.img, which are the ones that are not included in any # chained VBMeta image plus the chained VBMeta images themselves. # Currently custom_partitions are all chained to VBMeta image. vbmeta_partitions = common.AVB_PARTITIONS[:] + tuple(custom_partitions) vbmeta_system = OPTIONS.info_dict.get("avb_vbmeta_system", "").strip() if vbmeta_system: banner("vbmeta_system") partitions["vbmeta_system"] = AddVBMeta(output_zip, partitions, "vbmeta_system", vbmeta_system.split()) vbmeta_partitions = [ item for item in vbmeta_partitions if item not in vbmeta_system.split() ] vbmeta_partitions.append("vbmeta_system") vbmeta_vendor = OPTIONS.info_dict.get("avb_vbmeta_vendor", "").strip() if vbmeta_vendor: banner("vbmeta_vendor") partitions["vbmeta_vendor"] = AddVBMeta(output_zip, partitions, "vbmeta_vendor", vbmeta_vendor.split()) vbmeta_partitions = [ item for item in vbmeta_partitions if item not in vbmeta_vendor.split() ] vbmeta_partitions.append("vbmeta_vendor") if OPTIONS.info_dict.get("avb_building_vbmeta_image") == "true": banner("vbmeta") AddVBMeta(output_zip, partitions, "vbmeta", vbmeta_partitions) if OPTIONS.info_dict.get("use_dynamic_partitions") == "true": if OPTIONS.info_dict.get("build_super_empty_partition") == "true": banner("super_empty") AddSuperEmpty(output_zip) if OPTIONS.info_dict.get("build_super_partition") == "true": if OPTIONS.info_dict.get( "build_retrofit_dynamic_partitions_ota_package") == "true": banner("super split images") AddSuperSplit(output_zip) banner("radio") ab_partitions_txt = os.path.join(OPTIONS.input_tmp, "META", "ab_partitions.txt") if os.path.exists(ab_partitions_txt): with open(ab_partitions_txt) as f: ab_partitions = f.readlines() # For devices using A/B update, make sure we have all the needed images # ready under IMAGES/ or RADIO/. CheckAbOtaImages(output_zip, ab_partitions) # Generate care_map.pb for ab_partitions, then write this file to # target_files package. output_care_map = os.path.join(OPTIONS.input_tmp, "META", "care_map.pb") AddCareMapForAbOta(output_zip if output_zip else output_care_map, ab_partitions, partitions) # Radio images that need to be packed into IMAGES/, and product-img.zip. pack_radioimages_txt = os.path.join(OPTIONS.input_tmp, "META", "pack_radioimages.txt") if os.path.exists(pack_radioimages_txt): with open(pack_radioimages_txt) as f: AddPackRadioImages(output_zip, f.readlines()) # Calculate the vbmeta digest and put the result in to META/ boot_images = OPTIONS.info_dict.get("boot_images") # Disable the digest calculation if the target_file is used as a container # for boot images. boot_container = boot_images and len(boot_images.split()) >= 2 if (OPTIONS.info_dict.get("avb_enable") == "true" and not boot_container and OPTIONS.info_dict.get("avb_building_vbmeta_image") == "true"): avbtool = OPTIONS.info_dict["avb_avbtool"] digest = verity_utils.CalculateVbmetaDigest(OPTIONS.input_tmp, avbtool) vbmeta_digest_txt = os.path.join(OPTIONS.input_tmp, "META", "vbmeta_digest.txt") with open(vbmeta_digest_txt, 'w') as f: f.write(digest) if output_zip: common.ZipClose(output_zip) if OPTIONS.replace_updated_files_list: ReplaceUpdatedFiles(output_zip.filename, OPTIONS.replace_updated_files_list)
def AddImagesToTargetFiles(filename): """Creates and adds images (boot/recovery/system/...) to a target_files.zip. It works with either a zip file (zip mode), or a directory that contains the files to be packed into a target_files.zip (dir mode). The latter is used when being called from build/make/core/Makefile. The images will be created under IMAGES/ in the input target_files.zip. Args: filename: the target_files.zip, or the zip root directory. """ if os.path.isdir(filename): OPTIONS.input_tmp = os.path.abspath(filename) else: OPTIONS.input_tmp = common.UnzipTemp(filename) if not OPTIONS.add_missing: if os.path.isdir(os.path.join(OPTIONS.input_tmp, "IMAGES")): logger.warning("target_files appears to already contain images.") sys.exit(1) OPTIONS.info_dict = common.LoadInfoDict(OPTIONS.input_tmp, repacking=True) has_recovery = OPTIONS.info_dict.get("no_recovery") != "true" # {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)
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)
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.")
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."
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)
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."
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)