1b92167f787b4d9ea4db453b2464509489e1e606bGilad Arnold#!/usr/bin/python2
2553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold#
3553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
4553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold# Use of this source code is governed by a BSD-style license that can be
5553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold# found in the LICENSE file.
6553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
7553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold"""Command-line tool for checking and applying Chrome OS update payloads."""
8553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
9b92167f787b4d9ea4db453b2464509489e1e606bGilad Arnoldfrom __future__ import print_function
10b92167f787b4d9ea4db453b2464509489e1e606bGilad Arnold
11553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnoldimport optparse
12553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnoldimport os
13553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnoldimport sys
14553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
15553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold# pylint: disable=F0401
16553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnoldlib_dir = os.path.join(os.path.dirname(__file__), 'lib')
17553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnoldif os.path.exists(lib_dir) and os.path.isdir(lib_dir):
18553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  sys.path.insert(1, lib_dir)
19553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnoldimport update_payload
20553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
21553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
22553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold_TYPE_FULL = 'full'
23553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold_TYPE_DELTA = 'delta'
24553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
25553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
264fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnolddef ParseArguments(argv):
27553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  """Parse and validate command-line arguments.
28553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
29553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  Args:
304fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold    argv: command-line arguments to parse (excluding the program name)
31b92167f787b4d9ea4db453b2464509489e1e606bGilad Arnold
32553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  Returns:
334fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold    A tuple (opts, payload, extra_args), where `opts' are the options
34553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold    returned by the parser, `payload' is the name of the payload file
35553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold    (mandatory argument) and `extra_args' are any additional command-line
36553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold    arguments.
37553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  """
38553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  parser = optparse.OptionParser(
394fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold      usage=('Usage: %prog [OPTION...] PAYLOAD [DST_KERN DST_ROOT '
404fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold             '[SRC_KERN SRC_ROOT]]'),
414fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold      description=('Applies a Chrome OS update PAYLOAD to SRC_KERN and '
424fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold                   'SRC_ROOT emitting DST_KERN and DST_ROOT, respectively. '
434fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold                   'SRC_KERN and SRC_ROOT are only needed for delta payloads. '
444fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold                   'When no partitions are provided, verifies the payload '
454fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold                   'integrity.'),
464fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold      epilog=('Note: a payload may verify correctly but fail to apply, and '
474fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold              'vice versa; this is by design and can be thought of as static '
484fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold              'vs dynamic correctness. A payload that both verifies and '
494fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold              'applies correctly should be safe for use by the Chrome OS '
504fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold              'Update Engine. Use --check to verify a payload prior to '
514fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold              'applying it.'))
524fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold
53272a499e2db9d72a64490ca5ccbebe8155fc2966Gilad Arnold  check_opts = optparse.OptionGroup(parser, 'Checking payload integrity')
54553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  check_opts.add_option('-c', '--check', action='store_true', default=False,
554fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold                        help=('force payload integrity check (e.g. before '
564fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold                              'applying)'))
57432d601e236bf8b9110fdb497e5f5c87899346e2Don Garrett  check_opts.add_option('-D', '--describe', action='store_true', default=False,
58432d601e236bf8b9110fdb497e5f5c87899346e2Don Garrett                        help='Print a friendly description of the payload.')
59553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  check_opts.add_option('-r', '--report', metavar='FILE',
60553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold                        help="dump payload report (`-' for stdout)")
61553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  check_opts.add_option('-t', '--type', metavar='TYPE', dest='assert_type',
624fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold                        help=("assert that payload is either `%s' or `%s'" %
634fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold                              (_TYPE_FULL, _TYPE_DELTA)))
64553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  check_opts.add_option('-z', '--block-size', metavar='NUM', default=0,
65553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold                        type='int',
66553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold                        help='assert a non-default (4096) payload block size')
67553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  check_opts.add_option('-u', '--allow-unhashed', action='store_true',
68553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold                        default=False, help='allow unhashed operations')
69eaed0d1371d781d3f5effa1475f5202dea9467e7Gilad Arnold  check_opts.add_option('-d', '--disabled_tests', metavar='TESTLIST',
70eaed0d1371d781d3f5effa1475f5202dea9467e7Gilad Arnold                        default=(),
71eaed0d1371d781d3f5effa1475f5202dea9467e7Gilad Arnold                        help=('comma-separated list of tests to disable; '
72eaed0d1371d781d3f5effa1475f5202dea9467e7Gilad Arnold                              'available values: ' +
73eaed0d1371d781d3f5effa1475f5202dea9467e7Gilad Arnold                              ', '.join(update_payload.CHECKS_TO_DISABLE)))
749b90c93edcaa16f6c734f421ccf00201a474d9eaGilad Arnold  check_opts.add_option('-k', '--key', metavar='FILE',
7543116436524744f065ff29cfbe31e045339a1204Gilad Arnold                        help=('Override standard key used for signature '
7643116436524744f065ff29cfbe31e045339a1204Gilad Arnold                              'validation'))
77553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  check_opts.add_option('-m', '--meta-sig', metavar='FILE',
78553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold                        help='verify metadata against its signature')
79382df5ce2f4b67bf0998b01c6fedcdb5c35ebef9Gilad Arnold  check_opts.add_option('-p', '--root-part-size', metavar='NUM',
8006eea33088be4418264d12820f94c700977e3fa6Gilad Arnold                        default=0, type='int',
8106eea33088be4418264d12820f94c700977e3fa6Gilad Arnold                        help=('override rootfs partition size auto-inference'))
82382df5ce2f4b67bf0998b01c6fedcdb5c35ebef9Gilad Arnold  check_opts.add_option('-P', '--kern-part-size', metavar='NUM',
8306eea33088be4418264d12820f94c700977e3fa6Gilad Arnold                        default=0, type='int',
8406eea33088be4418264d12820f94c700977e3fa6Gilad Arnold                        help=('override kernel partition size auto-inference'))
85553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  parser.add_option_group(check_opts)
86553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
87272a499e2db9d72a64490ca5ccbebe8155fc2966Gilad Arnold  trace_opts = optparse.OptionGroup(parser, 'Applying payload')
88272a499e2db9d72a64490ca5ccbebe8155fc2966Gilad Arnold  trace_opts.add_option('-x', '--extract-bsdiff', action='store_true',
89272a499e2db9d72a64490ca5ccbebe8155fc2966Gilad Arnold                        default=False,
90272a499e2db9d72a64490ca5ccbebe8155fc2966Gilad Arnold                        help=('use temp input/output files with BSDIFF '
91272a499e2db9d72a64490ca5ccbebe8155fc2966Gilad Arnold                              'operations (not in-place)'))
9221a0250e767dd6fc787252b9cc05657405332774Gilad Arnold  trace_opts.add_option('--bspatch-path', metavar='FILE',
9321a0250e767dd6fc787252b9cc05657405332774Gilad Arnold                        help=('use the specified bspatch binary'))
94272a499e2db9d72a64490ca5ccbebe8155fc2966Gilad Arnold  parser.add_option_group(trace_opts)
95272a499e2db9d72a64490ca5ccbebe8155fc2966Gilad Arnold
96553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  trace_opts = optparse.OptionGroup(parser, 'Block tracing')
97553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  trace_opts.add_option('-b', '--root-block', metavar='BLOCK', type='int',
98553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold                        help='trace the origin for a rootfs block')
99553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  trace_opts.add_option('-B', '--kern-block', metavar='BLOCK', type='int',
100553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold                        help='trace the origin for a kernel block')
101553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  trace_opts.add_option('-s', '--skip', metavar='NUM', default='0', type='int',
102553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold                        help='skip first NUM occurrences of traced block')
103553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  parser.add_option_group(trace_opts)
104553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
1054fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold  # Parse command-line arguments.
1064fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold  opts, args = parser.parse_args(argv)
1074fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold
1084fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold  # Validate a value given to --type, if any.
1094fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold  if opts.assert_type not in (None, _TYPE_FULL, _TYPE_DELTA):
1104fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold    parser.error('invalid argument to --type: %s' % opts.assert_type)
1114fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold
112eaed0d1371d781d3f5effa1475f5202dea9467e7Gilad Arnold  # Convert and validate --disabled_tests value list, if provided.
113eaed0d1371d781d3f5effa1475f5202dea9467e7Gilad Arnold  if opts.disabled_tests:
114eaed0d1371d781d3f5effa1475f5202dea9467e7Gilad Arnold    opts.disabled_tests = opts.disabled_tests.split(',')
115eaed0d1371d781d3f5effa1475f5202dea9467e7Gilad Arnold    for test in opts.disabled_tests:
116eaed0d1371d781d3f5effa1475f5202dea9467e7Gilad Arnold      if test not in update_payload.CHECKS_TO_DISABLE:
117eaed0d1371d781d3f5effa1475f5202dea9467e7Gilad Arnold        parser.error('invalid argument to --disabled_tests: %s' % test)
118eaed0d1371d781d3f5effa1475f5202dea9467e7Gilad Arnold
1194fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold  # Ensure consistent use of block tracing options.
12053b62278d049a50c20e6693aeaefe9675ccb8407Gilad Arnold  do_block_trace = not (opts.root_block is None and opts.kern_block is None)
1214fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold  if opts.skip and not do_block_trace:
1224fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold    parser.error('--skip must be used with either --root-block or --kern-block')
1234fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold
1244fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold  # There are several options that imply --check.
1254fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold  opts.check = (opts.check or opts.report or opts.assert_type or
126e73dad9a9ea7121c9e80448dbda154c2510a860fGilad Arnold                opts.block_size or opts.allow_unhashed or
1279b90c93edcaa16f6c734f421ccf00201a474d9eaGilad Arnold                opts.disabled_tests or opts.meta_sig or opts.key or
12806eea33088be4418264d12820f94c700977e3fa6Gilad Arnold                opts.root_part_size or opts.kern_part_size)
1294fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold
1304fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold  # Check number of arguments, enforce payload type accordingly.
1314fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold  if len(args) == 3:
1324fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold    if opts.assert_type == _TYPE_DELTA:
1334fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold      parser.error('%s payload requires source partition arguments' %
1344fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold                   _TYPE_DELTA)
1354fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold    opts.assert_type = _TYPE_FULL
1364fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold  elif len(args) == 5:
1374fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold    if opts.assert_type == _TYPE_FULL:
1384fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold      parser.error('%s payload does not accept source partition arguments' %
1394fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold                   _TYPE_FULL)
1404fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold    opts.assert_type = _TYPE_DELTA
1414fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold  elif len(args) == 1:
1424fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold    # Not applying payload; if block tracing not requested either, do an
1434fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold    # integrity check.
1444fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold    if not do_block_trace:
1454fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold      opts.check = True
146272a499e2db9d72a64490ca5ccbebe8155fc2966Gilad Arnold    if opts.extract_bsdiff:
147272a499e2db9d72a64490ca5ccbebe8155fc2966Gilad Arnold      parser.error('--extract-bsdiff can only be used when applying payloads')
14821a0250e767dd6fc787252b9cc05657405332774Gilad Arnold    if opts.bspatch_path:
14921a0250e767dd6fc787252b9cc05657405332774Gilad Arnold      parser.error('--bspatch-path can only be used when applying payloads')
1504fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold  else:
1514fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold    parser.error('unexpected number of arguments')
1524fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold
15330027fdb6dec1418ad92270cf4932c3635bd2b3dDon Garrett  # By default, look for a metadata-signature file with a name based on the name
1549b90c93edcaa16f6c734f421ccf00201a474d9eaGilad Arnold  # of the payload we are checking. We only do it if check was triggered.
1559b90c93edcaa16f6c734f421ccf00201a474d9eaGilad Arnold  if opts.check and not opts.meta_sig:
15630027fdb6dec1418ad92270cf4932c3635bd2b3dDon Garrett    default_meta_sig = args[0] + '.metadata-signature'
15730027fdb6dec1418ad92270cf4932c3635bd2b3dDon Garrett    if os.path.isfile(default_meta_sig):
15830027fdb6dec1418ad92270cf4932c3635bd2b3dDon Garrett      opts.meta_sig = default_meta_sig
159b92167f787b4d9ea4db453b2464509489e1e606bGilad Arnold      print('Using default metadata signature', opts.meta_sig, file=sys.stderr)
16030027fdb6dec1418ad92270cf4932c3635bd2b3dDon Garrett
1614fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold  return opts, args[0], args[1:]
1624fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold
1634fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold
1644fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnolddef main(argv):
165553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  # Parse and validate arguments.
1664fbe409cb84e9ae89f22c6f3e80580ee49dbc0a2Gilad Arnold  options, payload_file_name, extra_args = ParseArguments(argv[1:])
167553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
168553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  with open(payload_file_name) as payload_file:
169553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold    payload = update_payload.Payload(payload_file)
170553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold    try:
171553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold      # Initialize payload.
172553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold      payload.Init()
173553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
174432d601e236bf8b9110fdb497e5f5c87899346e2Don Garrett      if options.describe:
175432d601e236bf8b9110fdb497e5f5c87899346e2Don Garrett        payload.Describe()
176432d601e236bf8b9110fdb497e5f5c87899346e2Don Garrett
177553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold      # Perform payload integrity checks.
178553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold      if options.check:
179553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold        report_file = None
180553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold        do_close_report_file = False
1817a7edfd034e37663337049ccb0aa59467f3b8fd1Gilad Arnold        metadata_sig_file = None
182553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold        try:
183553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold          if options.report:
184553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold            if options.report == '-':
185553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold              report_file = sys.stdout
186553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold            else:
187553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold              report_file = open(options.report, 'w')
188553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold              do_close_report_file = True
18903959b7eaeb9f14cc86a5e053b5e569590c8a44bGilad Arnold
1907a7edfd034e37663337049ccb0aa59467f3b8fd1Gilad Arnold          metadata_sig_file = options.meta_sig and open(options.meta_sig)
191553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold          payload.Check(
192553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold              pubkey_file_name=options.key,
1934f8c17cdb113fe1d3743cbd2827b5d38a1f1e51dGilad Arnold              metadata_sig_file=metadata_sig_file,
194553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold              report_out_file=report_file,
195553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold              assert_type=options.assert_type,
196553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold              block_size=int(options.block_size),
197382df5ce2f4b67bf0998b01c6fedcdb5c35ebef9Gilad Arnold              rootfs_part_size=options.root_part_size,
198382df5ce2f4b67bf0998b01c6fedcdb5c35ebef9Gilad Arnold              kernel_part_size=options.kern_part_size,
199eaed0d1371d781d3f5effa1475f5202dea9467e7Gilad Arnold              allow_unhashed=options.allow_unhashed,
200eaed0d1371d781d3f5effa1475f5202dea9467e7Gilad Arnold              disabled_tests=options.disabled_tests)
201553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold        finally:
2027a7edfd034e37663337049ccb0aa59467f3b8fd1Gilad Arnold          if metadata_sig_file:
2037a7edfd034e37663337049ccb0aa59467f3b8fd1Gilad Arnold            metadata_sig_file.close()
204553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold          if do_close_report_file:
205553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold            report_file.close()
206553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
207553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold      # Trace blocks.
208553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold      if options.root_block is not None:
209553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold        payload.TraceBlock(options.root_block, options.skip, sys.stdout, False)
210553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold      if options.kern_block is not None:
211553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold        payload.TraceBlock(options.kern_block, options.skip, sys.stdout, True)
212553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
213553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold      # Apply payload.
214553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold      if extra_args:
215272a499e2db9d72a64490ca5ccbebe8155fc2966Gilad Arnold        dargs = {'bsdiff_in_place': not options.extract_bsdiff}
21621a0250e767dd6fc787252b9cc05657405332774Gilad Arnold        if options.bspatch_path:
21721a0250e767dd6fc787252b9cc05657405332774Gilad Arnold          dargs['bspatch_path'] = options.bspatch_path
218272a499e2db9d72a64490ca5ccbebe8155fc2966Gilad Arnold        if options.assert_type == _TYPE_DELTA:
219272a499e2db9d72a64490ca5ccbebe8155fc2966Gilad Arnold          dargs['old_kernel_part'] = extra_args[2]
220272a499e2db9d72a64490ca5ccbebe8155fc2966Gilad Arnold          dargs['old_rootfs_part'] = extra_args[3]
221272a499e2db9d72a64490ca5ccbebe8155fc2966Gilad Arnold
222272a499e2db9d72a64490ca5ccbebe8155fc2966Gilad Arnold        payload.Apply(extra_args[0], extra_args[1], **dargs)
223553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
224553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold    except update_payload.PayloadError, e:
225553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold      sys.stderr.write('Error: %s\n' % e)
226553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold      return 1
227553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
228553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  return 0
229553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
230553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold
231553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnoldif __name__ == '__main__':
232553b0ec49bc64fc4b7df4358cd31396a87276d2bGilad Arnold  sys.exit(main(sys.argv))
233