blob: de6f7c1f6b824c5e4322c7151d2b58dfd02003e5 [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'))
56def WriteHwid(options):
57 """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)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080060 main_fw = crosfw.LoadMainFirmware()
61 Shell('gbb_utility --set --hwid="%s" "%s"' %
62 (options.hwid, main_fw.GetFileName()))
63 main_fw.Write(sections=['GBB'])
Tammo Spalink86a61c62012-05-25 15:10:35 +080064 _event_log.Log('write_hwid', hwid=options.hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -070065 print 'Wrote HWID: %r' % options.hwid
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080066
67
Tammo Spalink8fab5312012-05-28 18:33:30 +080068_hwdb_path_cmd_arg = CmdArg(
69 '--hwdb_path', metavar='PATH',
70 default=hwid_tool.DEFAULT_HWID_DATA_PATH,
71 help='Path to the HWID database.')
72
Tammo Spalink95c43732012-07-25 15:57:14 -070073_hwid_status_list_cmd_arg = CmdArg(
74 '--status', nargs='*', default=['supported'],
75 help='allow only HWIDs with these status values')
76
Jon Salzce124fb2012-10-02 17:42:03 +080077_probe_results_cmd_arg = CmdArg(
78 '--probe_results', metavar='RESULTS.yaml',
79 help=('Output from "gooftool probe" (used instead of '
80 'probing this system).'))
81
82_hwid_cmd_arg = CmdArg(
83 '--hwid', metavar='HWID',
84 help=('HWID to verify (instead of the currently set HWID of '
85 'this system)'))
86
Tammo Spalink95c43732012-07-25 15:57:14 -070087
88@Command('best_match_hwids',
Tammo Spalink8fab5312012-05-28 18:33:30 +080089 _hwdb_path_cmd_arg,
90 CmdArg('-b', '--board', metavar='BOARD',
Tammo Spalink95c43732012-07-25 15:57:14 -070091 help='optional BOARD name, needed only if data is present '
92 'for more than one'),
Tammo Spalink8fab5312012-05-28 18:33:30 +080093 CmdArg('--bom', metavar='BOM', help='BOM name'),
94 CmdArg('--variant', metavar='VARIANT', help='VARIANT code'),
Tammo Spalink5c699832012-07-03 17:50:39 +080095 CmdArg('--optimistic', action='store_true',
96 help='do not probe; assume singletons match'),
Tammo Spalink95c43732012-07-25 15:57:14 -070097 CmdArg('--comps', nargs='*', default=[],
98 help='list of canonical component names'),
99 CmdArg('--missing', nargs='*', default=[],
100 help='list component classes to be assumed missing'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800101 CmdArg('--status', nargs='*', default=['supported'],
Tammo Spalink95c43732012-07-25 15:57:14 -0700102 help='consider only HWIDs within this list of status values'))
103def BestMatchHwids(options):
Tammo Spalink8fab5312012-05-28 18:33:30 +0800104 """Determine a list of possible HWIDs using provided args and probeing.
105
106 VOLATILE can always be determined by probing. To get a unique
107 result, VARIANT must be specified for all cases where the matching
108 BOM has more than one associated variant code, otherwise all HWID
109 variants will be returned. Both VARIANT and BOM information can
Tammo Spalink95c43732012-07-25 15:57:14 -0700110 alternatively be specified using the --stdin_comps argument, which
111 allows specifying a list of canonical names (one per line) on stdin,
112 one per line. Based on what is known from BOM and stdin_comps,
113 determine a list of components to probe for, and use those probe
114 results to resolve a list of matching HWIDs. If no boms,
115 components, or variant codes are specified, then a list of all HWIDs
Andy Cheng8ece7382012-08-22 16:25:42 +0800116 that match probeable components will be returned.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800117
118 Returns (on stdout): A list of HWIDs that match the available probe
119 results and argument contraints, one per line.
Tammo Spalink70b48a52012-08-08 16:54:51 -0700120
121 Example:
122
123 // Three ways to specify a keyboard (assuming it is a variant component)
124 gooftool best_match_hwids --missing keyboard
125 gooftool best_match_hwids --variant A or
126 gooftool best_match_hwids --comps us_kbd
Tammo Spalink8fab5312012-05-28 18:33:30 +0800127 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800128
Tammo Spalink5c699832012-07-03 17:50:39 +0800129 map(hwid_tool.Validate.Status, options.status)
Tammo Spalink95c43732012-07-25 15:57:14 -0700130 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Tammo Spalink5c699832012-07-03 17:50:39 +0800131 comp_db = hw_db.comp_db
Tammo Spalink3a7e9022012-06-27 14:08:40 +0800132 device = hw_db.GetDevice(options.board)
Tammo Spalink5c699832012-07-03 17:50:39 +0800133 component_spec = hwid_tool.ComponentSpec.New()
Tammo Spalink8fab5312012-05-28 18:33:30 +0800134 if options.bom:
Tammo Spalink5c699832012-07-03 17:50:39 +0800135 device.BomExists(options.bom)
Tammo Spalink01e11722012-07-24 10:17:54 -0700136 component_spec = hwid_tool.CombineComponentSpecs(
Tammo Spalink5c699832012-07-03 17:50:39 +0800137 component_spec, device.boms[options.bom].primary)
Tammo Spalink8fab5312012-05-28 18:33:30 +0800138 if options.variant:
Tammo Spalink5c699832012-07-03 17:50:39 +0800139 device.VariantExists(options.variant)
140 variant_spec = device.variants[options.variant]
Tammo Spalink01e11722012-07-24 10:17:54 -0700141 if hwid_tool.ComponentSpecsConflict(component_spec, variant_spec):
Tammo Spalink95c43732012-07-25 15:57:14 -0700142 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700143 % YamlWrite(sorted(
144 hwid_tool.ComponentSpecClasses(component_spec) &
145 hwid_tool.ComponentSpecClasses(variant_spec))))
Tammo Spalink01e11722012-07-24 10:17:54 -0700146 component_spec = hwid_tool.CombineComponentSpecs(
147 component_spec, variant_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700148 if options.comps or options.missing:
149 map(comp_db.CompExists, options.comps)
150 map(comp_db.CompClassExists, options.missing)
151 extra_comp_spec = comp_db.CreateComponentSpec(
152 components=options.comps,
153 missing=options.missing)
154 print 'cmdline asserted components:\n%s' % extra_comp_spec.Encode()
155 if hwid_tool.ComponentSpecsConflict(component_spec, extra_comp_spec):
156 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700157 % YamlWrite(sorted(
158 hwid_tool.ComponentSpecClasses(component_spec) &
159 hwid_tool.ComponentSpecClasses(extra_comp_spec))))
Tammo Spalink95c43732012-07-25 15:57:14 -0700160 component_spec = hwid_tool.CombineComponentSpecs(
161 component_spec, extra_comp_spec)
Tammo Spalink01e11722012-07-24 10:17:54 -0700162 spec_classes = hwid_tool.ComponentSpecClasses(component_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700163 missing_classes = set(comp_db.all_comp_classes) - spec_classes
Tammo Spalink5c699832012-07-03 17:50:39 +0800164 if missing_classes and not options.optimistic:
Andy Cheng8ece7382012-08-22 16:25:42 +0800165 non_probeable_missing = missing_classes - PROBEABLE_COMPONENT_CLASSES
166 if non_probeable_missing:
Tammo Spalink95c43732012-07-25 15:57:14 -0700167 sys.exit('FAILURE: these classes are necessary, were not specified '
Tammo Spalink70b48a52012-08-08 16:54:51 -0700168 'as inputs, and cannot be probed for:\n%s'
169 'This problem can often be addressed by specifying all of '
170 'the missing components on the command line (see the command '
Andy Cheng8ece7382012-08-22 16:25:42 +0800171 'help).' % YamlWrite(list(non_probeable_missing)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700172 print 'probing for missing classes:'
173 print YamlWrite(list(missing_classes))
174 probe_results = Probe(target_comp_classes=list(missing_classes),
175 probe_volatile=False, probe_initial_config=False)
176 cooked_components = comp_db.MatchComponentProbeValues(
177 probe_results.found_probe_value_map)
178 if cooked_components.unmatched:
179 sys.exit('ERROR: some probed components are unrecognized:\n%s'
180 % YamlWrite(cooked_components.unmatched))
181 probed_comp_spec = comp_db.CreateComponentSpec(
182 components=cooked_components.matched,
183 missing=probe_results.missing_component_classes)
184 component_spec = hwid_tool.CombineComponentSpecs(
185 component_spec, probed_comp_spec)
186 print YamlWrite({'component data used for matching': {
187 'missing component classes': component_spec.classes_missing,
188 'found components': component_spec.components}})
189 component_data = hwid_tool.ComponentData(
190 extant_components=hwid_tool.ComponentSpecCompClassMap(
191 component_spec).keys(),
192 classes_missing=component_spec.classes_missing)
193 match_tree = device.BuildMatchTree(component_data)
194 if not match_tree:
195 sys.exit('FAILURE: NO matching BOMs found')
196 print 'potential BOMs/VARIANTs:'
197 potential_variants = set()
198 potential_volatiles = set()
199 for bom_name, variant_tree in match_tree.items():
200 print ' BOM: %-8s VARIANTS: %s' % (
201 bom_name, ', '.join(sorted(variant_tree)))
202 for variant_code in variant_tree:
203 potential_variants.add(variant_code)
204 for volatile_code in device.volatiles:
205 status = device.GetHwidStatus(bom_name, variant_code, volatile_code)
206 if status in options.status:
207 potential_volatiles.add(volatile_code)
208 print ''
209 if len(potential_variants) == 0:
210 sys.exit('FAILURE: no matching VARIANTs found')
211 if len(potential_volatiles) == 0:
212 sys.exit('FAILURE: no VOLATILEs found for potential matching BOMs/VARIANTS '
213 '(with specified status)')
Tammo Spalink394e4492012-08-01 10:20:30 -0700214 if (options.optimistic and
215 len(match_tree) == 1 and
216 len(potential_variants) == 1 and
217 len(potential_volatiles) == 1):
218 print ('MATCHING HWID: %s' % device.FmtHwid(match_tree.keys().pop(),
219 potential_variants.pop(),
220 potential_volatiles.pop()))
Tammo Spalink5c699832012-07-03 17:50:39 +0800221 return
Tammo Spalink95c43732012-07-25 15:57:14 -0700222 print ('probing VOLATILEs to resolve potential matches: %s\n' %
223 ', '.join(sorted(potential_volatiles)))
224 vol_probe_results = Probe(
225 target_comp_classes=[],
226 probe_volatile=True,
227 probe_initial_config=False)
228 cooked_volatiles = device.MatchVolatileValues(
229 vol_probe_results.found_volatile_values)
230 match_tree = device.BuildMatchTree(
231 component_data, cooked_volatiles.matched_tags)
232 matched_hwids = device.GetMatchTreeHwids(match_tree)
233 if matched_hwids:
234 for hwid in matched_hwids:
Ricky Liang02f3bd72012-09-21 14:33:01 +0800235 if matched_hwids[hwid] in options.status:
236 print 'MATCHING HWID: %s' % hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700237 return
238 print 'exact HWID matching failed, but the following BOMs match: %s' % (
239 ', '.join(sorted(match_tree)))
240 if options.optimistic and len(match_tree) == 1:
241 bom_name = set(match_tree).pop()
Tammo Spalink5c699832012-07-03 17:50:39 +0800242 bom = device.boms[bom_name]
Tammo Spalink95c43732012-07-25 15:57:14 -0700243 variant_matches = match_tree[bom_name]
Tammo Spalink5c699832012-07-03 17:50:39 +0800244 if len(variant_matches) == 1:
245 var_code = set(variant_matches).pop()
246 elif len(bom.variants) == 1:
247 var_code = set(bom.variants).pop()
248 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700249 sys.exit('FAILURE: NO matching HWIDs found; optimistic matching failed '
250 'because there were too many variants to choose from for BOM %r'
251 % bom_name)
252 hwids = [device.FmtHwid(bom_name, var_code, vol_code)
253 for vol_code in device.volatiles
254 if device.GetHwidStatus(bom_name, var_code, vol_code)
255 in options.status]
256 for hwid in hwids:
257 print 'MATCHING HWID: %s' % hwid
Tammo Spalink5c699832012-07-03 17:50:39 +0800258 return
259 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700260 print ('optimistic matching not attempted because either it was '
261 'not requested, or because the number of BOMs was <> 1\n')
262 sys.exit('FAILURE: NO matching HWIDs found')
Tammo Spalink8fab5312012-05-28 18:33:30 +0800263
264
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800265@Command('probe',
266 CmdArg('--comps', nargs='*',
267 help='List of keys from the component_db registry.'),
268 CmdArg('--no_vol', action='store_true',
269 help='Do not probe volatile data.'),
270 CmdArg('--no_ic', action='store_true',
Jon Salz0f8a6842012-09-25 11:28:22 +0800271 help='Do not probe initial_config data.'),
272 CmdArg('--include_vpd', action='store_true',
273 help='Include VPD data in volatiles.'))
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800274def RunProbe(options):
275 """Print yaml-formatted breakdown of probed device properties."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800276
Tammo Spalink01e11722012-07-24 10:17:54 -0700277 probe_results = Probe(target_comp_classes=options.comps,
Jon Salz0f8a6842012-09-25 11:28:22 +0800278 probe_volatile=not options.no_vol,
279 probe_initial_config=not options.no_ic,
280 probe_vpd=options.include_vpd)
Tammo Spalink3a7e9022012-06-27 14:08:40 +0800281 print probe_results.Encode()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800282
283
Tammo Spalink214caf42012-05-28 10:45:00 +0800284@Command('verify_components',
285 _hwdb_path_cmd_arg,
Tammo Spalink5c699832012-07-03 17:50:39 +0800286 CmdArg('target_comps', nargs='*'))
Tammo Spalink214caf42012-05-28 10:45:00 +0800287def VerifyComponents(options):
Andy Cheng8ece7382012-08-22 16:25:42 +0800288 """Verify that probeable components all match entries in the component_db.
Tammo Spalink214caf42012-05-28 10:45:00 +0800289
Tammo Spalink5c699832012-07-03 17:50:39 +0800290 Probe for each component class in the target_comps and verify
Tammo Spalink214caf42012-05-28 10:45:00 +0800291 that a corresponding match exists in the component_db -- make sure
292 that these components are present, that they have been approved, but
293 do not check against any specific BOM/HWID configurations.
294 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800295
Tammo Spalink5c699832012-07-03 17:50:39 +0800296 comp_db = hwid_tool.HardwareDb(options.hwdb_path).comp_db
Andy Chengc531e2f2012-10-15 19:09:17 +0800297 try:
298 result = Gooftool(component_db=comp_db).VerifyComponents(
299 options.target_comps)
300 except ValueError, e:
301 sys.exit(e)
302
303 # group by matches and errors
Tammo Spalink214caf42012-05-28 10:45:00 +0800304 matches = []
Andy Chengc531e2f2012-10-15 19:09:17 +0800305 errors = []
306 for result_list in result.values():
307 for component_name, _, error in result_list:
308 if component_name:
309 matches.append(component_name)
Tammo Spalink214caf42012-05-28 10:45:00 +0800310 else:
Andy Chengc531e2f2012-10-15 19:09:17 +0800311 errors.append(error)
312
Andy Cheng228a8c92012-08-27 10:53:57 +0800313 if matches:
314 print 'found probeable components:\n %s' % '\n '.join(matches)
Tammo Spalink214caf42012-05-28 10:45:00 +0800315 if errors:
Andy Cheng228a8c92012-08-27 10:53:57 +0800316 print '\nerrors:\n %s' % '\n '.join(errors)
317 sys.exit('\ncomponent verification FAILURE')
Tammo Spalink214caf42012-05-28 10:45:00 +0800318 else:
Andy Cheng228a8c92012-08-27 10:53:57 +0800319 print "\ncomponent verification SUCCESS"
Tammo Spalink214caf42012-05-28 10:45:00 +0800320
321
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800322@Command('verify_hwid',
Tammo Spalink95c43732012-07-25 15:57:14 -0700323 _hwid_status_list_cmd_arg,
Jon Salz0f8a6842012-09-25 11:28:22 +0800324 _hwdb_path_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800325 _probe_results_cmd_arg,
326 _hwid_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800327def VerifyHwid(options):
328 """Verify system HWID properties match probed device properties.
329
330 First probe components, volatile and initial_config parameters for
331 the DUT. Then use the available device data to produce a list of
332 candidate HWIDs. Then verify the HWID from the DUT is present in
333 that list. Then verify that the DUT initial config values match
334 those specified for its HWID. Finally, verify that VPD contains all
335 the necessary fields as specified by the board data, and when
336 possible verify that values are legitimate.
337 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800338
Ricky Liangf7857c12012-09-17 13:34:41 +0800339 def VerifyVpd(ro_vpd_keys, rw_vpd_keys):
Tammo Spalink5c699832012-07-03 17:50:39 +0800340 for key in ro_vpd_keys:
341 if key not in ro_vpd:
Ricky Liangf7857c12012-09-17 13:34:41 +0800342 sys.exit('Missing required RO VPD field: %s' % key)
Tammo Spalink01e11722012-07-24 10:17:54 -0700343 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800344 value = ro_vpd[key]
Ricky Liangf7857c12012-09-17 13:34:41 +0800345 if (known_valid_values is not None) and (value not in known_valid_values):
346 sys.exit('Invalid RO VPD entry : key %r, value %r' % (key, value))
Ricky Liangf7857c12012-09-17 13:34:41 +0800347 for key in rw_vpd_keys:
348 if key not in rw_vpd:
349 sys.exit('Missing required RW VPD field: %s' % key)
350 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
351 value = rw_vpd[key]
352 if (known_valid_values is not None) and (value not in known_valid_values):
353 sys.exit('Invalid RW VPD entry : key %r, value %r' % (key, value))
Jon Salz05aba9d2012-10-05 17:25:38 +0800354 _event_log.Log('vpd', ro_vpd=FilterVPD(ro_vpd), rw_vpd=FilterVPD(rw_vpd))
Tammo Spalink5c699832012-07-03 17:50:39 +0800355 map(hwid_tool.Validate.Status, options.status)
Jon Salz0f8a6842012-09-25 11:28:22 +0800356
Jon Salz81350812012-10-11 16:13:22 +0800357 if not options.hwid or not options.probe_results:
358 main_fw_file = crosfw.LoadMainFirmware().GetFileName()
Jon Salz0f8a6842012-09-25 11:28:22 +0800359
360 if options.hwid:
361 hwid_str = options.hwid
362 else:
363 gbb_result = Shell('gbb_utility -g --hwid %s' % main_fw_file).stdout
364 hwid_str = re.findall(r'hardware_id:(.*)', gbb_result)[0].strip()
Tammo Spalink95c43732012-07-25 15:57:14 -0700365 hwid = hwid_tool.ParseHwid(hwid_str)
Tammo Spalink5c699832012-07-03 17:50:39 +0800366 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Jon Salz0f8a6842012-09-25 11:28:22 +0800367 print 'Verifying HWID: %r\n' % hwid.hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700368 device = hw_db.GetDevice(hwid.board)
369 hwid_status = device.GetHwidStatus(hwid.bom, hwid.variant, hwid.volatile)
370 if hwid_status not in options.status:
Tammo Spalink5c699832012-07-03 17:50:39 +0800371 sys.exit('HWID status must be one of [%s], found %r' %
Hung-Te Lin4f5beb12012-08-20 14:48:06 +0800372 (', '.join(options.status), hwid_status))
Jon Salz0f8a6842012-09-25 11:28:22 +0800373 if options.probe_results:
374 # Pull in probe results (including VPD data) from the given file
375 # rather than probing the current system.
376 probe_results = hwid_tool.ProbeResults.Decode(
377 open(options.probe_results).read())
378 ro_vpd = {}
379 rw_vpd = {}
380 for k, v in probe_results.found_volatile_values.items():
381 match = re.match('^vpd\.(ro|rw)\.(\w+)$', k)
382 if match:
383 del probe_results.found_volatile_values[k]
384 (ro_vpd if match.group(1) == 'ro' else rw_vpd)[match.group(2)] = v
385 else:
386 probe_results = Probe()
387 ro_vpd = ReadRoVpd(main_fw_file)
388 rw_vpd = ReadRwVpd(main_fw_file)
Tammo Spalink95c43732012-07-25 15:57:14 -0700389 cooked_components = hw_db.comp_db.MatchComponentProbeValues(
390 probe_results.found_probe_value_map)
391 cooked_volatiles = device.MatchVolatileValues(
392 probe_results.found_volatile_values)
393 cooked_initial_configs = device.MatchInitialConfigValues(
394 probe_results.initial_configs)
395 component_data = hwid_tool.ComponentData(
396 extant_components=cooked_components.matched,
397 classes_missing=probe_results.missing_component_classes)
398 match_tree = device.BuildMatchTree(
399 component_data, cooked_volatiles.matched_tags)
400 matched_hwids = device.GetMatchTreeHwids(match_tree)
401 print 'HWID status: %s\n' % hwid_status
402 print 'probed system components:'
403 print YamlWrite(cooked_components.__dict__)
404 print 'missing component classes:'
405 print YamlWrite(probe_results.missing_component_classes)
406 print 'probed volatiles:'
407 print YamlWrite(cooked_volatiles.__dict__)
408 print 'probed initial_configs:'
409 print YamlWrite(cooked_initial_configs)
410 print 'hwid match tree:'
411 print YamlWrite(match_tree)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800412 _event_log.Log(
Tammo Spalink5c699832012-07-03 17:50:39 +0800413 'probe',
Tammo Spalink95c43732012-07-25 15:57:14 -0700414 found_components=cooked_components.__dict__,
415 missing_component_classes=probe_results.missing_component_classes,
416 volatiles=cooked_volatiles.__dict__,
417 initial_configs=cooked_initial_configs)
418 if hwid.hwid not in matched_hwids:
Tammo Spalink5c699832012-07-03 17:50:39 +0800419 err_msg = 'HWID verification FAILED.\n'
Tammo Spalink95c43732012-07-25 15:57:14 -0700420 if cooked_components.unmatched:
Tammo Spalink5c699832012-07-03 17:50:39 +0800421 sys.exit(err_msg + 'some components could not be indentified:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700422 YamlWrite(cooked_components.unmatched))
423 if not match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800424 sys.exit(err_msg + 'no matching boms were found for components:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700425 component_data.Encode())
426 if hwid.bom not in match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800427 sys.exit(err_msg + 'matching boms [%s] do not include target bom %r' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700428 (', '.join(sorted(match_tree)), hwid.bom))
429 err_msg += 'target bom %r matches components' % hwid.bom
430 if hwid.bom not in device.IntersectBomsAndInitialConfigs(
431 cooked_initial_configs):
Tammo Spalink5c699832012-07-03 17:50:39 +0800432 sys.exit(err_msg + ', but failed initial config verification')
Tammo Spalink95c43732012-07-25 15:57:14 -0700433 matched_variants = match_tree.get(hwid.bom, {})
434 if hwid.variant not in matched_variants:
Tammo Spalink5c699832012-07-03 17:50:39 +0800435 sys.exit(err_msg + ', but target variant_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700436 hwid.variant)
437 matched_volatiles = matched_variants.get(hwid.variant, {})
438 if hwid.volatile not in matched_volatiles:
Tammo Spalink5c699832012-07-03 17:50:39 +0800439 sys.exit(err_msg + ', but target volatile_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700440 hwid.volatile)
441 found_status = matched_volatiles.get(hwid.volatile, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800442 sys.exit(err_msg + ', but hwid status %r was unacceptable' % found_status)
Ricky Liangf7857c12012-09-17 13:34:41 +0800443 VerifyVpd(device.vpd_ro_fields, device.vpd_rw_fields)
Tammo Spalink5c699832012-07-03 17:50:39 +0800444 _event_log.Log('verified_hwid', hwid=hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -0700445 print 'Verification SUCCESS!'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800446
447
448@Command('verify_keys')
Tammo Spalink01e11722012-07-24 10:17:54 -0700449def VerifyKeys(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800450 """Verify keys in firmware and SSD match."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800451
452 return Gooftool().VerifyKeys()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800453
454
455@Command('set_fw_bitmap_locale')
Tammo Spalink01e11722012-07-24 10:17:54 -0700456def SetFirmwareBitmapLocale(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800457 """Use VPD locale value to set firmware bitmap default language."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800458
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800459 image_file = crosfw.LoadMainFirmware().GetFileName()
460 locale = ReadRoVpd(image_file).get('initial_locale', None)
461 if locale is None:
462 raise Error, 'Missing initial_locale VPD.'
463 bitmap_locales = []
464 with NamedTemporaryFile() as f:
465 Shell('gbb_utility -g --bmpfv=%s %s' % (f.name, image_file))
Tammo Spalink01e11722012-07-24 10:17:54 -0700466 bmpblk_data = unpack_bmpblock(f.read())
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800467 bitmap_locales = bmpblk_data.get('locales', bitmap_locales)
468 # Some locale values are just a language code and others are a
469 # hyphen-separated language code and country code pair. We care
470 # only about the language code part.
471 language_code = locale.partition('-')[0]
472 if language_code not in bitmap_locales:
473 raise Error, ('Firmware bitmaps do not contain support for the specified '
474 'initial locale language %r' % language_code)
475 else:
476 locale_index = bitmap_locales.index(language_code)
477 logging.info('Firmware bitmap initial locale set to %d (%s).',
478 locale_index, bitmap_locales[locale_index])
479 Shell('crossystem loc_idx=%d' % locale_index)
480
481
482@Command('verify_system_time')
Tammo Spalink01e11722012-07-24 10:17:54 -0700483def VerifySystemTime(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800484 """Verify system time is later than release filesystem creation time."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800485
486 return Gooftool().VerifySystemTime()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800487
488
489@Command('verify_rootfs')
Tammo Spalink01e11722012-07-24 10:17:54 -0700490def VerifyRootFs(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800491 """Verify rootfs on SSD is valid by checking hash."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800492
493 return Gooftool().VerifyRootFs()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800494
495
496@Command('verify_switch_wp')
Tammo Spalink01e11722012-07-24 10:17:54 -0700497def VerifyWpSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800498 """Verify hardware write protection switch is enabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800499
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800500 if Shell('crossystem wpsw_cur').stdout.strip() != '1':
Hung-Te Lin6d827542012-07-19 11:50:41 +0800501 raise Error, 'write protection switch is disabled'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800502
503
504@Command('verify_switch_dev')
Tammo Spalink01e11722012-07-24 10:17:54 -0700505def VerifyDevSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800506 """Verify developer switch is disabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800507
Hung-Te Lind7d34722012-07-26 16:48:35 +0800508 VBSD_HONOR_VIRT_DEV_SWITCH = 0x400
509 flags = int(Shell('crossystem vdat_flags').stdout.strip(), 0)
510 if (flags & VBSD_HONOR_VIRT_DEV_SWITCH) != 0:
511 # System is using virtual developer switch. That will be handled in
512 # prepare_wipe.sh by setting "crossystem disable_dev_request=1" -- although
513 # we can't verify that until next reboot, because the real values are stored
514 # in TPM.
515 logging.warn('VerifyDevSwitch: No physical switch.')
516 _event_log.Log('switch_dev', type='virtual switch')
517 return
518 if Shell('crossystem devsw_cur').stdout.strip() != '0':
519 raise Error, 'developer mode is not disabled'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800520
521
522@Command('write_protect')
Tammo Spalink01e11722012-07-24 10:17:54 -0700523def EnableFwWp(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800524 """Enable then verify firmware write protection."""
525
Hung-Te Linb21c6682012-08-01 13:53:57 +0800526 def CalculateLegacyRange(fw_type, length, section_data,
527 section_name):
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800528 ro_size = length / 2
529 ro_a = int(section_data[0] / ro_size)
530 ro_b = int((section_data[0] + section_data[1] - 1) / ro_size)
531 if ro_a != ro_b:
532 raise Error("%s firmware section %s has illegal size" %
Hung-Te Linb21c6682012-08-01 13:53:57 +0800533 (fw_type, section_name))
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800534 ro_offset = ro_a * ro_size
535 return (ro_offset, ro_size)
536
537 def WriteProtect(fw_file_path, fw_type, legacy_section):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800538 """Calculate protection size, then invoke flashrom.
539
540 Our supported chips only allow write protecting half their total
541 size, so we parition the flash chipset space accordingly.
542 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800543
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800544 raw_image = open(fw_file_path, 'rb').read()
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800545 wp_section = 'WP_RO'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800546 image = crosfw.FirmwareImage(raw_image)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800547 if image.has_section(wp_section):
548 section_data = image.get_section_area(wp_section)
549 ro_offset = section_data[0]
550 ro_size = section_data[1]
551 elif image.has_section(legacy_section):
552 section_data = image.get_section_area(legacy_section)
553 (ro_offset, ro_size) = CalculateLegacyRange(
Hung-Te Linb21c6682012-08-01 13:53:57 +0800554 fw_type, len(raw_image), section_data, legacy_section)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800555 else:
556 raise Error('could not find %s firmware section %s or %s' %
557 (fw_type, wp_section, legacy_section))
558
559 logging.debug('write protecting %s [off=%x size=%x]', fw_type,
560 ro_offset, ro_size)
561 crosfw.Flashrom(fw_type).EnableWriteProtection(ro_offset, ro_size)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800562
563 WriteProtect(crosfw.LoadMainFirmware().GetFileName(), 'main', 'RO_SECTION')
Tammo Spalink86a61c62012-05-25 15:10:35 +0800564 _event_log.Log('wp', fw='main')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800565 ec_fw_file = crosfw.LoadEcFirmware().GetFileName()
566 if ec_fw_file is not None:
567 WriteProtect(ec_fw_file, 'ec', 'EC_RO')
Tammo Spalink86a61c62012-05-25 15:10:35 +0800568 _event_log.Log('wp', fw='ec')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800569 else:
570 logging.warning('EC not write protected (seems there is no EC flash).')
571
572
573@Command('clear_gbb_flags')
Tammo Spalink01e11722012-07-24 10:17:54 -0700574def ClearGbbFlags(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800575 """Zero out the GBB flags, in preparation for transition to release state.
576
577 No GBB flags are set in release/shipping state, but they are useful
578 for factory/development. See "gbb_utility --flags" for details.
579 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800580
581 Gooftool().ClearGbbFlags()
Tammo Spalink86a61c62012-05-25 15:10:35 +0800582 _event_log.Log('clear_gbb_flags')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800583
584
585@Command('prepare_wipe',
586 CmdArg('--fast', action='store_true',
587 help='use non-secure but faster wipe method.'))
588def PrepareWipe(options):
589 """Prepare system for transition to release state in next reboot."""
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800590
Andy Cheng7a76cb82012-11-19 18:08:19 +0800591 Gooftool().PrepareWipe(options.fast)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800592
593@Command('verify',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800594 CmdArg('--no_write_protect', action='store_true',
595 help='Do not check write protection switch state.'),
Tammo Spalink95c43732012-07-25 15:57:14 -0700596 _hwid_status_list_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800597 _hwdb_path_cmd_arg,
598 _probe_results_cmd_arg,
599 _hwid_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800600def Verify(options):
601 """Verifies if whole factory process is ready for finalization.
602
603 This routine performs all the necessary checks to make sure the
604 device is ready to be finalized, but does not modify state. These
605 checks include dev switch, firmware write protection switch, hwid,
606 system time, keys, and root file system.
607 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800608
Hung-Te Lin6d827542012-07-19 11:50:41 +0800609 if not options.no_write_protect:
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800610 VerifyWpSwitch({})
Hung-Te Lin6d827542012-07-19 11:50:41 +0800611 VerifyDevSwitch({})
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800612 VerifyHwid(options)
613 VerifySystemTime({})
614 VerifyKeys({})
615 VerifyRootFs({})
616
617
Tammo Spalink86a61c62012-05-25 15:10:35 +0800618@Command('log_system_details')
Tammo Spalink01e11722012-07-24 10:17:54 -0700619def LogSystemDetails(options): # pylint: disable=W0613
Tammo Spalink86a61c62012-05-25 15:10:35 +0800620 """Write miscellaneous system details to the event log."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800621
Tammo Spalink86a61c62012-05-25 15:10:35 +0800622 raw_cs_data = Shell('crossystem').stdout.strip().splitlines()
623 # The crossytem output contains many lines like:
624 # 'key = value # description'
625 # Use regexps to pull out the key-value pairs and build a dict.
626 cs_data = dict((k, v.strip()) for k, v in
627 map(lambda x: re.findall(r'\A(\S+)\s+=\s+(.*)#.*\Z', x)[0],
628 raw_cs_data))
629 _event_log.Log(
630 'system_details',
631 platform_name=Shell('mosys platform name').stdout.strip(),
632 crossystem=cs_data,
633 modem_status=Shell('modem status').stdout.splitlines(),
634 ec_wp_status=Shell(
635 'flashrom -p internal:bus=lpc --get-size 2>/dev/null && '
636 'flashrom -p internal:bus=lpc --wp-status || '
637 'echo "EC is not available."').stdout,
638 bios_wp_status = Shell(
639 'flashrom -p internal:bus=spi --wp-status').stdout)
640
641
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800642_upload_method_cmd_arg = CmdArg(
643 '--upload_method', metavar='METHOD:PARAM',
644 help=('How to perform the upload. METHOD should be one of '
cychiang3b15bd52012-09-08 13:58:18 +0800645 '{ftp, shopfloor, ftps, cpfe}.'))
Jon Salz65266432012-07-30 19:02:49 +0800646_add_file_cmd_arg = CmdArg(
647 '--add_file', metavar='FILE', action='append',
648 help='Extra file to include in report (must be an absolute path)')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800649
650@Command('upload_report',
Jon Salz65266432012-07-30 19:02:49 +0800651 _upload_method_cmd_arg,
652 _add_file_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800653def UploadReport(options):
654 """Create and a report containing key device details."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800655
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800656 def NormalizeAsFileName(token):
657 return re.sub(r'\W+', '', token).strip()
Tammo Spalink86a61c62012-05-25 15:10:35 +0800658 ro_vpd = ReadRoVpd(crosfw.LoadMainFirmware().GetFileName())
659 device_sn = ro_vpd.get('serial_number', None)
660 if device_sn is None:
661 logging.warning('RO_VPD missing device serial number')
662 device_sn = 'MISSING_SN_' + TimedUuid()
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800663 target_name = '%s_%s.tbz2' % (time.strftime('%Y%m%dT%H%M%SZ', time.gmtime()),
664 NormalizeAsFileName(device_sn))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800665 target_path = os.path.join(gettempdir(), target_name)
666 # Intentionally ignoring dotfiles in EVENT_LOG_DIR.
667 tar_cmd = 'cd %s ; tar cjf %s *' % (EVENT_LOG_DIR, target_path)
668 tar_cmd += ' --add-file %s' % FACTORY_LOG_PATH
Jon Salz65266432012-07-30 19:02:49 +0800669 if options.add_file:
670 for f in options.add_file:
671 # Require absolute paths since the tar command may change the
672 # directory.
673 if not f.startswith('/'):
674 raise Error('Not an absolute path: %s' % f)
675 if not os.path.exists(f):
676 raise Error('File does not exist: %s' % f)
677 tar_cmd += ' --add-file %s' % pipes.quote(f)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800678 cmd_result = Shell(tar_cmd)
Jon Salzff88c022012-11-03 12:19:58 +0800679
680 if ((cmd_result.status == 1) and
681 all((x == '' or
682 'file changed as we read it' in x or
683 "Removing leading `/' from member names" in x)
684 for x in cmd_result.stderr.split('\n'))):
685 # That's OK. Make sure it's valid though.
686 Spawn(['tar', 'tfj', target_path], check_call=True, log=True,
687 ignore_stdout=True)
688 elif not cmd_result.success:
Tammo Spalink86a61c62012-05-25 15:10:35 +0800689 raise Error('unable to tar event logs, cmd %r failed, stderr: %r' %
690 (tar_cmd, cmd_result.stderr))
Jon Salzff88c022012-11-03 12:19:58 +0800691
Tammo Spalink86a61c62012-05-25 15:10:35 +0800692 if options.upload_method is None or options.upload_method == 'none':
693 logging.warning('REPORT UPLOAD SKIPPED (report left at %s)', target_path)
694 return
695 method, param = options.upload_method.split(':', 1)
696 if method == 'shopfloor':
697 report_upload.ShopFloorUpload(target_path, param)
698 elif method == 'ftp':
Jay Kim360c1dd2012-06-25 10:58:11 -0700699 report_upload.FtpUpload(target_path, 'ftp:' + param)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800700 elif method == 'ftps':
701 report_upload.CurlUrlUpload(target_path, '--ftp-ssl-reqd ftp:%s' % param)
702 elif method == 'cpfe':
703 report_upload.CpfeUpload(target_path, param)
704 else:
705 raise Error('unknown report upload method %r', method)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800706
707
708@Command('finalize',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800709 CmdArg('--no_write_protect', action='store_true',
710 help='Do not enable firmware write protection.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800711 CmdArg('--fast', action='store_true',
712 help='use non-secure but faster wipe method.'),
713 _hwdb_path_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700714 _hwid_status_list_cmd_arg,
Jon Salz65266432012-07-30 19:02:49 +0800715 _upload_method_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800716 _add_file_cmd_arg,
717 _probe_results_cmd_arg,
718 _hwid_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800719def Finalize(options):
720 """Verify system readiness and trigger transition into release state.
721
Hung-Te Lin6d827542012-07-19 11:50:41 +0800722 This routine first verifies system state (see verify command), modifies
723 firmware bitmaps to match locale, and then clears all of the factory-friendly
724 flags from the GBB. If everything is fine, it enables firmware write
725 protection (cannot rollback after this stage), uploads system logs & reports,
726 and sets the necessary boot flags to cause wipe of the factory image on the
727 next boot.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800728 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800729
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800730 Verify(options)
731 SetFirmwareBitmapLocale({})
Hung-Te Lin6d827542012-07-19 11:50:41 +0800732 ClearGbbFlags({})
733 if options.no_write_protect:
734 logging.warn('WARNING: Firmware Write Protection is SKIPPED.')
735 _event_log.Log('wp', fw='both', status='skipped')
736 else:
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800737 EnableFwWp({})
Jon Salza0f58e02012-05-29 19:33:39 +0800738 LogSystemDetails(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800739 UploadReport(options)
740 PrepareWipe(options)
741
742
743def Main():
744 """Run sub-command specified by the command line args."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800745
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800746 options = ParseCmdline(
747 'Perform Google required factory tests.',
748 CmdArg('-l', '--log', metavar='PATH',
749 help='Write logs to this file.'),
Jon Salza4bea382012-10-29 13:00:34 +0800750 CmdArg('--suppress-event-logs', action='store_true',
751 help='Suppress event logging.'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800752 verbosity_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800753 SetupLogging(options.verbosity, options.log)
Jon Salza4bea382012-10-29 13:00:34 +0800754 _event_log.suppress = options.suppress_event_logs
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800755 logging.debug('gooftool options: %s', repr(options))
756 try:
757 logging.debug('GOOFTOOL command %r', options.command_name)
758 options.command(options)
759 logging.info('GOOFTOOL command %r SUCCESS', options.command_name)
760 except Error, e:
761 logging.exception(e)
762 sys.exit('GOOFTOOL command %r ERROR: %s' % (options.command_name, e))
763 except Exception, e:
764 logging.exception(e)
765 sys.exit('UNCAUGHT RUNTIME EXCEPTION %s' % e)
766
767
768if __name__ == '__main__':
769 Main()