def MakeRecoveryPatch(input_tmp, output_zip, recovery_img, boot_img): """Generate a binary patch that creates the recovery image starting with the boot image. (Most of the space in these images is just the kernel, which is identical for the two, so the resulting patch should be efficient.) Add it to the output zip, along with a shell script that is run from init.rc on first boot to actually do the patching and install the new recovery image. recovery_img and boot_img should be File objects for the corresponding images. info should be the dictionary returned by common.LoadInfoDict() on the input target_files. Returns an Item for the shell script, which must be made executable. """ diff_program = ["imgdiff"] path = os.path.join(input_tmp, "SYSTEM", "etc", "recovery-resource.dat") if os.path.exists(path): diff_program.append("-b") diff_program.append(path) bonus_args = "-b /system/etc/recovery-resource.dat" else: bonus_args = "" d = common.Difference(recovery_img, boot_img, diff_program=diff_program) _, _, patch = d.ComputePatch() common.ZipWriteStr(output_zip, "recovery/recovery-from-boot.p", patch) Item.Get("system/recovery-from-boot.p", dir=False) boot_type, boot_device = common.GetTypeAndDevice("/boot", OPTIONS.info_dict) recovery_type, recovery_device = common.GetTypeAndDevice( "/recovery", OPTIONS.info_dict) sh = """#!/system/bin/sh if ! applypatch -c %(recovery_type)s:%(recovery_device)s:%(recovery_size)d:%(recovery_sha1)s; then log -t recovery "Installing new recovery image" applypatch %(bonus_args)s %(boot_type)s:%(boot_device)s:%(boot_size)d:%(boot_sha1)s %(recovery_type)s:%(recovery_device)s %(recovery_sha1)s %(recovery_size)d %(boot_sha1)s:/system/recovery-from-boot.p else log -t recovery "Recovery image already installed" fi """ % { 'boot_size': boot_img.size, 'boot_sha1': boot_img.sha1, 'recovery_size': recovery_img.size, 'recovery_sha1': recovery_img.sha1, 'boot_type': boot_type, 'boot_device': boot_device, 'recovery_type': recovery_type, 'recovery_device': recovery_device, 'bonus_args': bonus_args, } common.ZipWriteStr(output_zip, "recovery/etc/install-recovery.sh", sh) return Item.Get("system/etc/install-recovery.sh", dir=False)
def WriteRawImage(self, mount_point, fn): """Write the given package file into the partition for the given mount point.""" fstab = self.info["fstab"] if fstab: p = fstab[mount_point] partition_type = common.PARTITION_TYPES[p.fs_type] args = {'device': p.device, 'fn': fn} if partition_type == "MTD": self.script.append(( 'assert(package_extract_file("%(fn)s", "/tmp/%(device)s.img"),\n' ' write_raw_image("/tmp/%(device)s.img", "%(device)s"),\n' ' delete("/tmp/%(device)s.img"));') % args) elif partition_type == "EMMC": self.script.append( 'package_extract_file("%(fn)s", "%(device)s");' % args) elif partition_type == "BML": self.script.append(( 'assert(package_extract_file("%(fn)s", "/tmp/%(device)s.img"),\n' ' write_raw_image("/tmp/%(device)s.img", "%(device)s"),\n' ' delete("/tmp/%(device)s.img"));') % args) else: raise ValueError("don't know how to write \"%s\" partitions" % (p.fs_type, )) else: # backward compatibility with older target-files that lack recovery.fstab if self.info["partition_type"] == "MTD": partition_type, partition = common.GetTypeAndDevice( mount_point, self.info) self.script.append(( 'assert(package_extract_file("%(fn)s", "/tmp/%(partition)s.img"),\n' ' write_raw_image("/tmp/%(partition)s.img", "%(partition)s"),\n' ' delete("/tmp/%(partition)s.img"));') % { 'partition': partition, 'fn': fn }) elif self.info["partition_type"] == "EMMC": partition_type, partition = common.GetTypeAndDevice( mount_point, self.info) self.script.append( ('package_extract_file("%(fn)s", "%(dir)s%(partition)s");') % { 'partition': partition, 'fn': fn, 'dir': self.info.get("partition_path", ""), }) else: raise ValueError("don't know how to write \"%s\" partitions" % (self.info["partition_type"], ))
def WriteRadio(info, target_radio_img, source_radio_img=None): tf = common.File("radio.img", target_radio_img) if source_radio_img is None: tf.AddToZip(info.output_zip) info.script.Print("Writing radio...") info.script.WriteRawImage("/radio", tf.name) else: sf = common.File("radio.img", source_radio_img) if tf.sha1 == sf.sha1: print "radio image unchanged; skipping" else: diff = common.Difference(tf, sf, diff_program="bsdiff") common.ComputeDifferences([diff]) _, _, d = diff.GetPatch() if d is None or len(d) > tf.size * common.OPTIONS.patch_threshold: # computing difference failed, or difference is nearly as # big as the target: simply send the target. tf.AddToZip(info.output_zip) info.script.Print("Writing radio...") info.script.WriteRawImage("/radio", tf.name) else: common.ZipWriteStr(info.output_zip, "radio.img.p", d) info.script.Print("Patching radio...") radio_type, radio_device = common.GetTypeAndDevice( "/radio", info.info_dict) info.script.ApplyPatch( "%s:%s:%d:%s:%d:%s" % (radio_type, radio_device, sf.size, sf.sha1, tf.size, tf.sha1), "-", tf.size, tf.sha1, sf.sha1, "radio.img.p")
def IncrementalOTA_InstallEnd(info): try: target_bootloader_img = info.target_zip.read("RADIO/bootloader.img") try: source_bootloader_img = info.source_zip.read( "RADIO/bootloader.img") except KeyError: source_bootloader_img = None if source_bootloader_img == target_bootloader_img: print "bootloader unchanged; skipping" else: common.ZipWriteStr(info.output_zip, "bootloader.img", target_bootloader_img) info.script.Print("Writing bootloader...") info.script.WriteRawImage("/bootloader", "bootloader.img") except KeyError: print "no bootloader.img in target target_files; skipping install" tf = FindRadio(info.target_zip) if not tf: # failed to read TARGET radio image: don't include any radio in update. print "no radio.img in target target_files; skipping install" else: tf = common.File("radio.img", tf) sf = FindRadio(info.source_zip) if not sf: # failed to read SOURCE radio image: include the whole target # radio image. tf.AddToZip(info.output_zip) info.script.Print("Writing radio...") info.script.WriteRawImage("/radio", tf.name) else: sf = common.File("radio.img", sf) if tf.sha1 == sf.sha1: print "radio image unchanged; skipping" else: diff = common.Difference(tf, sf) common.ComputeDifferences([diff]) _, _, d = diff.GetPatch() if d is None or len( d) > tf.size * common.OPTIONS.patch_threshold: # computing difference failed, or difference is nearly as # big as the target: simply send the target. tf.AddToZip(info.output_zip) info.script.Print("Writing radio...") info.script.WriteRawImage("radio", tf.name) else: common.ZipWriteStr(info.output_zip, "radio.img.p", d) info.script.Print("Patching radio...") radio_type, radio_device = common.GetTypeAndDevice( "/radio", info.info_dict) info.script.ApplyPatch( "%s:%s:%d:%s:%d:%s" % (radio_type, radio_device, sf.size, sf.sha1, tf.size, tf.sha1), "-", tf.size, tf.sha1, sf.sha1, "radio.img.p")
def CheckPatchSource(self): partition_type, partition_device = common.GetTypeAndDevice( self.partition.mount_point, self.options.info_dict) self.script.PatchCheck( "%s:%s:%d:%s:%d:%s" % (partition_type, partition_device, self.source.size, self.source.bin.sha1, self.target.size, self.target.bin.sha1))
def PatchDiffToPartition(self): extract = self.IsExtract() if extract: if self.need_extract is None: target_dir = self.partition.mount_point else: target_dir = self.need_extract target = os.path.join(target_dir, self.target.file_name) else: target = "-" # Produce the image by applying a patch to the current # contents of the partition, and write it back to the # partition or some dir. partition_type, partition_device = common.GetTypeAndDevice(self.partition.mount_point, self.options.info_dict) if (OPTIONS.secure_boot): secure_boot_type = common.GetSecureBootType(self.partition.mount_point, self.options.info_dict) if (secure_boot_type): partition_type = "%s:%s" % (secure_boot_type, partition_type) self.script.Print("Patching image file %s to %s..." % (self.file_name,target)) self.script.ApplyPatch("%s:%s:%d:%s:%d:%s" % (partition_type, partition_device, self.source.size, self.source.bin.sha1, self.target.size, self.target.bin.sha1), target, self.target.size, self.target.bin.sha1, self.source.bin.sha1, "patch/" + self.file_name + ".p")
def WriteBootloader(info, bootloader, blacklist=None): if blacklist is None: blacklist = DEFAULT_BOOTLOADER_OTA_BLACKLIST info.script.Print("Writing bootloader...") try: huawei_boot_image = HuaweiBootImage(bootloader, "bootloader") except BadMagicError: raise ValueError("bootloader.img bad magic value") common.ZipWriteStr(info.output_zip, "bootloader-flag.txt", "updating-bootloader" + "\0" * 13) common.ZipWriteStr(info.output_zip, "bootloader-flag-clear.txt", "\0" * 32) _, misc_device = common.GetTypeAndDevice("/misc", info.info_dict) info.script.AppendExtra( 'package_extract_file("bootloader-flag.txt", "%s");' % misc_device) # OTA does not support partition changes, so # do not bundle the partition image in the OTA package. WriteHuaweiBootPartitionImages(info, huawei_boot_image, blacklist) info.script.AppendExtra( 'package_extract_file("bootloader-flag-clear.txt", "%s");' % misc_device)
def IncrementalOTA_VerifyEnd(info): target_radio_img = FindRadio(info.target_zip) if common.OPTIONS.full_radio: if not target_radio_img: assert False, "full radio option specified but no radio img found" else: return source_radio_img = FindRadio(info.source_zip) if not target_radio_img or not source_radio_img: return target_modem_img = MotobootImage(target_radio_img).GetUnpackedImage( "modem") if not target_modem_img: return source_modem_img = MotobootImage(source_radio_img).GetUnpackedImage( "modem") if not source_modem_img: return if target_modem_img.sha1 != source_modem_img.sha1: info.script.CacheFreeSpaceCheck(len(source_modem_img.data)) radio_type, radio_device = common.GetTypeAndDevice( "/modem", info.info_dict) info.script.PatchCheck( "%s:%s:%d:%s:%d:%s" % (radio_type, radio_device, len( source_modem_img.data), source_modem_img.sha1, len(target_modem_img.data), target_modem_img.sha1))
def IncrementalOTA_VerifyEnd(info): global multiboot_patchinfo global tos_patchinfo fstab = info.script.info.get("fstab", None) try: if fstab['/multiboot'].device: multibootimg_type, multibootimg_device = common.GetTypeAndDevice( "/multiboot", OPTIONS.info_dict) verbatim_targets, m_patch_list, output_files = \ intel_common.ComputeBinOrImgPatches(OPTIONS.source_tmp, OPTIONS.target_tmp, "multiboot.img") if output_files is None: print "multiboot.img is none, skipping install" else: print "multiboot.img is exist. Add the patch." if not verbatim_targets and m_patch_list: (tf, sf) = m_patch_list info.script.PatchCheck( "%s:%s:%d:%s:%d:%s" % (multibootimg_type, multibootimg_device, sf.size, sf.sha1, tf.size, tf.sha1)) multiboot_patchinfo = (multibootimg_type, multibootimg_device, sf, tf) common.ZipWriteStr(info.output_zip, "patch/multiboot.img.p", output_files) if fstab['/tos'].device: tosimg_type, tosimg_device = common.GetTypeAndDevice( "/tos", OPTIONS.info_dict) verbatim_targets, m_patch_list, output_files = \ intel_common.ComputeBinOrImgPatches(OPTIONS.source_tmp, OPTIONS.target_tmp, "tos.img") if output_files is None: print "tos.img is none, skipping install" else: print "tos.img is exist. Add the patch." if not verbatim_targets and m_patch_list: (tf, sf) = m_patch_list info.script.PatchCheck( "%s:%s:%d:%s:%d:%s" % (tosimg_type, tosimg_device, sf.size, sf.sha1, tf.size, tf.sha1)) tos_patchinfo = (tosimg_type, tosimg_device, sf, tf) common.ZipWriteStr(info.output_zip, "patch/tos.img.p", output_files) except (IOError, KeyError): print "No multiboot/tos partition in iOTA Verify"
def WriteRadio(info, uboot_bin): info.script.Print("Writing uboot...") common.ZipWriteStr(info.output_zip, LOCAL_UBOOT, uboot_bin) _, device = common.GetTypeAndDevice("/uboot", info.info_dict) info.script.AppendExtra('package_extract_file("%s", "%s");' % ( LOCAL_UBOOT, device, ))
def IncrementalOTA_InstallEnd(info): try: target_bootloader_img = info.target_zip.read("RADIO/bootloader.img") try: source_bootloader_img = info.source_zip.read( "RADIO/bootloader.img") except KeyError: source_bootloader_img = None if source_bootloader_img == target_bootloader_img: print "bootloader unchanged; skipping" else: WriteBootloader(info, target_bootloader_img) except KeyError: print "no bootloader.img in target target_files; skipping install" tf = FindRadio(info.target_zip) if not tf: # failed to read TARGET radio image: don't include any radio in update. print "no radio.img in target target_files; skipping install" # we have checked the existence of the radio image in # IncrementalOTA_VerifyEnd(), so it won't reach here. assert common.OPTIONS.full_radio == False else: tf = common.File("radio.img", tf) sf = FindRadio(info.source_zip) if not sf or common.OPTIONS.full_radio: # failed to read SOURCE radio image or one has specified the option to # include the whole target radio image. print( "no radio image in source target_files or full_radio specified; " "installing complete image") WriteRadio(info, tf.data) else: sf = common.File("radio.img", sf) if tf.sha1 == sf.sha1: print "radio image unchanged; skipping" else: diff = common.Difference(tf, sf, diff_program="bsdiff") common.ComputeDifferences([diff]) _, _, d = diff.GetPatch() if d is None or len( d) > tf.size * common.OPTIONS.patch_threshold: # computing difference failed, or difference is nearly as # big as the target: simply send the target. WriteRadio(info, tf.data) else: common.ZipWriteStr(info.output_zip, "radio.img.p", d) info.script.Print("Patching radio...") radio_type, radio_device = common.GetTypeAndDevice( "/radio", info.info_dict) info.script.ApplyPatch( "%s:%s:%d:%s:%d:%s" % (radio_type, radio_device, sf.size, sf.sha1, tf.size, tf.sha1), "-", tf.size, tf.sha1, sf.sha1, "radio.img.p")
def CheckPatchSource(self): partition_type, partition_device = common.GetTypeAndDevice( self.partition.mount_point, self.options.info_dict) if partition_type == "EMMC": strinfo = re.compile('soc:ap') partition_device = strinfo.sub('soc.ap', partition_device) self.script.PatchCheck( "%s:%s:%d:%s:%d:%s" % (partition_type, partition_device, self.source.size, self.source.bin.sha1, self.target.size, self.target.bin.sha1))
def IncrementalOTA_VerifyEnd(info): target_radio_img = FindRadio(info.target_zip) source_radio_img = FindRadio(info.source_zip) if not target_radio_img or not source_radio_img: return if source_radio_img != target_radio_img: info.script.CacheFreeSpaceCheck(len(source_radio_img)) radio_type, radio_device = common.GetTypeAndDevice("/radio", info.info_dict) info.script.PatchCheck("%s:%s:%d:%s:%d:%s" % ( radio_type, radio_device, len(source_radio_img), common.sha1(source_radio_img).hexdigest(), len(target_radio_img), common.sha1(target_radio_img).hexdigest()))
def GetCareMap(which, imgname): """Generate care_map of system (or vendor) partition""" assert which in ("system", "vendor") _, blk_device = common.GetTypeAndDevice("/" + which, OPTIONS.info_dict) simg = sparse_img.SparseImage(imgname) care_map_list = [] care_map_list.append(blk_device) care_map_list.append(simg.care_map.to_string_raw()) return care_map_list
def WriteBootloader(info, bootloader_img): common.ZipWriteStr(info.output_zip, "bootloader.img", bootloader_img) bl_type, bl_device = common.GetTypeAndDevice("/bootloader", info.info_dict) fstab = info.info_dict["fstab"] info.script.Print("Writing bootloader...") force_ro = "/sys/block/" + bl_device.split("/")[-1] + "/force_ro" info.script.AppendExtra( ('samsung.manta.write_bootloader(package_extract_file(' '"bootloader.img"), "%s", "%s");') % (bl_device, force_ro))
def SystemResize(info): if not SystemResize.ran_once: e2fsck = '"/sbin/e2fsck", "-fy"'; run_prog = 'run_program(' _, sys_dev = common.GetTypeAndDevice("/system", info.info_dict) sys_dev = ', "' + sys_dev + '");' try: resize2fs = '"/tmp/' + \ info.input_zip.getinfo("install/bin/resize2fs_static").filename + '"' except: resize2fs = '"/sbin/resize2fs"' info.script.AppendExtra(run_prog + e2fsck + sys_dev) info.script.AppendExtra(run_prog + resize2fs + sys_dev) info.script.AppendExtra(run_prog + e2fsck + sys_dev) SystemResize.ran_once = True
def IncrementalOTA_VerifyEnd(info): try: target_radio_img = info.target_zip.read("RADIO/radio.img") source_radio_img = info.source_zip.read("RADIO/radio.img") except KeyError: # No source or target radio. Nothing to verify pass else: if source_radio_img != target_radio_img: info.script.CacheFreeSpaceCheck(len(source_radio_img)) radio_type, radio_device = common.GetTypeAndDevice("/radio", info.info_dict) info.script.PatchCheck("%s:%s:%d:%s:%d:%s" % ( radio_type, radio_device, len(source_radio_img), common.sha1(source_radio_img).hexdigest(), len(target_radio_img), common.sha1(target_radio_img).hexdigest()))
def IncrementalOTA_VerifyEnd(info): target_radio_img = FindRadio(info.target_zip) source_radio_img = FindRadio(info.source_zip) if not target_radio_img or not source_radio_img: return target_modem_img = HuaweiBootImage(target_radio_img).GetUnpackedImage("modem") if not target_modem_img: return source_modem_img = HuaweiBootImage(source_radio_img).GetUnpackedImage("modem") if not source_modem_img: return if target_modem_img.sha1 != source_modem_img.sha1: info.script.CacheFreeSpaceCheck(len(source_modem_img.data)) radio_type, radio_device = common.GetTypeAndDevice("/modem", info.info_dict) info.script.PatchCheck("%s:%s:%d:%s:%d:%s" % ( radio_type, radio_device, len(source_modem_img.data), source_modem_img.sha1, len(target_modem_img.data), target_modem_img.sha1))
def IncrementalOTA_VerifyEnd(info): target_radio_img = FindRadio(info.target_zip) if common.OPTIONS.full_radio: if not target_radio_img: assert False, "full radio option specified but no radio img found" else: return source_radio_img = FindRadio(info.source_zip) if not target_radio_img or not source_radio_img: return if source_radio_img != target_radio_img: info.script.CacheFreeSpaceCheck(len(source_radio_img)) radio_type, radio_device = common.GetTypeAndDevice("/radio", info.info_dict) info.script.PatchCheck("%s:%s:%d:%s:%d:%s" % ( radio_type, radio_device, len(source_radio_img), common.sha1(source_radio_img).hexdigest(), len(target_radio_img), common.sha1(target_radio_img).hexdigest()))
def WritePartitionImage(info, image, group_name=None): filename = "%s.img" % image.name if group_name: filename = "%s.%s" % (group_name, filename) try: info.script.Print("writing partition image %s" % image.name) _, device = common.GetTypeAndDevice("/" + image.name, info.info_dict) except KeyError: print "skipping flash of %s; not in recovery.fstab" % image.name return common.ZipWriteStr(info.output_zip, filename, image.data) info.script.AppendExtra('package_extract_file("%s", "%s");' % (filename, device))
def IncrementalOTA_VerifyEnd(info): global patchinfo global verbatim print "Calculating fwupdate patch information" fwu_type, fwu_device = common.GetTypeAndDevice("/fwupdate", OPTIONS.info_dict) verbatim, fwu_patch, output_files = intel_common.ComputeFWUpdatePatches( OPTIONS.source_tmp, OPTIONS.target_tmp) if not verbatim and fwu_patch: (tf, sf) = fwu_patch # The below check ensures fwupdate partition is in an expected state before # the OTA system makes any changes info.script.PatchCheck( "%s:%s:%d:%s:%d:%s" % (fwu_type, fwu_device, sf.size, sf.sha1, tf.size, tf.sha1)) patchinfo = (fwu_type, fwu_device, sf, tf) common.ZipWriteStr(info.output_zip, "patch/fwu_image.bin.p", output_files)
def IncrementalOTA_InstallEnd(info): tf = FindRadio(info.target_zip) if not tf: # failed to read TARGET radio image: don't include any radio in update. print "no radio.img in target target_files; skipping install" else: tf = common.File("uboot.bin", tf) sf = FindRadio(info.source_zip) if not sf: # failed to read SOURCE radio image: include the whole target # radio image. WriteRadio(info, tf.data) else: sf = common.File("uboot.bin", sf) if tf.sha1 == sf.sha1: print "u-boot-with-spl-mbr-gpt.bin unchanged; skipping" else: diff = common.Difference(tf, sf, diff_program="bsdiff") common.ComputeDifferences([diff]) _, _, d = diff.GetPatch() if d is None or len( d) > tf.size * common.OPTIONS.patch_threshold: # computing difference failed, or difference is nearly as # big as the target: simply send the target. WriteRadio(info, tf.data) else: common.ZipWriteStr(info.output_zip, "u-boot-with-spl-mbr-gpt.bin.p", d) info.script.Print("Patching uboot...") uboot_type, uboot_device = common.GetTypeAndDevice( "/uboot", info.info_dict) info.script.PatchCheck("%s:%s:%d:%s:%d:%s" % (uboot_type, uboot_device, sf.size, sf.sha1, tf.size, tf.sha1)) info.script.ApplyPatch( "%s:%s:%d:%s:%d:%s" % (uboot_type, uboot_device, sf.size, sf.sha1, tf.size, tf.sha1), "-", tf.size, tf.sha1, sf.sha1, "u-boot-with-spl-mbr-gpt.bin.p")
def GetCareMap(which, imgname): """Generate care_map of system (or vendor) partition""" assert which in ("system", "vendor") _, blk_device = common.GetTypeAndDevice("/" + which, OPTIONS.info_dict) simg = sparse_img.SparseImage(imgname) care_map_list = [] care_map_list.append(blk_device) care_map_ranges = simg.care_map key = which + "_adjusted_partition_size" adjusted_blocks = OPTIONS.info_dict.get(key) if adjusted_blocks: assert adjusted_blocks > 0, "blocks should be positive for " + which care_map_ranges = care_map_ranges.intersect(rangelib.RangeSet( "0-%d" % (adjusted_blocks,))) care_map_list.append(care_map_ranges.to_string_raw()) return care_map_list
def IncrementalOTA_VerifyEnd(info): global patchinfo print "Calculating fwupdate patch information" src_fwupdate = get_file_data(OPTIONS.source_tmp, "fwu_image.bin") tgt_fwupdate = get_file_data(OPTIONS.target_tmp, "fwu_image.bin") diffs = [common.Difference(tgt_fwupdate, src_fwupdate)] common.ComputeDifferences(diffs) tf, sf, d = diffs[0].GetPatch() # If the patch size is almost as big as the actual file don't bother if d is None or len(d) > tf.size * 0.95: print "Firmware update image will be included verbatim" return common.ZipWriteStr(info.output_zip, "patch/fwu_image.bin.p", d) fwu_type, fwu_device = common.GetTypeAndDevice("/fwupdate", OPTIONS.info_dict) # This check ensure fwupdate partition is in an expected state before # the OTA system makes any changes info.script.PatchCheck("%s:%s:%d:%s:%d:%s" % (fwu_type, fwu_device, sf.size, sf.sha1, tf.size, tf.sha1)) patchinfo = (fwu_type, fwu_device, sf, tf)
def update_raw_image_verify(info, in_img, out_img, node, inc): if inc: src = get_image(info.source_zip, in_img) tgt = get_image(info.target_zip, in_img) else: src = None tgt = get_image(info.input_zip, in_img) if not tgt: return imgtype, imgdev = common.GetTypeAndDevice(node, info.info_dict) if src: if src.data == tgt.data: print "%s images identical, not patching" % (in_img, ) return else: print "%s images differ, will patch" % (in_img, ) d = common.Difference(tgt, src) _, _, d = d.ComputePatch() print "%s target: %d source: %d diff: %d" % (out_img, tgt.size, src.size, len(d)) out_img = "patch/%s.p" % (out_img, ) common.ZipWriteStr(info.output_zip, out_img, d) info.script.PatchCheck( "%s:%s:%d:%s:%d:%s" % (imgtype, imgdev, src.size, src.sha1, tgt.size, tgt.sha1)) info.script.CacheFreeSpaceCheck(src.size) img[node] = {} img[node]["out_img"] = out_img img[node]["src"] = src img[node]["tgt"] = tgt img[node]["type"] = imgtype img[node]["dev"] = imgdev
def WriteBootloader(info, bootloader): info.script.Print("Writing bootloader...") header_fmt = "<8sIII" header_size = struct.calcsize(header_fmt) magic, num_images, start_offset, bootloader_size = struct.unpack( header_fmt, bootloader[:header_size]) assert magic == "BOOTLDR!", "bootloader.img bad magic value" img_info_fmt = "<64sI" img_info_size = struct.calcsize(img_info_fmt) imgs = [struct.unpack(img_info_fmt, bootloader[header_size+i*img_info_size: header_size+(i+1)*img_info_size]) for i in range(num_images)] total = 0 p = start_offset img_dict = {} for name, size in imgs: img_dict[trunc_to_null(name)] = p, size p += size assert p - start_offset == bootloader_size, "bootloader.img corrupted" imgs = img_dict common.ZipWriteStr(info.output_zip, "bootloader-flag.txt", "updating-bootloader" + "\0" * 13) common.ZipWriteStr(info.output_zip, "bootloader-flag-clear.txt", "\0" * 32) _, misc_device = common.GetTypeAndDevice("/misc", info.info_dict) info.script.AppendExtra( 'package_extract_file("bootloader-flag.txt", "%s");' % (misc_device,)) # Depending on the build fingerprint, we can decide which partitions # to update. fp = info.info_dict["build.prop"]["ro.build.fingerprint"] if "release-keys" in fp: to_flash = release_partitions.split() else: to_flash = debug_partitions.split() # Write the images to separate files in the OTA package for i in to_flash: try: _, device = common.GetTypeAndDevice("/"+i, info.info_dict) except KeyError: print "skipping flash of %s; not in recovery.fstab" % (i,) continue common.ZipWriteStr(info.output_zip, "bootloader.%s.img" % (i,), bootloader[imgs[i][0]:imgs[i][0]+imgs[i][1]]) WriteImageAssert(info, "bootloader.%s.img" % (i,), bootloader[imgs[i][0]:imgs[i][0]+imgs[i][1]], device) info.script.AppendExtra( 'package_extract_file("bootloader-flag-clear.txt", "%s");' % (misc_device,)) try: for i in backup_partitions.split(): _, device = common.GetTypeAndDevice("/"+i+"b", info.info_dict) WriteImageAssert(info, "bootloader.%s.img" % (i,), bootloader[imgs[i][0]:imgs[i][0]+imgs[i][1]], device) except KeyError: pass
def WriteRadio(info, radio_img): info.script.Print("Writing radio...") common.ZipWriteStr(info.output_zip, "radio.img", radio_img) _, device = common.GetTypeAndDevice("/radio", info.info_dict) WriteImageAssert(info, "radio.img", radio_img, device)
def WriteBootloader(info, bootloader): info.script.Print("Writing bootloader...") # bootloader.img contains 6 separate images. Each goes to its own # partition; we write all 6 for development devices but skip one for # release devices.. There are backup partitions of all but the # special one that we also write. The special one is "sbl1", which # does not have a backup, so we don't update it on release devices.. header_fmt = "<8sIII" header_size = struct.calcsize(header_fmt) magic, num_images, start_offset, bootloader_size = struct.unpack( header_fmt, bootloader[:header_size]) assert magic == "BOOTLDR!", "bootloader.img bad magic value" img_info_fmt = "<64sI" img_info_size = struct.calcsize(img_info_fmt) imgs = [struct.unpack(img_info_fmt, bootloader[header_size+i*img_info_size: header_size+(i+1)*img_info_size]) for i in range(num_images)] total = 0 p = start_offset img_dict = {} for name, size in imgs: img_dict[trunc_to_null(name)] = p, size p += size assert p - start_offset == bootloader_size, "bootloader.img corrupted" imgs = img_dict common.ZipWriteStr(info.output_zip, "bootloader-flag.txt", "updating-bootloader" + "\0" * 13) common.ZipWriteStr(info.output_zip, "bootloader-flag-clear.txt", "\0" * 32) _, misc_device = common.GetTypeAndDevice("/misc", info.info_dict) info.script.AppendExtra( 'package_extract_file("bootloader-flag.txt", "%s");' % (misc_device,)) # flashing sbl1 is somewhat dangerous because if we die while doing # it the device can't boot. Do it for development devices but not # release devices. fp = info.info_dict["build.prop"]["ro.build.fingerprint"] if "release-keys" in fp: to_flash = "sbl2 sbl3 tz rpm aboot".split() else: to_flash = "sbl1 sbl2 sbl3 tz rpm aboot".split() # Write the images to separate files in the OTA package for i in to_flash: try: _, device = common.GetTypeAndDevice("/"+i, info.info_dict) except KeyError: print "skipping flash of %s; not in recovery.fstab" % (i,) continue common.ZipWriteStr(info.output_zip, "bootloader.%s.img" % (i,), bootloader[imgs[i][0]:imgs[i][0]+imgs[i][1]]) info.script.AppendExtra('package_extract_file("bootloader.%s.img", "%s");' % (i, device)) info.script.AppendExtra( 'package_extract_file("bootloader-flag-clear.txt", "%s");' % (misc_device,)) try: # there is no "sbl1b" partition for i in "sbl2 sbl3 tz rpm aboot".split(): _, device = common.GetTypeAndDevice("/"+i+"b", info.info_dict) info.script.AppendExtra( 'package_extract_file("bootloader.%s.img", "%s");' % (i, device)) except KeyError: pass
def WriteRadio(info, radio_img): info.script.Print("Writing radio...") common.ZipWriteStr(info.output_zip, "radio.img", radio_img) _, device = common.GetTypeAndDevice("/radio", info.info_dict) info.script.AppendExtra( 'package_extract_file("radio.img", "%s");' % (device,))
def AddOTAImage_Items(input_zip, output_zip, info_dict, script): try: output = input_zip.read("OTA/ota_update_list.txt") except: print "update_img_list not found" return storage_type = "EMMC" td_pair = common.GetTypeAndDevice("/boot", info_dict) if not td_pair: return storage_type = td_pair[0] isBackupImgExist = 0 isFirstRun = 0 part_list = [] general_img_list = [] loader_img_list = [] for line in output.split("\n"): if not line: continue columns = line.split() try: img_read = input_zip.read("IMAGES/%s" % columns[0]) except: print "read image %s fail, remove from update list" % columns[0] continue common.ZipWriteStr(output_zip, columns[0], img_read) if len(columns) == 2: general_img_list.append(columns[:2]) elif len(columns) == 3: loader_img_list.append(columns[:3]) else: print "incorrect format in ota_update_list.txt" return script.AppendExtra('show_mtupdate_stage("%s");' % mtStageFile) for img_name, mount_point in general_img_list: if general_img_list.index([img_name, mount_point]) == 0: script.AppendExtra( 'ifelse (\nless_than_int(get_mtupdate_stage("%s"), "1") ,\n(' % mtStageFile) script.AppendExtra('ui_print("start to update general image");') WriteRawImage2(script, mount_point, img_name, info_dict) if len(general_img_list) > 0: SwitchStage(script, "1") script.AppendExtra( '),\nui_print("general images are already updated");\n);') if len(loader_img_list) > 0: for img_name, mount_point, backup_mount_point in loader_img_list: if loader_img_list.index( [img_name, mount_point, backup_mount_point]) == 0: script.AppendExtra( 'ifelse (\nless_than_int(get_mtupdate_stage("%s"), "3") ,\n(' % mtStageFile) script.AppendExtra( 'if less_than_int(get_mtupdate_stage("%s"), "2") then\n' % mtStageFile) script.AppendExtra( 'ui_print("start to update alt loader image");') WriteRawImage2(script, backup_mount_point, img_name, info_dict) SwitchStage(script, "2") script.AppendExtra('endif;\n') for img_name, mount_point, backup_mount_point in loader_img_list: SwitchActive(script, mount_point, backup_mount_point) SwitchStage(script, "3") script.AppendExtra( '),\nui_print("alt loder images are already updated");\n);') for img_name, mount_point, backup_mount_point in loader_img_list: if loader_img_list.index( [img_name, mount_point, backup_mount_point]) == 0: script.AppendExtra( 'ifelse (\nless_than_int(get_mtupdate_stage("%s"), "5") ,\n(' % mtStageFile) script.AppendExtra( 'if less_than_int(get_mtupdate_stage("%s"), "4") then\n' % mtStageFile) script.AppendExtra( 'ui_print("start to update main loader image");') WriteRawImage2(script, mount_point, img_name, info_dict) SwitchStage(script, "4") script.AppendExtra('endif;\n') for img_name, mount_point, backup_mount_point in loader_img_list: SwitchActive(script, backup_mount_point, mount_point) script.AppendExtra( '),\nui_print("main loader images are already updated");\n);') script.AppendExtra('delete("%s");' % mtStageFile)