blob: a2461add1fb4ffbb087e284ddacd08d4343af7c8 [file] [log] [blame]
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001#!/usr/bin/python
Tammo Spalink01e11722012-07-24 10:17:54 -07002# pylint: disable=E1101
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08003#
4# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
5# Use of this source code is governed by a BSD-style license that can be
6# found in the LICENSE file.
7
8"""Google Factory Tool.
9
10This tool is indended to be used on factory assembly lines. It
11provides all of the Google required test functionality and must be run
12on each device as part of the assembly process.
13"""
14
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080015import logging
16import os
Jon Salz65266432012-07-30 19:02:49 +080017import pipes
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080018import re
19import sys
Hung-Te Lin6bd16472012-06-20 16:26:47 +080020import time
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080021
Tammo Spalink8fab5312012-05-28 18:33:30 +080022from tempfile import gettempdir, NamedTemporaryFile
Tammo Spalink86a61c62012-05-25 15:10:35 +080023
Tammo Spalinka40293e2012-07-04 14:58:56 +080024import factory_common # pylint: disable=W0611
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080025
Jon Salz0f8a6842012-09-25 11:28:22 +080026from cros.factory.common import Error, SetupLogging, Shell
Tammo Spalink394e4492012-08-01 10:20:30 -070027from cros.factory.common import YamlWrite
Tammo Spalink01e11722012-07-24 10:17:54 -070028from cros.factory.gooftool import crosfw
Andy Chengc531e2f2012-10-15 19:09:17 +080029from cros.factory.gooftool import Gooftool
Tammo Spalink01e11722012-07-24 10:17:54 -070030from cros.factory.gooftool import report_upload
31from cros.factory.gooftool.bmpblk import unpack_bmpblock
Andy Cheng8ece7382012-08-22 16:25:42 +080032from cros.factory.gooftool.probe import Probe, PROBEABLE_COMPONENT_CLASSES
Jon Salz0f8a6842012-09-25 11:28:22 +080033from cros.factory.gooftool.probe import ReadRoVpd, ReadRwVpd
Jon Salz05aba9d2012-10-05 17:25:38 +080034from cros.factory.gooftool.vpd_data import KNOWN_VPD_FIELD_DATA, FilterVPD
Tammo Spalinka40293e2012-07-04 14:58:56 +080035from cros.factory.hacked_argparse import CmdArg, Command, ParseCmdline
36from cros.factory.hacked_argparse import verbosity_cmd_arg
Tammo Spalink01e11722012-07-24 10:17:54 -070037from cros.factory.hwdb import hwid_tool
Jon Salz83591782012-06-26 11:09:58 +080038from cros.factory.event_log import EventLog, EVENT_LOG_DIR
39from cros.factory.event_log import TimedUuid
cychiang7fe09372012-07-04 14:31:23 +080040from cros.factory.test.factory import FACTORY_LOG_PATH
Jon Salzff88c022012-11-03 12:19:58 +080041from cros.factory.utils.process_utils import Spawn
Tammo Spalink86a61c62012-05-25 15:10:35 +080042
Tammo Spalink5c699832012-07-03 17:50:39 +080043
Tammo Spalink86a61c62012-05-25 15:10:35 +080044# Use a global event log, so that only a single log is created when
45# gooftool is called programmatically.
46_event_log = EventLog('gooftool')
47
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080048
Tammo Spalink5c699832012-07-03 17:50:39 +080049# TODO(tammo): Replace calls to sys.exit with raise Exit, and maybe
50# treat that specially (as a smoot exit, as opposed to the more
51# verbose output for generic Error).
52
53
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080054@Command('write_hwid',
55 CmdArg('hwid', metavar='HWID', help='HWID string'))
Andy Chengc92e6f92012-11-20 16:55:53 +080056def WriteHWID(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080057 """Write specified HWID value into the system BB."""
Andy Cheng7a76cb82012-11-19 18:08:19 +080058
Tammo Spalink95c43732012-07-25 15:57:14 -070059 logging.info('writing hwid string %r', options.hwid)
Andy Chengc92e6f92012-11-20 16:55:53 +080060 Gooftool().WriteHWID(options.hwid)
Tammo Spalink86a61c62012-05-25 15:10:35 +080061 _event_log.Log('write_hwid', hwid=options.hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -070062 print 'Wrote HWID: %r' % options.hwid
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080063
64
Tammo Spalink8fab5312012-05-28 18:33:30 +080065_hwdb_path_cmd_arg = CmdArg(
66 '--hwdb_path', metavar='PATH',
67 default=hwid_tool.DEFAULT_HWID_DATA_PATH,
68 help='Path to the HWID database.')
69
Tammo Spalink95c43732012-07-25 15:57:14 -070070_hwid_status_list_cmd_arg = CmdArg(
71 '--status', nargs='*', default=['supported'],
72 help='allow only HWIDs with these status values')
73
Jon Salzce124fb2012-10-02 17:42:03 +080074_probe_results_cmd_arg = CmdArg(
75 '--probe_results', metavar='RESULTS.yaml',
76 help=('Output from "gooftool probe" (used instead of '
77 'probing this system).'))
78
79_hwid_cmd_arg = CmdArg(
80 '--hwid', metavar='HWID',
81 help=('HWID to verify (instead of the currently set HWID of '
82 'this system)'))
83
Tammo Spalink95c43732012-07-25 15:57:14 -070084
85@Command('best_match_hwids',
Tammo Spalink8fab5312012-05-28 18:33:30 +080086 _hwdb_path_cmd_arg,
87 CmdArg('-b', '--board', metavar='BOARD',
Tammo Spalink95c43732012-07-25 15:57:14 -070088 help='optional BOARD name, needed only if data is present '
89 'for more than one'),
Tammo Spalink8fab5312012-05-28 18:33:30 +080090 CmdArg('--bom', metavar='BOM', help='BOM name'),
91 CmdArg('--variant', metavar='VARIANT', help='VARIANT code'),
Tammo Spalink5c699832012-07-03 17:50:39 +080092 CmdArg('--optimistic', action='store_true',
93 help='do not probe; assume singletons match'),
Tammo Spalink95c43732012-07-25 15:57:14 -070094 CmdArg('--comps', nargs='*', default=[],
95 help='list of canonical component names'),
96 CmdArg('--missing', nargs='*', default=[],
97 help='list component classes to be assumed missing'),
Tammo Spalink5c699832012-07-03 17:50:39 +080098 CmdArg('--status', nargs='*', default=['supported'],
Tammo Spalink95c43732012-07-25 15:57:14 -070099 help='consider only HWIDs within this list of status values'))
100def BestMatchHwids(options):
Tammo Spalink8fab5312012-05-28 18:33:30 +0800101 """Determine a list of possible HWIDs using provided args and probeing.
102
103 VOLATILE can always be determined by probing. To get a unique
104 result, VARIANT must be specified for all cases where the matching
105 BOM has more than one associated variant code, otherwise all HWID
106 variants will be returned. Both VARIANT and BOM information can
Tammo Spalink95c43732012-07-25 15:57:14 -0700107 alternatively be specified using the --stdin_comps argument, which
108 allows specifying a list of canonical names (one per line) on stdin,
109 one per line. Based on what is known from BOM and stdin_comps,
110 determine a list of components to probe for, and use those probe
111 results to resolve a list of matching HWIDs. If no boms,
112 components, or variant codes are specified, then a list of all HWIDs
Andy Cheng8ece7382012-08-22 16:25:42 +0800113 that match probeable components will be returned.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800114
115 Returns (on stdout): A list of HWIDs that match the available probe
116 results and argument contraints, one per line.
Tammo Spalink70b48a52012-08-08 16:54:51 -0700117
118 Example:
119
120 // Three ways to specify a keyboard (assuming it is a variant component)
121 gooftool best_match_hwids --missing keyboard
122 gooftool best_match_hwids --variant A or
123 gooftool best_match_hwids --comps us_kbd
Tammo Spalink8fab5312012-05-28 18:33:30 +0800124 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800125
Tammo Spalink5c699832012-07-03 17:50:39 +0800126 map(hwid_tool.Validate.Status, options.status)
Tammo Spalink95c43732012-07-25 15:57:14 -0700127 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Tammo Spalink5c699832012-07-03 17:50:39 +0800128 comp_db = hw_db.comp_db
Tammo Spalink3a7e9022012-06-27 14:08:40 +0800129 device = hw_db.GetDevice(options.board)
Tammo Spalink5c699832012-07-03 17:50:39 +0800130 component_spec = hwid_tool.ComponentSpec.New()
Tammo Spalink8fab5312012-05-28 18:33:30 +0800131 if options.bom:
Tammo Spalink5c699832012-07-03 17:50:39 +0800132 device.BomExists(options.bom)
Tammo Spalink01e11722012-07-24 10:17:54 -0700133 component_spec = hwid_tool.CombineComponentSpecs(
Tammo Spalink5c699832012-07-03 17:50:39 +0800134 component_spec, device.boms[options.bom].primary)
Tammo Spalink8fab5312012-05-28 18:33:30 +0800135 if options.variant:
Tammo Spalink5c699832012-07-03 17:50:39 +0800136 device.VariantExists(options.variant)
137 variant_spec = device.variants[options.variant]
Tammo Spalink01e11722012-07-24 10:17:54 -0700138 if hwid_tool.ComponentSpecsConflict(component_spec, variant_spec):
Tammo Spalink95c43732012-07-25 15:57:14 -0700139 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700140 % YamlWrite(sorted(
141 hwid_tool.ComponentSpecClasses(component_spec) &
142 hwid_tool.ComponentSpecClasses(variant_spec))))
Tammo Spalink01e11722012-07-24 10:17:54 -0700143 component_spec = hwid_tool.CombineComponentSpecs(
144 component_spec, variant_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700145 if options.comps or options.missing:
146 map(comp_db.CompExists, options.comps)
147 map(comp_db.CompClassExists, options.missing)
148 extra_comp_spec = comp_db.CreateComponentSpec(
149 components=options.comps,
150 missing=options.missing)
151 print 'cmdline asserted components:\n%s' % extra_comp_spec.Encode()
152 if hwid_tool.ComponentSpecsConflict(component_spec, extra_comp_spec):
153 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700154 % YamlWrite(sorted(
155 hwid_tool.ComponentSpecClasses(component_spec) &
156 hwid_tool.ComponentSpecClasses(extra_comp_spec))))
Tammo Spalink95c43732012-07-25 15:57:14 -0700157 component_spec = hwid_tool.CombineComponentSpecs(
158 component_spec, extra_comp_spec)
Tammo Spalink01e11722012-07-24 10:17:54 -0700159 spec_classes = hwid_tool.ComponentSpecClasses(component_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700160 missing_classes = set(comp_db.all_comp_classes) - spec_classes
Tammo Spalink5c699832012-07-03 17:50:39 +0800161 if missing_classes and not options.optimistic:
Andy Cheng8ece7382012-08-22 16:25:42 +0800162 non_probeable_missing = missing_classes - PROBEABLE_COMPONENT_CLASSES
163 if non_probeable_missing:
Tammo Spalink95c43732012-07-25 15:57:14 -0700164 sys.exit('FAILURE: these classes are necessary, were not specified '
Tammo Spalink70b48a52012-08-08 16:54:51 -0700165 'as inputs, and cannot be probed for:\n%s'
166 'This problem can often be addressed by specifying all of '
167 'the missing components on the command line (see the command '
Andy Cheng8ece7382012-08-22 16:25:42 +0800168 'help).' % YamlWrite(list(non_probeable_missing)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700169 print 'probing for missing classes:'
170 print YamlWrite(list(missing_classes))
171 probe_results = Probe(target_comp_classes=list(missing_classes),
172 probe_volatile=False, probe_initial_config=False)
173 cooked_components = comp_db.MatchComponentProbeValues(
174 probe_results.found_probe_value_map)
175 if cooked_components.unmatched:
176 sys.exit('ERROR: some probed components are unrecognized:\n%s'
177 % YamlWrite(cooked_components.unmatched))
178 probed_comp_spec = comp_db.CreateComponentSpec(
179 components=cooked_components.matched,
180 missing=probe_results.missing_component_classes)
181 component_spec = hwid_tool.CombineComponentSpecs(
182 component_spec, probed_comp_spec)
183 print YamlWrite({'component data used for matching': {
184 'missing component classes': component_spec.classes_missing,
185 'found components': component_spec.components}})
186 component_data = hwid_tool.ComponentData(
187 extant_components=hwid_tool.ComponentSpecCompClassMap(
188 component_spec).keys(),
189 classes_missing=component_spec.classes_missing)
190 match_tree = device.BuildMatchTree(component_data)
191 if not match_tree:
192 sys.exit('FAILURE: NO matching BOMs found')
193 print 'potential BOMs/VARIANTs:'
194 potential_variants = set()
195 potential_volatiles = set()
196 for bom_name, variant_tree in match_tree.items():
197 print ' BOM: %-8s VARIANTS: %s' % (
198 bom_name, ', '.join(sorted(variant_tree)))
199 for variant_code in variant_tree:
200 potential_variants.add(variant_code)
201 for volatile_code in device.volatiles:
202 status = device.GetHwidStatus(bom_name, variant_code, volatile_code)
203 if status in options.status:
204 potential_volatiles.add(volatile_code)
205 print ''
206 if len(potential_variants) == 0:
207 sys.exit('FAILURE: no matching VARIANTs found')
208 if len(potential_volatiles) == 0:
209 sys.exit('FAILURE: no VOLATILEs found for potential matching BOMs/VARIANTS '
210 '(with specified status)')
Tammo Spalink394e4492012-08-01 10:20:30 -0700211 if (options.optimistic and
212 len(match_tree) == 1 and
213 len(potential_variants) == 1 and
214 len(potential_volatiles) == 1):
215 print ('MATCHING HWID: %s' % device.FmtHwid(match_tree.keys().pop(),
216 potential_variants.pop(),
217 potential_volatiles.pop()))
Tammo Spalink5c699832012-07-03 17:50:39 +0800218 return
Tammo Spalink95c43732012-07-25 15:57:14 -0700219 print ('probing VOLATILEs to resolve potential matches: %s\n' %
220 ', '.join(sorted(potential_volatiles)))
221 vol_probe_results = Probe(
222 target_comp_classes=[],
223 probe_volatile=True,
224 probe_initial_config=False)
225 cooked_volatiles = device.MatchVolatileValues(
226 vol_probe_results.found_volatile_values)
227 match_tree = device.BuildMatchTree(
228 component_data, cooked_volatiles.matched_tags)
229 matched_hwids = device.GetMatchTreeHwids(match_tree)
230 if matched_hwids:
231 for hwid in matched_hwids:
Ricky Liang02f3bd72012-09-21 14:33:01 +0800232 if matched_hwids[hwid] in options.status:
233 print 'MATCHING HWID: %s' % hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700234 return
235 print 'exact HWID matching failed, but the following BOMs match: %s' % (
236 ', '.join(sorted(match_tree)))
237 if options.optimistic and len(match_tree) == 1:
238 bom_name = set(match_tree).pop()
Tammo Spalink5c699832012-07-03 17:50:39 +0800239 bom = device.boms[bom_name]
Tammo Spalink95c43732012-07-25 15:57:14 -0700240 variant_matches = match_tree[bom_name]
Tammo Spalink5c699832012-07-03 17:50:39 +0800241 if len(variant_matches) == 1:
242 var_code = set(variant_matches).pop()
243 elif len(bom.variants) == 1:
244 var_code = set(bom.variants).pop()
245 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700246 sys.exit('FAILURE: NO matching HWIDs found; optimistic matching failed '
247 'because there were too many variants to choose from for BOM %r'
248 % bom_name)
249 hwids = [device.FmtHwid(bom_name, var_code, vol_code)
250 for vol_code in device.volatiles
251 if device.GetHwidStatus(bom_name, var_code, vol_code)
252 in options.status]
253 for hwid in hwids:
254 print 'MATCHING HWID: %s' % hwid
Tammo Spalink5c699832012-07-03 17:50:39 +0800255 return
256 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700257 print ('optimistic matching not attempted because either it was '
258 'not requested, or because the number of BOMs was <> 1\n')
259 sys.exit('FAILURE: NO matching HWIDs found')
Tammo Spalink8fab5312012-05-28 18:33:30 +0800260
261
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800262@Command('probe',
263 CmdArg('--comps', nargs='*',
264 help='List of keys from the component_db registry.'),
265 CmdArg('--no_vol', action='store_true',
266 help='Do not probe volatile data.'),
267 CmdArg('--no_ic', action='store_true',
Jon Salz0f8a6842012-09-25 11:28:22 +0800268 help='Do not probe initial_config data.'),
269 CmdArg('--include_vpd', action='store_true',
270 help='Include VPD data in volatiles.'))
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800271def RunProbe(options):
272 """Print yaml-formatted breakdown of probed device properties."""
Andy Chengc92e6f92012-11-20 16:55:53 +0800273 print Gooftool().Probe(target_comp_classes=options.comps,
274 probe_volatile=not options.no_vol,
275 probe_initial_config=not options.no_ic,
276 probe_vpd=options.include_vpd).Encode()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800277
Tammo Spalink214caf42012-05-28 10:45:00 +0800278@Command('verify_components',
279 _hwdb_path_cmd_arg,
Tammo Spalink5c699832012-07-03 17:50:39 +0800280 CmdArg('target_comps', nargs='*'))
Tammo Spalink214caf42012-05-28 10:45:00 +0800281def VerifyComponents(options):
Andy Cheng8ece7382012-08-22 16:25:42 +0800282 """Verify that probeable components all match entries in the component_db.
Tammo Spalink214caf42012-05-28 10:45:00 +0800283
Tammo Spalink5c699832012-07-03 17:50:39 +0800284 Probe for each component class in the target_comps and verify
Tammo Spalink214caf42012-05-28 10:45:00 +0800285 that a corresponding match exists in the component_db -- make sure
286 that these components are present, that they have been approved, but
287 do not check against any specific BOM/HWID configurations.
288 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800289
Tammo Spalink5c699832012-07-03 17:50:39 +0800290 comp_db = hwid_tool.HardwareDb(options.hwdb_path).comp_db
Andy Chengc531e2f2012-10-15 19:09:17 +0800291 try:
292 result = Gooftool(component_db=comp_db).VerifyComponents(
293 options.target_comps)
294 except ValueError, e:
295 sys.exit(e)
296
297 # group by matches and errors
Tammo Spalink214caf42012-05-28 10:45:00 +0800298 matches = []
Andy Chengc531e2f2012-10-15 19:09:17 +0800299 errors = []
300 for result_list in result.values():
301 for component_name, _, error in result_list:
302 if component_name:
303 matches.append(component_name)
Tammo Spalink214caf42012-05-28 10:45:00 +0800304 else:
Andy Chengc531e2f2012-10-15 19:09:17 +0800305 errors.append(error)
306
Andy Cheng228a8c92012-08-27 10:53:57 +0800307 if matches:
308 print 'found probeable components:\n %s' % '\n '.join(matches)
Tammo Spalink214caf42012-05-28 10:45:00 +0800309 if errors:
Andy Cheng228a8c92012-08-27 10:53:57 +0800310 print '\nerrors:\n %s' % '\n '.join(errors)
311 sys.exit('\ncomponent verification FAILURE')
Tammo Spalink214caf42012-05-28 10:45:00 +0800312 else:
Andy Cheng228a8c92012-08-27 10:53:57 +0800313 print "\ncomponent verification SUCCESS"
Tammo Spalink214caf42012-05-28 10:45:00 +0800314
315
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800316@Command('verify_hwid',
Tammo Spalink95c43732012-07-25 15:57:14 -0700317 _hwid_status_list_cmd_arg,
Jon Salz0f8a6842012-09-25 11:28:22 +0800318 _hwdb_path_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800319 _probe_results_cmd_arg,
320 _hwid_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800321def VerifyHwid(options):
322 """Verify system HWID properties match probed device properties.
323
324 First probe components, volatile and initial_config parameters for
325 the DUT. Then use the available device data to produce a list of
326 candidate HWIDs. Then verify the HWID from the DUT is present in
327 that list. Then verify that the DUT initial config values match
328 those specified for its HWID. Finally, verify that VPD contains all
329 the necessary fields as specified by the board data, and when
330 possible verify that values are legitimate.
331 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800332
Ricky Liangf7857c12012-09-17 13:34:41 +0800333 def VerifyVpd(ro_vpd_keys, rw_vpd_keys):
Tammo Spalink5c699832012-07-03 17:50:39 +0800334 for key in ro_vpd_keys:
335 if key not in ro_vpd:
Ricky Liangf7857c12012-09-17 13:34:41 +0800336 sys.exit('Missing required RO VPD field: %s' % key)
Tammo Spalink01e11722012-07-24 10:17:54 -0700337 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800338 value = ro_vpd[key]
Ricky Liangf7857c12012-09-17 13:34:41 +0800339 if (known_valid_values is not None) and (value not in known_valid_values):
340 sys.exit('Invalid RO VPD entry : key %r, value %r' % (key, value))
Ricky Liangf7857c12012-09-17 13:34:41 +0800341 for key in rw_vpd_keys:
342 if key not in rw_vpd:
343 sys.exit('Missing required RW VPD field: %s' % key)
344 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
345 value = rw_vpd[key]
346 if (known_valid_values is not None) and (value not in known_valid_values):
347 sys.exit('Invalid RW VPD entry : key %r, value %r' % (key, value))
Jon Salz05aba9d2012-10-05 17:25:38 +0800348 _event_log.Log('vpd', ro_vpd=FilterVPD(ro_vpd), rw_vpd=FilterVPD(rw_vpd))
Tammo Spalink5c699832012-07-03 17:50:39 +0800349 map(hwid_tool.Validate.Status, options.status)
Jon Salz0f8a6842012-09-25 11:28:22 +0800350
Jon Salz81350812012-10-11 16:13:22 +0800351 if not options.hwid or not options.probe_results:
352 main_fw_file = crosfw.LoadMainFirmware().GetFileName()
Jon Salz0f8a6842012-09-25 11:28:22 +0800353
354 if options.hwid:
355 hwid_str = options.hwid
356 else:
357 gbb_result = Shell('gbb_utility -g --hwid %s' % main_fw_file).stdout
358 hwid_str = re.findall(r'hardware_id:(.*)', gbb_result)[0].strip()
Tammo Spalink95c43732012-07-25 15:57:14 -0700359 hwid = hwid_tool.ParseHwid(hwid_str)
Tammo Spalink5c699832012-07-03 17:50:39 +0800360 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Jon Salz0f8a6842012-09-25 11:28:22 +0800361 print 'Verifying HWID: %r\n' % hwid.hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700362 device = hw_db.GetDevice(hwid.board)
363 hwid_status = device.GetHwidStatus(hwid.bom, hwid.variant, hwid.volatile)
364 if hwid_status not in options.status:
Tammo Spalink5c699832012-07-03 17:50:39 +0800365 sys.exit('HWID status must be one of [%s], found %r' %
Hung-Te Lin4f5beb12012-08-20 14:48:06 +0800366 (', '.join(options.status), hwid_status))
Jon Salz0f8a6842012-09-25 11:28:22 +0800367 if options.probe_results:
368 # Pull in probe results (including VPD data) from the given file
369 # rather than probing the current system.
370 probe_results = hwid_tool.ProbeResults.Decode(
371 open(options.probe_results).read())
372 ro_vpd = {}
373 rw_vpd = {}
374 for k, v in probe_results.found_volatile_values.items():
375 match = re.match('^vpd\.(ro|rw)\.(\w+)$', k)
376 if match:
377 del probe_results.found_volatile_values[k]
378 (ro_vpd if match.group(1) == 'ro' else rw_vpd)[match.group(2)] = v
379 else:
380 probe_results = Probe()
381 ro_vpd = ReadRoVpd(main_fw_file)
382 rw_vpd = ReadRwVpd(main_fw_file)
Tammo Spalink95c43732012-07-25 15:57:14 -0700383 cooked_components = hw_db.comp_db.MatchComponentProbeValues(
384 probe_results.found_probe_value_map)
385 cooked_volatiles = device.MatchVolatileValues(
386 probe_results.found_volatile_values)
387 cooked_initial_configs = device.MatchInitialConfigValues(
388 probe_results.initial_configs)
389 component_data = hwid_tool.ComponentData(
390 extant_components=cooked_components.matched,
391 classes_missing=probe_results.missing_component_classes)
392 match_tree = device.BuildMatchTree(
393 component_data, cooked_volatiles.matched_tags)
394 matched_hwids = device.GetMatchTreeHwids(match_tree)
395 print 'HWID status: %s\n' % hwid_status
396 print 'probed system components:'
397 print YamlWrite(cooked_components.__dict__)
398 print 'missing component classes:'
399 print YamlWrite(probe_results.missing_component_classes)
400 print 'probed volatiles:'
401 print YamlWrite(cooked_volatiles.__dict__)
402 print 'probed initial_configs:'
403 print YamlWrite(cooked_initial_configs)
404 print 'hwid match tree:'
405 print YamlWrite(match_tree)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800406 _event_log.Log(
Tammo Spalink5c699832012-07-03 17:50:39 +0800407 'probe',
Tammo Spalink95c43732012-07-25 15:57:14 -0700408 found_components=cooked_components.__dict__,
409 missing_component_classes=probe_results.missing_component_classes,
410 volatiles=cooked_volatiles.__dict__,
411 initial_configs=cooked_initial_configs)
412 if hwid.hwid not in matched_hwids:
Tammo Spalink5c699832012-07-03 17:50:39 +0800413 err_msg = 'HWID verification FAILED.\n'
Tammo Spalink95c43732012-07-25 15:57:14 -0700414 if cooked_components.unmatched:
Tammo Spalink5c699832012-07-03 17:50:39 +0800415 sys.exit(err_msg + 'some components could not be indentified:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700416 YamlWrite(cooked_components.unmatched))
417 if not match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800418 sys.exit(err_msg + 'no matching boms were found for components:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700419 component_data.Encode())
420 if hwid.bom not in match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800421 sys.exit(err_msg + 'matching boms [%s] do not include target bom %r' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700422 (', '.join(sorted(match_tree)), hwid.bom))
423 err_msg += 'target bom %r matches components' % hwid.bom
424 if hwid.bom not in device.IntersectBomsAndInitialConfigs(
425 cooked_initial_configs):
Tammo Spalink5c699832012-07-03 17:50:39 +0800426 sys.exit(err_msg + ', but failed initial config verification')
Tammo Spalink95c43732012-07-25 15:57:14 -0700427 matched_variants = match_tree.get(hwid.bom, {})
428 if hwid.variant not in matched_variants:
Tammo Spalink5c699832012-07-03 17:50:39 +0800429 sys.exit(err_msg + ', but target variant_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700430 hwid.variant)
431 matched_volatiles = matched_variants.get(hwid.variant, {})
432 if hwid.volatile not in matched_volatiles:
Tammo Spalink5c699832012-07-03 17:50:39 +0800433 sys.exit(err_msg + ', but target volatile_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700434 hwid.volatile)
435 found_status = matched_volatiles.get(hwid.volatile, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800436 sys.exit(err_msg + ', but hwid status %r was unacceptable' % found_status)
Ricky Liangf7857c12012-09-17 13:34:41 +0800437 VerifyVpd(device.vpd_ro_fields, device.vpd_rw_fields)
Tammo Spalink5c699832012-07-03 17:50:39 +0800438 _event_log.Log('verified_hwid', hwid=hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -0700439 print 'Verification SUCCESS!'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800440
441
442@Command('verify_keys')
Tammo Spalink01e11722012-07-24 10:17:54 -0700443def VerifyKeys(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800444 """Verify keys in firmware and SSD match."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800445
446 return Gooftool().VerifyKeys()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800447
448
449@Command('set_fw_bitmap_locale')
Tammo Spalink01e11722012-07-24 10:17:54 -0700450def SetFirmwareBitmapLocale(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800451 """Use VPD locale value to set firmware bitmap default language."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800452
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800453 image_file = crosfw.LoadMainFirmware().GetFileName()
454 locale = ReadRoVpd(image_file).get('initial_locale', None)
455 if locale is None:
456 raise Error, 'Missing initial_locale VPD.'
457 bitmap_locales = []
458 with NamedTemporaryFile() as f:
459 Shell('gbb_utility -g --bmpfv=%s %s' % (f.name, image_file))
Tammo Spalink01e11722012-07-24 10:17:54 -0700460 bmpblk_data = unpack_bmpblock(f.read())
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800461 bitmap_locales = bmpblk_data.get('locales', bitmap_locales)
462 # Some locale values are just a language code and others are a
463 # hyphen-separated language code and country code pair. We care
464 # only about the language code part.
465 language_code = locale.partition('-')[0]
466 if language_code not in bitmap_locales:
467 raise Error, ('Firmware bitmaps do not contain support for the specified '
468 'initial locale language %r' % language_code)
469 else:
470 locale_index = bitmap_locales.index(language_code)
471 logging.info('Firmware bitmap initial locale set to %d (%s).',
472 locale_index, bitmap_locales[locale_index])
473 Shell('crossystem loc_idx=%d' % locale_index)
474
475
476@Command('verify_system_time')
Tammo Spalink01e11722012-07-24 10:17:54 -0700477def VerifySystemTime(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800478 """Verify system time is later than release filesystem creation time."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800479
480 return Gooftool().VerifySystemTime()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800481
482
483@Command('verify_rootfs')
Tammo Spalink01e11722012-07-24 10:17:54 -0700484def VerifyRootFs(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800485 """Verify rootfs on SSD is valid by checking hash."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800486
487 return Gooftool().VerifyRootFs()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800488
489
490@Command('verify_switch_wp')
Andy Chengc92e6f92012-11-20 16:55:53 +0800491def VerifyWPSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800492 """Verify hardware write protection switch is enabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800493
Andy Chengc92e6f92012-11-20 16:55:53 +0800494 Gooftool().VerifyWPSwitch()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800495
496
497@Command('verify_switch_dev')
Tammo Spalink01e11722012-07-24 10:17:54 -0700498def VerifyDevSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800499 """Verify developer switch is disabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800500
Hung-Te Lind7d34722012-07-26 16:48:35 +0800501 VBSD_HONOR_VIRT_DEV_SWITCH = 0x400
502 flags = int(Shell('crossystem vdat_flags').stdout.strip(), 0)
503 if (flags & VBSD_HONOR_VIRT_DEV_SWITCH) != 0:
504 # System is using virtual developer switch. That will be handled in
505 # prepare_wipe.sh by setting "crossystem disable_dev_request=1" -- although
506 # we can't verify that until next reboot, because the real values are stored
507 # in TPM.
508 logging.warn('VerifyDevSwitch: No physical switch.')
509 _event_log.Log('switch_dev', type='virtual switch')
510 return
511 if Shell('crossystem devsw_cur').stdout.strip() != '0':
512 raise Error, 'developer mode is not disabled'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800513
514
515@Command('write_protect')
Tammo Spalink01e11722012-07-24 10:17:54 -0700516def EnableFwWp(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800517 """Enable then verify firmware write protection."""
518
Hung-Te Linb21c6682012-08-01 13:53:57 +0800519 def CalculateLegacyRange(fw_type, length, section_data,
520 section_name):
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800521 ro_size = length / 2
522 ro_a = int(section_data[0] / ro_size)
523 ro_b = int((section_data[0] + section_data[1] - 1) / ro_size)
524 if ro_a != ro_b:
525 raise Error("%s firmware section %s has illegal size" %
Hung-Te Linb21c6682012-08-01 13:53:57 +0800526 (fw_type, section_name))
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800527 ro_offset = ro_a * ro_size
528 return (ro_offset, ro_size)
529
530 def WriteProtect(fw_file_path, fw_type, legacy_section):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800531 """Calculate protection size, then invoke flashrom.
532
533 Our supported chips only allow write protecting half their total
534 size, so we parition the flash chipset space accordingly.
535 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800536
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800537 raw_image = open(fw_file_path, 'rb').read()
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800538 wp_section = 'WP_RO'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800539 image = crosfw.FirmwareImage(raw_image)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800540 if image.has_section(wp_section):
541 section_data = image.get_section_area(wp_section)
542 ro_offset = section_data[0]
543 ro_size = section_data[1]
544 elif image.has_section(legacy_section):
545 section_data = image.get_section_area(legacy_section)
546 (ro_offset, ro_size) = CalculateLegacyRange(
Hung-Te Linb21c6682012-08-01 13:53:57 +0800547 fw_type, len(raw_image), section_data, legacy_section)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800548 else:
549 raise Error('could not find %s firmware section %s or %s' %
550 (fw_type, wp_section, legacy_section))
551
552 logging.debug('write protecting %s [off=%x size=%x]', fw_type,
553 ro_offset, ro_size)
554 crosfw.Flashrom(fw_type).EnableWriteProtection(ro_offset, ro_size)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800555
556 WriteProtect(crosfw.LoadMainFirmware().GetFileName(), 'main', 'RO_SECTION')
Tammo Spalink86a61c62012-05-25 15:10:35 +0800557 _event_log.Log('wp', fw='main')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800558 ec_fw_file = crosfw.LoadEcFirmware().GetFileName()
559 if ec_fw_file is not None:
560 WriteProtect(ec_fw_file, 'ec', 'EC_RO')
Tammo Spalink86a61c62012-05-25 15:10:35 +0800561 _event_log.Log('wp', fw='ec')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800562 else:
563 logging.warning('EC not write protected (seems there is no EC flash).')
564
565
566@Command('clear_gbb_flags')
Andy Chengc92e6f92012-11-20 16:55:53 +0800567def ClearGBBFlags(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800568 """Zero out the GBB flags, in preparation for transition to release state.
569
570 No GBB flags are set in release/shipping state, but they are useful
571 for factory/development. See "gbb_utility --flags" for details.
572 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800573
Andy Chengc92e6f92012-11-20 16:55:53 +0800574 Gooftool().ClearGBBFlags()
Tammo Spalink86a61c62012-05-25 15:10:35 +0800575 _event_log.Log('clear_gbb_flags')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800576
577
578@Command('prepare_wipe',
579 CmdArg('--fast', action='store_true',
580 help='use non-secure but faster wipe method.'))
581def PrepareWipe(options):
582 """Prepare system for transition to release state in next reboot."""
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800583
Andy Cheng7a76cb82012-11-19 18:08:19 +0800584 Gooftool().PrepareWipe(options.fast)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800585
586@Command('verify',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800587 CmdArg('--no_write_protect', action='store_true',
588 help='Do not check write protection switch state.'),
Tammo Spalink95c43732012-07-25 15:57:14 -0700589 _hwid_status_list_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800590 _hwdb_path_cmd_arg,
591 _probe_results_cmd_arg,
592 _hwid_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800593def Verify(options):
594 """Verifies if whole factory process is ready for finalization.
595
596 This routine performs all the necessary checks to make sure the
597 device is ready to be finalized, but does not modify state. These
598 checks include dev switch, firmware write protection switch, hwid,
599 system time, keys, and root file system.
600 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800601
Hung-Te Lin6d827542012-07-19 11:50:41 +0800602 if not options.no_write_protect:
Andy Chengc92e6f92012-11-20 16:55:53 +0800603 VerifyWPSwitch({})
Hung-Te Lin6d827542012-07-19 11:50:41 +0800604 VerifyDevSwitch({})
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800605 VerifyHwid(options)
606 VerifySystemTime({})
607 VerifyKeys({})
608 VerifyRootFs({})
609
610
Tammo Spalink86a61c62012-05-25 15:10:35 +0800611@Command('log_system_details')
Tammo Spalink01e11722012-07-24 10:17:54 -0700612def LogSystemDetails(options): # pylint: disable=W0613
Tammo Spalink86a61c62012-05-25 15:10:35 +0800613 """Write miscellaneous system details to the event log."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800614
Tammo Spalink86a61c62012-05-25 15:10:35 +0800615 raw_cs_data = Shell('crossystem').stdout.strip().splitlines()
616 # The crossytem output contains many lines like:
617 # 'key = value # description'
618 # Use regexps to pull out the key-value pairs and build a dict.
619 cs_data = dict((k, v.strip()) for k, v in
620 map(lambda x: re.findall(r'\A(\S+)\s+=\s+(.*)#.*\Z', x)[0],
621 raw_cs_data))
622 _event_log.Log(
623 'system_details',
624 platform_name=Shell('mosys platform name').stdout.strip(),
625 crossystem=cs_data,
626 modem_status=Shell('modem status').stdout.splitlines(),
627 ec_wp_status=Shell(
628 'flashrom -p internal:bus=lpc --get-size 2>/dev/null && '
629 'flashrom -p internal:bus=lpc --wp-status || '
630 'echo "EC is not available."').stdout,
631 bios_wp_status = Shell(
632 'flashrom -p internal:bus=spi --wp-status').stdout)
633
634
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800635_upload_method_cmd_arg = CmdArg(
636 '--upload_method', metavar='METHOD:PARAM',
637 help=('How to perform the upload. METHOD should be one of '
cychiang3b15bd52012-09-08 13:58:18 +0800638 '{ftp, shopfloor, ftps, cpfe}.'))
Jon Salz65266432012-07-30 19:02:49 +0800639_add_file_cmd_arg = CmdArg(
640 '--add_file', metavar='FILE', action='append',
641 help='Extra file to include in report (must be an absolute path)')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800642
643@Command('upload_report',
Jon Salz65266432012-07-30 19:02:49 +0800644 _upload_method_cmd_arg,
645 _add_file_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800646def UploadReport(options):
647 """Create and a report containing key device details."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800648
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800649 def NormalizeAsFileName(token):
650 return re.sub(r'\W+', '', token).strip()
Tammo Spalink86a61c62012-05-25 15:10:35 +0800651 ro_vpd = ReadRoVpd(crosfw.LoadMainFirmware().GetFileName())
652 device_sn = ro_vpd.get('serial_number', None)
653 if device_sn is None:
654 logging.warning('RO_VPD missing device serial number')
655 device_sn = 'MISSING_SN_' + TimedUuid()
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800656 target_name = '%s_%s.tbz2' % (time.strftime('%Y%m%dT%H%M%SZ', time.gmtime()),
657 NormalizeAsFileName(device_sn))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800658 target_path = os.path.join(gettempdir(), target_name)
659 # Intentionally ignoring dotfiles in EVENT_LOG_DIR.
660 tar_cmd = 'cd %s ; tar cjf %s *' % (EVENT_LOG_DIR, target_path)
661 tar_cmd += ' --add-file %s' % FACTORY_LOG_PATH
Jon Salz65266432012-07-30 19:02:49 +0800662 if options.add_file:
663 for f in options.add_file:
664 # Require absolute paths since the tar command may change the
665 # directory.
666 if not f.startswith('/'):
667 raise Error('Not an absolute path: %s' % f)
668 if not os.path.exists(f):
669 raise Error('File does not exist: %s' % f)
670 tar_cmd += ' --add-file %s' % pipes.quote(f)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800671 cmd_result = Shell(tar_cmd)
Jon Salzff88c022012-11-03 12:19:58 +0800672
673 if ((cmd_result.status == 1) and
674 all((x == '' or
675 'file changed as we read it' in x or
676 "Removing leading `/' from member names" in x)
677 for x in cmd_result.stderr.split('\n'))):
678 # That's OK. Make sure it's valid though.
679 Spawn(['tar', 'tfj', target_path], check_call=True, log=True,
680 ignore_stdout=True)
681 elif not cmd_result.success:
Tammo Spalink86a61c62012-05-25 15:10:35 +0800682 raise Error('unable to tar event logs, cmd %r failed, stderr: %r' %
683 (tar_cmd, cmd_result.stderr))
Jon Salzff88c022012-11-03 12:19:58 +0800684
Tammo Spalink86a61c62012-05-25 15:10:35 +0800685 if options.upload_method is None or options.upload_method == 'none':
686 logging.warning('REPORT UPLOAD SKIPPED (report left at %s)', target_path)
687 return
688 method, param = options.upload_method.split(':', 1)
689 if method == 'shopfloor':
690 report_upload.ShopFloorUpload(target_path, param)
691 elif method == 'ftp':
Jay Kim360c1dd2012-06-25 10:58:11 -0700692 report_upload.FtpUpload(target_path, 'ftp:' + param)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800693 elif method == 'ftps':
694 report_upload.CurlUrlUpload(target_path, '--ftp-ssl-reqd ftp:%s' % param)
695 elif method == 'cpfe':
696 report_upload.CpfeUpload(target_path, param)
697 else:
698 raise Error('unknown report upload method %r', method)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800699
700
701@Command('finalize',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800702 CmdArg('--no_write_protect', action='store_true',
703 help='Do not enable firmware write protection.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800704 CmdArg('--fast', action='store_true',
705 help='use non-secure but faster wipe method.'),
706 _hwdb_path_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700707 _hwid_status_list_cmd_arg,
Jon Salz65266432012-07-30 19:02:49 +0800708 _upload_method_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800709 _add_file_cmd_arg,
710 _probe_results_cmd_arg,
711 _hwid_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800712def Finalize(options):
713 """Verify system readiness and trigger transition into release state.
714
Hung-Te Lin6d827542012-07-19 11:50:41 +0800715 This routine first verifies system state (see verify command), modifies
716 firmware bitmaps to match locale, and then clears all of the factory-friendly
717 flags from the GBB. If everything is fine, it enables firmware write
718 protection (cannot rollback after this stage), uploads system logs & reports,
719 and sets the necessary boot flags to cause wipe of the factory image on the
720 next boot.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800721 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800722
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800723 Verify(options)
724 SetFirmwareBitmapLocale({})
Andy Chengc92e6f92012-11-20 16:55:53 +0800725 ClearGBBFlags({})
Hung-Te Lin6d827542012-07-19 11:50:41 +0800726 if options.no_write_protect:
727 logging.warn('WARNING: Firmware Write Protection is SKIPPED.')
728 _event_log.Log('wp', fw='both', status='skipped')
729 else:
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800730 EnableFwWp({})
Jon Salza0f58e02012-05-29 19:33:39 +0800731 LogSystemDetails(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800732 UploadReport(options)
733 PrepareWipe(options)
734
735
736def Main():
737 """Run sub-command specified by the command line args."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800738
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800739 options = ParseCmdline(
740 'Perform Google required factory tests.',
741 CmdArg('-l', '--log', metavar='PATH',
742 help='Write logs to this file.'),
Jon Salza4bea382012-10-29 13:00:34 +0800743 CmdArg('--suppress-event-logs', action='store_true',
744 help='Suppress event logging.'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800745 verbosity_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800746 SetupLogging(options.verbosity, options.log)
Jon Salza4bea382012-10-29 13:00:34 +0800747 _event_log.suppress = options.suppress_event_logs
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800748 logging.debug('gooftool options: %s', repr(options))
749 try:
750 logging.debug('GOOFTOOL command %r', options.command_name)
751 options.command(options)
752 logging.info('GOOFTOOL command %r SUCCESS', options.command_name)
753 except Error, e:
754 logging.exception(e)
755 sys.exit('GOOFTOOL command %r ERROR: %s' % (options.command_name, e))
756 except Exception, e:
757 logging.exception(e)
758 sys.exit('UNCAUGHT RUNTIME EXCEPTION %s' % e)
759
760
761if __name__ == '__main__':
762 Main()