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 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 WriteRawImages(info): print "WriteRawImages" image_info = LoadImageInfo(info.input_zip) if image_info is None: return fstab = info.info_dict["fstab"] try: bootareas_loc = fstab["/bootareas"].device fota_loc = fstab["/fota"].device flag_loc = fstab["/fota-flag"].device except KeyError: print "There is no bootareas/fota/fota-flag partition in recovery.fstab;" else: info.script.AppendExtra(('brcm.backup_bootareas("%s", "%s", "%s");') % (bootareas_loc, fota_loc, flag_loc)) for dir in sorted(image_info.keys()): image_name = image_info[dir] print "WriteRawImages,", dir, ":", image_name tmp_img = common.GetBootableImage(image_name, image_name, common.OPTIONS.input_tmp, "BOOTABLE_IMAGES") if tmp_img: common.ZipWriteStr(info.output_zip, image_name, tmp_img.data) info.script.WriteRawImage(dir, image_name) try: flag_loc = fstab["/fota-flag"].device except KeyError: print "There is no fota-flag partition in recovery.fstab;" else: info.script.AppendExtra(('brcm.clean_flag("%s");') % (flag_loc))
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 FullOTA_InstallEnd(info): # copy the vbmeta and dtbo into the package. try: vbmeta_img = common.GetBootableImage( "vbmeta.img", "vbmeta.img", OPTIONS.input_tmp, "VBMETA") dtbo_img = common.GetBootableImage( "dtbo.img", "dtbo.img", OPTIONS.input_tmp, "DTBO") except KeyError: print "no vbmeta or dtbo images in target_files; skipping install" return # copy the vbmeta into the package. common.ZipWriteStr(info.output_zip, "vbmeta.img", vbmeta_img.data) # emit the script code to trigger the vbmeta updater on the device info.script.WriteRawImage("/vbmeta", "vbmeta.img") # copy the dtbo into the package. common.ZipWriteStr(info.output_zip, "dtbo.img", dtbo_img.data) # emit the script code to trigger the dtbo updater on the device info.script.WriteRawImage("/dtbo", "dtbo.img")
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 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)
def WriteFullOTAPackage(input_zip, output_zip): # TODO: how to determine this? We don't know what version it will # be installed on top of. For now, we expect the API just won't # change very often. script = edify_generator.EdifyGenerator(3, OPTIONS.info_dict) if OPTIONS.override_prop: metadata = { "post-timestamp": GetBuildProp("ro.build.date.utc", OPTIONS.info_dict), } else: metadata = { "post-build": GetBuildProp("ro.build.fingerprint", OPTIONS.info_dict), "pre-device": GetBuildProp("ro.product.device", OPTIONS.info_dict), "post-timestamp": GetBuildProp("ro.build.date.utc", OPTIONS.info_dict), } device_specific = common.DeviceSpecificParams( input_zip=input_zip, input_version=OPTIONS.info_dict["recovery_api_version"], output_zip=output_zip, script=script, input_tmp=OPTIONS.input_tmp, metadata=metadata, info_dict=OPTIONS.info_dict) #if not OPTIONS.omit_prereq: # ts = GetBuildProp("ro.build.date.utc", OPTIONS.info_dict) # ts_text = GetBuildProp("ro.build.date", OPTIONS.info_dict) # script.AssertOlderBuild(ts, ts_text) AppendAssertions(script, OPTIONS.info_dict) device_specific.FullOTA_Assertions() device_specific.FullOTA_InstallBegin() if OPTIONS.backuptool: script.Mount("/system") script.RunBackup("backup") script.Unmount("/system") script.ShowProgress(0.5, 0) if OPTIONS.wipe_user_data: script.FormatPartition("/data") if "selinux_fc" in OPTIONS.info_dict: WritePolicyConfig(OPTIONS.info_dict["selinux_fc"], output_zip) script.FormatPartition("/system") script.Mount("/system") #script.UnpackPackageDir("recovery", "/system") script.UnpackPackageDir("system", "/system") symlinks = CopySystemFiles(input_zip, output_zip) script.MakeSymlinks(symlinks) boot_img = common.GetBootableImage("boot.img", "boot.img", OPTIONS.input_tmp, "BOOT") #recovery_img = common.GetBootableImage("recovery.img", "recovery.img", # OPTIONS.input_tmp, "RECOVERY") #MakeRecoveryPatch(OPTIONS.input_tmp, output_zip, recovery_img, boot_img) Item.GetMetadata(input_zip) Item.Get("system").SetPermissions(script) common.CheckSize(boot_img.data, "boot.img", OPTIONS.info_dict) common.ZipWriteStr(output_zip, "boot.img", boot_img.data) script.ShowProgress(0.2, 0) if OPTIONS.backuptool: script.ShowProgress(0.2, 10) script.RunBackup("restore") script.ShowProgress(0.2, 10) script.WriteRawImage("/boot", "boot.img") script.ShowProgress(0.1, 0) device_specific.FullOTA_InstallEnd() if OPTIONS.extra_script is not None: script.AppendExtra(OPTIONS.extra_script) script.UnmountAll() script.AddToZip(input_zip, output_zip) WriteMetadata(metadata, output_zip)
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 WriteFullOTAPackage(input_zip, output_file): target_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts) # We don't know what version it will be installed on top of. We expect the API # just won't change very often. Similarly for fstab, it might have changed in # the target build. target_api_version = target_info["recovery_api_version"] script = edify_generator.EdifyGenerator(target_api_version, target_info) if target_info.oem_props and not OPTIONS.oem_no_mount: target_info.WriteMountOemScript(script) metadata = GetPackageMetadata(target_info) if not OPTIONS.no_signing: staging_file = common.MakeTempFile(suffix='.zip') else: staging_file = output_file output_zip = zipfile.ZipFile( staging_file, "w", compression=zipfile.ZIP_DEFLATED) device_specific = common.DeviceSpecificParams( input_zip=input_zip, input_version=target_api_version, output_zip=output_zip, script=script, input_tmp=OPTIONS.input_tmp, metadata=metadata, info_dict=OPTIONS.info_dict) assert HasRecoveryPatch(input_zip, info_dict=OPTIONS.info_dict) # Assertions (e.g. downgrade check, device properties check). #ts = target_info.GetBuildProp("ro.build.date.utc") #ts_text = target_info.GetBuildProp("ro.build.date") #script.AssertOlderBuild(ts, ts_text) target_info.WriteDeviceAssertions(script, OPTIONS.oem_no_mount) device_specific.FullOTA_Assertions() block_diff_dict = GetBlockDifferences(target_zip=input_zip, source_zip=None, target_info=target_info, source_info=None, device_specific=device_specific) # Two-step package strategy (in chronological order, which is *not* # the order in which the generated script has things): # # if stage is not "2/3" or "3/3": # write recovery image to boot partition # set stage to "2/3" # reboot to boot partition and restart recovery # else if stage is "2/3": # write recovery image to recovery partition # set stage to "3/3" # reboot to recovery partition and restart recovery # else: # (stage must be "3/3") # set stage to "" # do normal full package installation: # wipe and install system, boot image, etc. # set up system to update recovery partition on first boot # complete script normally # (allow recovery to mark itself finished and reboot) #recovery_img = common.GetBootableImage("recovery.img", "recovery.img", # OPTIONS.input_tmp, "RECOVERY") if OPTIONS.two_step: if not target_info.get("multistage_support"): assert False, "two-step packages not supported by this build" fs = target_info["fstab"]["/misc"] assert fs.fs_type.upper() == "EMMC", \ "two-step packages only supported on devices with EMMC /misc partitions" bcb_dev = {"bcb_dev": fs.device} common.ZipWriteStr(output_zip, "recovery.img", recovery_img.data) script.AppendExtra(""" if get_stage("%(bcb_dev)s") == "2/3" then """ % bcb_dev) # Stage 2/3: Write recovery image to /recovery (currently running /boot). script.Comment("Stage 2/3") #script.WriteRawImage("/recovery", "recovery.img") script.AppendExtra(""" set_stage("%(bcb_dev)s", "3/3"); reboot_now("%(bcb_dev)s", "recovery"); else if get_stage("%(bcb_dev)s") == "3/3" then """ % bcb_dev) # Stage 3/3: Make changes. script.Comment("Stage 3/3") # Dump fingerprints script.Print("Target: {}".format(target_info.fingerprint)) androidver = target_info.GetBuildProp("ro.build.version.release") buildid = target_info.GetBuildProp("ro.build.id") builddate = target_info.GetBuildProp("ro.build.date") securep = target_info.GetBuildProp("ro.build.version.security_patch") name = target_info.GetBuildProp("ro.product.name") model = target_info.GetBuildProp("ro.product.model") manufacturer = target_info.GetBuildProp("ro.product.manufacturer") builduser = target_info.GetBuildProp("ro.build.user") buildsdk = target_info.GetBuildProp("ro.build.version.sdk") # Start output script.Print("----------------------------------------------") script.Print(" _____ _ _ _ _ ___ ") script.Print(" _____ _|_ _| | | |_ __ ___ | | | |_ _|") script.Print(" / _ \ \/ / | | | |_| | '_ ` _ \ | | | || |") script.Print("| __/> < | | | _ | | | | | | | |_| || |") script.Print(" \___/_/\_\ |_| |_| |_|_| |_| |_| \___/|___|") script.Print("") script.Print(" extended TouHou modified UI") script.Print(" Based on AOSP") script.Print("----------------------------------------------") script.Print("ROM Information :") script.Print("Build Date : %s"%(builddate)) script.Print("Android Version : %s"%(androidver)) script.Print("exTHmUI Version : %s"%(buildid)) script.Print("SDK Version : %s"%(buildsdk)) script.Print("Security Patch Date: %s"%(securep)) script.Print("----------------------------------------------") script.Print("Device Information :") script.Print("Manufacturer : %s"%(manufacturer)) script.Print("Name : %s"%(name)) script.Print("Model : %s"%(model)) script.Print("----------------------------------------------") script.Print("Installing exTHmUI to your device...") script.Print("") device_specific.FullOTA_InstallBegin() CopyInstallTools(output_zip) script.UnpackPackageDir("install", "/tmp/install") script.SetPermissionsRecursive("/tmp/install", 0, 0, 0o755, 0o644, None, None) script.SetPermissionsRecursive("/tmp/install/bin", 0, 0, 0o755, 0o755, None, None) if target_info.get("system_root_image") == "true": sysmount = "/" else: sysmount = "/system" if OPTIONS.backuptool: script.RunBackup("backup", sysmount, target_info.get('use_dynamic_partitions') == "true") # All other partitions as well as the data wipe use 10% of the progress, and # the update of the system partition takes the remaining progress. system_progress = 0.9 - (len(block_diff_dict) - 1) * 0.1 if OPTIONS.wipe_user_data: system_progress -= 0.1 progress_dict = {partition: 0.1 for partition in block_diff_dict} progress_dict["system"] = system_progress if target_info.get('use_dynamic_partitions') == "true": # Use empty source_info_dict to indicate that all partitions / groups must # be re-added. dynamic_partitions_diff = common.DynamicPartitionsDifference( info_dict=OPTIONS.info_dict, block_diffs=block_diff_dict.values(), progress_dict=progress_dict, build_without_vendor=(not HasPartition(input_zip, "vendor"))) dynamic_partitions_diff.WriteScript(script, output_zip, write_verify_script=OPTIONS.verify) else: for block_diff in block_diff_dict.values(): block_diff.WriteScript(script, output_zip, progress=progress_dict.get(block_diff.partition), write_verify_script=OPTIONS.verify) CheckVintfIfTrebleEnabled(OPTIONS.input_tmp, target_info) boot_img = common.GetBootableImage( "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT") common.CheckSize(boot_img.data, "boot.img", target_info) common.ZipWriteStr(output_zip, "boot.img", boot_img.data) device_specific.FullOTA_PostValidate() if OPTIONS.backuptool: script.ShowProgress(0.02, 10) script.RunBackup("restore", sysmount, target_info.get('use_dynamic_partitions') == "true") script.WriteRawImage("/boot", "boot.img") script.ShowProgress(0.1, 10) device_specific.FullOTA_InstallEnd() if OPTIONS.extra_script is not None: script.AppendExtra(OPTIONS.extra_script) script.UnmountAll() if OPTIONS.wipe_user_data: script.ShowProgress(0.1, 10) script.FormatPartition("/data") if OPTIONS.two_step: script.AppendExtra(""" set_stage("%(bcb_dev)s", ""); """ % bcb_dev) script.AppendExtra("else\n") # Stage 1/3: Nothing to verify for full OTA. Write recovery image to /boot. script.Comment("Stage 1/3") _WriteRecoveryImageToBoot(script, output_zip) script.AppendExtra(""" set_stage("%(bcb_dev)s", "2/3"); reboot_now("%(bcb_dev)s", ""); endif; endif; """ % bcb_dev) script.SetProgress(1) script.AddToZip(input_zip, output_zip, input_path=OPTIONS.updater_binary) metadata.required_cache = script.required_cache # We haven't written the metadata entry, which will be done in # FinalizeMetadata. common.ZipClose(output_zip) needed_property_files = ( NonAbOtaPropertyFiles(), ) FinalizeMetadata(metadata, staging_file, output_file, needed_property_files)
def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info, apk_key_map, key_passwords, platform_api_level, codename_to_api_level_map): maxsize = max([ len(os.path.basename(i.filename)) for i in input_tf_zip.infolist() if i.filename.endswith('.apk') ]) rebuild_recovery = False tmpdir = tempfile.mkdtemp() def write_to_temp(fn, attr, data): fn = os.path.join(tmpdir, fn) if fn.endswith("/"): fn = os.path.join(tmpdir, fn) os.mkdir(fn) else: d = os.path.dirname(fn) if d and not os.path.exists(d): os.makedirs(d) if attr >> 16 == 0xa1ff: os.symlink(data, fn) else: with open(fn, "wb") as f: f.write(data) for info in input_tf_zip.infolist(): if info.filename.startswith("IMAGES/"): continue data = input_tf_zip.read(info.filename) out_info = copy.copy(info) # Replace keys if requested. if (info.filename == "META/misc_info.txt" and OPTIONS.replace_verity_private_key): ReplaceVerityPrivateKey(input_tf_zip, output_tf_zip, misc_info, OPTIONS.replace_verity_private_key[1]) elif (info.filename in ("BOOT/RAMDISK/verity_key", "BOOT/verity_key") and OPTIONS.replace_verity_public_key): new_data = ReplaceVerityPublicKey( output_tf_zip, info.filename, OPTIONS.replace_verity_public_key[1]) write_to_temp(info.filename, info.external_attr, new_data) # Copy BOOT/, RECOVERY/, META/, ROOT/ to rebuild recovery patch. elif (info.filename.startswith("BOOT/") or info.filename.startswith("RECOVERY/") or info.filename.startswith("META/") or info.filename.startswith("ROOT/") or info.filename == "SYSTEM/etc/recovery-resource.dat"): write_to_temp(info.filename, info.external_attr, data) # Sign APKs. if info.filename.endswith(".apk"): name = os.path.basename(info.filename) key = apk_key_map[name] if key not in common.SPECIAL_CERT_STRINGS: print " signing: %-*s (%s)" % (maxsize, name, key) signed_data = SignApk(data, key, key_passwords[key], platform_api_level, codename_to_api_level_map) common.ZipWriteStr(output_tf_zip, out_info, signed_data) else: # an APK we're not supposed to sign. print "NOT signing: %s" % (name, ) common.ZipWriteStr(output_tf_zip, out_info, data) elif info.filename in ("SYSTEM/build.prop", "VENDOR/build.prop", "BOOT/RAMDISK/default.prop", "RECOVERY/RAMDISK/default.prop"): print "rewriting %s:" % (info.filename, ) new_data = RewriteProps(data, misc_info) common.ZipWriteStr(output_tf_zip, out_info, new_data) if info.filename in ("BOOT/RAMDISK/default.prop", "RECOVERY/RAMDISK/default.prop"): write_to_temp(info.filename, info.external_attr, new_data) elif info.filename.endswith("mac_permissions.xml"): print "rewriting %s with new keys." % (info.filename, ) new_data = ReplaceCerts(data) common.ZipWriteStr(output_tf_zip, out_info, new_data) elif info.filename in ("SYSTEM/recovery-from-boot.p", "SYSTEM/etc/recovery.img", "SYSTEM/bin/install-recovery.sh"): rebuild_recovery = True elif (OPTIONS.replace_ota_keys and info.filename in ("RECOVERY/RAMDISK/res/keys", "SYSTEM/etc/security/otacerts.zip")): # don't copy these files if we're regenerating them below pass elif (OPTIONS.replace_verity_private_key and info.filename == "META/misc_info.txt"): pass elif (OPTIONS.replace_verity_public_key and info.filename in ("BOOT/RAMDISK/verity_key", "BOOT/verity_key")): pass else: # a non-APK file; copy it verbatim common.ZipWriteStr(output_tf_zip, out_info, data) if OPTIONS.replace_ota_keys: new_recovery_keys = ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info) if new_recovery_keys: write_to_temp("RECOVERY/RAMDISK/res/keys", 0o755 << 16, new_recovery_keys) if rebuild_recovery: recovery_img = common.GetBootableImage("recovery.img", "recovery.img", tmpdir, "RECOVERY", info_dict=misc_info) boot_img = common.GetBootableImage("boot.img", "boot.img", tmpdir, "BOOT", info_dict=misc_info) def output_sink(fn, data): common.ZipWriteStr(output_tf_zip, "SYSTEM/" + fn, data) common.MakeRecoveryPatch(tmpdir, output_sink, recovery_img, boot_img, info_dict=misc_info) shutil.rmtree(tmpdir)
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.")
new_data = ReplaceVerityPublicKey( output_tf_zip, dest, OPTIONS.replace_verity_public_key[1]) write_to_temp(dest, 0o755 << 16, new_data) # Replace the keyid string in BOOT/cmdline. if OPTIONS.replace_verity_keyid: new_cmdline = ReplaceVerityKeyId(input_tf_zip, output_tf_zip, OPTIONS.replace_verity_keyid[1]) # Writing the new cmdline to tmpdir is redundant as the bootimage # gets build in the add_image_to_target_files and rebuild_recovery # is not exercised while building the boot image for the A/B # path write_to_temp("BOOT/cmdline", 0o755 << 16, new_cmdline) if rebuild_recovery: recovery_img = common.GetBootableImage( "recovery.img", "recovery.img", tmpdir, "RECOVERY", info_dict=misc_info) boot_img = common.GetBootableImage( "boot.img", "boot.img", tmpdir, "BOOT", info_dict=misc_info) def output_sink(fn, data): common.ZipWriteStr(output_tf_zip, "SYSTEM/" + fn, data) common.MakeRecoveryPatch(tmpdir, output_sink, recovery_img, boot_img, info_dict=misc_info) shutil.rmtree(tmpdir) def ReplaceCerts(data): """Given a string of data, replace all occurences of a set of X509 certs with a newer set of X509 certs and return
def WriteFullOTAPackage(input_zip, output_file): target_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts) # We don't know what version it will be installed on top of. We expect the API # just won't change very often. Similarly for fstab, it might have changed in # the target build. target_api_version = target_info["recovery_api_version"] script = edify_generator.EdifyGenerator(target_api_version, target_info) if target_info.oem_props and not OPTIONS.oem_no_mount: target_info.WriteMountOemScript(script) metadata = GetPackageMetadata(target_info) if not OPTIONS.no_signing: staging_file = common.MakeTempFile(suffix='.zip') else: staging_file = output_file output_zip = zipfile.ZipFile(staging_file, "w", compression=zipfile.ZIP_DEFLATED) device_specific = common.DeviceSpecificParams( input_zip=input_zip, input_version=target_api_version, output_zip=output_zip, script=script, input_tmp=OPTIONS.input_tmp, metadata=metadata, info_dict=OPTIONS.info_dict) assert HasRecoveryPatch(input_zip, info_dict=OPTIONS.info_dict) # Assertions (e.g. downgrade check, device properties check). ts = target_info.GetBuildProp("ro.build.date.utc") ts_text = target_info.GetBuildProp("ro.build.date") script.AssertOlderBuild(ts, ts_text) target_info.WriteDeviceAssertions(script, OPTIONS.oem_no_mount) device_specific.FullOTA_Assertions() block_diff_dict = GetBlockDifferences(target_zip=input_zip, source_zip=None, target_info=target_info, source_info=None, device_specific=device_specific) # Two-step package strategy (in chronological order, which is *not* # the order in which the generated script has things): # # if stage is not "2/3" or "3/3": # write recovery image to boot partition # set stage to "2/3" # reboot to boot partition and restart recovery # else if stage is "2/3": # write recovery image to recovery partition # set stage to "3/3" # reboot to recovery partition and restart recovery # else: # (stage must be "3/3") # set stage to "" # do normal full package installation: # wipe and install system, boot image, etc. # set up system to update recovery partition on first boot # complete script normally # (allow recovery to mark itself finished and reboot) #recovery_img = common.GetBootableImage("recovery.img", "recovery.img", # OPTIONS.input_tmp, "RECOVERY") if OPTIONS.two_step: if not target_info.get("multistage_support"): assert False, "two-step packages not supported by this build" fs = target_info["fstab"]["/misc"] assert fs.fs_type.upper() == "EMMC", \ "two-step packages only supported on devices with EMMC /misc partitions" bcb_dev = {"bcb_dev": fs.device} common.ZipWriteStr(output_zip, "recovery.img", recovery_img.data) script.AppendExtra(""" if get_stage("%(bcb_dev)s") == "2/3" then """ % bcb_dev) # Stage 2/3: Write recovery image to /recovery (currently running /boot). script.Comment("Stage 2/3") #script.WriteRawImage("/recovery", "recovery.img") script.AppendExtra(""" set_stage("%(bcb_dev)s", "3/3"); reboot_now("%(bcb_dev)s", "recovery"); else if get_stage("%(bcb_dev)s") == "3/3" then """ % bcb_dev) # Stage 3/3: Make changes. script.Comment("Stage 3/3") # Dump fingerprints script.Print("Target: {}".format(target_info.fingerprint)) script.AppendExtra( "ifelse(is_mounted(\"/system\"), unmount(\"/system\"));") device_specific.FullOTA_InstallBegin() # All other partitions as well as the data wipe use 10% of the progress, and # the update of the system partition takes the remaining progress. system_progress = 0.9 - (len(block_diff_dict) - 1) * 0.1 if OPTIONS.wipe_user_data: system_progress -= 0.1 progress_dict = {partition: 0.1 for partition in block_diff_dict} progress_dict["system"] = system_progress if target_info.get('use_dynamic_partitions') == "true": # Use empty source_info_dict to indicate that all partitions / groups must # be re-added. dynamic_partitions_diff = common.DynamicPartitionsDifference( info_dict=OPTIONS.info_dict, block_diffs=block_diff_dict.values(), progress_dict=progress_dict) dynamic_partitions_diff.WriteScript(script, output_zip, write_verify_script=OPTIONS.verify) else: for block_diff in block_diff_dict.values(): block_diff.WriteScript(script, output_zip, progress=progress_dict.get( block_diff.partition), write_verify_script=OPTIONS.verify) CheckVintfIfTrebleEnabled(OPTIONS.input_tmp, target_info) boot_img = common.GetBootableImage("boot.img", "boot.img", OPTIONS.input_tmp, "BOOT") common.CheckSize(boot_img.data, "boot.img", target_info) common.ZipWriteStr(output_zip, "boot.img", boot_img.data) script.WriteRawImage("/boot", "boot.img") script.ShowProgress(0.1, 10) device_specific.FullOTA_InstallEnd() if OPTIONS.extra_script is not None: script.AppendExtra(OPTIONS.extra_script) script.UnmountAll() if OPTIONS.wipe_user_data: script.ShowProgress(0.1, 10) script.FormatPartition("/data") if OPTIONS.two_step: script.AppendExtra(""" set_stage("%(bcb_dev)s", ""); """ % bcb_dev) script.AppendExtra("else\n") # Stage 1/3: Nothing to verify for full OTA. Write recovery image to /boot. script.Comment("Stage 1/3") _WriteRecoveryImageToBoot(script, output_zip) script.AppendExtra(""" set_stage("%(bcb_dev)s", "2/3"); reboot_now("%(bcb_dev)s", ""); endif; endif; """ % bcb_dev) script.SetProgress(1) script.AddToZip(input_zip, output_zip, input_path=OPTIONS.updater_binary) metadata.required_cache = script.required_cache # We haven't written the metadata entry, which will be done in # FinalizeMetadata. common.ZipClose(output_zip) needed_property_files = (NonAbOtaPropertyFiles(), ) FinalizeMetadata(metadata, staging_file, output_file, needed_property_files)
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 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") common.ZipClose(input_zip) output_zip = zipfile.ZipFile(filename, "a", compression=zipfile.ZIP_DEFLATED) fstab = OPTIONS.info_dict["fstab"] if fstab: ubi_fs = (fstab["/system"].fs_type == "ubifs") else: ubi_fs = False 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) # overlay boot image in product out folder if outpath: open(outpath + '/boot.img', 'w').write(boot_image.data) os.chmod( outpath + '/boot.img', stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH) banner("recovery") recovery_image = None 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) # overlay recovery image in product out folder if outpath: open(outpath + '/recovery.img', 'w').write(recovery_image.data) os.chmod( outpath + '/recovery.img', stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH) if not ubi_fs: banner("system") AddSystem(output_zip, recovery_img=recovery_image, boot_img=boot_image) if has_vendor: banner("vendor") AddVendor(output_zip) #banner("userdata") #AddUserdata(output_zip) #banner("cache") #AddCache(output_zip) if outpath: zip_dir(OPTIONS.input_tmp, 'META', outpath, 'oem_fota_meta') zip_dir(OPTIONS.input_tmp, 'OTA', outpath, 'oem_fota_meta') if ubi_fs: zip_dir(OPTIONS.input_tmp, 'SYSTEM', outpath, 'oem_fota_meta') zf = zipfile.ZipFile(outpath + '/oem_fota_meta.zip', "a", zipfile.zlib.DEFLATED) if not ubi_fs: common.ZipWrite(zf, outpath + '/system.map', '/IMAGES/system.map') common.ZipWrite(zf, OPTIONS.input_tmp + '/SYSTEM/build.prop', '/SYSTEM/build.prop') common.ZipWrite(zf, OPTIONS.input_tmp + '/SYSTEM/recovery-from-boot.p', '/SYSTEM/recovery-from-boot.p') common.ZipWrite( zf, OPTIONS.input_tmp + '/SYSTEM/bin/install-recovery.sh', '/SYSTEM/bin/install-recovery.sh') common.ZipWrite(zf, OPTIONS.input_tmp + '/RADIO/filesmap', '/RADIO/filesmap') zf.close() common.ZipClose(output_zip)
def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip): source_version = OPTIONS.source_info_dict["recovery_api_version"] target_version = OPTIONS.target_info_dict["recovery_api_version"] if source_version == 0: print( "WARNING: generating edify script for a source that " "can't install it.") script = edify_generator.EdifyGenerator(source_version, OPTIONS.target_info_dict) if OPTIONS.override_prop: metadata = { "post-timestamp": GetBuildProp("ro.build.date.utc", OPTIONS.target_info_dict), } else: metadata = { "pre-device": GetBuildProp("ro.product.device", OPTIONS.source_info_dict), "post-timestamp": GetBuildProp("ro.build.date.utc", OPTIONS.target_info_dict), } device_specific = common.DeviceSpecificParams( source_zip=source_zip, source_version=source_version, target_zip=target_zip, target_version=target_version, output_zip=output_zip, script=script, metadata=metadata, info_dict=OPTIONS.info_dict) print "Loading target..." target_data = LoadSystemFiles(target_zip) print "Loading source..." source_data = LoadSystemFiles(source_zip) verbatim_targets = [] patch_list = [] diffs = [] renames = {} largest_source_size = 0 matching_file_cache = {} for fn in source_data.keys(): sf = source_data[fn] assert fn == sf.name matching_file_cache["path:" + fn] = sf # Only allow eligability for filename/sha matching # if there isn't a perfect path match. if target_data.get(sf.name) is None: matching_file_cache["file:" + fn.split("/")[-1]] = sf matching_file_cache["sha:" + sf.sha1] = sf for fn in sorted(target_data.keys()): tf = target_data[fn] assert fn == tf.name sf = ClosestFileMatch(tf, matching_file_cache, renames) if sf is not None and sf.name != tf.name: print "File has moved from " + sf.name + " to " + tf.name renames[sf.name] = tf if sf is None or fn in OPTIONS.require_verbatim: # This file should be included verbatim if fn in OPTIONS.prohibit_verbatim: raise common.ExternalError("\"%s\" must be sent verbatim" % (fn, )) print "send", fn, "verbatim" tf.AddToZip(output_zip) verbatim_targets.append((fn, tf.size)) elif tf.sha1 != sf.sha1: # File is different; consider sending as a patch diffs.append(common.Difference(tf, sf)) else: # Target file data identical to source (may still be renamed) pass # common.ComputeDifferences(diffs) # # for diff in diffs: # tf, sf, d = diff.GetPatch() # if d is None or len(d) > tf.size * OPTIONS.patch_threshold: # # patch is almost as big as the file; don't bother patching # tf.AddToZip(output_zip) # verbatim_targets.append((tf.name, tf.size)) # else: # common.ZipWriteStr(output_zip, "patch/" + sf.name + ".p", d) # patch_list.append((sf.name, tf, sf, tf.size, common.sha1(d).hexdigest())) # largest_source_size = max(largest_source_size, sf.size) if not OPTIONS.override_prop: source_fp = GetBuildProp("ro.build.fingerprint", OPTIONS.source_info_dict) target_fp = GetBuildProp("ro.build.fingerprint", OPTIONS.target_info_dict) metadata["pre-build"] = source_fp metadata["post-build"] = target_fp script.Mount("/system") script.AssertSomeFingerprint(source_fp, target_fp) source_boot = common.GetBootableImage("/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT", OPTIONS.source_info_dict) target_boot = common.GetBootableImage("/tmp/boot.img", "boot.img", OPTIONS.target_tmp, "BOOT") updating_boot = (source_boot.data != target_boot.data) #source_recovery = common.GetBootableImage( # "/tmp/recovery.img", "recovery.img", OPTIONS.source_tmp, "RECOVERY", # OPTIONS.source_info_dict) #target_recovery = common.GetBootableImage( # "/tmp/recovery.img", "recovery.img", OPTIONS.target_tmp, "RECOVERY") #updating_recovery = (source_recovery.data != target_recovery.data) updating_recovery = False # Here's how we divide up the progress bar: # 0.1 for verifying the start state (PatchCheck calls) # 0.8 for applying patches (ApplyPatch calls) # 0.1 for unpacking verbatim files, symlinking, and doing the # device-specific commands. AppendAssertions(script, OPTIONS.target_info_dict) device_specific.IncrementalOTA_Assertions() script.Print("Verifying current system...") device_specific.IncrementalOTA_VerifyBegin() script.ShowProgress(0.1, 0) total_verify_size = float(sum([i[2].size for i in patch_list]) + 1) if updating_boot: total_verify_size += source_boot.size so_far = 0 for fn, tf, sf, size, patch_sha in patch_list: script.PatchCheck("/" + fn, tf.sha1, sf.sha1) so_far += sf.size script.SetProgress(so_far / total_verify_size) if updating_boot: d = common.Difference(target_boot, source_boot) _, _, d = d.ComputePatch() print "boot target: %d source: %d diff: %d" % ( target_boot.size, source_boot.size, len(d)) common.ZipWriteStr(output_zip, "patch/boot.img.p", d) boot_type, boot_device = common.GetTypeAndDevice( "/boot", OPTIONS.info_dict) script.PatchCheck( "%s:%s:%d:%s:%d:%s" % (boot_type, boot_device, source_boot.size, source_boot.sha1, target_boot.size, target_boot.sha1)) so_far += source_boot.size script.SetProgress(so_far / total_verify_size) if patch_list or updating_recovery or updating_boot: script.CacheFreeSpaceCheck(largest_source_size) device_specific.IncrementalOTA_VerifyEnd() script.Comment("---- start making changes here ----") device_specific.IncrementalOTA_InstallBegin() if OPTIONS.wipe_user_data: script.Print("Erasing user data...") script.FormatPartition("/data") script.Print("Removing unneeded files...") script.DeleteFiles(["/" + i[0] for i in verbatim_targets] + [ "/" + i for i in sorted(source_data) if i not in target_data and i not in renames ] + ["/system/recovery.img"]) script.ShowProgress(0.8, 0) total_patch_size = float(sum([i[1].size for i in patch_list]) + 1) if updating_boot: total_patch_size += target_boot.size so_far = 0 script.Print("Patching system files...") deferred_patch_list = [] for item in patch_list: fn, tf, sf, size, _ = item if tf.name == "system/build.prop": deferred_patch_list.append(item) continue script.ApplyPatch("/" + fn, "-", tf.size, tf.sha1, sf.sha1, "patch/" + fn + ".p") so_far += tf.size script.SetProgress(so_far / total_patch_size) if updating_boot: # Produce the boot image by applying a patch to the current # contents of the boot partition, and write it back to the # partition. script.Print("Patching boot image...") script.ApplyPatch( "%s:%s:%d:%s:%d:%s" % (boot_type, boot_device, source_boot.size, source_boot.sha1, target_boot.size, target_boot.sha1), "-", target_boot.size, target_boot.sha1, source_boot.sha1, "patch/boot.img.p") so_far += target_boot.size script.SetProgress(so_far / total_patch_size) print "boot image changed; including." else: print "boot image unchanged; skipping." if updating_recovery: # Recovery is generated as a patch using both the boot image # (which contains the same linux kernel as recovery) and the file # /system/etc/recovery-resource.dat (which contains all the images # used in the recovery UI) as sources. This lets us minimize the # size of the patch, which must be included in every OTA package. # # For older builds where recovery-resource.dat is not present, we # use only the boot image as the source. MakeRecoveryPatch(OPTIONS.target_tmp, output_zip, target_recovery, target_boot) script.DeleteFiles([ "/system/recovery-from-boot.p", "/system/etc/install-recovery.sh" ]) print "recovery image changed; including as patch from boot." else: print "recovery image unchanged; skipping." script.ShowProgress(0.1, 10) target_symlinks = CopySystemFiles(target_zip, None) target_symlinks_d = dict([(i[1], i[0]) for i in target_symlinks]) temp_script = script.MakeTemporary() Item.GetMetadata(target_zip) Item.Get("system").SetPermissions(temp_script) # Note that this call will mess up the tree of Items, so make sure # we're done with it. source_symlinks = CopySystemFiles(source_zip, None) source_symlinks_d = dict([(i[1], i[0]) for i in source_symlinks]) # Delete all the symlinks in source that aren't in target. This # needs to happen before verbatim files are unpacked, in case a # symlink in the source is replaced by a real file in the target. to_delete = [] for dest, link in source_symlinks: if link not in target_symlinks_d: to_delete.append(link) script.DeleteFiles(to_delete) if verbatim_targets: script.Print("Unpacking new files...") script.UnpackPackageDir("system", "/system") #if updating_recovery: # script.Print("Unpacking new recovery...") # script.UnpackPackageDir("recovery", "/system") if len(renames) > 0: script.Print("Renaming files...") for src in renames: print "Renaming " + src + " to " + renames[src].name script.RenameFile(src, renames[src].name) script.Print("Symlinks and permissions...") # Create all the symlinks that don't already exist, or point to # somewhere different than what we want. Delete each symlink before # creating it, since the 'symlink' command won't overwrite. to_create = [] for dest, link in target_symlinks: if link in source_symlinks_d: if dest != source_symlinks_d[link]: to_create.append((dest, link)) else: to_create.append((dest, link)) script.DeleteFiles([i[1] for i in to_create]) script.MakeSymlinks(to_create) # Now that the symlinks are created, we can set all the # permissions. script.AppendScript(temp_script) # Do device-specific installation (eg, write radio image). device_specific.IncrementalOTA_InstallEnd() if OPTIONS.extra_script is not None: script.AppendExtra(OPTIONS.extra_script) # Patch the build.prop file last, so if something fails but the # device can still come up, it appears to be the old build and will # get set the OTA package again to retry. script.Print("Patching remaining system files...") for item in deferred_patch_list: fn, tf, sf, size, _ = item script.ApplyPatch("/" + fn, "-", tf.size, tf.sha1, sf.sha1, "patch/" + fn + ".p") script.SetPermissions("/system/build.prop", 0, 0, 0644, None, None) script.AddToZip(target_zip, output_zip) WriteMetadata(metadata, output_zip)
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)
======= if image == "recovery-two-step.img": >>>>>>> android-7.1.2_r2 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="")
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 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 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) has_recovery = (OPTIONS.info_dict.get("no_recovery") != "true") system_root_image = (OPTIONS.info_dict.get("system_root_image", None) == "true") board_bvb_enable = (OPTIONS.info_dict.get("board_bvb_enable", None) == "true") # Brillo Verified Boot is incompatible with certain # configurations. Explicitly check for these. if board_bvb_enable: assert not has_recovery, "has_recovery incompatible with bvb" assert not system_root_image, "system_root_image incompatible with bvb" assert not OPTIONS.rebuild_recovery, "rebuild_recovery incompatible with bvb" assert not has_vendor, "VENDOR images currently incompatible with bvb" 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: if board_bvb_enable: # With Brillo Verified Boot, we need to build system.img before # boot.img since the latter includes the dm-verity root hash and # salt for the former. pass else: banner("boot") 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_img_path = AddSystem(output_zip, recovery_img=recovery_image, boot_img=boot_image) if OPTIONS.info_dict.get("board_bvb_enable", None) == "true": # If we're using Brillo Verified Boot, we can now build boot.img # given that we have system.img. banner("boot") boot_image = common.GetBootableImage("IMAGES/boot.img", "boot.img", OPTIONS.input_tmp, "BOOT", system_img_path=system_img_path) if boot_image: boot_image.AddToZip(output_zip) if has_vendor: banner("vendor") AddVendor(output_zip) 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 line in lines: 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): common.ZipWrite(output_zip, img_radio_path, os.path.join("IMAGES", img_name)) else: for root, _, files in os.walk(img_vendor_dir): if img_name in files: common.ZipWrite(output_zip, os.path.join(root, img_name), os.path.join("IMAGES", img_name)) break # 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 common.ZipClose(output_zip)
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 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 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") AddSystem(output_zip, recovery_img=recovery_image, boot_img=boot_image) if has_vendor: banner("vendor") AddVendor(output_zip) banner("userdata") AddUserdata(output_zip) banner("cache") AddCache(output_zip) # For devices using A/B update, copy over images from RADIO/ to IMAGES/ and # make sure we have all the needed images ready under IMAGES/. 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 line in lines: 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 common.ZipClose(output_zip)
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("CUSTOM/") has_custom = True except KeyError: has_custom = 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() #yutianliang add for VFOZBENQ-91 add :allowZip64=True output_zip = zipfile.ZipFile(filename, "a", compression=zipfile.ZIP_DEFLATED, allowZip64=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) banner("recovery") recovery_image = None 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) if "mtk_header_support" in OPTIONS.info_dict: banner("recovery_bthdr") recovery_bthdr_image = common.GetBootableImage( "IMAGES/recovery_bthdr.img", "recovery_bthdr.img", OPTIONS.input_tmp, "RECOVERY") if recovery_bthdr_image: recovery_bthdr_image.AddToZip(output_zip) banner("system") AddSystem(output_zip, recovery_img=recovery_image, boot_img=boot_image) if has_vendor: banner("vendor") AddVendor(output_zip) if has_custom: banner("custom") AddCustom(output_zip) banner("userdata") AddUserdata(output_zip) banner("cache") AddCache(output_zip) output_zip.close()
def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_file): target_info = common.BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts) source_info = common.BuildInfo(OPTIONS.source_info_dict, OPTIONS.oem_dicts) target_api_version = target_info["recovery_api_version"] source_api_version = source_info["recovery_api_version"] if source_api_version == 0: logger.warning( "Generating edify script for a source that can't install it.") script = edify_generator.EdifyGenerator( source_api_version, target_info, fstab=source_info["fstab"]) if target_info.oem_props or source_info.oem_props: if not OPTIONS.oem_no_mount: source_info.WriteMountOemScript(script) metadata = GetPackageMetadata(target_info, source_info) if not OPTIONS.no_signing: staging_file = common.MakeTempFile(suffix='.zip') else: staging_file = output_file output_zip = zipfile.ZipFile( staging_file, "w", compression=zipfile.ZIP_DEFLATED) device_specific = common.DeviceSpecificParams( source_zip=source_zip, source_version=source_api_version, source_tmp=OPTIONS.source_tmp, target_zip=target_zip, target_version=target_api_version, target_tmp=OPTIONS.target_tmp, output_zip=output_zip, script=script, metadata=metadata, info_dict=source_info) source_boot = common.GetBootableImage( "/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT", source_info) target_boot = common.GetBootableImage( "/tmp/boot.img", "boot.img", OPTIONS.target_tmp, "BOOT", target_info) updating_boot = (not OPTIONS.two_step and (source_boot.data != target_boot.data)) target_recovery = common.GetBootableImage( "/tmp/recovery.img", "recovery.img", OPTIONS.target_tmp, "RECOVERY") block_diff_dict = GetBlockDifferences(target_zip=target_zip, source_zip=source_zip, target_info=target_info, source_info=source_info, device_specific=device_specific) CheckVintfIfTrebleEnabled(OPTIONS.target_tmp, target_info) # Assertions (e.g. device properties check). target_info.WriteDeviceAssertions(script, OPTIONS.oem_no_mount) device_specific.IncrementalOTA_Assertions() # Two-step incremental package strategy (in chronological order, # which is *not* the order in which the generated script has # things): # # if stage is not "2/3" or "3/3": # do verification on current system # write recovery image to boot partition # set stage to "2/3" # reboot to boot partition and restart recovery # else if stage is "2/3": # write recovery image to recovery partition # set stage to "3/3" # reboot to recovery partition and restart recovery # else: # (stage must be "3/3") # perform update: # patch system files, etc. # force full install of new boot image # set up system to update recovery partition on first boot # complete script normally # (allow recovery to mark itself finished and reboot) if OPTIONS.two_step: if not source_info.get("multistage_support"): assert False, "two-step packages not supported by this build" fs = source_info["fstab"]["/misc"] assert fs.fs_type.upper() == "EMMC", \ "two-step packages only supported on devices with EMMC /misc partitions" bcb_dev = {"bcb_dev": fs.device} common.ZipWriteStr(output_zip, "recovery.img", target_recovery.data) script.AppendExtra(""" if get_stage("%(bcb_dev)s") == "2/3" then """ % bcb_dev) # Stage 2/3: Write recovery image to /recovery (currently running /boot). script.Comment("Stage 2/3") script.AppendExtra("sleep(20);\n") script.WriteRawImage("/recovery", "recovery.img") script.AppendExtra(""" set_stage("%(bcb_dev)s", "3/3"); reboot_now("%(bcb_dev)s", "recovery"); else if get_stage("%(bcb_dev)s") != "3/3" then """ % bcb_dev) # Stage 1/3: (a) Verify the current system. script.Comment("Stage 1/3") # Dump fingerprints script.Print("Source: {}".format(source_info.fingerprint)) script.Print("Target: {}".format(target_info.fingerprint)) script.Print("Verifying current system...") device_specific.IncrementalOTA_VerifyBegin() WriteFingerprintAssertion(script, target_info, source_info) # Check the required cache size (i.e. stashed blocks). required_cache_sizes = [diff.required_cache for diff in block_diff_dict.values()] if updating_boot: boot_type, boot_device_expr = common.GetTypeAndDeviceExpr("/boot", source_info) d = common.Difference(target_boot, source_boot) _, _, d = d.ComputePatch() if d is None: include_full_boot = True common.ZipWriteStr(output_zip, "boot.img", target_boot.data) else: include_full_boot = False logger.info( "boot target: %d source: %d diff: %d", target_boot.size, source_boot.size, len(d)) common.ZipWriteStr(output_zip, "boot.img.p", d) target_expr = 'concat("{}:",{},":{}:{}")'.format( boot_type, boot_device_expr, target_boot.size, target_boot.sha1) source_expr = 'concat("{}:",{},":{}:{}")'.format( boot_type, boot_device_expr, source_boot.size, source_boot.sha1) script.PatchPartitionExprCheck(target_expr, source_expr) required_cache_sizes.append(target_boot.size) if required_cache_sizes: script.CacheFreeSpaceCheck(max(required_cache_sizes)) # Verify the existing partitions. for diff in block_diff_dict.values(): diff.WriteVerifyScript(script, touched_blocks_only=True) device_specific.IncrementalOTA_VerifyEnd() if OPTIONS.two_step: # Stage 1/3: (b) Write recovery image to /boot. _WriteRecoveryImageToBoot(script, output_zip) script.AppendExtra(""" set_stage("%(bcb_dev)s", "2/3"); reboot_now("%(bcb_dev)s", ""); else """ % bcb_dev) # Stage 3/3: Make changes. script.Comment("Stage 3/3") script.Comment("---- start making changes here ----") device_specific.IncrementalOTA_InstallBegin() progress_dict = {partition: 0.1 for partition in block_diff_dict} progress_dict["system"] = 1 - len(block_diff_dict) * 0.1 if OPTIONS.source_info_dict.get("use_dynamic_partitions") == "true": if OPTIONS.target_info_dict.get("use_dynamic_partitions") != "true": raise RuntimeError( "can't generate incremental that disables dynamic partitions") dynamic_partitions_diff = common.DynamicPartitionsDifference( info_dict=OPTIONS.target_info_dict, source_info_dict=OPTIONS.source_info_dict, block_diffs=block_diff_dict.values(), progress_dict=progress_dict) dynamic_partitions_diff.WriteScript( script, output_zip, write_verify_script=OPTIONS.verify) else: for block_diff in block_diff_dict.values(): block_diff.WriteScript(script, output_zip, progress=progress_dict.get(block_diff.partition), write_verify_script=OPTIONS.verify) if OPTIONS.two_step: common.ZipWriteStr(output_zip, "boot.img", target_boot.data) script.WriteRawImage("/boot", "boot.img") logger.info("writing full boot image (forced by two-step mode)") if not OPTIONS.two_step: if updating_boot: if include_full_boot: logger.info("boot image changed; including full.") script.Print("Installing boot image...") script.WriteRawImage("/boot", "boot.img") else: # Produce the boot image by applying a patch to the current # contents of the boot partition, and write it back to the # partition. logger.info("boot image changed; including patch.") script.Print("Patching boot image...") script.ShowProgress(0.1, 10) target_expr = 'concat("{}:",{},":{}:{}")'.format( boot_type, boot_device_expr, target_boot.size, target_boot.sha1) source_expr = 'concat("{}:",{},":{}:{}")'.format( boot_type, boot_device_expr, source_boot.size, source_boot.sha1) script.PatchPartitionExpr(target_expr, source_expr, '"boot.img.p"') else: logger.info("boot image unchanged; skipping.") # Do device-specific installation (eg, write radio image). device_specific.IncrementalOTA_InstallEnd() if OPTIONS.extra_script is not None: script.AppendExtra(OPTIONS.extra_script) if OPTIONS.wipe_user_data: script.Print("Erasing user data...") script.FormatPartition("/data") if OPTIONS.two_step: script.AppendExtra(""" set_stage("%(bcb_dev)s", ""); endif; endif; """ % bcb_dev) script.SetProgress(1) # For downgrade OTAs, we prefer to use the update-binary in the source # build that is actually newer than the one in the target build. if OPTIONS.downgrade: script.AddToZip(source_zip, output_zip, input_path=OPTIONS.updater_binary) else: script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary) metadata.required_cache = script.required_cache # We haven't written the metadata entry yet, which will be handled in # FinalizeMetadata(). common.ZipClose(output_zip) # Sign the generated zip package unless no_signing is specified. needed_property_files = ( NonAbOtaPropertyFiles(), ) FinalizeMetadata(metadata, staging_file, output_file, needed_property_files)
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 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") AddSystem(output_zip, recovery_img=recovery_image, boot_img=boot_image) if has_vendor: banner("vendor") AddVendor(output_zip) banner("userdata") AddUserdata(output_zip) banner("cache") AddCache(output_zip) common.ZipClose(output_zip)
def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info, apk_key_map, key_passwords, platform_api_level, codename_to_api_level_map): maxsize = max([len(os.path.basename(i.filename)) for i in input_tf_zip.infolist() if i.filename.endswith('.apk')]) rebuild_recovery = False system_root_image = misc_info.get("system_root_image") == "true" # tmpdir will only be used to regenerate the recovery-from-boot patch. tmpdir = tempfile.mkdtemp() def write_to_temp(fn, attr, data): fn = os.path.join(tmpdir, fn) if fn.endswith("/"): fn = os.path.join(tmpdir, fn) os.mkdir(fn) else: d = os.path.dirname(fn) if d and not os.path.exists(d): os.makedirs(d) if attr >> 16 == 0xa1ff: os.symlink(data, fn) else: with open(fn, "wb") as f: f.write(data) for info in input_tf_zip.infolist(): if info.filename.startswith("IMAGES/"): continue data = input_tf_zip.read(info.filename) out_info = copy.copy(info) # Sign APKs. if info.filename.endswith(".apk"): name = os.path.basename(info.filename) key = apk_key_map[name] if key not in common.SPECIAL_CERT_STRINGS: print " signing: %-*s (%s)" % (maxsize, name, key) signed_data = SignApk(data, key, key_passwords[key], platform_api_level, codename_to_api_level_map) common.ZipWriteStr(output_tf_zip, out_info, signed_data) else: # an APK we're not supposed to sign. print "NOT signing: %s" % (name,) common.ZipWriteStr(output_tf_zip, out_info, data) # System properties. elif info.filename in ("SYSTEM/build.prop", "VENDOR/build.prop", "BOOT/RAMDISK/default.prop", "ROOT/default.prop", "RECOVERY/RAMDISK/default.prop"): print "rewriting %s:" % (info.filename,) new_data = RewriteProps(data, misc_info) common.ZipWriteStr(output_tf_zip, out_info, new_data) if info.filename in ("BOOT/RAMDISK/default.prop", "ROOT/default.prop", "RECOVERY/RAMDISK/default.prop"): write_to_temp(info.filename, info.external_attr, new_data) elif info.filename.endswith("mac_permissions.xml"): print "rewriting %s with new keys." % (info.filename,) new_data = ReplaceCerts(data) common.ZipWriteStr(output_tf_zip, out_info, new_data) # Trigger a rebuild of the recovery patch if needed. elif info.filename in ("SYSTEM/recovery-from-boot.p", "SYSTEM/etc/recovery.img", "SYSTEM/bin/install-recovery.sh"): rebuild_recovery = True # Don't copy OTA keys if we're replacing them. elif (OPTIONS.replace_ota_keys and info.filename in ( "BOOT/RAMDISK/res/keys", "BOOT/RAMDISK/etc/update_engine/update-payload-key.pub.pem", "RECOVERY/RAMDISK/res/keys", "SYSTEM/etc/security/otacerts.zip", "SYSTEM/etc/update_engine/update-payload-key.pub.pem")): pass # Skip META/misc_info.txt if we will replace the verity private key later. elif (OPTIONS.replace_verity_private_key and info.filename == "META/misc_info.txt"): pass # Skip verity public key if we will replace it. elif (OPTIONS.replace_verity_public_key and info.filename in ("BOOT/RAMDISK/verity_key", "ROOT/verity_key")): pass # Skip verity keyid (for system_root_image use) if we will replace it. elif (OPTIONS.replace_verity_keyid and info.filename == "BOOT/cmdline"): pass # Skip the care_map as we will regenerate the system/vendor images. elif (info.filename == "META/care_map.txt"): pass # Copy BOOT/, RECOVERY/, META/, ROOT/ to rebuild recovery patch. This case # must come AFTER other matching rules. elif (info.filename.startswith("BOOT/") or info.filename.startswith("RECOVERY/") or info.filename.startswith("META/") or info.filename.startswith("ROOT/") or info.filename == "SYSTEM/etc/recovery-resource.dat"): write_to_temp(info.filename, info.external_attr, data) common.ZipWriteStr(output_tf_zip, out_info, data) # A non-APK file; copy it verbatim. else: common.ZipWriteStr(output_tf_zip, out_info, data) if OPTIONS.replace_ota_keys: new_recovery_keys = ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info) if new_recovery_keys: if system_root_image: recovery_keys_location = "BOOT/RAMDISK/res/keys" else: recovery_keys_location = "RECOVERY/RAMDISK/res/keys" # The "new_recovery_keys" has been already written into the output_tf_zip # while calling ReplaceOtaKeys(). We're just putting the same copy to # tmpdir in case we need to regenerate the recovery-from-boot patch. write_to_temp(recovery_keys_location, 0o755 << 16, new_recovery_keys) # Replace the keyid string in META/misc_info.txt. if OPTIONS.replace_verity_private_key: ReplaceVerityPrivateKey(input_tf_zip, output_tf_zip, misc_info, OPTIONS.replace_verity_private_key[1]) if OPTIONS.replace_verity_public_key: if system_root_image: dest = "ROOT/verity_key" else: dest = "BOOT/RAMDISK/verity_key" # We are replacing the one in boot image only, since the one under # recovery won't ever be needed. new_data = ReplaceVerityPublicKey( output_tf_zip, dest, OPTIONS.replace_verity_public_key[1]) write_to_temp(dest, 0o755 << 16, new_data) # Replace the keyid string in BOOT/cmdline. if OPTIONS.replace_verity_keyid: new_cmdline = ReplaceVerityKeyId(input_tf_zip, output_tf_zip, OPTIONS.replace_verity_keyid[1]) # Writing the new cmdline to tmpdir is redundant as the bootimage # gets build in the add_image_to_target_files and rebuild_recovery # is not exercised while building the boot image for the A/B # path write_to_temp("BOOT/cmdline", 0o755 << 16, new_cmdline) if rebuild_recovery: recovery_img = common.GetBootableImage( "recovery.img", "recovery.img", tmpdir, "RECOVERY", info_dict=misc_info) boot_img = common.GetBootableImage( "boot.img", "boot.img", tmpdir, "BOOT", info_dict=misc_info) def output_sink(fn, data): common.ZipWriteStr(output_tf_zip, "SYSTEM/" + fn, data) common.MakeRecoveryPatch(tmpdir, output_sink, recovery_img, boot_img, info_dict=misc_info) shutil.rmtree(tmpdir)
def AddImagesToTargetFiles(filename): OPTIONS.input_tmp, input_zip = common.UnzipTemp(filename) OPTIONS.out_path = filename[0:filename.find("obj")] 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 OPTIONS.info_dict = common.LoadInfoDict(input_zip) # 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) if "selinux_fc" in OPTIONS.info_dict: OPTIONS.info_dict["selinux_fc"] = os.path.join(OPTIONS.input_tmp, "BOOT", "RAMDISK", "file_contexts") common.ZipClose(input_zip) output_zip = zipfile.ZipFile(filename, "a", compression=zipfile.ZIP_DEFLATED) 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) banner("recovery") recovery_image = None 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") if not CopySystem(output_zip, filename): AddSystem(output_zip, recovery_img=recovery_image, boot_img=boot_image) if has_vendor: banner("vendor") AddVendor(output_zip) banner("userdata") AddUserdata(output_zip) banner("cache") AddCache(output_zip) banner("usbmsc") AddUsbmsc(output_zip) common.ZipClose(output_zip)