blob: a02f62808f1bc9c9fd67d1bb4cbc70fc0554d450 [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
Tammo Spalink86a61c62012-05-25 15:10:35 +080041
Tammo Spalink5c699832012-07-03 17:50:39 +080042
Tammo Spalink86a61c62012-05-25 15:10:35 +080043# Use a global event log, so that only a single log is created when
44# gooftool is called programmatically.
45_event_log = EventLog('gooftool')
46
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080047
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080048def FindScript(script_name):
Hung-Te Linb7313ca2012-07-31 15:27:57 +080049 # __file__ is in /usr/local/factory/py/gooftool/gooftool.py
50 # scripts should be in /usr/local/factory/sh/*
51 factory_base = os.path.realpath(os.path.join(
52 os.path.dirname(os.path.realpath(__file__)), '..', '..'))
53 script_path = os.path.join(factory_base, 'sh', script_name)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080054 if not os.path.exists(script_path):
55 raise Error('Needed script %s does not exist.' % script_path)
56 return script_path
57
58
Tammo Spalink5c699832012-07-03 17:50:39 +080059# TODO(tammo): Replace calls to sys.exit with raise Exit, and maybe
60# treat that specially (as a smoot exit, as opposed to the more
61# verbose output for generic Error).
62
63
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080064@Command('write_hwid',
65 CmdArg('hwid', metavar='HWID', help='HWID string'))
66def WriteHwid(options):
67 """Write specified HWID value into the system BB."""
Tammo Spalink95c43732012-07-25 15:57:14 -070068 logging.info('writing hwid string %r', options.hwid)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080069 main_fw = crosfw.LoadMainFirmware()
70 Shell('gbb_utility --set --hwid="%s" "%s"' %
71 (options.hwid, main_fw.GetFileName()))
72 main_fw.Write(sections=['GBB'])
Tammo Spalink86a61c62012-05-25 15:10:35 +080073 _event_log.Log('write_hwid', hwid=options.hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -070074 print 'Wrote HWID: %r' % options.hwid
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080075
76
Tammo Spalink8fab5312012-05-28 18:33:30 +080077_hwdb_path_cmd_arg = CmdArg(
78 '--hwdb_path', metavar='PATH',
79 default=hwid_tool.DEFAULT_HWID_DATA_PATH,
80 help='Path to the HWID database.')
81
Tammo Spalink95c43732012-07-25 15:57:14 -070082_hwid_status_list_cmd_arg = CmdArg(
83 '--status', nargs='*', default=['supported'],
84 help='allow only HWIDs with these status values')
85
Jon Salzce124fb2012-10-02 17:42:03 +080086_probe_results_cmd_arg = CmdArg(
87 '--probe_results', metavar='RESULTS.yaml',
88 help=('Output from "gooftool probe" (used instead of '
89 'probing this system).'))
90
91_hwid_cmd_arg = CmdArg(
92 '--hwid', metavar='HWID',
93 help=('HWID to verify (instead of the currently set HWID of '
94 'this system)'))
95
Tammo Spalink95c43732012-07-25 15:57:14 -070096
97@Command('best_match_hwids',
Tammo Spalink8fab5312012-05-28 18:33:30 +080098 _hwdb_path_cmd_arg,
99 CmdArg('-b', '--board', metavar='BOARD',
Tammo Spalink95c43732012-07-25 15:57:14 -0700100 help='optional BOARD name, needed only if data is present '
101 'for more than one'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800102 CmdArg('--bom', metavar='BOM', help='BOM name'),
103 CmdArg('--variant', metavar='VARIANT', help='VARIANT code'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800104 CmdArg('--optimistic', action='store_true',
105 help='do not probe; assume singletons match'),
Tammo Spalink95c43732012-07-25 15:57:14 -0700106 CmdArg('--comps', nargs='*', default=[],
107 help='list of canonical component names'),
108 CmdArg('--missing', nargs='*', default=[],
109 help='list component classes to be assumed missing'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800110 CmdArg('--status', nargs='*', default=['supported'],
Tammo Spalink95c43732012-07-25 15:57:14 -0700111 help='consider only HWIDs within this list of status values'))
112def BestMatchHwids(options):
Tammo Spalink8fab5312012-05-28 18:33:30 +0800113 """Determine a list of possible HWIDs using provided args and probeing.
114
115 VOLATILE can always be determined by probing. To get a unique
116 result, VARIANT must be specified for all cases where the matching
117 BOM has more than one associated variant code, otherwise all HWID
118 variants will be returned. Both VARIANT and BOM information can
Tammo Spalink95c43732012-07-25 15:57:14 -0700119 alternatively be specified using the --stdin_comps argument, which
120 allows specifying a list of canonical names (one per line) on stdin,
121 one per line. Based on what is known from BOM and stdin_comps,
122 determine a list of components to probe for, and use those probe
123 results to resolve a list of matching HWIDs. If no boms,
124 components, or variant codes are specified, then a list of all HWIDs
Andy Cheng8ece7382012-08-22 16:25:42 +0800125 that match probeable components will be returned.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800126
127 Returns (on stdout): A list of HWIDs that match the available probe
128 results and argument contraints, one per line.
Tammo Spalink70b48a52012-08-08 16:54:51 -0700129
130 Example:
131
132 // Three ways to specify a keyboard (assuming it is a variant component)
133 gooftool best_match_hwids --missing keyboard
134 gooftool best_match_hwids --variant A or
135 gooftool best_match_hwids --comps us_kbd
Tammo Spalink8fab5312012-05-28 18:33:30 +0800136 """
Tammo Spalink5c699832012-07-03 17:50:39 +0800137 map(hwid_tool.Validate.Status, options.status)
Tammo Spalink95c43732012-07-25 15:57:14 -0700138 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Tammo Spalink5c699832012-07-03 17:50:39 +0800139 comp_db = hw_db.comp_db
Tammo Spalink3a7e9022012-06-27 14:08:40 +0800140 device = hw_db.GetDevice(options.board)
Tammo Spalink5c699832012-07-03 17:50:39 +0800141 component_spec = hwid_tool.ComponentSpec.New()
Tammo Spalink8fab5312012-05-28 18:33:30 +0800142 if options.bom:
Tammo Spalink5c699832012-07-03 17:50:39 +0800143 device.BomExists(options.bom)
Tammo Spalink01e11722012-07-24 10:17:54 -0700144 component_spec = hwid_tool.CombineComponentSpecs(
Tammo Spalink5c699832012-07-03 17:50:39 +0800145 component_spec, device.boms[options.bom].primary)
Tammo Spalink8fab5312012-05-28 18:33:30 +0800146 if options.variant:
Tammo Spalink5c699832012-07-03 17:50:39 +0800147 device.VariantExists(options.variant)
148 variant_spec = device.variants[options.variant]
Tammo Spalink01e11722012-07-24 10:17:54 -0700149 if hwid_tool.ComponentSpecsConflict(component_spec, variant_spec):
Tammo Spalink95c43732012-07-25 15:57:14 -0700150 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700151 % YamlWrite(sorted(
152 hwid_tool.ComponentSpecClasses(component_spec) &
153 hwid_tool.ComponentSpecClasses(variant_spec))))
Tammo Spalink01e11722012-07-24 10:17:54 -0700154 component_spec = hwid_tool.CombineComponentSpecs(
155 component_spec, variant_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700156 if options.comps or options.missing:
157 map(comp_db.CompExists, options.comps)
158 map(comp_db.CompClassExists, options.missing)
159 extra_comp_spec = comp_db.CreateComponentSpec(
160 components=options.comps,
161 missing=options.missing)
162 print 'cmdline asserted components:\n%s' % extra_comp_spec.Encode()
163 if hwid_tool.ComponentSpecsConflict(component_spec, extra_comp_spec):
164 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700165 % YamlWrite(sorted(
166 hwid_tool.ComponentSpecClasses(component_spec) &
167 hwid_tool.ComponentSpecClasses(extra_comp_spec))))
Tammo Spalink95c43732012-07-25 15:57:14 -0700168 component_spec = hwid_tool.CombineComponentSpecs(
169 component_spec, extra_comp_spec)
Tammo Spalink01e11722012-07-24 10:17:54 -0700170 spec_classes = hwid_tool.ComponentSpecClasses(component_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700171 missing_classes = set(comp_db.all_comp_classes) - spec_classes
Tammo Spalink5c699832012-07-03 17:50:39 +0800172 if missing_classes and not options.optimistic:
Andy Cheng8ece7382012-08-22 16:25:42 +0800173 non_probeable_missing = missing_classes - PROBEABLE_COMPONENT_CLASSES
174 if non_probeable_missing:
Tammo Spalink95c43732012-07-25 15:57:14 -0700175 sys.exit('FAILURE: these classes are necessary, were not specified '
Tammo Spalink70b48a52012-08-08 16:54:51 -0700176 'as inputs, and cannot be probed for:\n%s'
177 'This problem can often be addressed by specifying all of '
178 'the missing components on the command line (see the command '
Andy Cheng8ece7382012-08-22 16:25:42 +0800179 'help).' % YamlWrite(list(non_probeable_missing)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700180 print 'probing for missing classes:'
181 print YamlWrite(list(missing_classes))
182 probe_results = Probe(target_comp_classes=list(missing_classes),
183 probe_volatile=False, probe_initial_config=False)
184 cooked_components = comp_db.MatchComponentProbeValues(
185 probe_results.found_probe_value_map)
186 if cooked_components.unmatched:
187 sys.exit('ERROR: some probed components are unrecognized:\n%s'
188 % YamlWrite(cooked_components.unmatched))
189 probed_comp_spec = comp_db.CreateComponentSpec(
190 components=cooked_components.matched,
191 missing=probe_results.missing_component_classes)
192 component_spec = hwid_tool.CombineComponentSpecs(
193 component_spec, probed_comp_spec)
194 print YamlWrite({'component data used for matching': {
195 'missing component classes': component_spec.classes_missing,
196 'found components': component_spec.components}})
197 component_data = hwid_tool.ComponentData(
198 extant_components=hwid_tool.ComponentSpecCompClassMap(
199 component_spec).keys(),
200 classes_missing=component_spec.classes_missing)
201 match_tree = device.BuildMatchTree(component_data)
202 if not match_tree:
203 sys.exit('FAILURE: NO matching BOMs found')
204 print 'potential BOMs/VARIANTs:'
205 potential_variants = set()
206 potential_volatiles = set()
207 for bom_name, variant_tree in match_tree.items():
208 print ' BOM: %-8s VARIANTS: %s' % (
209 bom_name, ', '.join(sorted(variant_tree)))
210 for variant_code in variant_tree:
211 potential_variants.add(variant_code)
212 for volatile_code in device.volatiles:
213 status = device.GetHwidStatus(bom_name, variant_code, volatile_code)
214 if status in options.status:
215 potential_volatiles.add(volatile_code)
216 print ''
217 if len(potential_variants) == 0:
218 sys.exit('FAILURE: no matching VARIANTs found')
219 if len(potential_volatiles) == 0:
220 sys.exit('FAILURE: no VOLATILEs found for potential matching BOMs/VARIANTS '
221 '(with specified status)')
Tammo Spalink394e4492012-08-01 10:20:30 -0700222 if (options.optimistic and
223 len(match_tree) == 1 and
224 len(potential_variants) == 1 and
225 len(potential_volatiles) == 1):
226 print ('MATCHING HWID: %s' % device.FmtHwid(match_tree.keys().pop(),
227 potential_variants.pop(),
228 potential_volatiles.pop()))
Tammo Spalink5c699832012-07-03 17:50:39 +0800229 return
Tammo Spalink95c43732012-07-25 15:57:14 -0700230 print ('probing VOLATILEs to resolve potential matches: %s\n' %
231 ', '.join(sorted(potential_volatiles)))
232 vol_probe_results = Probe(
233 target_comp_classes=[],
234 probe_volatile=True,
235 probe_initial_config=False)
236 cooked_volatiles = device.MatchVolatileValues(
237 vol_probe_results.found_volatile_values)
238 match_tree = device.BuildMatchTree(
239 component_data, cooked_volatiles.matched_tags)
240 matched_hwids = device.GetMatchTreeHwids(match_tree)
241 if matched_hwids:
242 for hwid in matched_hwids:
Ricky Liang02f3bd72012-09-21 14:33:01 +0800243 if matched_hwids[hwid] in options.status:
244 print 'MATCHING HWID: %s' % hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700245 return
246 print 'exact HWID matching failed, but the following BOMs match: %s' % (
247 ', '.join(sorted(match_tree)))
248 if options.optimistic and len(match_tree) == 1:
249 bom_name = set(match_tree).pop()
Tammo Spalink5c699832012-07-03 17:50:39 +0800250 bom = device.boms[bom_name]
Tammo Spalink95c43732012-07-25 15:57:14 -0700251 variant_matches = match_tree[bom_name]
Tammo Spalink5c699832012-07-03 17:50:39 +0800252 if len(variant_matches) == 1:
253 var_code = set(variant_matches).pop()
254 elif len(bom.variants) == 1:
255 var_code = set(bom.variants).pop()
256 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700257 sys.exit('FAILURE: NO matching HWIDs found; optimistic matching failed '
258 'because there were too many variants to choose from for BOM %r'
259 % bom_name)
260 hwids = [device.FmtHwid(bom_name, var_code, vol_code)
261 for vol_code in device.volatiles
262 if device.GetHwidStatus(bom_name, var_code, vol_code)
263 in options.status]
264 for hwid in hwids:
265 print 'MATCHING HWID: %s' % hwid
Tammo Spalink5c699832012-07-03 17:50:39 +0800266 return
267 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700268 print ('optimistic matching not attempted because either it was '
269 'not requested, or because the number of BOMs was <> 1\n')
270 sys.exit('FAILURE: NO matching HWIDs found')
Tammo Spalink8fab5312012-05-28 18:33:30 +0800271
272
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800273@Command('probe',
274 CmdArg('--comps', nargs='*',
275 help='List of keys from the component_db registry.'),
276 CmdArg('--no_vol', action='store_true',
277 help='Do not probe volatile data.'),
278 CmdArg('--no_ic', action='store_true',
Jon Salz0f8a6842012-09-25 11:28:22 +0800279 help='Do not probe initial_config data.'),
280 CmdArg('--include_vpd', action='store_true',
281 help='Include VPD data in volatiles.'))
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800282def RunProbe(options):
283 """Print yaml-formatted breakdown of probed device properties."""
Tammo Spalink01e11722012-07-24 10:17:54 -0700284 probe_results = Probe(target_comp_classes=options.comps,
Jon Salz0f8a6842012-09-25 11:28:22 +0800285 probe_volatile=not options.no_vol,
286 probe_initial_config=not options.no_ic,
287 probe_vpd=options.include_vpd)
Tammo Spalink3a7e9022012-06-27 14:08:40 +0800288 print probe_results.Encode()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800289
290
Tammo Spalink214caf42012-05-28 10:45:00 +0800291@Command('verify_components',
292 _hwdb_path_cmd_arg,
Tammo Spalink5c699832012-07-03 17:50:39 +0800293 CmdArg('target_comps', nargs='*'))
Tammo Spalink214caf42012-05-28 10:45:00 +0800294def VerifyComponents(options):
Andy Cheng8ece7382012-08-22 16:25:42 +0800295 """Verify that probeable components all match entries in the component_db.
Tammo Spalink214caf42012-05-28 10:45:00 +0800296
Tammo Spalink5c699832012-07-03 17:50:39 +0800297 Probe for each component class in the target_comps and verify
Tammo Spalink214caf42012-05-28 10:45:00 +0800298 that a corresponding match exists in the component_db -- make sure
299 that these components are present, that they have been approved, but
300 do not check against any specific BOM/HWID configurations.
301 """
Tammo Spalink5c699832012-07-03 17:50:39 +0800302 comp_db = hwid_tool.HardwareDb(options.hwdb_path).comp_db
Andy Chengc531e2f2012-10-15 19:09:17 +0800303 try:
304 result = Gooftool(component_db=comp_db).VerifyComponents(
305 options.target_comps)
306 except ValueError, e:
307 sys.exit(e)
308
309 # group by matches and errors
Tammo Spalink214caf42012-05-28 10:45:00 +0800310 matches = []
Andy Chengc531e2f2012-10-15 19:09:17 +0800311 errors = []
312 for result_list in result.values():
313 for component_name, _, error in result_list:
314 if component_name:
315 matches.append(component_name)
Tammo Spalink214caf42012-05-28 10:45:00 +0800316 else:
Andy Chengc531e2f2012-10-15 19:09:17 +0800317 errors.append(error)
318
Andy Cheng228a8c92012-08-27 10:53:57 +0800319 if matches:
320 print 'found probeable components:\n %s' % '\n '.join(matches)
Tammo Spalink214caf42012-05-28 10:45:00 +0800321 if errors:
Andy Cheng228a8c92012-08-27 10:53:57 +0800322 print '\nerrors:\n %s' % '\n '.join(errors)
323 sys.exit('\ncomponent verification FAILURE')
Tammo Spalink214caf42012-05-28 10:45:00 +0800324 else:
Andy Cheng228a8c92012-08-27 10:53:57 +0800325 print "\ncomponent verification SUCCESS"
Tammo Spalink214caf42012-05-28 10:45:00 +0800326
327
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800328@Command('verify_hwid',
Tammo Spalink95c43732012-07-25 15:57:14 -0700329 _hwid_status_list_cmd_arg,
Jon Salz0f8a6842012-09-25 11:28:22 +0800330 _hwdb_path_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800331 _probe_results_cmd_arg,
332 _hwid_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800333def VerifyHwid(options):
334 """Verify system HWID properties match probed device properties.
335
336 First probe components, volatile and initial_config parameters for
337 the DUT. Then use the available device data to produce a list of
338 candidate HWIDs. Then verify the HWID from the DUT is present in
339 that list. Then verify that the DUT initial config values match
340 those specified for its HWID. Finally, verify that VPD contains all
341 the necessary fields as specified by the board data, and when
342 possible verify that values are legitimate.
343 """
Ricky Liangf7857c12012-09-17 13:34:41 +0800344 def VerifyVpd(ro_vpd_keys, rw_vpd_keys):
Tammo Spalink5c699832012-07-03 17:50:39 +0800345 for key in ro_vpd_keys:
346 if key not in ro_vpd:
Ricky Liangf7857c12012-09-17 13:34:41 +0800347 sys.exit('Missing required RO VPD field: %s' % key)
Tammo Spalink01e11722012-07-24 10:17:54 -0700348 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800349 value = ro_vpd[key]
Ricky Liangf7857c12012-09-17 13:34:41 +0800350 if (known_valid_values is not None) and (value not in known_valid_values):
351 sys.exit('Invalid RO VPD entry : key %r, value %r' % (key, value))
Ricky Liangf7857c12012-09-17 13:34:41 +0800352 for key in rw_vpd_keys:
353 if key not in rw_vpd:
354 sys.exit('Missing required RW VPD field: %s' % key)
355 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
356 value = rw_vpd[key]
357 if (known_valid_values is not None) and (value not in known_valid_values):
358 sys.exit('Invalid RW VPD entry : key %r, value %r' % (key, value))
Jon Salz05aba9d2012-10-05 17:25:38 +0800359 _event_log.Log('vpd', ro_vpd=FilterVPD(ro_vpd), rw_vpd=FilterVPD(rw_vpd))
Tammo Spalink5c699832012-07-03 17:50:39 +0800360 map(hwid_tool.Validate.Status, options.status)
Jon Salz0f8a6842012-09-25 11:28:22 +0800361
Jon Salz81350812012-10-11 16:13:22 +0800362 if not options.hwid or not options.probe_results:
363 main_fw_file = crosfw.LoadMainFirmware().GetFileName()
Jon Salz0f8a6842012-09-25 11:28:22 +0800364
365 if options.hwid:
366 hwid_str = options.hwid
367 else:
368 gbb_result = Shell('gbb_utility -g --hwid %s' % main_fw_file).stdout
369 hwid_str = re.findall(r'hardware_id:(.*)', gbb_result)[0].strip()
Tammo Spalink95c43732012-07-25 15:57:14 -0700370 hwid = hwid_tool.ParseHwid(hwid_str)
Tammo Spalink5c699832012-07-03 17:50:39 +0800371 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Jon Salz0f8a6842012-09-25 11:28:22 +0800372 print 'Verifying HWID: %r\n' % hwid.hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700373 device = hw_db.GetDevice(hwid.board)
374 hwid_status = device.GetHwidStatus(hwid.bom, hwid.variant, hwid.volatile)
375 if hwid_status not in options.status:
Tammo Spalink5c699832012-07-03 17:50:39 +0800376 sys.exit('HWID status must be one of [%s], found %r' %
Hung-Te Lin4f5beb12012-08-20 14:48:06 +0800377 (', '.join(options.status), hwid_status))
Jon Salz0f8a6842012-09-25 11:28:22 +0800378 if options.probe_results:
379 # Pull in probe results (including VPD data) from the given file
380 # rather than probing the current system.
381 probe_results = hwid_tool.ProbeResults.Decode(
382 open(options.probe_results).read())
383 ro_vpd = {}
384 rw_vpd = {}
385 for k, v in probe_results.found_volatile_values.items():
386 match = re.match('^vpd\.(ro|rw)\.(\w+)$', k)
387 if match:
388 del probe_results.found_volatile_values[k]
389 (ro_vpd if match.group(1) == 'ro' else rw_vpd)[match.group(2)] = v
390 else:
391 probe_results = Probe()
392 ro_vpd = ReadRoVpd(main_fw_file)
393 rw_vpd = ReadRwVpd(main_fw_file)
Tammo Spalink95c43732012-07-25 15:57:14 -0700394 cooked_components = hw_db.comp_db.MatchComponentProbeValues(
395 probe_results.found_probe_value_map)
396 cooked_volatiles = device.MatchVolatileValues(
397 probe_results.found_volatile_values)
398 cooked_initial_configs = device.MatchInitialConfigValues(
399 probe_results.initial_configs)
400 component_data = hwid_tool.ComponentData(
401 extant_components=cooked_components.matched,
402 classes_missing=probe_results.missing_component_classes)
403 match_tree = device.BuildMatchTree(
404 component_data, cooked_volatiles.matched_tags)
405 matched_hwids = device.GetMatchTreeHwids(match_tree)
406 print 'HWID status: %s\n' % hwid_status
407 print 'probed system components:'
408 print YamlWrite(cooked_components.__dict__)
409 print 'missing component classes:'
410 print YamlWrite(probe_results.missing_component_classes)
411 print 'probed volatiles:'
412 print YamlWrite(cooked_volatiles.__dict__)
413 print 'probed initial_configs:'
414 print YamlWrite(cooked_initial_configs)
415 print 'hwid match tree:'
416 print YamlWrite(match_tree)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800417 _event_log.Log(
Tammo Spalink5c699832012-07-03 17:50:39 +0800418 'probe',
Tammo Spalink95c43732012-07-25 15:57:14 -0700419 found_components=cooked_components.__dict__,
420 missing_component_classes=probe_results.missing_component_classes,
421 volatiles=cooked_volatiles.__dict__,
422 initial_configs=cooked_initial_configs)
423 if hwid.hwid not in matched_hwids:
Tammo Spalink5c699832012-07-03 17:50:39 +0800424 err_msg = 'HWID verification FAILED.\n'
Tammo Spalink95c43732012-07-25 15:57:14 -0700425 if cooked_components.unmatched:
Tammo Spalink5c699832012-07-03 17:50:39 +0800426 sys.exit(err_msg + 'some components could not be indentified:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700427 YamlWrite(cooked_components.unmatched))
428 if not match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800429 sys.exit(err_msg + 'no matching boms were found for components:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700430 component_data.Encode())
431 if hwid.bom not in match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800432 sys.exit(err_msg + 'matching boms [%s] do not include target bom %r' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700433 (', '.join(sorted(match_tree)), hwid.bom))
434 err_msg += 'target bom %r matches components' % hwid.bom
435 if hwid.bom not in device.IntersectBomsAndInitialConfigs(
436 cooked_initial_configs):
Tammo Spalink5c699832012-07-03 17:50:39 +0800437 sys.exit(err_msg + ', but failed initial config verification')
Tammo Spalink95c43732012-07-25 15:57:14 -0700438 matched_variants = match_tree.get(hwid.bom, {})
439 if hwid.variant not in matched_variants:
Tammo Spalink5c699832012-07-03 17:50:39 +0800440 sys.exit(err_msg + ', but target variant_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700441 hwid.variant)
442 matched_volatiles = matched_variants.get(hwid.variant, {})
443 if hwid.volatile not in matched_volatiles:
Tammo Spalink5c699832012-07-03 17:50:39 +0800444 sys.exit(err_msg + ', but target volatile_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700445 hwid.volatile)
446 found_status = matched_volatiles.get(hwid.volatile, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800447 sys.exit(err_msg + ', but hwid status %r was unacceptable' % found_status)
Ricky Liangf7857c12012-09-17 13:34:41 +0800448 VerifyVpd(device.vpd_ro_fields, device.vpd_rw_fields)
Tammo Spalink5c699832012-07-03 17:50:39 +0800449 _event_log.Log('verified_hwid', hwid=hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -0700450 print 'Verification SUCCESS!'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800451
452
453@Command('verify_keys')
Tammo Spalink01e11722012-07-24 10:17:54 -0700454def VerifyKeys(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800455 """Verify keys in firmware and SSD match."""
Tammo Spalink461ddce2012-05-10 19:28:55 +0800456 script = FindScript('verify_keys.sh')
Andy Cheng025eedc2012-11-13 18:23:22 +0800457 kernel_device = Gooftool().GetReleaseKernelPartitionPath()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800458 main_fw_file = crosfw.LoadMainFirmware().GetFileName()
459 result = Shell('%s %s %s' % (script, kernel_device, main_fw_file))
460 if not result.success:
461 raise Error, '%r failed, stderr: %r' % (script, result.stderr)
462
463
464@Command('set_fw_bitmap_locale')
Tammo Spalink01e11722012-07-24 10:17:54 -0700465def SetFirmwareBitmapLocale(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800466 """Use VPD locale value to set firmware bitmap default language."""
467 image_file = crosfw.LoadMainFirmware().GetFileName()
468 locale = ReadRoVpd(image_file).get('initial_locale', None)
469 if locale is None:
470 raise Error, 'Missing initial_locale VPD.'
471 bitmap_locales = []
472 with NamedTemporaryFile() as f:
473 Shell('gbb_utility -g --bmpfv=%s %s' % (f.name, image_file))
Tammo Spalink01e11722012-07-24 10:17:54 -0700474 bmpblk_data = unpack_bmpblock(f.read())
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800475 bitmap_locales = bmpblk_data.get('locales', bitmap_locales)
476 # Some locale values are just a language code and others are a
477 # hyphen-separated language code and country code pair. We care
478 # only about the language code part.
479 language_code = locale.partition('-')[0]
480 if language_code not in bitmap_locales:
481 raise Error, ('Firmware bitmaps do not contain support for the specified '
482 'initial locale language %r' % language_code)
483 else:
484 locale_index = bitmap_locales.index(language_code)
485 logging.info('Firmware bitmap initial locale set to %d (%s).',
486 locale_index, bitmap_locales[locale_index])
487 Shell('crossystem loc_idx=%d' % locale_index)
488
489
490@Command('verify_system_time')
Tammo Spalink01e11722012-07-24 10:17:54 -0700491def VerifySystemTime(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800492 """Verify system time is later than release filesystem creation time."""
Tammo Spalink461ddce2012-05-10 19:28:55 +0800493 script = FindScript('verify_system_time.sh')
Andy Cheng025eedc2012-11-13 18:23:22 +0800494 rootfs_device = Gooftool().GetReleaseRootPartitionPath()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800495 result = Shell('%s %s' % (script, rootfs_device))
496 if not result.success:
497 raise Error, '%r failed, stderr: %r' % (script, result.stderr)
498
499
500@Command('verify_rootfs')
Tammo Spalink01e11722012-07-24 10:17:54 -0700501def VerifyRootFs(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800502 """Verify rootfs on SSD is valid by checking hash."""
Tammo Spalink461ddce2012-05-10 19:28:55 +0800503 script = FindScript('verify_rootfs.sh')
Andy Cheng025eedc2012-11-13 18:23:22 +0800504 rootfs_device = Gooftool().GetReleaseRootPartitionPath()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800505 result = Shell('%s %s' % (script, rootfs_device))
506 if not result.success:
Jon Salzb52ae702012-09-20 13:57:52 +0800507 raise Error, '%r failed, stdout: %r, stderr: %r' % (
508 script, result.stdout, result.stderr)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800509
510
511@Command('verify_switch_wp')
Tammo Spalink01e11722012-07-24 10:17:54 -0700512def VerifyWpSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800513 """Verify hardware write protection switch is enabled."""
514 if Shell('crossystem wpsw_cur').stdout.strip() != '1':
Hung-Te Lin6d827542012-07-19 11:50:41 +0800515 raise Error, 'write protection switch is disabled'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800516
517
518@Command('verify_switch_dev')
Tammo Spalink01e11722012-07-24 10:17:54 -0700519def VerifyDevSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800520 """Verify developer switch is disabled."""
Hung-Te Lind7d34722012-07-26 16:48:35 +0800521 VBSD_HONOR_VIRT_DEV_SWITCH = 0x400
522 flags = int(Shell('crossystem vdat_flags').stdout.strip(), 0)
523 if (flags & VBSD_HONOR_VIRT_DEV_SWITCH) != 0:
524 # System is using virtual developer switch. That will be handled in
525 # prepare_wipe.sh by setting "crossystem disable_dev_request=1" -- although
526 # we can't verify that until next reboot, because the real values are stored
527 # in TPM.
528 logging.warn('VerifyDevSwitch: No physical switch.')
529 _event_log.Log('switch_dev', type='virtual switch')
530 return
531 if Shell('crossystem devsw_cur').stdout.strip() != '0':
532 raise Error, 'developer mode is not disabled'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800533
534
535@Command('write_protect')
Tammo Spalink01e11722012-07-24 10:17:54 -0700536def EnableFwWp(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800537 """Enable then verify firmware write protection."""
538
Hung-Te Linb21c6682012-08-01 13:53:57 +0800539 def CalculateLegacyRange(fw_type, length, section_data,
540 section_name):
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800541 ro_size = length / 2
542 ro_a = int(section_data[0] / ro_size)
543 ro_b = int((section_data[0] + section_data[1] - 1) / ro_size)
544 if ro_a != ro_b:
545 raise Error("%s firmware section %s has illegal size" %
Hung-Te Linb21c6682012-08-01 13:53:57 +0800546 (fw_type, section_name))
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800547 ro_offset = ro_a * ro_size
548 return (ro_offset, ro_size)
549
550 def WriteProtect(fw_file_path, fw_type, legacy_section):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800551 """Calculate protection size, then invoke flashrom.
552
553 Our supported chips only allow write protecting half their total
554 size, so we parition the flash chipset space accordingly.
555 """
556 raw_image = open(fw_file_path, 'rb').read()
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800557 wp_section = 'WP_RO'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800558 image = crosfw.FirmwareImage(raw_image)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800559 if image.has_section(wp_section):
560 section_data = image.get_section_area(wp_section)
561 ro_offset = section_data[0]
562 ro_size = section_data[1]
563 elif image.has_section(legacy_section):
564 section_data = image.get_section_area(legacy_section)
565 (ro_offset, ro_size) = CalculateLegacyRange(
Hung-Te Linb21c6682012-08-01 13:53:57 +0800566 fw_type, len(raw_image), section_data, legacy_section)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800567 else:
568 raise Error('could not find %s firmware section %s or %s' %
569 (fw_type, wp_section, legacy_section))
570
571 logging.debug('write protecting %s [off=%x size=%x]', fw_type,
572 ro_offset, ro_size)
573 crosfw.Flashrom(fw_type).EnableWriteProtection(ro_offset, ro_size)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800574
575 WriteProtect(crosfw.LoadMainFirmware().GetFileName(), 'main', 'RO_SECTION')
Tammo Spalink86a61c62012-05-25 15:10:35 +0800576 _event_log.Log('wp', fw='main')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800577 ec_fw_file = crosfw.LoadEcFirmware().GetFileName()
578 if ec_fw_file is not None:
579 WriteProtect(ec_fw_file, 'ec', 'EC_RO')
Tammo Spalink86a61c62012-05-25 15:10:35 +0800580 _event_log.Log('wp', fw='ec')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800581 else:
582 logging.warning('EC not write protected (seems there is no EC flash).')
583
584
585@Command('clear_gbb_flags')
Tammo Spalink01e11722012-07-24 10:17:54 -0700586def ClearGbbFlags(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800587 """Zero out the GBB flags, in preparation for transition to release state.
588
589 No GBB flags are set in release/shipping state, but they are useful
590 for factory/development. See "gbb_utility --flags" for details.
591 """
Tammo Spalink461ddce2012-05-10 19:28:55 +0800592 script = FindScript('clear_gbb_flags.sh')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800593 result = Shell(script)
594 if not result.success:
595 raise Error, '%r failed, stderr: %r' % (script, result.stderr)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800596 _event_log.Log('clear_gbb_flags')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800597
598
599@Command('prepare_wipe',
600 CmdArg('--fast', action='store_true',
601 help='use non-secure but faster wipe method.'))
602def PrepareWipe(options):
603 """Prepare system for transition to release state in next reboot."""
Tammo Spalink461ddce2012-05-10 19:28:55 +0800604 script = FindScript('prepare_wipe.sh')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800605 tag = 'fast' if options.fast else ''
Andy Cheng025eedc2012-11-13 18:23:22 +0800606 rootfs_device = Gooftool().GetReleaseRootPartitionPath()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800607 result = Shell('FACTORY_WIPE_TAGS=%s %s %s' % (tag, script, rootfs_device))
608 if not result.success:
609 raise Error, '%r failed, stderr: %r' % (script, result.stderr)
610
611
612@Command('verify',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800613 CmdArg('--no_write_protect', action='store_true',
614 help='Do not check write protection switch state.'),
Tammo Spalink95c43732012-07-25 15:57:14 -0700615 _hwid_status_list_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800616 _hwdb_path_cmd_arg,
617 _probe_results_cmd_arg,
618 _hwid_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800619def Verify(options):
620 """Verifies if whole factory process is ready for finalization.
621
622 This routine performs all the necessary checks to make sure the
623 device is ready to be finalized, but does not modify state. These
624 checks include dev switch, firmware write protection switch, hwid,
625 system time, keys, and root file system.
626 """
Hung-Te Lin6d827542012-07-19 11:50:41 +0800627 if not options.no_write_protect:
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800628 VerifyWpSwitch({})
Hung-Te Lin6d827542012-07-19 11:50:41 +0800629 VerifyDevSwitch({})
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800630 VerifyHwid(options)
631 VerifySystemTime({})
632 VerifyKeys({})
633 VerifyRootFs({})
634
635
Tammo Spalink86a61c62012-05-25 15:10:35 +0800636@Command('log_system_details')
Tammo Spalink01e11722012-07-24 10:17:54 -0700637def LogSystemDetails(options): # pylint: disable=W0613
Tammo Spalink86a61c62012-05-25 15:10:35 +0800638 """Write miscellaneous system details to the event log."""
639 raw_cs_data = Shell('crossystem').stdout.strip().splitlines()
640 # The crossytem output contains many lines like:
641 # 'key = value # description'
642 # Use regexps to pull out the key-value pairs and build a dict.
643 cs_data = dict((k, v.strip()) for k, v in
644 map(lambda x: re.findall(r'\A(\S+)\s+=\s+(.*)#.*\Z', x)[0],
645 raw_cs_data))
646 _event_log.Log(
647 'system_details',
648 platform_name=Shell('mosys platform name').stdout.strip(),
649 crossystem=cs_data,
650 modem_status=Shell('modem status').stdout.splitlines(),
651 ec_wp_status=Shell(
652 'flashrom -p internal:bus=lpc --get-size 2>/dev/null && '
653 'flashrom -p internal:bus=lpc --wp-status || '
654 'echo "EC is not available."').stdout,
655 bios_wp_status = Shell(
656 'flashrom -p internal:bus=spi --wp-status').stdout)
657
658
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800659_upload_method_cmd_arg = CmdArg(
660 '--upload_method', metavar='METHOD:PARAM',
661 help=('How to perform the upload. METHOD should be one of '
cychiang3b15bd52012-09-08 13:58:18 +0800662 '{ftp, shopfloor, ftps, cpfe}.'))
Jon Salz65266432012-07-30 19:02:49 +0800663_add_file_cmd_arg = CmdArg(
664 '--add_file', metavar='FILE', action='append',
665 help='Extra file to include in report (must be an absolute path)')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800666
667@Command('upload_report',
Jon Salz65266432012-07-30 19:02:49 +0800668 _upload_method_cmd_arg,
669 _add_file_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800670def UploadReport(options):
671 """Create and a report containing key device details."""
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800672 def NormalizeAsFileName(token):
673 return re.sub(r'\W+', '', token).strip()
Tammo Spalink86a61c62012-05-25 15:10:35 +0800674 ro_vpd = ReadRoVpd(crosfw.LoadMainFirmware().GetFileName())
675 device_sn = ro_vpd.get('serial_number', None)
676 if device_sn is None:
677 logging.warning('RO_VPD missing device serial number')
678 device_sn = 'MISSING_SN_' + TimedUuid()
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800679 target_name = '%s_%s.tbz2' % (time.strftime('%Y%m%dT%H%M%SZ', time.gmtime()),
680 NormalizeAsFileName(device_sn))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800681 target_path = os.path.join(gettempdir(), target_name)
682 # Intentionally ignoring dotfiles in EVENT_LOG_DIR.
683 tar_cmd = 'cd %s ; tar cjf %s *' % (EVENT_LOG_DIR, target_path)
684 tar_cmd += ' --add-file %s' % FACTORY_LOG_PATH
Jon Salz65266432012-07-30 19:02:49 +0800685 if options.add_file:
686 for f in options.add_file:
687 # Require absolute paths since the tar command may change the
688 # directory.
689 if not f.startswith('/'):
690 raise Error('Not an absolute path: %s' % f)
691 if not os.path.exists(f):
692 raise Error('File does not exist: %s' % f)
693 tar_cmd += ' --add-file %s' % pipes.quote(f)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800694 cmd_result = Shell(tar_cmd)
695 if not cmd_result.success:
696 raise Error('unable to tar event logs, cmd %r failed, stderr: %r' %
697 (tar_cmd, cmd_result.stderr))
698 if options.upload_method is None or options.upload_method == 'none':
699 logging.warning('REPORT UPLOAD SKIPPED (report left at %s)', target_path)
700 return
701 method, param = options.upload_method.split(':', 1)
702 if method == 'shopfloor':
703 report_upload.ShopFloorUpload(target_path, param)
704 elif method == 'ftp':
Jay Kim360c1dd2012-06-25 10:58:11 -0700705 report_upload.FtpUpload(target_path, 'ftp:' + param)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800706 elif method == 'ftps':
707 report_upload.CurlUrlUpload(target_path, '--ftp-ssl-reqd ftp:%s' % param)
708 elif method == 'cpfe':
709 report_upload.CpfeUpload(target_path, param)
710 else:
711 raise Error('unknown report upload method %r', method)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800712
713
714@Command('finalize',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800715 CmdArg('--no_write_protect', action='store_true',
716 help='Do not enable firmware write protection.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800717 CmdArg('--fast', action='store_true',
718 help='use non-secure but faster wipe method.'),
719 _hwdb_path_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700720 _hwid_status_list_cmd_arg,
Jon Salz65266432012-07-30 19:02:49 +0800721 _upload_method_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800722 _add_file_cmd_arg,
723 _probe_results_cmd_arg,
724 _hwid_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800725def Finalize(options):
726 """Verify system readiness and trigger transition into release state.
727
Hung-Te Lin6d827542012-07-19 11:50:41 +0800728 This routine first verifies system state (see verify command), modifies
729 firmware bitmaps to match locale, and then clears all of the factory-friendly
730 flags from the GBB. If everything is fine, it enables firmware write
731 protection (cannot rollback after this stage), uploads system logs & reports,
732 and sets the necessary boot flags to cause wipe of the factory image on the
733 next boot.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800734 """
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800735 Verify(options)
736 SetFirmwareBitmapLocale({})
Hung-Te Lin6d827542012-07-19 11:50:41 +0800737 ClearGbbFlags({})
738 if options.no_write_protect:
739 logging.warn('WARNING: Firmware Write Protection is SKIPPED.')
740 _event_log.Log('wp', fw='both', status='skipped')
741 else:
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800742 EnableFwWp({})
Jon Salza0f58e02012-05-29 19:33:39 +0800743 LogSystemDetails(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800744 UploadReport(options)
745 PrepareWipe(options)
746
747
748def Main():
749 """Run sub-command specified by the command line args."""
750 options = ParseCmdline(
751 'Perform Google required factory tests.',
752 CmdArg('-l', '--log', metavar='PATH',
753 help='Write logs to this file.'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800754 verbosity_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800755 SetupLogging(options.verbosity, options.log)
756 logging.debug('gooftool options: %s', repr(options))
757 try:
758 logging.debug('GOOFTOOL command %r', options.command_name)
759 options.command(options)
760 logging.info('GOOFTOOL command %r SUCCESS', options.command_name)
761 except Error, e:
762 logging.exception(e)
763 sys.exit('GOOFTOOL command %r ERROR: %s' % (options.command_name, e))
764 except Exception, e:
765 logging.exception(e)
766 sys.exit('UNCAUGHT RUNTIME EXCEPTION %s' % e)
767
768
769if __name__ == '__main__':
770 Main()