From 32b527d6cb951335f06c37c4d9a7a8216974a86a Mon Sep 17 00:00:00 2001 From: Doug Zongker Date: Tue, 4 Mar 2014 10:03:02 -0800 Subject: [PATCH] test block system image patch at build time After building a patch for the system image (for incremental block OTAs), apply it to a local copy of the file and test that it succeeds. This is an imperfect test as it's using the local client's syspatch_host, which may differ from the syspatch library actually used in the target build, but it's somewhat better than nothing. Change-Id: Ic0001b0145881e2ebd4b5b36ce9b5bcebd76deb4 --- core/Makefile | 3 +- tools/releasetools/ota_from_target_files | 69 ++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/core/Makefile b/core/Makefile index c0b2902e5..bae7d5984 100644 --- a/core/Makefile +++ b/core/Makefile @@ -1136,7 +1136,8 @@ DISTTOOLS := $(HOST_OUT_EXECUTABLES)/minigzip \ $(HOST_OUT_EXECUTABLES)/make_ext4fs \ $(HOST_OUT_EXECUTABLES)/simg2img \ $(HOST_OUT_EXECUTABLES)/e2fsck \ - $(HOST_OUT_EXECUTABLES)/xdelta3 + $(HOST_OUT_EXECUTABLES)/xdelta3 \ + $(HOST_OUT_EXECUTABLES)/syspatch_host OTATOOLS := $(DISTTOOLS) \ $(HOST_OUT_EXECUTABLES)/aapt diff --git a/tools/releasetools/ota_from_target_files b/tools/releasetools/ota_from_target_files index 59dd06e7f..f71bd1f6f 100755 --- a/tools/releasetools/ota_from_target_files +++ b/tools/releasetools/ota_from_target_files @@ -621,7 +621,6 @@ def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip): src_sys_sha1 = sha1(src_data).hexdigest() print "source system sha1:", src_sys_sha1 src_file.write(src_data) - src_data = None print "building target system image..." tgt_file = tempfile.NamedTemporaryFile() @@ -632,10 +631,14 @@ def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip): print "target system sha1:", tgt_sys_sha1 tgt_sys_len = len(tgt_data) tgt_file.write(tgt_data) - tgt_data = None system_type, system_device = common.GetTypeAndDevice("/system", OPTIONS.info_dict) system_patch = common.MakeSystemPatch(src_file, tgt_file) + + TestBlockPatch(src_data, src_mapdata, system_patch.data, tgt_mapdata, tgt_sys_sha1) + src_data = None + tgt_data = None + system_patch.AddToZip(output_zip, compression=zipfile.ZIP_STORED) src_mapfilename = system_patch.name + ".src.map" common.ZipWriteStr(output_zip, src_mapfilename, src_mapdata) @@ -769,6 +772,66 @@ endif; script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary) WriteMetadata(metadata, output_zip) +def ParseMap(map_str): + x = map_str.split() + assert int(x[0]) == 4096 + assert int(x[1]) == len(x)-2 + return int(x[0]), [int(i) for i in x[2:]] + +def TestBlockPatch(src_muimg, src_map, patch_data, tgt_map, tgt_sha1): + src_blksize, src_regions = ParseMap(src_map) + tgt_blksize, tgt_regions = ParseMap(tgt_map) + + with tempfile.NamedTemporaryFile() as src_file,\ + tempfile.NamedTemporaryFile() as patch_file,\ + tempfile.NamedTemporaryFile() as tgt_file,\ + tempfile.NamedTemporaryFile() as src_map_file,\ + tempfile.NamedTemporaryFile() as tgt_map_file: + + src_total = sum(src_regions) * src_blksize + src_file.truncate(src_total) + p = 0 + for i in range(0, len(src_regions), 2): + c, dc = src_regions[i:i+2] + src_file.write(src_muimg[p:(p+c*src_blksize)]) + p += c*src_blksize + src_file.seek(dc*src_blksize, 1) + assert src_file.tell() == src_total + + patch_file.write(patch_data) + + tgt_total = sum(tgt_regions) * tgt_blksize + tgt_file.truncate(tgt_total) + + src_map_file.write(src_map) + tgt_map_file.write(tgt_map) + + src_file.flush() + src_map_file.flush() + patch_file.flush() + tgt_file.flush() + tgt_map_file.flush() + + p = common.Run(["syspatch_host", src_file.name, src_map_file.name, + patch_file.name, tgt_file.name, tgt_map_file.name], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + stdoutdata, _ = p.communicate() + if p.returncode != 0: + print stdoutdata + raise ValueError("failed to reconstruct target system image from patch") + + h = sha1() + for i in range(0, len(tgt_regions), 2): + c, dc = tgt_regions[i:i+2] + h.update(tgt_file.read(c*tgt_blksize)) + tgt_file.seek(dc*tgt_blksize, 1) + + if h.hexdigest() != tgt_sha1: + raise ValueError("patch reconstructed incorrect target system image") + + print "test of system image patch succeeded" + + def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip): target_has_recovery_patch = HasRecoveryPatch(target_zip) source_has_recovery_patch = HasRecoveryPatch(source_zip) @@ -859,7 +922,7 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip): if d is None or len(d) > tf.size * OPTIONS.patch_threshold or \ path not in known_paths: # patch is almost as big as the file; don't bother patching - # or a patch + rename cannot take place due to the target + # or a patch + rename cannot take place due to the target # directory not existing tf.AddToZip(output_zip) verbatim_targets.append((tf.name, tf.size)) -- 2.11.0