update_payload: Add puffdiff support.
This patch adds support for applier.py to be able to apply PUFFDIFF
operation using puffin binary. It also fixes minor deficiencies for the
PUFFDIFF operation.
BUG=chromium:768461
TEST=unittests pass;
TEST=scripts/paycheck.py payload-puffin.delta new_kern.dat new_root.dat old_kern.dat old_root.dat
Change-Id: I5612ead8d8b8176e7263cfcb15403e8d36319642
Reviewed-on: https://chromium-review.googlesource.com/713540
Commit-Ready: Amin Hassani <ahassani@chromium.org>
Tested-by: Amin Hassani <ahassani@chromium.org>
Reviewed-by: Ben Chan <benchan@chromium.org>
Reviewed-by: Sen Jiang <senj@chromium.org>
diff --git a/scripts/update_payload/applier.py b/scripts/update_payload/applier.py
index cc77165..84d7e3c 100644
--- a/scripts/update_payload/applier.py
+++ b/scripts/update_payload/applier.py
@@ -213,7 +213,7 @@
self.minor_version = payload.manifest.minor_version
self.bsdiff_in_place = bsdiff_in_place
self.bspatch_path = bspatch_path or 'bspatch'
- self.puffpatch_path = puffpatch_path or 'imgpatch'
+ self.puffpatch_path = puffpatch_path or 'puffin'
self.truncate_to_expected_size = truncate_to_expected_size
def _ApplyReplaceOperation(self, op, op_name, out_data, part_file, part_size):
@@ -322,23 +322,6 @@
part_file.seek(ex.start_block * block_size)
part_file.write('\0' * (ex.num_blocks * block_size))
- def _ApplyBsdiffOperation(self, op, op_name, patch_data, new_part_file):
- """Applies a BSDIFF operation.
-
- Args:
- op: the operation object
- op_name: name string for error reporting
- patch_data: the binary patch content
- new_part_file: the target partition file object
-
- Raises:
- PayloadError if something goes wrong.
- """
- # Implemented using a SOURCE_BSDIFF operation with the source and target
- # partition set to the new partition.
- self._ApplyDiffOperation(op, op_name, patch_data, new_part_file,
- new_part_file)
-
def _ApplySourceCopyOperation(self, op, op_name, old_part_file,
new_part_file):
"""Applies a SOURCE_COPY operation.
@@ -393,8 +376,7 @@
patch_file.write(patch_data)
if (hasattr(new_part_file, 'fileno') and
- ((not old_part_file) or hasattr(old_part_file, 'fileno')) and
- op.type != common.OpType.PUFFDIFF):
+ ((not old_part_file) or hasattr(old_part_file, 'fileno'))):
# Construct input and output extents argument for bspatch.
in_extents_arg, _, _ = _ExtentsToBspatchArg(
op.src_extents, block_size, '%s.src_extents' % op_name,
@@ -407,10 +389,23 @@
# Diff from source partition.
old_file_name = '/dev/fd/%d' % old_part_file.fileno()
- # Invoke bspatch on partition file with extents args.
- bspatch_cmd = [self.bspatch_path, old_file_name, new_file_name,
- patch_file_name, in_extents_arg, out_extents_arg]
- subprocess.check_call(bspatch_cmd)
+ if op.type in (common.OpType.BSDIFF, common.OpType.SOURCE_BSDIFF):
+ # Invoke bspatch on partition file with extents args.
+ bspatch_cmd = [self.bspatch_path, old_file_name, new_file_name,
+ patch_file_name, in_extents_arg, out_extents_arg]
+ subprocess.check_call(bspatch_cmd)
+ elif op.type == common.OpType.PUFFDIFF:
+ # Invoke puffpatch on partition file with extents args.
+ puffpatch_cmd = [self.puffpatch_path,
+ "--operation=puffpatch",
+ "--src_file=%s" % old_file_name,
+ "--dst_file=%s" % new_file_name,
+ "--patch_file=%s" % patch_file_name,
+ "--src_extents=%s" % in_extents_arg,
+ "--dst_extents=%s" % out_extents_arg]
+ subprocess.check_call(puffpatch_cmd)
+ else:
+ raise PayloadError("Unknown operation %s", op.type)
# Pad with zeros past the total output length.
if pad_len:
@@ -429,12 +424,21 @@
with tempfile.NamedTemporaryFile(delete=False) as out_file:
out_file_name = out_file.name
- # Invoke bspatch.
- patch_cmd = [self.bspatch_path, in_file_name, out_file_name,
- patch_file_name]
- if op.type == common.OpType.PUFFDIFF:
- patch_cmd[0] = self.puffpatch_path
- subprocess.check_call(patch_cmd)
+ if op.type in (common.OpType.BSDIFF, common.OpType.SOURCE_BSDIFF):
+ # Invoke bspatch.
+ bspatch_cmd = [self.bspatch_path, in_file_name, out_file_name,
+ patch_file_name]
+ subprocess.check_call(bspatch_cmd)
+ elif op.type == common.OpType.PUFFDIFF:
+ # Invoke puffpatch.
+ puffpatch_cmd = [self.puffpatch_path,
+ "--operation=puffpatch",
+ "--src_file=%s" % in_file_name,
+ "--dst_file=%s" % out_file_name,
+ "--patch_file=%s" % patch_file_name]
+ subprocess.check_call(puffpatch_cmd)
+ else:
+ raise PayloadError("Unknown operation %s", op.type)
# Read output.
with open(out_file_name, 'rb') as out_file:
@@ -487,7 +491,8 @@
elif op.type == common.OpType.ZERO:
self._ApplyZeroOperation(op, op_name, new_part_file)
elif op.type == common.OpType.BSDIFF:
- self._ApplyBsdiffOperation(op, op_name, data, new_part_file)
+ self._ApplyDiffOperation(op, op_name, data, new_part_file,
+ new_part_file)
elif op.type == common.OpType.SOURCE_COPY:
self._ApplySourceCopyOperation(op, op_name, old_part_file,
new_part_file)
diff --git a/scripts/update_payload/checker_unittest.py b/scripts/update_payload/checker_unittest.py
index d79b00b..eecd456 100755
--- a/scripts/update_payload/checker_unittest.py
+++ b/scripts/update_payload/checker_unittest.py
@@ -818,7 +818,7 @@
Args:
op_type_name: 'REPLACE', 'REPLACE_BZ', 'MOVE', 'BSDIFF', 'SOURCE_COPY',
- or 'SOURCE_BSDIFF'.
+ 'SOURCE_BSDIFF' or 'PUFFDIFF'.
is_last: Whether we're testing the last operation in a sequence.
allow_signature: Whether we're testing a signature-capable operation.
allow_unhashed: Whether we're allowing to not hash the data.
@@ -857,7 +857,8 @@
total_src_blocks = 0
if op_type in (common.OpType.MOVE, common.OpType.BSDIFF,
- common.OpType.SOURCE_COPY, common.OpType.SOURCE_BSDIFF):
+ common.OpType.SOURCE_COPY, common.OpType.SOURCE_BSDIFF,
+ common.OpType.PUFFDIFF):
if fail_src_extents:
self.AddToMessage(op.src_extents,
self.NewExtentList((1, 0)))
@@ -872,7 +873,8 @@
payload_checker.minor_version = 2 if fail_bad_minor_version else 1
elif op_type in (common.OpType.SOURCE_COPY, common.OpType.SOURCE_BSDIFF):
payload_checker.minor_version = 1 if fail_bad_minor_version else 2
- elif op_type in (common.OpType.ZERO, common.OpType.DISCARD):
+ elif op_type in (common.OpType.ZERO, common.OpType.DISCARD,
+ common.OpType.PUFFDIFF):
payload_checker.minor_version = 3 if fail_bad_minor_version else 4
if op_type not in (common.OpType.MOVE, common.OpType.SOURCE_COPY):
@@ -1277,7 +1279,7 @@
AddParametricTests('CheckOperation',
{'op_type_name': ('REPLACE', 'REPLACE_BZ', 'MOVE',
'BSDIFF', 'SOURCE_COPY',
- 'SOURCE_BSDIFF'),
+ 'SOURCE_BSDIFF', 'PUFFDIFF'),
'is_last': (True, False),
'allow_signature': (True, False),
'allow_unhashed': (True, False),