blob: 7d5a4f1df5ce934de77a66a08eb761419dc132ea [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
Andy Cheng2582d292012-12-04 17:38:28 +080022from tempfile import gettempdir
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
Ricky Liang53390232013-03-08 15:37:57 +080028from cros.factory.event_log import EventLog, EVENT_LOG_DIR
29from cros.factory.event_log import TimedUuid
Andy Chengc531e2f2012-10-15 19:09:17 +080030from cros.factory.gooftool import Gooftool
Ricky Liang53390232013-03-08 15:37:57 +080031from cros.factory.gooftool import crosfw
Tammo Spalink01e11722012-07-24 10:17:54 -070032from cros.factory.gooftool import report_upload
Andy Cheng8ece7382012-08-22 16:25:42 +080033from cros.factory.gooftool.probe import Probe, PROBEABLE_COMPONENT_CLASSES
Jon Salz0f8a6842012-09-25 11:28:22 +080034from cros.factory.gooftool.probe import ReadRoVpd, ReadRwVpd
Jon Salz193d7c62013-03-07 13:40:19 +080035from cros.factory.gooftool.vpd_data import KNOWN_VPD_FIELD_DATA
Tammo Spalinka40293e2012-07-04 14:58:56 +080036from cros.factory.hacked_argparse import CmdArg, Command, ParseCmdline
37from cros.factory.hacked_argparse import verbosity_cmd_arg
Tammo Spalink01e11722012-07-24 10:17:54 -070038from cros.factory.hwdb import hwid_tool
cychiang7fe09372012-07-04 14:31:23 +080039from cros.factory.test.factory import FACTORY_LOG_PATH
Jon Salzff88c022012-11-03 12:19:58 +080040from cros.factory.utils.process_utils import Spawn
Jon Salz8baad8b2013-03-11 20:01:45 +080041from cros.factory.privacy import FilterDict
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
Ricky Lianga70a1202013-03-15 15:03:17 +080054def GetGooftool(options):
55 if options.hwid_version == 2:
56 hwdb_path = getattr(options, 'hwdb_path', None)
57 component_db = (
58 hwid_tool.HardwareDb(options.hwdb_path).comp_db if hwdb_path else None)
59 return Gooftool(hwid_version=2, component_db=component_db)
60 elif options.hwid_version == 3:
61 board = getattr(options, 'board', None)
62 hwdb_path = getattr(options, 'hwdb_path', None)
63 return Gooftool(hwid_version=3, board=board, hwdb_path=hwdb_path)
64 else:
65 raise Error, 'Invalid HWID version: %r' % options.hwid_version
66
67
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080068@Command('write_hwid',
69 CmdArg('hwid', metavar='HWID', help='HWID string'))
Andy Chengc92e6f92012-11-20 16:55:53 +080070def WriteHWID(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080071 """Write specified HWID value into the system BB."""
Andy Cheng7a76cb82012-11-19 18:08:19 +080072
Tammo Spalink95c43732012-07-25 15:57:14 -070073 logging.info('writing hwid string %r', options.hwid)
Ricky Lianga70a1202013-03-15 15:03:17 +080074 GetGooftool(options).WriteHWID(options.hwid)
Tammo Spalink86a61c62012-05-25 15:10:35 +080075 _event_log.Log('write_hwid', hwid=options.hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -070076 print 'Wrote HWID: %r' % options.hwid
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080077
78
Ricky Liang53390232013-03-08 15:37:57 +080079_board_cmd_arg = CmdArg(
80 '--board', metavar='BOARD',
81 default=None, help='Board name to test.')
82
Tammo Spalink8fab5312012-05-28 18:33:30 +080083_hwdb_path_cmd_arg = CmdArg(
84 '--hwdb_path', metavar='PATH',
85 default=hwid_tool.DEFAULT_HWID_DATA_PATH,
86 help='Path to the HWID database.')
87
Tammo Spalink95c43732012-07-25 15:57:14 -070088_hwid_status_list_cmd_arg = CmdArg(
89 '--status', nargs='*', default=['supported'],
90 help='allow only HWIDs with these status values')
91
Jon Salzce124fb2012-10-02 17:42:03 +080092_probe_results_cmd_arg = CmdArg(
93 '--probe_results', metavar='RESULTS.yaml',
94 help=('Output from "gooftool probe" (used instead of '
95 'probing this system).'))
96
Ricky Liang53390232013-03-08 15:37:57 +080097_device_info_cmd_arg = CmdArg(
98 '--device_info', metavar='DEVICE_INFO', default=None,
99 help='A dict of device info to use instead of fetching from shopfllor '
100 'server.')
101
Jon Salzce124fb2012-10-02 17:42:03 +0800102_hwid_cmd_arg = CmdArg(
103 '--hwid', metavar='HWID',
Ricky Lianga70a1202013-03-15 15:03:17 +0800104 help='HWID to verify (instead of the currently set HWID of this system).')
Jon Salzce124fb2012-10-02 17:42:03 +0800105
Tammo Spalink95c43732012-07-25 15:57:14 -0700106
107@Command('best_match_hwids',
Tammo Spalink8fab5312012-05-28 18:33:30 +0800108 _hwdb_path_cmd_arg,
109 CmdArg('-b', '--board', metavar='BOARD',
Tammo Spalink95c43732012-07-25 15:57:14 -0700110 help='optional BOARD name, needed only if data is present '
111 'for more than one'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800112 CmdArg('--bom', metavar='BOM', help='BOM name'),
113 CmdArg('--variant', metavar='VARIANT', help='VARIANT code'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800114 CmdArg('--optimistic', action='store_true',
115 help='do not probe; assume singletons match'),
Tammo Spalink95c43732012-07-25 15:57:14 -0700116 CmdArg('--comps', nargs='*', default=[],
117 help='list of canonical component names'),
118 CmdArg('--missing', nargs='*', default=[],
119 help='list component classes to be assumed missing'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800120 CmdArg('--status', nargs='*', default=['supported'],
Tammo Spalink95c43732012-07-25 15:57:14 -0700121 help='consider only HWIDs within this list of status values'))
122def BestMatchHwids(options):
Tammo Spalink8fab5312012-05-28 18:33:30 +0800123 """Determine a list of possible HWIDs using provided args and probeing.
124
125 VOLATILE can always be determined by probing. To get a unique
126 result, VARIANT must be specified for all cases where the matching
127 BOM has more than one associated variant code, otherwise all HWID
128 variants will be returned. Both VARIANT and BOM information can
Tammo Spalink95c43732012-07-25 15:57:14 -0700129 alternatively be specified using the --stdin_comps argument, which
130 allows specifying a list of canonical names (one per line) on stdin,
131 one per line. Based on what is known from BOM and stdin_comps,
132 determine a list of components to probe for, and use those probe
133 results to resolve a list of matching HWIDs. If no boms,
134 components, or variant codes are specified, then a list of all HWIDs
Andy Cheng8ece7382012-08-22 16:25:42 +0800135 that match probeable components will be returned.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800136
137 Returns (on stdout): A list of HWIDs that match the available probe
138 results and argument contraints, one per line.
Tammo Spalink70b48a52012-08-08 16:54:51 -0700139
140 Example:
141
142 // Three ways to specify a keyboard (assuming it is a variant component)
143 gooftool best_match_hwids --missing keyboard
144 gooftool best_match_hwids --variant A or
145 gooftool best_match_hwids --comps us_kbd
Tammo Spalink8fab5312012-05-28 18:33:30 +0800146 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800147
Tammo Spalink5c699832012-07-03 17:50:39 +0800148 map(hwid_tool.Validate.Status, options.status)
Tammo Spalink95c43732012-07-25 15:57:14 -0700149 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Tammo Spalink5c699832012-07-03 17:50:39 +0800150 comp_db = hw_db.comp_db
Tammo Spalink3a7e9022012-06-27 14:08:40 +0800151 device = hw_db.GetDevice(options.board)
Tammo Spalink5c699832012-07-03 17:50:39 +0800152 component_spec = hwid_tool.ComponentSpec.New()
Tammo Spalink8fab5312012-05-28 18:33:30 +0800153 if options.bom:
Tammo Spalink5c699832012-07-03 17:50:39 +0800154 device.BomExists(options.bom)
Tammo Spalink01e11722012-07-24 10:17:54 -0700155 component_spec = hwid_tool.CombineComponentSpecs(
Tammo Spalink5c699832012-07-03 17:50:39 +0800156 component_spec, device.boms[options.bom].primary)
Tammo Spalink8fab5312012-05-28 18:33:30 +0800157 if options.variant:
Tammo Spalink5c699832012-07-03 17:50:39 +0800158 device.VariantExists(options.variant)
159 variant_spec = device.variants[options.variant]
Tammo Spalink01e11722012-07-24 10:17:54 -0700160 if hwid_tool.ComponentSpecsConflict(component_spec, variant_spec):
Tammo Spalink95c43732012-07-25 15:57:14 -0700161 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700162 % YamlWrite(sorted(
163 hwid_tool.ComponentSpecClasses(component_spec) &
164 hwid_tool.ComponentSpecClasses(variant_spec))))
Tammo Spalink01e11722012-07-24 10:17:54 -0700165 component_spec = hwid_tool.CombineComponentSpecs(
166 component_spec, variant_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700167 if options.comps or options.missing:
168 map(comp_db.CompExists, options.comps)
169 map(comp_db.CompClassExists, options.missing)
170 extra_comp_spec = comp_db.CreateComponentSpec(
171 components=options.comps,
172 missing=options.missing)
173 print 'cmdline asserted components:\n%s' % extra_comp_spec.Encode()
174 if hwid_tool.ComponentSpecsConflict(component_spec, extra_comp_spec):
175 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700176 % YamlWrite(sorted(
177 hwid_tool.ComponentSpecClasses(component_spec) &
178 hwid_tool.ComponentSpecClasses(extra_comp_spec))))
Tammo Spalink95c43732012-07-25 15:57:14 -0700179 component_spec = hwid_tool.CombineComponentSpecs(
180 component_spec, extra_comp_spec)
Tammo Spalink01e11722012-07-24 10:17:54 -0700181 spec_classes = hwid_tool.ComponentSpecClasses(component_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700182 missing_classes = set(comp_db.all_comp_classes) - spec_classes
Tammo Spalink5c699832012-07-03 17:50:39 +0800183 if missing_classes and not options.optimistic:
Andy Cheng8ece7382012-08-22 16:25:42 +0800184 non_probeable_missing = missing_classes - PROBEABLE_COMPONENT_CLASSES
185 if non_probeable_missing:
Tammo Spalink95c43732012-07-25 15:57:14 -0700186 sys.exit('FAILURE: these classes are necessary, were not specified '
Tammo Spalink70b48a52012-08-08 16:54:51 -0700187 'as inputs, and cannot be probed for:\n%s'
188 'This problem can often be addressed by specifying all of '
189 'the missing components on the command line (see the command '
Andy Cheng8ece7382012-08-22 16:25:42 +0800190 'help).' % YamlWrite(list(non_probeable_missing)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700191 print 'probing for missing classes:'
192 print YamlWrite(list(missing_classes))
193 probe_results = Probe(target_comp_classes=list(missing_classes),
194 probe_volatile=False, probe_initial_config=False)
195 cooked_components = comp_db.MatchComponentProbeValues(
196 probe_results.found_probe_value_map)
197 if cooked_components.unmatched:
198 sys.exit('ERROR: some probed components are unrecognized:\n%s'
199 % YamlWrite(cooked_components.unmatched))
200 probed_comp_spec = comp_db.CreateComponentSpec(
201 components=cooked_components.matched,
202 missing=probe_results.missing_component_classes)
203 component_spec = hwid_tool.CombineComponentSpecs(
204 component_spec, probed_comp_spec)
205 print YamlWrite({'component data used for matching': {
206 'missing component classes': component_spec.classes_missing,
207 'found components': component_spec.components}})
208 component_data = hwid_tool.ComponentData(
209 extant_components=hwid_tool.ComponentSpecCompClassMap(
210 component_spec).keys(),
211 classes_missing=component_spec.classes_missing)
212 match_tree = device.BuildMatchTree(component_data)
213 if not match_tree:
214 sys.exit('FAILURE: NO matching BOMs found')
215 print 'potential BOMs/VARIANTs:'
216 potential_variants = set()
217 potential_volatiles = set()
218 for bom_name, variant_tree in match_tree.items():
219 print ' BOM: %-8s VARIANTS: %s' % (
220 bom_name, ', '.join(sorted(variant_tree)))
221 for variant_code in variant_tree:
222 potential_variants.add(variant_code)
223 for volatile_code in device.volatiles:
224 status = device.GetHwidStatus(bom_name, variant_code, volatile_code)
225 if status in options.status:
226 potential_volatiles.add(volatile_code)
227 print ''
228 if len(potential_variants) == 0:
229 sys.exit('FAILURE: no matching VARIANTs found')
230 if len(potential_volatiles) == 0:
231 sys.exit('FAILURE: no VOLATILEs found for potential matching BOMs/VARIANTS '
232 '(with specified status)')
Tammo Spalink394e4492012-08-01 10:20:30 -0700233 if (options.optimistic and
234 len(match_tree) == 1 and
235 len(potential_variants) == 1 and
236 len(potential_volatiles) == 1):
237 print ('MATCHING HWID: %s' % device.FmtHwid(match_tree.keys().pop(),
238 potential_variants.pop(),
239 potential_volatiles.pop()))
Tammo Spalink5c699832012-07-03 17:50:39 +0800240 return
Tammo Spalink95c43732012-07-25 15:57:14 -0700241 print ('probing VOLATILEs to resolve potential matches: %s\n' %
242 ', '.join(sorted(potential_volatiles)))
243 vol_probe_results = Probe(
244 target_comp_classes=[],
245 probe_volatile=True,
246 probe_initial_config=False)
247 cooked_volatiles = device.MatchVolatileValues(
248 vol_probe_results.found_volatile_values)
249 match_tree = device.BuildMatchTree(
250 component_data, cooked_volatiles.matched_tags)
251 matched_hwids = device.GetMatchTreeHwids(match_tree)
252 if matched_hwids:
253 for hwid in matched_hwids:
Ricky Liang02f3bd72012-09-21 14:33:01 +0800254 if matched_hwids[hwid] in options.status:
255 print 'MATCHING HWID: %s' % hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700256 return
257 print 'exact HWID matching failed, but the following BOMs match: %s' % (
258 ', '.join(sorted(match_tree)))
259 if options.optimistic and len(match_tree) == 1:
260 bom_name = set(match_tree).pop()
Tammo Spalink5c699832012-07-03 17:50:39 +0800261 bom = device.boms[bom_name]
Tammo Spalink95c43732012-07-25 15:57:14 -0700262 variant_matches = match_tree[bom_name]
Tammo Spalink5c699832012-07-03 17:50:39 +0800263 if len(variant_matches) == 1:
264 var_code = set(variant_matches).pop()
265 elif len(bom.variants) == 1:
266 var_code = set(bom.variants).pop()
267 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700268 sys.exit('FAILURE: NO matching HWIDs found; optimistic matching failed '
269 'because there were too many variants to choose from for BOM %r'
270 % bom_name)
271 hwids = [device.FmtHwid(bom_name, var_code, vol_code)
272 for vol_code in device.volatiles
273 if device.GetHwidStatus(bom_name, var_code, vol_code)
274 in options.status]
275 for hwid in hwids:
276 print 'MATCHING HWID: %s' % hwid
Tammo Spalink5c699832012-07-03 17:50:39 +0800277 return
278 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700279 print ('optimistic matching not attempted because either it was '
280 'not requested, or because the number of BOMs was <> 1\n')
281 sys.exit('FAILURE: NO matching HWIDs found')
Tammo Spalink8fab5312012-05-28 18:33:30 +0800282
283
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800284@Command('probe',
285 CmdArg('--comps', nargs='*',
286 help='List of keys from the component_db registry.'),
287 CmdArg('--no_vol', action='store_true',
288 help='Do not probe volatile data.'),
289 CmdArg('--no_ic', action='store_true',
Jon Salz0f8a6842012-09-25 11:28:22 +0800290 help='Do not probe initial_config data.'),
291 CmdArg('--include_vpd', action='store_true',
292 help='Include VPD data in volatiles.'))
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800293def RunProbe(options):
294 """Print yaml-formatted breakdown of probed device properties."""
Ricky Lianga70a1202013-03-15 15:03:17 +0800295 print GetGooftool(options).Probe(
296 target_comp_classes=options.comps,
297 probe_volatile=not options.no_vol,
298 probe_initial_config=not options.no_ic,
299 probe_vpd=options.include_vpd).Encode()
Ricky Liang53390232013-03-08 15:37:57 +0800300
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800301
Tammo Spalink214caf42012-05-28 10:45:00 +0800302@Command('verify_components',
303 _hwdb_path_cmd_arg,
Tammo Spalink5c699832012-07-03 17:50:39 +0800304 CmdArg('target_comps', nargs='*'))
Tammo Spalink214caf42012-05-28 10:45:00 +0800305def VerifyComponents(options):
Andy Cheng8ece7382012-08-22 16:25:42 +0800306 """Verify that probeable components all match entries in the component_db.
Tammo Spalink214caf42012-05-28 10:45:00 +0800307
Tammo Spalink5c699832012-07-03 17:50:39 +0800308 Probe for each component class in the target_comps and verify
Tammo Spalink214caf42012-05-28 10:45:00 +0800309 that a corresponding match exists in the component_db -- make sure
310 that these components are present, that they have been approved, but
311 do not check against any specific BOM/HWID configurations.
312 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800313
Andy Chengc531e2f2012-10-15 19:09:17 +0800314 try:
Ricky Lianga70a1202013-03-15 15:03:17 +0800315 result = GetGooftool(options).VerifyComponents(
Andy Chengc531e2f2012-10-15 19:09:17 +0800316 options.target_comps)
317 except ValueError, e:
318 sys.exit(e)
319
Ricky Liang53390232013-03-08 15:37:57 +0800320 PrintVerifyComponentsResults(result)
321
322
323def PrintVerifyComponentsResults(result):
324 """Prints out the results of VerifyComponents method call.
325
326 Groups the results into two groups: 'matches' and 'errors', and prints out
327 their values.
328 """
Andy Chengc531e2f2012-10-15 19:09:17 +0800329 # group by matches and errors
Tammo Spalink214caf42012-05-28 10:45:00 +0800330 matches = []
Andy Chengc531e2f2012-10-15 19:09:17 +0800331 errors = []
332 for result_list in result.values():
333 for component_name, _, error in result_list:
334 if component_name:
335 matches.append(component_name)
Tammo Spalink214caf42012-05-28 10:45:00 +0800336 else:
Andy Chengc531e2f2012-10-15 19:09:17 +0800337 errors.append(error)
338
Andy Cheng228a8c92012-08-27 10:53:57 +0800339 if matches:
340 print 'found probeable components:\n %s' % '\n '.join(matches)
Tammo Spalink214caf42012-05-28 10:45:00 +0800341 if errors:
Andy Cheng228a8c92012-08-27 10:53:57 +0800342 print '\nerrors:\n %s' % '\n '.join(errors)
343 sys.exit('\ncomponent verification FAILURE')
Tammo Spalink214caf42012-05-28 10:45:00 +0800344 else:
Andy Cheng228a8c92012-08-27 10:53:57 +0800345 print "\ncomponent verification SUCCESS"
Tammo Spalink214caf42012-05-28 10:45:00 +0800346
347
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800348@Command('verify_hwid',
Tammo Spalink95c43732012-07-25 15:57:14 -0700349 _hwid_status_list_cmd_arg,
Jon Salz0f8a6842012-09-25 11:28:22 +0800350 _hwdb_path_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800351 _probe_results_cmd_arg,
352 _hwid_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800353def VerifyHwid(options):
354 """Verify system HWID properties match probed device properties.
355
356 First probe components, volatile and initial_config parameters for
357 the DUT. Then use the available device data to produce a list of
358 candidate HWIDs. Then verify the HWID from the DUT is present in
359 that list. Then verify that the DUT initial config values match
360 those specified for its HWID. Finally, verify that VPD contains all
361 the necessary fields as specified by the board data, and when
362 possible verify that values are legitimate.
363 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800364
Ricky Liangf7857c12012-09-17 13:34:41 +0800365 def VerifyVpd(ro_vpd_keys, rw_vpd_keys):
Tammo Spalink5c699832012-07-03 17:50:39 +0800366 for key in ro_vpd_keys:
367 if key not in ro_vpd:
Ricky Liangf7857c12012-09-17 13:34:41 +0800368 sys.exit('Missing required RO VPD field: %s' % key)
Tammo Spalink01e11722012-07-24 10:17:54 -0700369 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800370 value = ro_vpd[key]
Ricky Liangf7857c12012-09-17 13:34:41 +0800371 if (known_valid_values is not None) and (value not in known_valid_values):
372 sys.exit('Invalid RO VPD entry : key %r, value %r' % (key, value))
Ricky Liangf7857c12012-09-17 13:34:41 +0800373 for key in rw_vpd_keys:
374 if key not in rw_vpd:
375 sys.exit('Missing required RW VPD field: %s' % key)
376 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
377 value = rw_vpd[key]
378 if (known_valid_values is not None) and (value not in known_valid_values):
379 sys.exit('Invalid RW VPD entry : key %r, value %r' % (key, value))
Jon Salz8baad8b2013-03-11 20:01:45 +0800380 _event_log.Log('vpd', ro_vpd=FilterDict(ro_vpd), rw_vpd=FilterDict(rw_vpd))
Tammo Spalink5c699832012-07-03 17:50:39 +0800381 map(hwid_tool.Validate.Status, options.status)
Jon Salz0f8a6842012-09-25 11:28:22 +0800382
Jon Salz81350812012-10-11 16:13:22 +0800383 if not options.hwid or not options.probe_results:
384 main_fw_file = crosfw.LoadMainFirmware().GetFileName()
Jon Salz0f8a6842012-09-25 11:28:22 +0800385
386 if options.hwid:
387 hwid_str = options.hwid
388 else:
389 gbb_result = Shell('gbb_utility -g --hwid %s' % main_fw_file).stdout
390 hwid_str = re.findall(r'hardware_id:(.*)', gbb_result)[0].strip()
Tammo Spalink95c43732012-07-25 15:57:14 -0700391 hwid = hwid_tool.ParseHwid(hwid_str)
Tammo Spalink5c699832012-07-03 17:50:39 +0800392 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Jon Salz0f8a6842012-09-25 11:28:22 +0800393 print 'Verifying HWID: %r\n' % hwid.hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700394 device = hw_db.GetDevice(hwid.board)
395 hwid_status = device.GetHwidStatus(hwid.bom, hwid.variant, hwid.volatile)
396 if hwid_status not in options.status:
Tammo Spalink5c699832012-07-03 17:50:39 +0800397 sys.exit('HWID status must be one of [%s], found %r' %
Hung-Te Lin4f5beb12012-08-20 14:48:06 +0800398 (', '.join(options.status), hwid_status))
Jon Salz0f8a6842012-09-25 11:28:22 +0800399 if options.probe_results:
400 # Pull in probe results (including VPD data) from the given file
401 # rather than probing the current system.
402 probe_results = hwid_tool.ProbeResults.Decode(
403 open(options.probe_results).read())
404 ro_vpd = {}
405 rw_vpd = {}
406 for k, v in probe_results.found_volatile_values.items():
407 match = re.match('^vpd\.(ro|rw)\.(\w+)$', k)
408 if match:
409 del probe_results.found_volatile_values[k]
410 (ro_vpd if match.group(1) == 'ro' else rw_vpd)[match.group(2)] = v
411 else:
412 probe_results = Probe()
413 ro_vpd = ReadRoVpd(main_fw_file)
414 rw_vpd = ReadRwVpd(main_fw_file)
Tammo Spalink95c43732012-07-25 15:57:14 -0700415 cooked_components = hw_db.comp_db.MatchComponentProbeValues(
416 probe_results.found_probe_value_map)
417 cooked_volatiles = device.MatchVolatileValues(
418 probe_results.found_volatile_values)
419 cooked_initial_configs = device.MatchInitialConfigValues(
420 probe_results.initial_configs)
421 component_data = hwid_tool.ComponentData(
422 extant_components=cooked_components.matched,
423 classes_missing=probe_results.missing_component_classes)
424 match_tree = device.BuildMatchTree(
425 component_data, cooked_volatiles.matched_tags)
426 matched_hwids = device.GetMatchTreeHwids(match_tree)
427 print 'HWID status: %s\n' % hwid_status
428 print 'probed system components:'
429 print YamlWrite(cooked_components.__dict__)
430 print 'missing component classes:'
431 print YamlWrite(probe_results.missing_component_classes)
432 print 'probed volatiles:'
433 print YamlWrite(cooked_volatiles.__dict__)
434 print 'probed initial_configs:'
435 print YamlWrite(cooked_initial_configs)
436 print 'hwid match tree:'
437 print YamlWrite(match_tree)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800438 _event_log.Log(
Tammo Spalink5c699832012-07-03 17:50:39 +0800439 'probe',
Tammo Spalink95c43732012-07-25 15:57:14 -0700440 found_components=cooked_components.__dict__,
441 missing_component_classes=probe_results.missing_component_classes,
442 volatiles=cooked_volatiles.__dict__,
443 initial_configs=cooked_initial_configs)
444 if hwid.hwid not in matched_hwids:
Tammo Spalink5c699832012-07-03 17:50:39 +0800445 err_msg = 'HWID verification FAILED.\n'
Tammo Spalink95c43732012-07-25 15:57:14 -0700446 if cooked_components.unmatched:
Tammo Spalink5c699832012-07-03 17:50:39 +0800447 sys.exit(err_msg + 'some components could not be indentified:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700448 YamlWrite(cooked_components.unmatched))
449 if not match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800450 sys.exit(err_msg + 'no matching boms were found for components:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700451 component_data.Encode())
452 if hwid.bom not in match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800453 sys.exit(err_msg + 'matching boms [%s] do not include target bom %r' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700454 (', '.join(sorted(match_tree)), hwid.bom))
455 err_msg += 'target bom %r matches components' % hwid.bom
456 if hwid.bom not in device.IntersectBomsAndInitialConfigs(
457 cooked_initial_configs):
Tammo Spalink5c699832012-07-03 17:50:39 +0800458 sys.exit(err_msg + ', but failed initial config verification')
Tammo Spalink95c43732012-07-25 15:57:14 -0700459 matched_variants = match_tree.get(hwid.bom, {})
460 if hwid.variant not in matched_variants:
Tammo Spalink5c699832012-07-03 17:50:39 +0800461 sys.exit(err_msg + ', but target variant_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700462 hwid.variant)
463 matched_volatiles = matched_variants.get(hwid.variant, {})
464 if hwid.volatile not in matched_volatiles:
Tammo Spalink5c699832012-07-03 17:50:39 +0800465 sys.exit(err_msg + ', but target volatile_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700466 hwid.volatile)
467 found_status = matched_volatiles.get(hwid.volatile, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800468 sys.exit(err_msg + ', but hwid status %r was unacceptable' % found_status)
Ricky Liangf7857c12012-09-17 13:34:41 +0800469 VerifyVpd(device.vpd_ro_fields, device.vpd_rw_fields)
Tammo Spalink5c699832012-07-03 17:50:39 +0800470 _event_log.Log('verified_hwid', hwid=hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -0700471 print 'Verification SUCCESS!'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800472
473
474@Command('verify_keys')
Tammo Spalink01e11722012-07-24 10:17:54 -0700475def VerifyKeys(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800476 """Verify keys in firmware and SSD match."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800477
Ricky Lianga70a1202013-03-15 15:03:17 +0800478 return GetGooftool(options).VerifyKeys()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800479
480
481@Command('set_fw_bitmap_locale')
Tammo Spalink01e11722012-07-24 10:17:54 -0700482def SetFirmwareBitmapLocale(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800483 """Use VPD locale value to set firmware bitmap default language."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800484
Ricky Lianga70a1202013-03-15 15:03:17 +0800485 (index, locale) = GetGooftool(options).SetFirmwareBitmapLocale()
Andy Cheng2582d292012-12-04 17:38:28 +0800486 logging.info('Firmware bitmap initial locale set to %d (%s).',
487 index, locale)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800488
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."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800493
Ricky Lianga70a1202013-03-15 15:03:17 +0800494 return GetGooftool(options).VerifySystemTime()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800495
496
497@Command('verify_rootfs')
Tammo Spalink01e11722012-07-24 10:17:54 -0700498def VerifyRootFs(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800499 """Verify rootfs on SSD is valid by checking hash."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800500
Ricky Lianga70a1202013-03-15 15:03:17 +0800501 return GetGooftool(options).VerifyRootFs()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800502
503
504@Command('verify_switch_wp')
Andy Chengc92e6f92012-11-20 16:55:53 +0800505def VerifyWPSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800506 """Verify hardware write protection switch is enabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800507
Ricky Lianga70a1202013-03-15 15:03:17 +0800508 GetGooftool(options).VerifyWPSwitch()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800509
510
511@Command('verify_switch_dev')
Tammo Spalink01e11722012-07-24 10:17:54 -0700512def VerifyDevSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800513 """Verify developer switch is disabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800514
Ricky Lianga70a1202013-03-15 15:03:17 +0800515 if GetGooftool(options).CheckDevSwitchForDisabling():
Hung-Te Lind7d34722012-07-26 16:48:35 +0800516 logging.warn('VerifyDevSwitch: No physical switch.')
517 _event_log.Log('switch_dev', type='virtual switch')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800518
519
520@Command('write_protect')
Tammo Spalink01e11722012-07-24 10:17:54 -0700521def EnableFwWp(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800522 """Enable then verify firmware write protection."""
523
Hung-Te Linb21c6682012-08-01 13:53:57 +0800524 def CalculateLegacyRange(fw_type, length, section_data,
525 section_name):
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800526 ro_size = length / 2
527 ro_a = int(section_data[0] / ro_size)
528 ro_b = int((section_data[0] + section_data[1] - 1) / ro_size)
529 if ro_a != ro_b:
530 raise Error("%s firmware section %s has illegal size" %
Hung-Te Linb21c6682012-08-01 13:53:57 +0800531 (fw_type, section_name))
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800532 ro_offset = ro_a * ro_size
533 return (ro_offset, ro_size)
534
535 def WriteProtect(fw_file_path, fw_type, legacy_section):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800536 """Calculate protection size, then invoke flashrom.
537
538 Our supported chips only allow write protecting half their total
539 size, so we parition the flash chipset space accordingly.
540 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800541
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800542 raw_image = open(fw_file_path, 'rb').read()
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800543 wp_section = 'WP_RO'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800544 image = crosfw.FirmwareImage(raw_image)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800545 if image.has_section(wp_section):
546 section_data = image.get_section_area(wp_section)
547 ro_offset = section_data[0]
548 ro_size = section_data[1]
549 elif image.has_section(legacy_section):
550 section_data = image.get_section_area(legacy_section)
551 (ro_offset, ro_size) = CalculateLegacyRange(
Hung-Te Linb21c6682012-08-01 13:53:57 +0800552 fw_type, len(raw_image), section_data, legacy_section)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800553 else:
554 raise Error('could not find %s firmware section %s or %s' %
555 (fw_type, wp_section, legacy_section))
556
557 logging.debug('write protecting %s [off=%x size=%x]', fw_type,
558 ro_offset, ro_size)
559 crosfw.Flashrom(fw_type).EnableWriteProtection(ro_offset, ro_size)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800560
561 WriteProtect(crosfw.LoadMainFirmware().GetFileName(), 'main', 'RO_SECTION')
Tammo Spalink86a61c62012-05-25 15:10:35 +0800562 _event_log.Log('wp', fw='main')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800563 ec_fw_file = crosfw.LoadEcFirmware().GetFileName()
564 if ec_fw_file is not None:
565 WriteProtect(ec_fw_file, 'ec', 'EC_RO')
Tammo Spalink86a61c62012-05-25 15:10:35 +0800566 _event_log.Log('wp', fw='ec')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800567 else:
568 logging.warning('EC not write protected (seems there is no EC flash).')
569
570
571@Command('clear_gbb_flags')
Andy Chengc92e6f92012-11-20 16:55:53 +0800572def ClearGBBFlags(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800573 """Zero out the GBB flags, in preparation for transition to release state.
574
575 No GBB flags are set in release/shipping state, but they are useful
576 for factory/development. See "gbb_utility --flags" for details.
577 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800578
Ricky Lianga70a1202013-03-15 15:03:17 +0800579 GetGooftool(options).ClearGBBFlags()
Tammo Spalink86a61c62012-05-25 15:10:35 +0800580 _event_log.Log('clear_gbb_flags')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800581
582
583@Command('prepare_wipe',
584 CmdArg('--fast', action='store_true',
585 help='use non-secure but faster wipe method.'))
586def PrepareWipe(options):
587 """Prepare system for transition to release state in next reboot."""
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800588
Ricky Lianga70a1202013-03-15 15:03:17 +0800589 GetGooftool(options).PrepareWipe(options.fast)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800590
591@Command('verify',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800592 CmdArg('--no_write_protect', action='store_true',
593 help='Do not check write protection switch state.'),
Tammo Spalink95c43732012-07-25 15:57:14 -0700594 _hwid_status_list_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800595 _hwdb_path_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800596 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800597 _probe_results_cmd_arg,
598 _hwid_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800599def Verify(options):
600 """Verifies if whole factory process is ready for finalization.
601
602 This routine performs all the necessary checks to make sure the
603 device is ready to be finalized, but does not modify state. These
604 checks include dev switch, firmware write protection switch, hwid,
605 system time, keys, and root file system.
606 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800607
Hung-Te Lin6d827542012-07-19 11:50:41 +0800608 if not options.no_write_protect:
Ricky Lianga70a1202013-03-15 15:03:17 +0800609 VerifyWPSwitch(options)
610 VerifyDevSwitch(options)
611 if options.hwid_version == 2:
612 VerifyHwid(options)
613 elif options.hwid_version == 3:
614 VerifyHwidV3(options)
615 else:
616 raise Error, 'Invalid HWID version: %r' % options.hwid_version
617 VerifySystemTime(options)
618 VerifyKeys(options)
619 VerifyRootFs(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800620
621
Tammo Spalink86a61c62012-05-25 15:10:35 +0800622@Command('log_system_details')
Tammo Spalink01e11722012-07-24 10:17:54 -0700623def LogSystemDetails(options): # pylint: disable=W0613
Tammo Spalink86a61c62012-05-25 15:10:35 +0800624 """Write miscellaneous system details to the event log."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800625
Ricky Lianga70a1202013-03-15 15:03:17 +0800626 _event_log.Log('system_details', **Gooftool(
627 hwid_version=options.hwid_version).GetSystemDetails())
Tammo Spalink86a61c62012-05-25 15:10:35 +0800628
629
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800630_upload_method_cmd_arg = CmdArg(
631 '--upload_method', metavar='METHOD:PARAM',
632 help=('How to perform the upload. METHOD should be one of '
cychiang3b15bd52012-09-08 13:58:18 +0800633 '{ftp, shopfloor, ftps, cpfe}.'))
Jon Salz65266432012-07-30 19:02:49 +0800634_add_file_cmd_arg = CmdArg(
635 '--add_file', metavar='FILE', action='append',
636 help='Extra file to include in report (must be an absolute path)')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800637
638@Command('upload_report',
Jon Salz65266432012-07-30 19:02:49 +0800639 _upload_method_cmd_arg,
640 _add_file_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800641def UploadReport(options):
642 """Create and a report containing key device details."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800643
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800644 def NormalizeAsFileName(token):
645 return re.sub(r'\W+', '', token).strip()
Tammo Spalink86a61c62012-05-25 15:10:35 +0800646 ro_vpd = ReadRoVpd(crosfw.LoadMainFirmware().GetFileName())
647 device_sn = ro_vpd.get('serial_number', None)
648 if device_sn is None:
649 logging.warning('RO_VPD missing device serial number')
650 device_sn = 'MISSING_SN_' + TimedUuid()
Vic Yang85199e72013-01-28 14:33:11 +0800651 target_name = '%s_%s.tar.xz' % (time.strftime('%Y%m%dT%H%M%SZ',
652 time.gmtime()),
653 NormalizeAsFileName(device_sn))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800654 target_path = os.path.join(gettempdir(), target_name)
655 # Intentionally ignoring dotfiles in EVENT_LOG_DIR.
Vic Yang85199e72013-01-28 14:33:11 +0800656 tar_cmd = 'cd %s ; tar cJf %s *' % (EVENT_LOG_DIR, target_path)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800657 tar_cmd += ' --add-file %s' % FACTORY_LOG_PATH
Jon Salz65266432012-07-30 19:02:49 +0800658 if options.add_file:
659 for f in options.add_file:
660 # Require absolute paths since the tar command may change the
661 # directory.
662 if not f.startswith('/'):
663 raise Error('Not an absolute path: %s' % f)
664 if not os.path.exists(f):
665 raise Error('File does not exist: %s' % f)
666 tar_cmd += ' --add-file %s' % pipes.quote(f)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800667 cmd_result = Shell(tar_cmd)
Jon Salzff88c022012-11-03 12:19:58 +0800668
669 if ((cmd_result.status == 1) and
670 all((x == '' or
671 'file changed as we read it' in x or
672 "Removing leading `/' from member names" in x)
673 for x in cmd_result.stderr.split('\n'))):
674 # That's OK. Make sure it's valid though.
Vic Yang85199e72013-01-28 14:33:11 +0800675 Spawn(['tar', 'tfJ', target_path], check_call=True, log=True,
Jon Salzff88c022012-11-03 12:19:58 +0800676 ignore_stdout=True)
677 elif not cmd_result.success:
Tammo Spalink86a61c62012-05-25 15:10:35 +0800678 raise Error('unable to tar event logs, cmd %r failed, stderr: %r' %
679 (tar_cmd, cmd_result.stderr))
Jon Salzff88c022012-11-03 12:19:58 +0800680
Tammo Spalink86a61c62012-05-25 15:10:35 +0800681 if options.upload_method is None or options.upload_method == 'none':
682 logging.warning('REPORT UPLOAD SKIPPED (report left at %s)', target_path)
683 return
684 method, param = options.upload_method.split(':', 1)
685 if method == 'shopfloor':
686 report_upload.ShopFloorUpload(target_path, param)
687 elif method == 'ftp':
Jay Kim360c1dd2012-06-25 10:58:11 -0700688 report_upload.FtpUpload(target_path, 'ftp:' + param)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800689 elif method == 'ftps':
690 report_upload.CurlUrlUpload(target_path, '--ftp-ssl-reqd ftp:%s' % param)
691 elif method == 'cpfe':
Shawn Nematbakhsh3404a092013-01-28 16:49:09 -0800692 report_upload.CpfeUpload(target_path, pipes.quote(param))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800693 else:
694 raise Error('unknown report upload method %r', method)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800695
696
697@Command('finalize',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800698 CmdArg('--no_write_protect', action='store_true',
699 help='Do not enable firmware write protection.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800700 CmdArg('--fast', action='store_true',
701 help='use non-secure but faster wipe method.'),
702 _hwdb_path_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700703 _hwid_status_list_cmd_arg,
Jon Salz65266432012-07-30 19:02:49 +0800704 _upload_method_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800705 _add_file_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800706 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800707 _probe_results_cmd_arg,
708 _hwid_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800709def Finalize(options):
710 """Verify system readiness and trigger transition into release state.
711
Hung-Te Lin6d827542012-07-19 11:50:41 +0800712 This routine first verifies system state (see verify command), modifies
713 firmware bitmaps to match locale, and then clears all of the factory-friendly
714 flags from the GBB. If everything is fine, it enables firmware write
715 protection (cannot rollback after this stage), uploads system logs & reports,
716 and sets the necessary boot flags to cause wipe of the factory image on the
717 next boot.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800718 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800719
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800720 Verify(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800721 SetFirmwareBitmapLocale(options)
722 ClearGBBFlags(options)
Hung-Te Lin6d827542012-07-19 11:50:41 +0800723 if options.no_write_protect:
724 logging.warn('WARNING: Firmware Write Protection is SKIPPED.')
725 _event_log.Log('wp', fw='both', status='skipped')
726 else:
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800727 EnableFwWp({})
Jon Salza0f58e02012-05-29 19:33:39 +0800728 LogSystemDetails(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800729 UploadReport(options)
730 PrepareWipe(options)
731
732
Ricky Liang53390232013-03-08 15:37:57 +0800733@Command('verify_components_v3',
734 _board_cmd_arg,
735 _hwdb_path_cmd_arg,
736 CmdArg('target_comps', nargs='*'))
737def VerifyComponentsV3(options):
738 """Verify that probeable components all match entries in the component_db.
739
740 This method uses the HWIDv3 component database to verify components.
741
742 Probe for each component class in the target_comps and verify
743 that a corresponding match exists in the component_db -- make sure
744 that these components are present, that they have been approved, but
745 do not check against any specific BOM/HWID configurations.
746 """
747
Ricky Lianga70a1202013-03-15 15:03:17 +0800748 result = GetGooftool(options).VerifyComponentsV3(options.target_comps)
Ricky Liang53390232013-03-08 15:37:57 +0800749 PrintVerifyComponentsResults(result)
750
751
752@Command('generate_hwid_v3',
753 _board_cmd_arg,
754 _hwdb_path_cmd_arg,
755 _device_info_cmd_arg)
756def GenerateHwidV3(options):
757 """Generates the HWID of the DUT.
758
759 The HWID is generated based on the given device info and the probe results
760 retrieved by probing the DUT. If there are conflits of component information
761 between device info and probe result, priority is given to device info.
762 """
763 try:
764 device_info = eval(options.device_info)
765 except Exception, e:
766 raise Error, 'Invalid device_info: %s' % e
767 probe_results = Probe()
768 print 'device_info:'
769 print device_info
770 print 'probe result:'
771 print probe_results.Encode()
772
773 # Do not log device_info for now until we're sure that it does not contain
774 # any sensitive infomation.
775 # TODO(jcliang): Add logging for device_info when appropriate.
776
777 _event_log.Log(
778 'probe',
779 found_components=probe_results.found_probe_value_map,
780 missing_component_classes=probe_results.missing_component_classes,
781 volatiles=probe_results.found_volatile_values,
782 initial_configs=probe_results.initial_configs)
783
Ricky Lianga70a1202013-03-15 15:03:17 +0800784 hwid_object = GetGooftool(options).GenerateHwidV3(
785 device_info, probe_results.Encode())
Ricky Liang53390232013-03-08 15:37:57 +0800786
787 final_bom = {}
788 for component_class, component_values in (
789 hwid_object.bom.components.iteritems()):
790 final_bom[component_class] = [v.probed_string for v in component_values]
791 _event_log.Log(
792 'final_bom',
793 final_bom=final_bom)
794 _event_log.Log(
795 'generated_hwid',
796 encoded_string=hwid_object.encoded_string,
797 binary_string=hwid_object.binary_string)
798 print 'Encoded HWID string:', hwid_object.encoded_string
799 print 'Binary HWID string:', hwid_object.binary_string
800
801
802@Command('verify_hwid_v3',
803 _board_cmd_arg,
804 _hwdb_path_cmd_arg,
805 _hwid_cmd_arg)
806def VerifyHwidV3(options):
807 """Verify system HWID properties match probed device properties.
808
809 First probe components, volatile and initial_config parameters for
810 the DUT. Then use the available device data to produce a list of
811 candidate HWIDs. Then verify the HWID from the DUT is present in
812 that list. Then verify that the DUT initial config values match
813 those specified for its HWID. Finally, verify that VPD contains all
814 the necessary fields as specified by the board data, and when
815 possible verify that values are legitimate.
816 """
817 main_fw_file = crosfw.LoadMainFirmware().GetFileName()
818 if options.hwid:
819 hwid_str = options.hwid
820 else:
821 gbb_result = Shell('gbb_utility -g --hwid %s' % main_fw_file).stdout
822 hwid_str = re.findall(r'hardware_id:(.*)', gbb_result)[0].strip()
823 print 'Verifying HWID: %r\n' % hwid_str
824 probe_results = Probe()
825 probed_ro_vpd = ReadRoVpd(main_fw_file)
826 probed_rw_vpd = ReadRwVpd(main_fw_file)
827 print 'probe result:'
828 print probe_results.Encode()
829 _event_log.Log(
830 'probe',
831 found_components=probe_results.found_probe_value_map,
832 missing_component_classes=probe_results.missing_component_classes,
833 volatiles=probe_results.found_volatile_values,
834 initial_configs=probe_results.initial_configs)
835 _event_log.Log('vpd', probed_ro_vpd=FilterDict(probed_ro_vpd),
836 probed_rw_vpd=FilterDict(probed_rw_vpd))
837
Ricky Lianga70a1202013-03-15 15:03:17 +0800838 GetGooftool(options).VerifyHwidV3(
839 hwid_str, probe_results.Encode(), probed_ro_vpd, probed_rw_vpd)
Ricky Liang53390232013-03-08 15:37:57 +0800840
841 _event_log.Log('verified_hwid', hwid=hwid_str)
842 print 'Verification SUCCESS!'
843
844
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800845def Main():
846 """Run sub-command specified by the command line args."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800847
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800848 options = ParseCmdline(
849 'Perform Google required factory tests.',
850 CmdArg('-l', '--log', metavar='PATH',
851 help='Write logs to this file.'),
Jon Salza4bea382012-10-29 13:00:34 +0800852 CmdArg('--suppress-event-logs', action='store_true',
853 help='Suppress event logging.'),
Ricky Lianga70a1202013-03-15 15:03:17 +0800854 CmdArg('-i', '--hwid-version', default=2, choices=[2, 3], type=int,
855 help='Version of HWID to operate on.'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800856 verbosity_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800857 SetupLogging(options.verbosity, options.log)
Jon Salza4bea382012-10-29 13:00:34 +0800858 _event_log.suppress = options.suppress_event_logs
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800859 logging.debug('gooftool options: %s', repr(options))
860 try:
861 logging.debug('GOOFTOOL command %r', options.command_name)
862 options.command(options)
863 logging.info('GOOFTOOL command %r SUCCESS', options.command_name)
864 except Error, e:
865 logging.exception(e)
866 sys.exit('GOOFTOOL command %r ERROR: %s' % (options.command_name, e))
867 except Exception, e:
868 logging.exception(e)
869 sys.exit('UNCAUGHT RUNTIME EXCEPTION %s' % e)
870
871
872if __name__ == '__main__':
873 Main()