blob: cedeffc9be16999ea842a0ccea530825350eaea7 [file] [log] [blame]
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001#!/usr/bin/python
Jon Salze60307f2014-08-05 16:20:00 +08002# -*- coding: utf-8 -*-
3# Copyright 2014 The Chromium OS Authors. All rights reserved.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08004# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
Jon Salze60307f2014-08-05 16:20:00 +08007# pylint: disable=E1101
8
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08009"""Google Factory Tool.
10
11This tool is indended to be used on factory assembly lines. It
12provides all of the Google required test functionality and must be run
13on each device as part of the assembly process.
14"""
15
Ricky Liang5b4568d2013-04-23 17:15:23 +080016import collections
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080017import logging
18import os
Jon Salz65266432012-07-30 19:02:49 +080019import pipes
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080020import re
21import sys
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080022import threading
Hung-Te Lin6bd16472012-06-20 16:26:47 +080023import time
Jon Salza88b83b2013-05-27 20:00:35 +080024import xmlrpclib
Ricky Liang7905f272013-03-16 01:57:10 +080025import yaml
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080026
Andy Cheng2582d292012-12-04 17:38:28 +080027from tempfile import gettempdir
Tammo Spalink86a61c62012-05-25 15:10:35 +080028
Tammo Spalinka40293e2012-07-04 14:58:56 +080029import factory_common # pylint: disable=W0611
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080030
Ricky Liang53390232013-03-08 15:37:57 +080031from cros.factory.gooftool import crosfw
Tammo Spalink01e11722012-07-24 10:17:54 -070032from cros.factory.gooftool import report_upload
Hung-Te Lin84c77fa2016-03-02 17:43:30 +080033from cros.factory.gooftool.core import Gooftool
Hung-Te Lin0e0f9362015-11-18 18:18:05 +080034from cros.factory.gooftool.common import Shell
Andy Cheng8ece7382012-08-22 16:25:42 +080035from cros.factory.gooftool.probe import Probe, PROBEABLE_COMPONENT_CLASSES
Jon Salz0f8a6842012-09-25 11:28:22 +080036from cros.factory.gooftool.probe import ReadRoVpd, ReadRwVpd
henryhsu44d793a2013-07-20 00:07:38 +080037from cros.factory.gooftool.probe import CalculateFirmwareHashes
Jon Salz193d7c62013-03-07 13:40:19 +080038from cros.factory.gooftool.vpd_data import KNOWN_VPD_FIELD_DATA
Tammo Spalinka40293e2012-07-04 14:58:56 +080039from cros.factory.hacked_argparse import CmdArg, Command, ParseCmdline
40from cros.factory.hacked_argparse import verbosity_cmd_arg
Hung-Te Lin604e0c22015-11-24 15:17:07 +080041from cros.factory.hwid.v2 import hwid_tool
42from cros.factory.hwid.v2.yaml_datastore import YamlWrite
43from cros.factory.hwid.v3 import common
44from cros.factory.hwid.v3 import hwid_utils
Hung-Te Lin91492a12014-11-25 18:56:30 +080045from cros.factory.test import event_log
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +080046from cros.factory.test.env import paths
47from cros.factory.test.factory import FACTORY_LOG_PATH
Hung-Te Lin3f096842016-01-13 17:37:06 +080048from cros.factory.test.rules.privacy import FilterDict
Jon Salz40b9f822014-07-25 16:39:55 +080049from cros.factory.utils import file_utils
Hung-Te Lin0e0f9362015-11-18 18:18:05 +080050from cros.factory.utils.debug_utils import SetupLogging
Jon Salzff88c022012-11-03 12:19:58 +080051from cros.factory.utils.process_utils import Spawn
Joel Kitchingd3bc2662014-12-16 16:03:32 -080052from cros.factory.utils.type_utils import Error
Tammo Spalink86a61c62012-05-25 15:10:35 +080053
Tammo Spalink5c699832012-07-03 17:50:39 +080054
Tammo Spalink5c699832012-07-03 17:50:39 +080055# TODO(tammo): Replace calls to sys.exit with raise Exit, and maybe
56# treat that specially (as a smoot exit, as opposed to the more
57# verbose output for generic Error).
58
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080059_global_gooftool = None
60_gooftool_lock = threading.Lock()
Tammo Spalink5c699832012-07-03 17:50:39 +080061
Hung-Te Lin56b18402015-01-16 14:52:30 +080062
Ricky Lianga70a1202013-03-15 15:03:17 +080063def GetGooftool(options):
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080064 global _global_gooftool # pylint: disable=W0603
Ricky Lianga70a1202013-03-15 15:03:17 +080065
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080066 if _global_gooftool is None:
67 with _gooftool_lock:
Ricky Liang43b879b2014-02-24 11:36:55 +080068 hwid_version = getattr(options, 'hwid_version', 3)
69 if hwid_version == 2:
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080070 hwdb_path = getattr(options, 'hwdb_path', None)
71 component_db = (
72 hwid_tool.HardwareDb(options.hwdb_path).comp_db if hwdb_path
73 else None)
74 _global_gooftool = Gooftool(hwid_version=2, component_db=component_db)
Ricky Liang43b879b2014-02-24 11:36:55 +080075 elif hwid_version == 3:
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080076 board = getattr(options, 'board', None)
77 hwdb_path = getattr(options, 'hwdb_path', None)
78 _global_gooftool = Gooftool(hwid_version=3, board=board,
79 hwdb_path=hwdb_path)
80 else:
81 raise Error, 'Invalid HWID version: %r' % options.hwid_version
82
83 return _global_gooftool
Ricky Lianga70a1202013-03-15 15:03:17 +080084
Hung-Te Lin56b18402015-01-16 14:52:30 +080085
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080086@Command('write_hwid',
87 CmdArg('hwid', metavar='HWID', help='HWID string'))
Andy Chengc92e6f92012-11-20 16:55:53 +080088def WriteHWID(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080089 """Write specified HWID value into the system BB."""
Andy Cheng7a76cb82012-11-19 18:08:19 +080090
Tammo Spalink95c43732012-07-25 15:57:14 -070091 logging.info('writing hwid string %r', options.hwid)
Ricky Lianga70a1202013-03-15 15:03:17 +080092 GetGooftool(options).WriteHWID(options.hwid)
Andy Cheng0465d132013-03-20 12:12:06 +080093 event_log.Log('write_hwid', hwid=options.hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -070094 print 'Wrote HWID: %r' % options.hwid
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080095
96
Ricky Liang53390232013-03-08 15:37:57 +080097_board_cmd_arg = CmdArg(
98 '--board', metavar='BOARD',
99 default=None, help='Board name to test.')
100
Tammo Spalink8fab5312012-05-28 18:33:30 +0800101_hwdb_path_cmd_arg = CmdArg(
102 '--hwdb_path', metavar='PATH',
Ricky Liangeede7922013-06-19 10:18:41 +0800103 default=common.DEFAULT_HWID_DATA_PATH,
Tammo Spalink8fab5312012-05-28 18:33:30 +0800104 help='Path to the HWID database.')
105
Tammo Spalink95c43732012-07-25 15:57:14 -0700106_hwid_status_list_cmd_arg = CmdArg(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800107 '--status', nargs='*', default=['supported'],
108 help='allow only HWIDs with these status values')
Tammo Spalink95c43732012-07-25 15:57:14 -0700109
Jon Salzce124fb2012-10-02 17:42:03 +0800110_probe_results_cmd_arg = CmdArg(
111 '--probe_results', metavar='RESULTS.yaml',
Ricky Liangc662be32013-12-24 11:50:23 +0800112 help=('Output from "gooftool probe --include_vpd" (used instead of '
Jon Salzce124fb2012-10-02 17:42:03 +0800113 'probing this system).'))
114
Ricky Liang53390232013-03-08 15:37:57 +0800115_device_info_cmd_arg = CmdArg(
Ricky Liangf89f73a2013-03-19 05:00:24 +0800116 '--device_info', metavar='DEVICE_INFO.yaml', default=None,
Ricky Liang53390232013-03-08 15:37:57 +0800117 help='A dict of device info to use instead of fetching from shopfllor '
118 'server.')
119
Jon Salzce124fb2012-10-02 17:42:03 +0800120_hwid_cmd_arg = CmdArg(
121 '--hwid', metavar='HWID',
Ricky Lianga70a1202013-03-15 15:03:17 +0800122 help='HWID to verify (instead of the currently set HWID of this system).')
Jon Salzce124fb2012-10-02 17:42:03 +0800123
Bernie Thompson3c11c872013-07-22 18:22:45 -0700124_rma_mode_cmd_arg = CmdArg(
125 '--rma_mode', action='store_true',
126 help='Enable RMA mode, do not check for deprecated components.')
Tammo Spalink95c43732012-07-25 15:57:14 -0700127
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800128_cros_core_cmd_arg = CmdArg(
129 '--cros_core', action='store_true',
130 help='Finalize for ChromeOS Core devices (may add or remove few test '
131 'items. For example, branding verification or firmware bitmap '
132 'locale settings).')
133
Ricky Liang43b879b2014-02-24 11:36:55 +0800134_hwid_version_cmd_arg = CmdArg(
135 '-i', '--hwid-version', default=3, choices=(2, 3), type=int,
136 help='Version of HWID to operate on. (default: %(default)s)')
137
bowgotsai13820f42015-09-10 23:18:04 +0800138_enforced_release_channels_cmd_arg = CmdArg(
139 '--enforced_release_channels', nargs='*', default=None,
140 help='Enforced release image channels.')
141
Ricky Liang43b879b2014-02-24 11:36:55 +0800142
Tammo Spalink95c43732012-07-25 15:57:14 -0700143@Command('best_match_hwids',
Tammo Spalink8fab5312012-05-28 18:33:30 +0800144 _hwdb_path_cmd_arg,
145 CmdArg('-b', '--board', metavar='BOARD',
Tammo Spalink95c43732012-07-25 15:57:14 -0700146 help='optional BOARD name, needed only if data is present '
147 'for more than one'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800148 CmdArg('--bom', metavar='BOM', help='BOM name'),
149 CmdArg('--variant', metavar='VARIANT', help='VARIANT code'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800150 CmdArg('--optimistic', action='store_true',
151 help='do not probe; assume singletons match'),
Tammo Spalink95c43732012-07-25 15:57:14 -0700152 CmdArg('--comps', nargs='*', default=[],
153 help='list of canonical component names'),
154 CmdArg('--missing', nargs='*', default=[],
155 help='list component classes to be assumed missing'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800156 CmdArg('--status', nargs='*', default=['supported'],
Tammo Spalink95c43732012-07-25 15:57:14 -0700157 help='consider only HWIDs within this list of status values'))
158def BestMatchHwids(options):
Ricky Liangc662be32013-12-24 11:50:23 +0800159 """Determine a list of possible HWIDs using provided args and probing.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800160
161 VOLATILE can always be determined by probing. To get a unique
162 result, VARIANT must be specified for all cases where the matching
163 BOM has more than one associated variant code, otherwise all HWID
164 variants will be returned. Both VARIANT and BOM information can
Tammo Spalink95c43732012-07-25 15:57:14 -0700165 alternatively be specified using the --stdin_comps argument, which
166 allows specifying a list of canonical names (one per line) on stdin,
167 one per line. Based on what is known from BOM and stdin_comps,
168 determine a list of components to probe for, and use those probe
169 results to resolve a list of matching HWIDs. If no boms,
170 components, or variant codes are specified, then a list of all HWIDs
Andy Cheng8ece7382012-08-22 16:25:42 +0800171 that match probeable components will be returned.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800172
173 Returns (on stdout): A list of HWIDs that match the available probe
174 results and argument contraints, one per line.
Tammo Spalink70b48a52012-08-08 16:54:51 -0700175
176 Example:
177
178 // Three ways to specify a keyboard (assuming it is a variant component)
179 gooftool best_match_hwids --missing keyboard
180 gooftool best_match_hwids --variant A or
181 gooftool best_match_hwids --comps us_kbd
Tammo Spalink8fab5312012-05-28 18:33:30 +0800182 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800183
Tammo Spalink5c699832012-07-03 17:50:39 +0800184 map(hwid_tool.Validate.Status, options.status)
Tammo Spalink95c43732012-07-25 15:57:14 -0700185 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Tammo Spalink5c699832012-07-03 17:50:39 +0800186 comp_db = hw_db.comp_db
Tammo Spalink3a7e9022012-06-27 14:08:40 +0800187 device = hw_db.GetDevice(options.board)
Tammo Spalink5c699832012-07-03 17:50:39 +0800188 component_spec = hwid_tool.ComponentSpec.New()
Tammo Spalink8fab5312012-05-28 18:33:30 +0800189 if options.bom:
Tammo Spalink5c699832012-07-03 17:50:39 +0800190 device.BomExists(options.bom)
Tammo Spalink01e11722012-07-24 10:17:54 -0700191 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800192 component_spec, device.boms[options.bom].primary)
Tammo Spalink8fab5312012-05-28 18:33:30 +0800193 if options.variant:
Tammo Spalink5c699832012-07-03 17:50:39 +0800194 device.VariantExists(options.variant)
195 variant_spec = device.variants[options.variant]
Tammo Spalink01e11722012-07-24 10:17:54 -0700196 if hwid_tool.ComponentSpecsConflict(component_spec, variant_spec):
Tammo Spalink95c43732012-07-25 15:57:14 -0700197 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700198 % YamlWrite(sorted(
199 hwid_tool.ComponentSpecClasses(component_spec) &
200 hwid_tool.ComponentSpecClasses(variant_spec))))
Tammo Spalink01e11722012-07-24 10:17:54 -0700201 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800202 component_spec, variant_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700203 if options.comps or options.missing:
204 map(comp_db.CompExists, options.comps)
205 map(comp_db.CompClassExists, options.missing)
206 extra_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800207 components=options.comps,
208 missing=options.missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700209 print 'cmdline asserted components:\n%s' % extra_comp_spec.Encode()
210 if hwid_tool.ComponentSpecsConflict(component_spec, extra_comp_spec):
211 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700212 % YamlWrite(sorted(
213 hwid_tool.ComponentSpecClasses(component_spec) &
214 hwid_tool.ComponentSpecClasses(extra_comp_spec))))
Tammo Spalink95c43732012-07-25 15:57:14 -0700215 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800216 component_spec, extra_comp_spec)
Tammo Spalink01e11722012-07-24 10:17:54 -0700217 spec_classes = hwid_tool.ComponentSpecClasses(component_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700218 missing_classes = set(comp_db.all_comp_classes) - spec_classes
Tammo Spalink5c699832012-07-03 17:50:39 +0800219 if missing_classes and not options.optimistic:
Andy Cheng8ece7382012-08-22 16:25:42 +0800220 non_probeable_missing = missing_classes - PROBEABLE_COMPONENT_CLASSES
221 if non_probeable_missing:
Tammo Spalink95c43732012-07-25 15:57:14 -0700222 sys.exit('FAILURE: these classes are necessary, were not specified '
Tammo Spalink70b48a52012-08-08 16:54:51 -0700223 'as inputs, and cannot be probed for:\n%s'
224 'This problem can often be addressed by specifying all of '
225 'the missing components on the command line (see the command '
Andy Cheng8ece7382012-08-22 16:25:42 +0800226 'help).' % YamlWrite(list(non_probeable_missing)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700227 print 'probing for missing classes:'
228 print YamlWrite(list(missing_classes))
229 probe_results = Probe(target_comp_classes=list(missing_classes),
230 probe_volatile=False, probe_initial_config=False)
231 cooked_components = comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800232 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700233 if cooked_components.unmatched:
234 sys.exit('ERROR: some probed components are unrecognized:\n%s'
235 % YamlWrite(cooked_components.unmatched))
236 probed_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800237 components=cooked_components.matched,
238 missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700239 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800240 component_spec, probed_comp_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700241 print YamlWrite({'component data used for matching': {
Hung-Te Lin56b18402015-01-16 14:52:30 +0800242 'missing component classes': component_spec.classes_missing,
243 'found components': component_spec.components}})
Tammo Spalink95c43732012-07-25 15:57:14 -0700244 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800245 extant_components=hwid_tool.ComponentSpecCompClassMap(
246 component_spec).keys(),
247 classes_missing=component_spec.classes_missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700248 match_tree = device.BuildMatchTree(component_data)
249 if not match_tree:
250 sys.exit('FAILURE: NO matching BOMs found')
251 print 'potential BOMs/VARIANTs:'
252 potential_variants = set()
253 potential_volatiles = set()
254 for bom_name, variant_tree in match_tree.items():
255 print ' BOM: %-8s VARIANTS: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800256 bom_name, ', '.join(sorted(variant_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700257 for variant_code in variant_tree:
258 potential_variants.add(variant_code)
259 for volatile_code in device.volatiles:
260 status = device.GetHwidStatus(bom_name, variant_code, volatile_code)
261 if status in options.status:
262 potential_volatiles.add(volatile_code)
263 print ''
264 if len(potential_variants) == 0:
265 sys.exit('FAILURE: no matching VARIANTs found')
266 if len(potential_volatiles) == 0:
267 sys.exit('FAILURE: no VOLATILEs found for potential matching BOMs/VARIANTS '
268 '(with specified status)')
Tammo Spalink394e4492012-08-01 10:20:30 -0700269 if (options.optimistic and
270 len(match_tree) == 1 and
271 len(potential_variants) == 1 and
272 len(potential_volatiles) == 1):
273 print ('MATCHING HWID: %s' % device.FmtHwid(match_tree.keys().pop(),
274 potential_variants.pop(),
275 potential_volatiles.pop()))
Tammo Spalink5c699832012-07-03 17:50:39 +0800276 return
Tammo Spalink95c43732012-07-25 15:57:14 -0700277 print ('probing VOLATILEs to resolve potential matches: %s\n' %
278 ', '.join(sorted(potential_volatiles)))
279 vol_probe_results = Probe(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800280 target_comp_classes=[],
281 probe_volatile=True,
282 probe_initial_config=False)
Tammo Spalink95c43732012-07-25 15:57:14 -0700283 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800284 vol_probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700285 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800286 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700287 matched_hwids = device.GetMatchTreeHwids(match_tree)
288 if matched_hwids:
289 for hwid in matched_hwids:
Ricky Liang02f3bd72012-09-21 14:33:01 +0800290 if matched_hwids[hwid] in options.status:
291 print 'MATCHING HWID: %s' % hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700292 return
293 print 'exact HWID matching failed, but the following BOMs match: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800294 ', '.join(sorted(match_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700295 if options.optimistic and len(match_tree) == 1:
296 bom_name = set(match_tree).pop()
Tammo Spalink5c699832012-07-03 17:50:39 +0800297 bom = device.boms[bom_name]
Tammo Spalink95c43732012-07-25 15:57:14 -0700298 variant_matches = match_tree[bom_name]
Tammo Spalink5c699832012-07-03 17:50:39 +0800299 if len(variant_matches) == 1:
300 var_code = set(variant_matches).pop()
301 elif len(bom.variants) == 1:
302 var_code = set(bom.variants).pop()
303 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700304 sys.exit('FAILURE: NO matching HWIDs found; optimistic matching failed '
305 'because there were too many variants to choose from for BOM %r'
306 % bom_name)
307 hwids = [device.FmtHwid(bom_name, var_code, vol_code)
308 for vol_code in device.volatiles
309 if device.GetHwidStatus(bom_name, var_code, vol_code)
310 in options.status]
311 for hwid in hwids:
312 print 'MATCHING HWID: %s' % hwid
Tammo Spalink5c699832012-07-03 17:50:39 +0800313 return
314 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700315 print ('optimistic matching not attempted because either it was '
316 'not requested, or because the number of BOMs was <> 1\n')
317 sys.exit('FAILURE: NO matching HWIDs found')
Tammo Spalink8fab5312012-05-28 18:33:30 +0800318
319
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800320@Command('probe',
321 CmdArg('--comps', nargs='*',
322 help='List of keys from the component_db registry.'),
Ricky Liangb30da672013-06-14 12:36:34 +0800323 CmdArg('--fast_fw_probe', action='store_true',
324 help='Do a fast probe for EC and main firmware versions only. '
325 'This implies --no_vol and --no_ic.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800326 CmdArg('--no_vol', action='store_true',
327 help='Do not probe volatile data.'),
328 CmdArg('--no_ic', action='store_true',
Jon Salz0f8a6842012-09-25 11:28:22 +0800329 help='Do not probe initial_config data.'),
330 CmdArg('--include_vpd', action='store_true',
331 help='Include VPD data in volatiles.'))
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800332def RunProbe(options):
333 """Print yaml-formatted breakdown of probed device properties."""
Ricky Lianga70a1202013-03-15 15:03:17 +0800334 print GetGooftool(options).Probe(
335 target_comp_classes=options.comps,
Ricky Liangb30da672013-06-14 12:36:34 +0800336 fast_fw_probe=options.fast_fw_probe,
Ricky Lianga70a1202013-03-15 15:03:17 +0800337 probe_volatile=not options.no_vol,
338 probe_initial_config=not options.no_ic,
339 probe_vpd=options.include_vpd).Encode()
Ricky Liang53390232013-03-08 15:37:57 +0800340
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800341
Tammo Spalink214caf42012-05-28 10:45:00 +0800342@Command('verify_components',
343 _hwdb_path_cmd_arg,
Tammo Spalink5c699832012-07-03 17:50:39 +0800344 CmdArg('target_comps', nargs='*'))
Tammo Spalink214caf42012-05-28 10:45:00 +0800345def VerifyComponents(options):
Andy Cheng8ece7382012-08-22 16:25:42 +0800346 """Verify that probeable components all match entries in the component_db.
Tammo Spalink214caf42012-05-28 10:45:00 +0800347
Tammo Spalink5c699832012-07-03 17:50:39 +0800348 Probe for each component class in the target_comps and verify
Tammo Spalink214caf42012-05-28 10:45:00 +0800349 that a corresponding match exists in the component_db -- make sure
350 that these components are present, that they have been approved, but
351 do not check against any specific BOM/HWID configurations.
352 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800353
Andy Chengc531e2f2012-10-15 19:09:17 +0800354 try:
Ricky Lianga70a1202013-03-15 15:03:17 +0800355 result = GetGooftool(options).VerifyComponents(
Andy Chengc531e2f2012-10-15 19:09:17 +0800356 options.target_comps)
357 except ValueError, e:
358 sys.exit(e)
359
Ricky Liang53390232013-03-08 15:37:57 +0800360 PrintVerifyComponentsResults(result)
361
362
363def PrintVerifyComponentsResults(result):
364 """Prints out the results of VerifyComponents method call.
365
366 Groups the results into two groups: 'matches' and 'errors', and prints out
367 their values.
368 """
Andy Chengc531e2f2012-10-15 19:09:17 +0800369 # group by matches and errors
Tammo Spalink214caf42012-05-28 10:45:00 +0800370 matches = []
Andy Chengc531e2f2012-10-15 19:09:17 +0800371 errors = []
372 for result_list in result.values():
373 for component_name, _, error in result_list:
374 if component_name:
375 matches.append(component_name)
Tammo Spalink214caf42012-05-28 10:45:00 +0800376 else:
Andy Chengc531e2f2012-10-15 19:09:17 +0800377 errors.append(error)
378
Andy Cheng228a8c92012-08-27 10:53:57 +0800379 if matches:
380 print 'found probeable components:\n %s' % '\n '.join(matches)
Tammo Spalink214caf42012-05-28 10:45:00 +0800381 if errors:
Andy Cheng228a8c92012-08-27 10:53:57 +0800382 print '\nerrors:\n %s' % '\n '.join(errors)
383 sys.exit('\ncomponent verification FAILURE')
Tammo Spalink214caf42012-05-28 10:45:00 +0800384 else:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800385 print '\ncomponent verification SUCCESS'
Tammo Spalink214caf42012-05-28 10:45:00 +0800386
387
Ricky Liang43b879b2014-02-24 11:36:55 +0800388@Command('verify_hwid_v2',
Tammo Spalink95c43732012-07-25 15:57:14 -0700389 _hwid_status_list_cmd_arg,
Jon Salz0f8a6842012-09-25 11:28:22 +0800390 _hwdb_path_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800391 _probe_results_cmd_arg,
392 _hwid_cmd_arg)
Ricky Liang43b879b2014-02-24 11:36:55 +0800393def VerifyHWIDv2(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800394 """Verify system HWID properties match probed device properties.
395
396 First probe components, volatile and initial_config parameters for
397 the DUT. Then use the available device data to produce a list of
398 candidate HWIDs. Then verify the HWID from the DUT is present in
399 that list. Then verify that the DUT initial config values match
400 those specified for its HWID. Finally, verify that VPD contains all
401 the necessary fields as specified by the board data, and when
402 possible verify that values are legitimate.
403 """
Ricky Liangf7857c12012-09-17 13:34:41 +0800404 def VerifyVpd(ro_vpd_keys, rw_vpd_keys):
Tammo Spalink5c699832012-07-03 17:50:39 +0800405 for key in ro_vpd_keys:
406 if key not in ro_vpd:
Ricky Liangf7857c12012-09-17 13:34:41 +0800407 sys.exit('Missing required RO VPD field: %s' % key)
Tammo Spalink01e11722012-07-24 10:17:54 -0700408 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800409 value = ro_vpd[key]
Ricky Liangf7857c12012-09-17 13:34:41 +0800410 if (known_valid_values is not None) and (value not in known_valid_values):
411 sys.exit('Invalid RO VPD entry : key %r, value %r' % (key, value))
Ricky Liangf7857c12012-09-17 13:34:41 +0800412 for key in rw_vpd_keys:
413 if key not in rw_vpd:
414 sys.exit('Missing required RW VPD field: %s' % key)
415 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
416 value = rw_vpd[key]
417 if (known_valid_values is not None) and (value not in known_valid_values):
418 sys.exit('Invalid RW VPD entry : key %r, value %r' % (key, value))
Andy Cheng0465d132013-03-20 12:12:06 +0800419 event_log.Log('vpd', ro_vpd=FilterDict(ro_vpd), rw_vpd=FilterDict(rw_vpd))
Tammo Spalink5c699832012-07-03 17:50:39 +0800420 map(hwid_tool.Validate.Status, options.status)
Jon Salz0f8a6842012-09-25 11:28:22 +0800421
Jon Salz0f8a6842012-09-25 11:28:22 +0800422 if options.hwid:
423 hwid_str = options.hwid
424 else:
Hung-Te Lin74346d72016-01-07 22:16:57 +0800425 main_fw_file = crosfw.LoadMainFirmware().GetFileName()
Jon Salz0f8a6842012-09-25 11:28:22 +0800426 gbb_result = Shell('gbb_utility -g --hwid %s' % main_fw_file).stdout
427 hwid_str = re.findall(r'hardware_id:(.*)', gbb_result)[0].strip()
Tammo Spalink95c43732012-07-25 15:57:14 -0700428 hwid = hwid_tool.ParseHwid(hwid_str)
Tammo Spalink5c699832012-07-03 17:50:39 +0800429 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Jon Salz0f8a6842012-09-25 11:28:22 +0800430 print 'Verifying HWID: %r\n' % hwid.hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700431 device = hw_db.GetDevice(hwid.board)
432 hwid_status = device.GetHwidStatus(hwid.bom, hwid.variant, hwid.volatile)
433 if hwid_status not in options.status:
Tammo Spalink5c699832012-07-03 17:50:39 +0800434 sys.exit('HWID status must be one of [%s], found %r' %
Hung-Te Lin4f5beb12012-08-20 14:48:06 +0800435 (', '.join(options.status), hwid_status))
Jon Salz0f8a6842012-09-25 11:28:22 +0800436 if options.probe_results:
437 # Pull in probe results (including VPD data) from the given file
438 # rather than probing the current system.
439 probe_results = hwid_tool.ProbeResults.Decode(
440 open(options.probe_results).read())
441 ro_vpd = {}
442 rw_vpd = {}
443 for k, v in probe_results.found_volatile_values.items():
Hung-Te Lin56b18402015-01-16 14:52:30 +0800444 match = re.match(r'^vpd\.(ro|rw)\.(\w+)$', k)
Jon Salz0f8a6842012-09-25 11:28:22 +0800445 if match:
446 del probe_results.found_volatile_values[k]
447 (ro_vpd if match.group(1) == 'ro' else rw_vpd)[match.group(2)] = v
448 else:
449 probe_results = Probe()
Hung-Te Lin74346d72016-01-07 22:16:57 +0800450 ro_vpd = ReadRoVpd()
451 rw_vpd = ReadRwVpd()
Tammo Spalink95c43732012-07-25 15:57:14 -0700452 cooked_components = hw_db.comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800453 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700454 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800455 probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700456 cooked_initial_configs = device.MatchInitialConfigValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800457 probe_results.initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700458 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800459 extant_components=cooked_components.matched,
460 classes_missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700461 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800462 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700463 matched_hwids = device.GetMatchTreeHwids(match_tree)
464 print 'HWID status: %s\n' % hwid_status
465 print 'probed system components:'
466 print YamlWrite(cooked_components.__dict__)
467 print 'missing component classes:'
468 print YamlWrite(probe_results.missing_component_classes)
469 print 'probed volatiles:'
470 print YamlWrite(cooked_volatiles.__dict__)
471 print 'probed initial_configs:'
472 print YamlWrite(cooked_initial_configs)
473 print 'hwid match tree:'
474 print YamlWrite(match_tree)
Andy Cheng0465d132013-03-20 12:12:06 +0800475 event_log.Log(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800476 'probe',
477 found_components=cooked_components.__dict__,
478 missing_component_classes=probe_results.missing_component_classes,
479 volatiles=cooked_volatiles.__dict__,
480 initial_configs=cooked_initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700481 if hwid.hwid not in matched_hwids:
Tammo Spalink5c699832012-07-03 17:50:39 +0800482 err_msg = 'HWID verification FAILED.\n'
Tammo Spalink95c43732012-07-25 15:57:14 -0700483 if cooked_components.unmatched:
Tammo Spalink5c699832012-07-03 17:50:39 +0800484 sys.exit(err_msg + 'some components could not be indentified:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700485 YamlWrite(cooked_components.unmatched))
486 if not match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800487 sys.exit(err_msg + 'no matching boms were found for components:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700488 component_data.Encode())
489 if hwid.bom not in match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800490 sys.exit(err_msg + 'matching boms [%s] do not include target bom %r' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700491 (', '.join(sorted(match_tree)), hwid.bom))
492 err_msg += 'target bom %r matches components' % hwid.bom
493 if hwid.bom not in device.IntersectBomsAndInitialConfigs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800494 cooked_initial_configs):
Tammo Spalink5c699832012-07-03 17:50:39 +0800495 sys.exit(err_msg + ', but failed initial config verification')
Tammo Spalink95c43732012-07-25 15:57:14 -0700496 matched_variants = match_tree.get(hwid.bom, {})
497 if hwid.variant not in matched_variants:
Tammo Spalink5c699832012-07-03 17:50:39 +0800498 sys.exit(err_msg + ', but target variant_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700499 hwid.variant)
500 matched_volatiles = matched_variants.get(hwid.variant, {})
501 if hwid.volatile not in matched_volatiles:
Tammo Spalink5c699832012-07-03 17:50:39 +0800502 sys.exit(err_msg + ', but target volatile_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700503 hwid.volatile)
504 found_status = matched_volatiles.get(hwid.volatile, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800505 sys.exit(err_msg + ', but hwid status %r was unacceptable' % found_status)
Ricky Liangf7857c12012-09-17 13:34:41 +0800506 VerifyVpd(device.vpd_ro_fields, device.vpd_rw_fields)
Andy Cheng0465d132013-03-20 12:12:06 +0800507 event_log.Log('verified_hwid', hwid=hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -0700508 print 'Verification SUCCESS!'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800509
510
Hung-Te Line1d80f62016-03-31 14:58:13 +0800511@Command('verify_keys',
512 CmdArg('kernel_device', nargs='?', help='Kernel device to verify.'),
513 CmdArg('main_firmware', nargs='?', help='Main firmware image file.'))
Tammo Spalink01e11722012-07-24 10:17:54 -0700514def VerifyKeys(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800515 """Verify keys in firmware and SSD match."""
Hung-Te Line1d80f62016-03-31 14:58:13 +0800516 return GetGooftool(options).VerifyKeys(
517 options.kernel_device, options.main_firmware)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800518
519
520@Command('set_fw_bitmap_locale')
Tammo Spalink01e11722012-07-24 10:17:54 -0700521def SetFirmwareBitmapLocale(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800522 """Use VPD locale value to set firmware bitmap default language."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800523
Ricky Lianga70a1202013-03-15 15:03:17 +0800524 (index, locale) = GetGooftool(options).SetFirmwareBitmapLocale()
Andy Cheng2582d292012-12-04 17:38:28 +0800525 logging.info('Firmware bitmap initial locale set to %d (%s).',
526 index, locale)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800527
528
Hung-Te Line1d80f62016-03-31 14:58:13 +0800529@Command('verify_system_time',
530 CmdArg('root_dev', nargs='?', help='Root device to check.'))
Tammo Spalink01e11722012-07-24 10:17:54 -0700531def VerifySystemTime(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800532 """Verify system time is later than release filesystem creation time."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800533
Hung-Te Line1d80f62016-03-31 14:58:13 +0800534 return GetGooftool(options).VerifySystemTime(options.root_dev)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800535
536
Hung-Te Line1d80f62016-03-31 14:58:13 +0800537@Command('verify_rootfs',
538 CmdArg('release_rootfs', nargs='?', help='Release root file system.'))
Tammo Spalink01e11722012-07-24 10:17:54 -0700539def VerifyRootFs(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800540 """Verify rootfs on SSD is valid by checking hash."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800541
Hung-Te Line1d80f62016-03-31 14:58:13 +0800542 return GetGooftool(options).VerifyRootFs(options.release_rootfs)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800543
Hung-Te Lin56b18402015-01-16 14:52:30 +0800544
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800545@Command('verify_tpm')
546def VerifyTPM(options): # pylint: disable=W0613
547 """Verify TPM is cleared."""
548
549 return GetGooftool(options).VerifyTPM()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800550
Hung-Te Lin56b18402015-01-16 14:52:30 +0800551
Hung-Te Lindd708d42014-07-11 17:05:01 +0800552@Command('verify_me_locked')
553def VerifyManagementEngineLocked(options): # pylint: disable=W0613
554 """Verify Managment Engine is locked."""
555
556 return GetGooftool(options).VerifyManagementEngineLocked()
557
Hung-Te Lin56b18402015-01-16 14:52:30 +0800558
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800559@Command('verify_switch_wp')
Andy Chengc92e6f92012-11-20 16:55:53 +0800560def VerifyWPSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800561 """Verify hardware write protection switch is enabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800562
Ricky Lianga70a1202013-03-15 15:03:17 +0800563 GetGooftool(options).VerifyWPSwitch()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800564
565
566@Command('verify_switch_dev')
Tammo Spalink01e11722012-07-24 10:17:54 -0700567def VerifyDevSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800568 """Verify developer switch is disabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800569
Ricky Lianga70a1202013-03-15 15:03:17 +0800570 if GetGooftool(options).CheckDevSwitchForDisabling():
Hung-Te Lind7d34722012-07-26 16:48:35 +0800571 logging.warn('VerifyDevSwitch: No physical switch.')
Andy Cheng0465d132013-03-20 12:12:06 +0800572 event_log.Log('switch_dev', type='virtual switch')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800573
574
Jon Salzadd90d32014-04-29 16:16:27 +0800575@Command('verify_branding')
576def VerifyBranding(options): # pylint: disable=W0613
577 """Verify that branding fields are properly set.
578
579 customization_id, if set in the RO VPD, must be of the correct format.
580
581 rlz_brand_code must be set either in the RO VPD or OEM partition, and must
582 be of the correct format.
583 """
584 return GetGooftool(options).VerifyBranding()
585
586
bowgotsai13820f42015-09-10 23:18:04 +0800587@Command('verify_release_channel',
588 _enforced_release_channels_cmd_arg)
bowgotsai529139c2015-05-30 01:39:49 +0800589def VerifyReleaseChannel(options): # pylint: disable=W0613
590 """Verify that release image channel is correct.
591
592 ChromeOS has four channels: canary, dev, beta and stable.
593 The last three channels support image auto-updates, checks
594 that release image channel is one of them.
595 """
bowgotsai13820f42015-09-10 23:18:04 +0800596 return GetGooftool(options).VerifyReleaseChannel(
597 options.enforced_release_channels)
bowgotsai529139c2015-05-30 01:39:49 +0800598
599
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800600@Command('write_protect')
Tammo Spalink01e11722012-07-24 10:17:54 -0700601def EnableFwWp(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800602 """Enable then verify firmware write protection."""
603
Hung-Te Linb21c6682012-08-01 13:53:57 +0800604 def CalculateLegacyRange(fw_type, length, section_data,
605 section_name):
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800606 ro_size = length / 2
607 ro_a = int(section_data[0] / ro_size)
608 ro_b = int((section_data[0] + section_data[1] - 1) / ro_size)
609 if ro_a != ro_b:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800610 raise Error('%s firmware section %s has illegal size' %
Hung-Te Linb21c6682012-08-01 13:53:57 +0800611 (fw_type, section_name))
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800612 ro_offset = ro_a * ro_size
613 return (ro_offset, ro_size)
614
615 def WriteProtect(fw_file_path, fw_type, legacy_section):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800616 """Calculate protection size, then invoke flashrom.
617
618 Our supported chips only allow write protecting half their total
619 size, so we parition the flash chipset space accordingly.
620 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800621
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800622 raw_image = open(fw_file_path, 'rb').read()
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800623 wp_section = 'WP_RO'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800624 image = crosfw.FirmwareImage(raw_image)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800625 if image.has_section(wp_section):
626 section_data = image.get_section_area(wp_section)
627 ro_offset = section_data[0]
628 ro_size = section_data[1]
629 elif image.has_section(legacy_section):
630 section_data = image.get_section_area(legacy_section)
631 (ro_offset, ro_size) = CalculateLegacyRange(
Hung-Te Linb21c6682012-08-01 13:53:57 +0800632 fw_type, len(raw_image), section_data, legacy_section)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800633 else:
634 raise Error('could not find %s firmware section %s or %s' %
635 (fw_type, wp_section, legacy_section))
636
637 logging.debug('write protecting %s [off=%x size=%x]', fw_type,
638 ro_offset, ro_size)
639 crosfw.Flashrom(fw_type).EnableWriteProtection(ro_offset, ro_size)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800640
641 WriteProtect(crosfw.LoadMainFirmware().GetFileName(), 'main', 'RO_SECTION')
Andy Cheng0465d132013-03-20 12:12:06 +0800642 event_log.Log('wp', fw='main')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800643 ec_fw_file = crosfw.LoadEcFirmware().GetFileName()
644 if ec_fw_file is not None:
645 WriteProtect(ec_fw_file, 'ec', 'EC_RO')
Andy Cheng0465d132013-03-20 12:12:06 +0800646 event_log.Log('wp', fw='ec')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800647 else:
648 logging.warning('EC not write protected (seems there is no EC flash).')
649
650
651@Command('clear_gbb_flags')
Andy Chengc92e6f92012-11-20 16:55:53 +0800652def ClearGBBFlags(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800653 """Zero out the GBB flags, in preparation for transition to release state.
654
655 No GBB flags are set in release/shipping state, but they are useful
656 for factory/development. See "gbb_utility --flags" for details.
657 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800658
Ricky Lianga70a1202013-03-15 15:03:17 +0800659 GetGooftool(options).ClearGBBFlags()
Andy Cheng0465d132013-03-20 12:12:06 +0800660 event_log.Log('clear_gbb_flags')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800661
662
Jon Salzaa3a30e2013-05-15 15:56:28 +0800663@Command('clear_factory_vpd_entries')
664def ClearFactoryVPDEntries(options): # pylint: disable=W0613
665 """Clears factory.* items in the RW VPD."""
666 entries = GetGooftool(options).ClearFactoryVPDEntries()
667 event_log.Log('clear_factory_vpd_entries', entries=FilterDict(entries))
668
669
Mattias Nisslercca761b2015-04-15 21:53:04 +0200670@Command('generate_stable_device_secret')
671def GenerateStableDeviceSecret(options): # pylint: disable=W0613
672 """Generates a a fresh stable device secret and stores it in the RO VPD."""
673 GetGooftool(options).GenerateStableDeviceSecret()
674 event_log.Log('generate_stable_device_secret')
675
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800676_cutoff_args_cmd_arg = CmdArg(
677 '--cutoff_args',
678 help='Battery cutoff arguments to be passed to battery_cutoff.sh '
679 'after wiping. Should be the following format: '
680 '[--method shutdown|reboot|battery_cutoff|battery_cutoff_at_shutdown] '
681 '[--check-ac connect_ac|remove_ac] '
682 '[--min-battery-percent <minimum battery percentage>] '
683 '[--max-battery-percent <maximum battery percentage>] '
684 '[--min-battery-voltage <minimum battery voltage>] '
685 '[--max-battery-voltage <maximum battery voltage>]')
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800686_shopfloor_url_args_cmd_arg = CmdArg(
687 '--shopfloor_url',
688 help='Shopfloor server url to be informed when in-place wipe is done. '
689 'After in-place wipe, a XML-RPC request will be sent to the '
690 'given url to indicate the completion of wipe.')
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800691@Command('wipe_in_place',
692 CmdArg('--fast', action='store_true',
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800693 help='use non-secure but faster wipe method.'),
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800694 _cutoff_args_cmd_arg,
695 _shopfloor_url_args_cmd_arg)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800696def WipeInPlace(options):
697 """Start factory wipe directly without reboot."""
698
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800699 GetGooftool(options).WipeInPlace(options.fast, options.cutoff_args,
700 options.shopfloor_url)
Mattias Nisslercca761b2015-04-15 21:53:04 +0200701
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800702@Command('prepare_wipe',
703 CmdArg('--fast', action='store_true',
704 help='use non-secure but faster wipe method.'))
705def PrepareWipe(options):
706 """Prepare system for transition to release state in next reboot."""
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800707
Ricky Lianga70a1202013-03-15 15:03:17 +0800708 GetGooftool(options).PrepareWipe(options.fast)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800709
Hung-Te Lin56b18402015-01-16 14:52:30 +0800710
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800711@Command('verify',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800712 CmdArg('--no_write_protect', action='store_true',
713 help='Do not check write protection switch state.'),
Ricky Liang43b879b2014-02-24 11:36:55 +0800714 _hwid_version_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700715 _hwid_status_list_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800716 _hwdb_path_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800717 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800718 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800719 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800720 _rma_mode_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800721 _cros_core_cmd_arg,
722 _enforced_release_channels_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800723def Verify(options):
724 """Verifies if whole factory process is ready for finalization.
725
726 This routine performs all the necessary checks to make sure the
727 device is ready to be finalized, but does not modify state. These
728 checks include dev switch, firmware write protection switch, hwid,
729 system time, keys, and root file system.
730 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800731
Hung-Te Lin6d827542012-07-19 11:50:41 +0800732 if not options.no_write_protect:
Ricky Lianga70a1202013-03-15 15:03:17 +0800733 VerifyWPSwitch(options)
Hung-Te Lindd708d42014-07-11 17:05:01 +0800734 VerifyManagementEngineLocked(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800735 VerifyDevSwitch(options)
736 if options.hwid_version == 2:
Ricky Liang43b879b2014-02-24 11:36:55 +0800737 VerifyHWIDv2(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800738 elif options.hwid_version == 3:
Ricky Liangc662be32013-12-24 11:50:23 +0800739 VerifyHWIDv3(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800740 else:
741 raise Error, 'Invalid HWID version: %r' % options.hwid_version
742 VerifySystemTime(options)
743 VerifyKeys(options)
744 VerifyRootFs(options)
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800745 VerifyTPM(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800746 if options.cros_core:
747 logging.info('VerifyBranding is skipped for ChromeOS Core device.')
748 else:
749 VerifyBranding(options)
bowgotsai529139c2015-05-30 01:39:49 +0800750 VerifyReleaseChannel(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800751
Hung-Te Lin56b18402015-01-16 14:52:30 +0800752
Jon Salzfe9036f2014-01-16 14:11:23 +0800753@Command('untar_stateful_files')
Hung-Te Lin388bce22014-06-03 19:56:40 +0800754def UntarStatefulFiles(unused_options):
Jon Salzfe9036f2014-01-16 14:11:23 +0800755 """Untars stateful files from stateful_files.tar.xz on stateful partition.
756
757 If that file does not exist (which should only be R30 and earlier),
758 this is a no-op.
759 """
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +0800760 tar_file = os.path.join(paths.DEVICE_STATEFUL_PATH, 'stateful_files.tar.xz')
Jon Salzfe9036f2014-01-16 14:11:23 +0800761 if os.path.exists(tar_file):
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +0800762 Spawn(['tar', 'xf', tar_file], cwd=paths.DEVICE_STATEFUL_PATH,
Jon Salzfe9036f2014-01-16 14:11:23 +0800763 log=True, check_call=True)
764 else:
765 logging.warning('No stateful files at %s', tar_file)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800766
Jon Salz40b9f822014-07-25 16:39:55 +0800767
768@Command('log_source_hashes')
769def LogSourceHashes(options): # pylint: disable=W0613
770 """Logs hashes of source files in the factory toolkit."""
Jon Salze60307f2014-08-05 16:20:00 +0800771 # WARNING: The following line is necessary to validate the integrity
772 # of the factory software. Do not remove or modify it.
773 #
774 # 警告:此行会验证工厂软件的完整性,禁止删除或修改。
Jon Salz40b9f822014-07-25 16:39:55 +0800775 event_log.Log(
776 'source_hashes',
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +0800777 **file_utils.HashSourceTree(os.path.join(paths.FACTORY_PATH, 'py')))
Jon Salz40b9f822014-07-25 16:39:55 +0800778
779
Tammo Spalink86a61c62012-05-25 15:10:35 +0800780@Command('log_system_details')
Tammo Spalink01e11722012-07-24 10:17:54 -0700781def LogSystemDetails(options): # pylint: disable=W0613
Tammo Spalink86a61c62012-05-25 15:10:35 +0800782 """Write miscellaneous system details to the event log."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800783
Ricky Liang43b879b2014-02-24 11:36:55 +0800784 event_log.Log('system_details', **GetGooftool(options).GetSystemDetails())
Tammo Spalink86a61c62012-05-25 15:10:35 +0800785
786
Jon Salza88b83b2013-05-27 20:00:35 +0800787def CreateReportArchiveBlob(*args, **kwargs):
788 """Creates a report archive and returns it as a blob.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800789
Jon Salza88b83b2013-05-27 20:00:35 +0800790 Args:
791 See CreateReportArchive.
Andy Cheng7a76cb82012-11-19 18:08:19 +0800792
Jon Salza88b83b2013-05-27 20:00:35 +0800793 Returns:
794 An xmlrpclib.Binary object containing a .tar.xz file.
795 """
796 with open(CreateReportArchive(*args, **kwargs)) as f:
797 return xmlrpclib.Binary(f.read())
798
799
800def CreateReportArchive(device_sn=None, add_file=None):
801 """Creates a report archive in a temporary directory.
802
803 Args:
804 device_sn: The device serial number (optional).
805 add_file: A list of files to add (optional).
806
807 Returns:
808 Path to the archive.
809 """
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800810 def NormalizeAsFileName(token):
811 return re.sub(r'\W+', '', token).strip()
Jon Salza88b83b2013-05-27 20:00:35 +0800812
813 target_name = '%s%s.tar.xz' % (
814 time.strftime('%Y%m%dT%H%M%SZ',
815 time.gmtime()),
Hung-Te Lin56b18402015-01-16 14:52:30 +0800816 ('' if device_sn is None else
817 '_' + NormalizeAsFileName(device_sn)))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800818 target_path = os.path.join(gettempdir(), target_name)
Jon Salza88b83b2013-05-27 20:00:35 +0800819
Tammo Spalink86a61c62012-05-25 15:10:35 +0800820 # Intentionally ignoring dotfiles in EVENT_LOG_DIR.
Andy Cheng0465d132013-03-20 12:12:06 +0800821 tar_cmd = 'cd %s ; tar cJf %s *' % (event_log.EVENT_LOG_DIR, target_path)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800822 tar_cmd += ' --add-file %s' % FACTORY_LOG_PATH
Jon Salza88b83b2013-05-27 20:00:35 +0800823 if add_file:
824 for f in add_file:
Jon Salz65266432012-07-30 19:02:49 +0800825 # Require absolute paths since the tar command may change the
826 # directory.
827 if not f.startswith('/'):
828 raise Error('Not an absolute path: %s' % f)
829 if not os.path.exists(f):
830 raise Error('File does not exist: %s' % f)
831 tar_cmd += ' --add-file %s' % pipes.quote(f)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800832 cmd_result = Shell(tar_cmd)
Jon Salzff88c022012-11-03 12:19:58 +0800833
834 if ((cmd_result.status == 1) and
835 all((x == '' or
836 'file changed as we read it' in x or
837 "Removing leading `/' from member names" in x)
838 for x in cmd_result.stderr.split('\n'))):
839 # That's OK. Make sure it's valid though.
Vic Yang85199e72013-01-28 14:33:11 +0800840 Spawn(['tar', 'tfJ', target_path], check_call=True, log=True,
Jon Salzff88c022012-11-03 12:19:58 +0800841 ignore_stdout=True)
842 elif not cmd_result.success:
Tammo Spalink86a61c62012-05-25 15:10:35 +0800843 raise Error('unable to tar event logs, cmd %r failed, stderr: %r' %
844 (tar_cmd, cmd_result.stderr))
Jon Salzff88c022012-11-03 12:19:58 +0800845
Jon Salza88b83b2013-05-27 20:00:35 +0800846 return target_path
847
848_upload_method_cmd_arg = CmdArg(
849 '--upload_method', metavar='METHOD:PARAM',
850 help=('How to perform the upload. METHOD should be one of '
851 '{ftp, shopfloor, ftps, cpfe}.'))
852_add_file_cmd_arg = CmdArg(
853 '--add_file', metavar='FILE', action='append',
854 help='Extra file to include in report (must be an absolute path)')
855
Hung-Te Lin56b18402015-01-16 14:52:30 +0800856
Jon Salza88b83b2013-05-27 20:00:35 +0800857@Command('upload_report',
858 _upload_method_cmd_arg,
859 _add_file_cmd_arg)
860def UploadReport(options):
861 """Create a report containing key device details."""
Hung-Te Lin74346d72016-01-07 22:16:57 +0800862 ro_vpd = ReadRoVpd()
Jon Salza88b83b2013-05-27 20:00:35 +0800863 device_sn = ro_vpd.get('serial_number', None)
864 if device_sn is None:
865 logging.warning('RO_VPD missing device serial number')
866 device_sn = 'MISSING_SN_' + event_log.TimedUuid()
867 target_path = CreateReportArchive(device_sn)
868
Tammo Spalink86a61c62012-05-25 15:10:35 +0800869 if options.upload_method is None or options.upload_method == 'none':
870 logging.warning('REPORT UPLOAD SKIPPED (report left at %s)', target_path)
871 return
872 method, param = options.upload_method.split(':', 1)
873 if method == 'shopfloor':
874 report_upload.ShopFloorUpload(target_path, param)
875 elif method == 'ftp':
Jay Kim360c1dd2012-06-25 10:58:11 -0700876 report_upload.FtpUpload(target_path, 'ftp:' + param)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800877 elif method == 'ftps':
878 report_upload.CurlUrlUpload(target_path, '--ftp-ssl-reqd ftp:%s' % param)
879 elif method == 'cpfe':
Shawn Nematbakhsh3404a092013-01-28 16:49:09 -0800880 report_upload.CpfeUpload(target_path, pipes.quote(param))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800881 else:
882 raise Error('unknown report upload method %r', method)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800883
884
885@Command('finalize',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800886 CmdArg('--no_write_protect', action='store_true',
887 help='Do not enable firmware write protection.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800888 CmdArg('--fast', action='store_true',
889 help='use non-secure but faster wipe method.'),
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800890 CmdArg('--wipe_in_place', action='store_true',
891 help='Start factory wiping in place without reboot.'),
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800892 _cutoff_args_cmd_arg,
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800893 _shopfloor_url_args_cmd_arg,
Ricky Liang43b879b2014-02-24 11:36:55 +0800894 _hwid_version_cmd_arg,
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800895 _hwdb_path_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700896 _hwid_status_list_cmd_arg,
Jon Salz65266432012-07-30 19:02:49 +0800897 _upload_method_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800898 _add_file_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800899 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800900 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800901 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800902 _rma_mode_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800903 _cros_core_cmd_arg,
904 _enforced_release_channels_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800905def Finalize(options):
906 """Verify system readiness and trigger transition into release state.
907
Jon Salzaa3a30e2013-05-15 15:56:28 +0800908 This routine does the following:
909 - Verifies system state (see verify command)
Jon Salzfe9036f2014-01-16 14:11:23 +0800910 - Untars stateful_files.tar.xz, if it exists, in the stateful partition, to
911 initialize files such as the CRX cache
Jon Salzaa3a30e2013-05-15 15:56:28 +0800912 - Modifies firmware bitmaps to match locale
913 - Clears all factory-friendly flags from the GBB
914 - Removes factory-specific entries from RW_VPD (factory.*)
915 - Enables firmware write protection (cannot rollback after this)
916 - Uploads system logs & reports
917 - Sets the necessary boot flags to cause wipe of the factory image on the
918 next boot.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800919 """
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800920 Verify(options)
Jon Salz40b9f822014-07-25 16:39:55 +0800921 LogSourceHashes(options)
Jon Salzfe9036f2014-01-16 14:11:23 +0800922 UntarStatefulFiles(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800923 if options.cros_core:
924 logging.info('SetFirmwareBitmapLocale is skipped for ChromeOS Core device.')
925 else:
926 SetFirmwareBitmapLocale(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800927 ClearGBBFlags(options)
Jon Salzaa3a30e2013-05-15 15:56:28 +0800928 ClearFactoryVPDEntries(options)
Mattias Nisslercca761b2015-04-15 21:53:04 +0200929 GenerateStableDeviceSecret(options)
Hung-Te Lin6d827542012-07-19 11:50:41 +0800930 if options.no_write_protect:
931 logging.warn('WARNING: Firmware Write Protection is SKIPPED.')
Andy Cheng0465d132013-03-20 12:12:06 +0800932 event_log.Log('wp', fw='both', status='skipped')
Hung-Te Lin6d827542012-07-19 11:50:41 +0800933 else:
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800934 EnableFwWp({})
Jon Salza0f58e02012-05-29 19:33:39 +0800935 LogSystemDetails(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800936 UploadReport(options)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800937 if options.wipe_in_place:
938 event_log.Log('wipe_in_place')
939 WipeInPlace(options)
940 else:
941 PrepareWipe(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800942
943
Ricky Liangc662be32013-12-24 11:50:23 +0800944def VerifyHWIDv3(options):
945 """A simple wrapper that calls out to HWID utils to verify version 3 HWID.
Ricky Liang53390232013-03-08 15:37:57 +0800946
Ricky Liangc662be32013-12-24 11:50:23 +0800947 This is mainly for Gooftool to verify v3 HWID during finalize. For testing
948 and development purposes, please use `hwid` command.
Ricky Liang53390232013-03-08 15:37:57 +0800949 """
Ricky Liangc662be32013-12-24 11:50:23 +0800950 db = GetGooftool(options).db
951 encoded_string = options.hwid or hwid_utils.GetHWIDString()
Ricky Liang7905f272013-03-16 01:57:10 +0800952 if options.probe_results:
Ricky Liangc662be32013-12-24 11:50:23 +0800953 probed_results = yaml.load(open(options.probe_results).read())
Ricky Liang7905f272013-03-16 01:57:10 +0800954 else:
Ricky Liangc662be32013-12-24 11:50:23 +0800955 probed_results = yaml.load(Probe(probe_vpd=True).Encode())
956 vpd = hwid_utils.GetVPD(probed_results)
Ricky Liang53390232013-03-08 15:37:57 +0800957
Hung-Te Lin11052952015-03-18 13:48:59 +0800958 event_log.Log('probed_results', probed_results=FilterDict(probed_results))
959 event_log.Log('vpd', vpd=FilterDict(vpd))
Ricky Liang53390232013-03-08 15:37:57 +0800960
Ricky Liangc662be32013-12-24 11:50:23 +0800961 hwid_utils.VerifyHWID(db, encoded_string, probed_results, vpd,
Hung-Te Lin56b18402015-01-16 14:52:30 +0800962 rma_mode=options.rma_mode)
Ricky Liang53390232013-03-08 15:37:57 +0800963
Ricky Liangc662be32013-12-24 11:50:23 +0800964 event_log.Log('verified_hwid', hwid=encoded_string)
Ricky Liang53390232013-03-08 15:37:57 +0800965
966
Ricky Liang59611a62013-06-11 13:47:33 +0800967def ParseDecodedHWID(hwid):
968 """Parse the HWID object into a more compact dict.
969
970 Args:
971 hwid: A decoded HWID object.
972
973 Returns:
974 A dict containing the board name, the binary string, and the list of
975 components.
976 """
977 results = {}
978 results['board'] = hwid.database.board
979 results['binary_string'] = hwid.binary_string
980 results['components'] = collections.defaultdict(list)
981 components = hwid.bom.components
982 for comp_cls in sorted(components):
983 for (comp_name, probed_values, _) in sorted(components[comp_cls]):
984 if not probed_values:
985 db_components = hwid.database.components
986 probed_values = db_components.GetComponentAttributes(
987 comp_cls, comp_name).get('values')
988 results['components'][comp_cls].append(
989 {comp_name: probed_values if probed_values else None})
990 # Convert defaultdict to dict.
991 results['components'] = dict(results['components'])
992 return results
993
994
henryhsu44d793a2013-07-20 00:07:38 +0800995@Command('get_firmware_hash',
996 CmdArg('--file', metavar='FILE', help='Firmware File.'))
997def GetFirmwareHash(options):
henryhsuf6f835c2013-07-20 20:49:25 +0800998 """Get firmware hash from a file"""
henryhsu44d793a2013-07-20 00:07:38 +0800999 if os.path.exists(options.file):
1000 hashes = CalculateFirmwareHashes(options.file)
1001 for section, value_dict in hashes.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +08001002 print '%s:' % section
henryhsu44d793a2013-07-20 00:07:38 +08001003 for key, value in value_dict.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +08001004 print ' %s: %s' % (key, value)
henryhsu44d793a2013-07-20 00:07:38 +08001005 else:
1006 raise Error('File does not exist: %s' % options.file)
1007
henryhsuf6f835c2013-07-20 20:49:25 +08001008
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001009def Main():
1010 """Run sub-command specified by the command line args."""
Andy Cheng7a76cb82012-11-19 18:08:19 +08001011
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001012 options = ParseCmdline(
Ricky Liangc662be32013-12-24 11:50:23 +08001013 ('Perform Google required factory tests. All the HWID-related functions '
1014 'provided here are mainly for the deprecated HWID v2. To access HWID '
1015 'v3-related utilities, please use `hwid` command.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001016 CmdArg('-l', '--log', metavar='PATH',
1017 help='Write logs to this file.'),
Jon Salza4bea382012-10-29 13:00:34 +08001018 CmdArg('--suppress-event-logs', action='store_true',
1019 help='Suppress event logging.'),
Tammo Spalink8fab5312012-05-28 18:33:30 +08001020 verbosity_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001021 SetupLogging(options.verbosity, options.log)
Andy Cheng0465d132013-03-20 12:12:06 +08001022 event_log.SetGlobalLoggerDefaultPrefix('gooftool')
1023 event_log.GetGlobalLogger().suppress = options.suppress_event_logs
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001024 logging.debug('gooftool options: %s', repr(options))
1025 try:
1026 logging.debug('GOOFTOOL command %r', options.command_name)
1027 options.command(options)
1028 logging.info('GOOFTOOL command %r SUCCESS', options.command_name)
1029 except Error, e:
1030 logging.exception(e)
1031 sys.exit('GOOFTOOL command %r ERROR: %s' % (options.command_name, e))
1032 except Exception, e:
1033 logging.exception(e)
1034 sys.exit('UNCAUGHT RUNTIME EXCEPTION %s' % e)
1035
1036
1037if __name__ == '__main__':
1038 Main()