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 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) 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 ComputeFWUpdatePatches(source_tfp_dir, target_tfp_dir, variant=None, existing_ota_zip=None): patch_list = None verbatim = None output_files = None # In case an already "fixed up" ota package is passed - Do nothing if existing_ota_zip and patch_or_verbatim_exists("fwu_image.bin", existing_ota_zip): return verbatim, patch_list, output_files src_fwupdate_data = readfile_from_provdata(source_tfp_dir, "fwu_image.bin", variant) if not src_fwupdate_data: return verbatim, patch_list, output_files tgt_fwupdate_data = readfile_from_provdata(target_tfp_dir, "fwu_image.bin", variant) if not tgt_fwupdate_data: return verbatim, patch_list, output_files src_fwupdate = common.File("fwu_image.bin", src_fwupdate_data) tgt_fwupdate = common.File("fwu_image.bin", tgt_fwupdate_data) diffs = [common.Difference(tgt_fwupdate, src_fwupdate)] common.ComputeDifferences(diffs) tf, sf, d = diffs[0].GetPatch() verbatim = False # If the patch size is almost as big as the actual file # the fwu_image will be included in the OTA verbatim. if d is None or len(d) > tf.size * 0.95: print("Firmware update image will be included verbatim") verbatim = True else: patch_list = (tf,sf) output_files = d return verbatim, patch_list, output_files
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 ComputeBootloaderPatch(source_tfp_dir, target_tfp_dir, variant=None, base_variant=None, existing_ota_zip=None): target_data = LoadBootloaderFiles(target_tfp_dir, variant=variant, base_variant=base_variant) source_data = LoadBootloaderFiles(source_tfp_dir, variant=variant, base_variant=base_variant) diffs = [] # List of files that will be included in the OTA verbatim because # they are either new or the patch is > 95% in size of the original # file. If this isn't empty you just need to call edify generator # UnpackPackageDir("bootloader", "/bootloader") verbatim_targets = [] # Returned list of common.File objects that need to be added to # the OTA archive, for each one call AddToZip() output_files = [] # Returned list of patches to be created. # Each element is a tuple of the form (path, target File object, # source File object, target file size) patch_list = [] for fn in sorted(target_data.keys()): filepath = os.path.join('bootloader', fn) if existing_ota_zip and patch_or_verbatim_exists(filepath, existing_ota_zip): continue tf = target_data[fn] sf = source_data.get(fn, None) if sf is None: verbatim_targets.append(fn) output_files.append(tf) elif tf.sha1 != sf.sha1: diffs.append(common.Difference(tf, sf)) common.ComputeDifferences(diffs) for diff in diffs: tf, sf, d = diff.GetPatch() if d is None or len(d) > tf.size * 0.95: output_files.append(tf) verbatim_targets.append(tf.name) else: output_files.append(common.File("patch/" + tf.name + ".p", d)) patch_list.append((tf, sf)) # output list of files that need to be deleted, pass this to # edify generator DeleteFiles in InstallEnd delete_files = ["/bootloader/"+i for i in sorted(source_data) if i not in target_data] return (output_files, delete_files, patch_list, verbatim_targets)
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 ComputeBinOrImgPatches(source_tfp_dir, target_tfp_dir, filename=None, variant=None, existing_ota_zip=None): patch_list = [] verbatim = None output_files = None if filename is None: print("Error input, no filename ") return [None, None, None] source_loader_filepath = os.path.join(source_tfp_dir, "RADIO", filename) if not os.path.exists(source_loader_filepath): print("Source:Can't find ", source_loader_filepath) return [None, None, None] source_loader_file = open(source_loader_filepath) source_loader_data = source_loader_file.read() source_loader_file.close() target_loader_filepath = os.path.join(target_tfp_dir, "RADIO", filename) if not os.path.exists(target_loader_filepath): print("Target Can't find ", target_loader_filepath) return [None, None, None] target_loader_file = open(target_loader_filepath) target_loader_data = target_loader_file.read() target_loader_file.close() src_bin = common.File(filename, source_loader_data) tgt_bin = common.File(filename, target_loader_data) diffs = [common.Difference(tgt_bin, src_bin)] common.ComputeDifferences(diffs) tf, sf, d = diffs[0].GetPatch() verbatim = False # If the patch size is almost as big as the actual file # the image will be included in the OTA verbatim. if d is None or len(d) > tf.size * 0.95: print(filename, "update will be included verbatim") verbatim = True else: patch_list = (tf,sf) output_files = d return verbatim, patch_list, output_files
def IncrementalEspUpdateInit(info): global target_data global source_data global delete_files global bootloader_update target_data = LoadBootloaderFiles(OPTIONS.target_tmp) source_data = LoadBootloaderFiles(OPTIONS.source_tmp) diffs = [] for fn in sorted(target_data.keys()): tf = target_data[fn] sf = source_data.get(fn, None) if sf is None: tf.AddToZip(info.output_zip) verbatim_targets.append(fn) elif tf.sha1 != sf.sha1: diffs.append(common.Difference(tf, sf)) common.ComputeDifferences(diffs) for diff in diffs: tf, sf, d = diff.GetPatch() if d is None or len(d) > tf.size * 0.95: tf.AddToZip(info.output_zip) verbatim_targets.append(tf.name) else: common.ZipWriteStr(info.output_zip, "patch/" + tf.name + ".p", d) patch_list.append( (tf.name, tf, sf, tf.size, common.sha1(d).hexdigest())) delete_files = ( ["/" + i[0] for i in verbatim_targets] + ["/" + i for i in sorted(source_data) if i not in target_data]) if (delete_files or patch_list or verbatim_targets or os.path.exists(os.path.join(OPTIONS.target_tmp, sfu_path))): print "EFI System Partition will be updated" bootloader_update = True
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)