blob: d69c559399271cea91e11a9a5a5d77fe9ad53cd8 [file] [log] [blame]
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001#!/usr/bin/python
Jon Salze60307f2014-08-05 16:20:00 +08002# -*- coding: utf-8 -*-
3# Copyright 2014 The Chromium OS Authors. All rights reserved.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08004# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
Jon Salze60307f2014-08-05 16:20:00 +08007# pylint: disable=E1101
8
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08009"""Google Factory Tool.
10
11This tool is indended to be used on factory assembly lines. It
12provides all of the Google required test functionality and must be run
13on each device as part of the assembly process.
14"""
15
Ricky Liang5b4568d2013-04-23 17:15:23 +080016import collections
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080017import logging
18import os
Jon Salz65266432012-07-30 19:02:49 +080019import pipes
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080020import re
21import sys
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080022import threading
Hung-Te Lin6bd16472012-06-20 16:26:47 +080023import time
Jon Salza88b83b2013-05-27 20:00:35 +080024import xmlrpclib
Ricky Liang7905f272013-03-16 01:57:10 +080025import yaml
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080026
Andy Cheng2582d292012-12-04 17:38:28 +080027from tempfile import gettempdir
Tammo Spalink86a61c62012-05-25 15:10:35 +080028
Tammo Spalinka40293e2012-07-04 14:58:56 +080029import factory_common # pylint: disable=W0611
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080030
Joel Kitchingd3bc2662014-12-16 16:03:32 -080031from cros.factory.common import SetupLogging, Shell
Andy Chengc531e2f2012-10-15 19:09:17 +080032from cros.factory.gooftool import Gooftool
Ricky Liang53390232013-03-08 15:37:57 +080033from cros.factory.gooftool import crosfw
Tammo Spalink01e11722012-07-24 10:17:54 -070034from cros.factory.gooftool import report_upload
Andy Cheng8ece7382012-08-22 16:25:42 +080035from cros.factory.gooftool.probe import Probe, PROBEABLE_COMPONENT_CLASSES
Jon Salz0f8a6842012-09-25 11:28:22 +080036from cros.factory.gooftool.probe import ReadRoVpd, ReadRwVpd
henryhsu44d793a2013-07-20 00:07:38 +080037from cros.factory.gooftool.probe import CalculateFirmwareHashes
Jon Salz193d7c62013-03-07 13:40:19 +080038from cros.factory.gooftool.vpd_data import KNOWN_VPD_FIELD_DATA
Tammo Spalinka40293e2012-07-04 14:58:56 +080039from cros.factory.hacked_argparse import CmdArg, Command, ParseCmdline
40from cros.factory.hacked_argparse import verbosity_cmd_arg
Tammo Spalink01e11722012-07-24 10:17:54 -070041from cros.factory.hwdb import hwid_tool
Hung-Te Linca61e732014-08-27 10:27:25 +080042from cros.factory.hwdb.yaml_datastore import YamlWrite
Ricky Liangeede7922013-06-19 10:18:41 +080043from cros.factory.hwid import common
Ricky Liangc662be32013-12-24 11:50:23 +080044from cros.factory.hwid import hwid_utils
Hung-Te Lin91492a12014-11-25 18:56:30 +080045from cros.factory.test import event_log
Jon Salz40b9f822014-07-25 16:39:55 +080046from cros.factory.test import factory
Jon Salzfe9036f2014-01-16 14:11:23 +080047from cros.factory.test.factory import FACTORY_LOG_PATH, DEVICE_STATEFUL_PATH
Jon Salz40b9f822014-07-25 16:39:55 +080048from cros.factory.utils import file_utils
Jon Salzff88c022012-11-03 12:19:58 +080049from cros.factory.utils.process_utils import Spawn
Joel Kitchingd3bc2662014-12-16 16:03:32 -080050from cros.factory.utils.type_utils import Error
Jon Salz8baad8b2013-03-11 20:01:45 +080051from cros.factory.privacy import FilterDict
Tammo Spalink86a61c62012-05-25 15:10:35 +080052
Tammo Spalink5c699832012-07-03 17:50:39 +080053
Tammo Spalink5c699832012-07-03 17:50:39 +080054# TODO(tammo): Replace calls to sys.exit with raise Exit, and maybe
55# treat that specially (as a smoot exit, as opposed to the more
56# verbose output for generic Error).
57
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080058_global_gooftool = None
59_gooftool_lock = threading.Lock()
Tammo Spalink5c699832012-07-03 17:50:39 +080060
Hung-Te Lin56b18402015-01-16 14:52:30 +080061
Ricky Lianga70a1202013-03-15 15:03:17 +080062def GetGooftool(options):
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080063 global _global_gooftool # pylint: disable=W0603
Ricky Lianga70a1202013-03-15 15:03:17 +080064
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080065 if _global_gooftool is None:
66 with _gooftool_lock:
Ricky Liang43b879b2014-02-24 11:36:55 +080067 hwid_version = getattr(options, 'hwid_version', 3)
68 if hwid_version == 2:
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080069 hwdb_path = getattr(options, 'hwdb_path', None)
70 component_db = (
71 hwid_tool.HardwareDb(options.hwdb_path).comp_db if hwdb_path
72 else None)
73 _global_gooftool = Gooftool(hwid_version=2, component_db=component_db)
Ricky Liang43b879b2014-02-24 11:36:55 +080074 elif hwid_version == 3:
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080075 board = getattr(options, 'board', None)
76 hwdb_path = getattr(options, 'hwdb_path', None)
77 _global_gooftool = Gooftool(hwid_version=3, board=board,
78 hwdb_path=hwdb_path)
79 else:
80 raise Error, 'Invalid HWID version: %r' % options.hwid_version
81
82 return _global_gooftool
Ricky Lianga70a1202013-03-15 15:03:17 +080083
Hung-Te Lin56b18402015-01-16 14:52:30 +080084
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080085@Command('write_hwid',
86 CmdArg('hwid', metavar='HWID', help='HWID string'))
Andy Chengc92e6f92012-11-20 16:55:53 +080087def WriteHWID(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080088 """Write specified HWID value into the system BB."""
Andy Cheng7a76cb82012-11-19 18:08:19 +080089
Tammo Spalink95c43732012-07-25 15:57:14 -070090 logging.info('writing hwid string %r', options.hwid)
Ricky Lianga70a1202013-03-15 15:03:17 +080091 GetGooftool(options).WriteHWID(options.hwid)
Andy Cheng0465d132013-03-20 12:12:06 +080092 event_log.Log('write_hwid', hwid=options.hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -070093 print 'Wrote HWID: %r' % options.hwid
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080094
95
Ricky Liang53390232013-03-08 15:37:57 +080096_board_cmd_arg = CmdArg(
97 '--board', metavar='BOARD',
98 default=None, help='Board name to test.')
99
Tammo Spalink8fab5312012-05-28 18:33:30 +0800100_hwdb_path_cmd_arg = CmdArg(
101 '--hwdb_path', metavar='PATH',
Ricky Liangeede7922013-06-19 10:18:41 +0800102 default=common.DEFAULT_HWID_DATA_PATH,
Tammo Spalink8fab5312012-05-28 18:33:30 +0800103 help='Path to the HWID database.')
104
Tammo Spalink95c43732012-07-25 15:57:14 -0700105_hwid_status_list_cmd_arg = CmdArg(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800106 '--status', nargs='*', default=['supported'],
107 help='allow only HWIDs with these status values')
Tammo Spalink95c43732012-07-25 15:57:14 -0700108
Jon Salzce124fb2012-10-02 17:42:03 +0800109_probe_results_cmd_arg = CmdArg(
110 '--probe_results', metavar='RESULTS.yaml',
Ricky Liangc662be32013-12-24 11:50:23 +0800111 help=('Output from "gooftool probe --include_vpd" (used instead of '
Jon Salzce124fb2012-10-02 17:42:03 +0800112 'probing this system).'))
113
Ricky Liang53390232013-03-08 15:37:57 +0800114_device_info_cmd_arg = CmdArg(
Ricky Liangf89f73a2013-03-19 05:00:24 +0800115 '--device_info', metavar='DEVICE_INFO.yaml', default=None,
Ricky Liang53390232013-03-08 15:37:57 +0800116 help='A dict of device info to use instead of fetching from shopfllor '
117 'server.')
118
Jon Salzce124fb2012-10-02 17:42:03 +0800119_hwid_cmd_arg = CmdArg(
120 '--hwid', metavar='HWID',
Ricky Lianga70a1202013-03-15 15:03:17 +0800121 help='HWID to verify (instead of the currently set HWID of this system).')
Jon Salzce124fb2012-10-02 17:42:03 +0800122
Bernie Thompson3c11c872013-07-22 18:22:45 -0700123_rma_mode_cmd_arg = CmdArg(
124 '--rma_mode', action='store_true',
125 help='Enable RMA mode, do not check for deprecated components.')
Tammo Spalink95c43732012-07-25 15:57:14 -0700126
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800127_cros_core_cmd_arg = CmdArg(
128 '--cros_core', action='store_true',
129 help='Finalize for ChromeOS Core devices (may add or remove few test '
130 'items. For example, branding verification or firmware bitmap '
131 'locale settings).')
132
Ricky Liang43b879b2014-02-24 11:36:55 +0800133_hwid_version_cmd_arg = CmdArg(
134 '-i', '--hwid-version', default=3, choices=(2, 3), type=int,
135 help='Version of HWID to operate on. (default: %(default)s)')
136
137
Tammo Spalink95c43732012-07-25 15:57:14 -0700138@Command('best_match_hwids',
Tammo Spalink8fab5312012-05-28 18:33:30 +0800139 _hwdb_path_cmd_arg,
140 CmdArg('-b', '--board', metavar='BOARD',
Tammo Spalink95c43732012-07-25 15:57:14 -0700141 help='optional BOARD name, needed only if data is present '
142 'for more than one'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800143 CmdArg('--bom', metavar='BOM', help='BOM name'),
144 CmdArg('--variant', metavar='VARIANT', help='VARIANT code'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800145 CmdArg('--optimistic', action='store_true',
146 help='do not probe; assume singletons match'),
Tammo Spalink95c43732012-07-25 15:57:14 -0700147 CmdArg('--comps', nargs='*', default=[],
148 help='list of canonical component names'),
149 CmdArg('--missing', nargs='*', default=[],
150 help='list component classes to be assumed missing'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800151 CmdArg('--status', nargs='*', default=['supported'],
Tammo Spalink95c43732012-07-25 15:57:14 -0700152 help='consider only HWIDs within this list of status values'))
153def BestMatchHwids(options):
Ricky Liangc662be32013-12-24 11:50:23 +0800154 """Determine a list of possible HWIDs using provided args and probing.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800155
156 VOLATILE can always be determined by probing. To get a unique
157 result, VARIANT must be specified for all cases where the matching
158 BOM has more than one associated variant code, otherwise all HWID
159 variants will be returned. Both VARIANT and BOM information can
Tammo Spalink95c43732012-07-25 15:57:14 -0700160 alternatively be specified using the --stdin_comps argument, which
161 allows specifying a list of canonical names (one per line) on stdin,
162 one per line. Based on what is known from BOM and stdin_comps,
163 determine a list of components to probe for, and use those probe
164 results to resolve a list of matching HWIDs. If no boms,
165 components, or variant codes are specified, then a list of all HWIDs
Andy Cheng8ece7382012-08-22 16:25:42 +0800166 that match probeable components will be returned.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800167
168 Returns (on stdout): A list of HWIDs that match the available probe
169 results and argument contraints, one per line.
Tammo Spalink70b48a52012-08-08 16:54:51 -0700170
171 Example:
172
173 // Three ways to specify a keyboard (assuming it is a variant component)
174 gooftool best_match_hwids --missing keyboard
175 gooftool best_match_hwids --variant A or
176 gooftool best_match_hwids --comps us_kbd
Tammo Spalink8fab5312012-05-28 18:33:30 +0800177 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800178
Tammo Spalink5c699832012-07-03 17:50:39 +0800179 map(hwid_tool.Validate.Status, options.status)
Tammo Spalink95c43732012-07-25 15:57:14 -0700180 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Tammo Spalink5c699832012-07-03 17:50:39 +0800181 comp_db = hw_db.comp_db
Tammo Spalink3a7e9022012-06-27 14:08:40 +0800182 device = hw_db.GetDevice(options.board)
Tammo Spalink5c699832012-07-03 17:50:39 +0800183 component_spec = hwid_tool.ComponentSpec.New()
Tammo Spalink8fab5312012-05-28 18:33:30 +0800184 if options.bom:
Tammo Spalink5c699832012-07-03 17:50:39 +0800185 device.BomExists(options.bom)
Tammo Spalink01e11722012-07-24 10:17:54 -0700186 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800187 component_spec, device.boms[options.bom].primary)
Tammo Spalink8fab5312012-05-28 18:33:30 +0800188 if options.variant:
Tammo Spalink5c699832012-07-03 17:50:39 +0800189 device.VariantExists(options.variant)
190 variant_spec = device.variants[options.variant]
Tammo Spalink01e11722012-07-24 10:17:54 -0700191 if hwid_tool.ComponentSpecsConflict(component_spec, variant_spec):
Tammo Spalink95c43732012-07-25 15:57:14 -0700192 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700193 % YamlWrite(sorted(
194 hwid_tool.ComponentSpecClasses(component_spec) &
195 hwid_tool.ComponentSpecClasses(variant_spec))))
Tammo Spalink01e11722012-07-24 10:17:54 -0700196 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800197 component_spec, variant_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700198 if options.comps or options.missing:
199 map(comp_db.CompExists, options.comps)
200 map(comp_db.CompClassExists, options.missing)
201 extra_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800202 components=options.comps,
203 missing=options.missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700204 print 'cmdline asserted components:\n%s' % extra_comp_spec.Encode()
205 if hwid_tool.ComponentSpecsConflict(component_spec, extra_comp_spec):
206 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700207 % YamlWrite(sorted(
208 hwid_tool.ComponentSpecClasses(component_spec) &
209 hwid_tool.ComponentSpecClasses(extra_comp_spec))))
Tammo Spalink95c43732012-07-25 15:57:14 -0700210 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800211 component_spec, extra_comp_spec)
Tammo Spalink01e11722012-07-24 10:17:54 -0700212 spec_classes = hwid_tool.ComponentSpecClasses(component_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700213 missing_classes = set(comp_db.all_comp_classes) - spec_classes
Tammo Spalink5c699832012-07-03 17:50:39 +0800214 if missing_classes and not options.optimistic:
Andy Cheng8ece7382012-08-22 16:25:42 +0800215 non_probeable_missing = missing_classes - PROBEABLE_COMPONENT_CLASSES
216 if non_probeable_missing:
Tammo Spalink95c43732012-07-25 15:57:14 -0700217 sys.exit('FAILURE: these classes are necessary, were not specified '
Tammo Spalink70b48a52012-08-08 16:54:51 -0700218 'as inputs, and cannot be probed for:\n%s'
219 'This problem can often be addressed by specifying all of '
220 'the missing components on the command line (see the command '
Andy Cheng8ece7382012-08-22 16:25:42 +0800221 'help).' % YamlWrite(list(non_probeable_missing)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700222 print 'probing for missing classes:'
223 print YamlWrite(list(missing_classes))
224 probe_results = Probe(target_comp_classes=list(missing_classes),
225 probe_volatile=False, probe_initial_config=False)
226 cooked_components = comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800227 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700228 if cooked_components.unmatched:
229 sys.exit('ERROR: some probed components are unrecognized:\n%s'
230 % YamlWrite(cooked_components.unmatched))
231 probed_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800232 components=cooked_components.matched,
233 missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700234 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800235 component_spec, probed_comp_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700236 print YamlWrite({'component data used for matching': {
Hung-Te Lin56b18402015-01-16 14:52:30 +0800237 'missing component classes': component_spec.classes_missing,
238 'found components': component_spec.components}})
Tammo Spalink95c43732012-07-25 15:57:14 -0700239 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800240 extant_components=hwid_tool.ComponentSpecCompClassMap(
241 component_spec).keys(),
242 classes_missing=component_spec.classes_missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700243 match_tree = device.BuildMatchTree(component_data)
244 if not match_tree:
245 sys.exit('FAILURE: NO matching BOMs found')
246 print 'potential BOMs/VARIANTs:'
247 potential_variants = set()
248 potential_volatiles = set()
249 for bom_name, variant_tree in match_tree.items():
250 print ' BOM: %-8s VARIANTS: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800251 bom_name, ', '.join(sorted(variant_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700252 for variant_code in variant_tree:
253 potential_variants.add(variant_code)
254 for volatile_code in device.volatiles:
255 status = device.GetHwidStatus(bom_name, variant_code, volatile_code)
256 if status in options.status:
257 potential_volatiles.add(volatile_code)
258 print ''
259 if len(potential_variants) == 0:
260 sys.exit('FAILURE: no matching VARIANTs found')
261 if len(potential_volatiles) == 0:
262 sys.exit('FAILURE: no VOLATILEs found for potential matching BOMs/VARIANTS '
263 '(with specified status)')
Tammo Spalink394e4492012-08-01 10:20:30 -0700264 if (options.optimistic and
265 len(match_tree) == 1 and
266 len(potential_variants) == 1 and
267 len(potential_volatiles) == 1):
268 print ('MATCHING HWID: %s' % device.FmtHwid(match_tree.keys().pop(),
269 potential_variants.pop(),
270 potential_volatiles.pop()))
Tammo Spalink5c699832012-07-03 17:50:39 +0800271 return
Tammo Spalink95c43732012-07-25 15:57:14 -0700272 print ('probing VOLATILEs to resolve potential matches: %s\n' %
273 ', '.join(sorted(potential_volatiles)))
274 vol_probe_results = Probe(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800275 target_comp_classes=[],
276 probe_volatile=True,
277 probe_initial_config=False)
Tammo Spalink95c43732012-07-25 15:57:14 -0700278 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800279 vol_probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700280 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800281 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700282 matched_hwids = device.GetMatchTreeHwids(match_tree)
283 if matched_hwids:
284 for hwid in matched_hwids:
Ricky Liang02f3bd72012-09-21 14:33:01 +0800285 if matched_hwids[hwid] in options.status:
286 print 'MATCHING HWID: %s' % hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700287 return
288 print 'exact HWID matching failed, but the following BOMs match: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800289 ', '.join(sorted(match_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700290 if options.optimistic and len(match_tree) == 1:
291 bom_name = set(match_tree).pop()
Tammo Spalink5c699832012-07-03 17:50:39 +0800292 bom = device.boms[bom_name]
Tammo Spalink95c43732012-07-25 15:57:14 -0700293 variant_matches = match_tree[bom_name]
Tammo Spalink5c699832012-07-03 17:50:39 +0800294 if len(variant_matches) == 1:
295 var_code = set(variant_matches).pop()
296 elif len(bom.variants) == 1:
297 var_code = set(bom.variants).pop()
298 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700299 sys.exit('FAILURE: NO matching HWIDs found; optimistic matching failed '
300 'because there were too many variants to choose from for BOM %r'
301 % bom_name)
302 hwids = [device.FmtHwid(bom_name, var_code, vol_code)
303 for vol_code in device.volatiles
304 if device.GetHwidStatus(bom_name, var_code, vol_code)
305 in options.status]
306 for hwid in hwids:
307 print 'MATCHING HWID: %s' % hwid
Tammo Spalink5c699832012-07-03 17:50:39 +0800308 return
309 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700310 print ('optimistic matching not attempted because either it was '
311 'not requested, or because the number of BOMs was <> 1\n')
312 sys.exit('FAILURE: NO matching HWIDs found')
Tammo Spalink8fab5312012-05-28 18:33:30 +0800313
314
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800315@Command('probe',
316 CmdArg('--comps', nargs='*',
317 help='List of keys from the component_db registry.'),
Ricky Liangb30da672013-06-14 12:36:34 +0800318 CmdArg('--fast_fw_probe', action='store_true',
319 help='Do a fast probe for EC and main firmware versions only. '
320 'This implies --no_vol and --no_ic.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800321 CmdArg('--no_vol', action='store_true',
322 help='Do not probe volatile data.'),
323 CmdArg('--no_ic', action='store_true',
Jon Salz0f8a6842012-09-25 11:28:22 +0800324 help='Do not probe initial_config data.'),
325 CmdArg('--include_vpd', action='store_true',
326 help='Include VPD data in volatiles.'))
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800327def RunProbe(options):
328 """Print yaml-formatted breakdown of probed device properties."""
Ricky Lianga70a1202013-03-15 15:03:17 +0800329 print GetGooftool(options).Probe(
330 target_comp_classes=options.comps,
Ricky Liangb30da672013-06-14 12:36:34 +0800331 fast_fw_probe=options.fast_fw_probe,
Ricky Lianga70a1202013-03-15 15:03:17 +0800332 probe_volatile=not options.no_vol,
333 probe_initial_config=not options.no_ic,
334 probe_vpd=options.include_vpd).Encode()
Ricky Liang53390232013-03-08 15:37:57 +0800335
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800336
Tammo Spalink214caf42012-05-28 10:45:00 +0800337@Command('verify_components',
338 _hwdb_path_cmd_arg,
Tammo Spalink5c699832012-07-03 17:50:39 +0800339 CmdArg('target_comps', nargs='*'))
Tammo Spalink214caf42012-05-28 10:45:00 +0800340def VerifyComponents(options):
Andy Cheng8ece7382012-08-22 16:25:42 +0800341 """Verify that probeable components all match entries in the component_db.
Tammo Spalink214caf42012-05-28 10:45:00 +0800342
Tammo Spalink5c699832012-07-03 17:50:39 +0800343 Probe for each component class in the target_comps and verify
Tammo Spalink214caf42012-05-28 10:45:00 +0800344 that a corresponding match exists in the component_db -- make sure
345 that these components are present, that they have been approved, but
346 do not check against any specific BOM/HWID configurations.
347 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800348
Andy Chengc531e2f2012-10-15 19:09:17 +0800349 try:
Ricky Lianga70a1202013-03-15 15:03:17 +0800350 result = GetGooftool(options).VerifyComponents(
Andy Chengc531e2f2012-10-15 19:09:17 +0800351 options.target_comps)
352 except ValueError, e:
353 sys.exit(e)
354
Ricky Liang53390232013-03-08 15:37:57 +0800355 PrintVerifyComponentsResults(result)
356
357
358def PrintVerifyComponentsResults(result):
359 """Prints out the results of VerifyComponents method call.
360
361 Groups the results into two groups: 'matches' and 'errors', and prints out
362 their values.
363 """
Andy Chengc531e2f2012-10-15 19:09:17 +0800364 # group by matches and errors
Tammo Spalink214caf42012-05-28 10:45:00 +0800365 matches = []
Andy Chengc531e2f2012-10-15 19:09:17 +0800366 errors = []
367 for result_list in result.values():
368 for component_name, _, error in result_list:
369 if component_name:
370 matches.append(component_name)
Tammo Spalink214caf42012-05-28 10:45:00 +0800371 else:
Andy Chengc531e2f2012-10-15 19:09:17 +0800372 errors.append(error)
373
Andy Cheng228a8c92012-08-27 10:53:57 +0800374 if matches:
375 print 'found probeable components:\n %s' % '\n '.join(matches)
Tammo Spalink214caf42012-05-28 10:45:00 +0800376 if errors:
Andy Cheng228a8c92012-08-27 10:53:57 +0800377 print '\nerrors:\n %s' % '\n '.join(errors)
378 sys.exit('\ncomponent verification FAILURE')
Tammo Spalink214caf42012-05-28 10:45:00 +0800379 else:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800380 print '\ncomponent verification SUCCESS'
Tammo Spalink214caf42012-05-28 10:45:00 +0800381
382
Ricky Liang43b879b2014-02-24 11:36:55 +0800383@Command('verify_hwid_v2',
Tammo Spalink95c43732012-07-25 15:57:14 -0700384 _hwid_status_list_cmd_arg,
Jon Salz0f8a6842012-09-25 11:28:22 +0800385 _hwdb_path_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800386 _probe_results_cmd_arg,
387 _hwid_cmd_arg)
Ricky Liang43b879b2014-02-24 11:36:55 +0800388def VerifyHWIDv2(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800389 """Verify system HWID properties match probed device properties.
390
391 First probe components, volatile and initial_config parameters for
392 the DUT. Then use the available device data to produce a list of
393 candidate HWIDs. Then verify the HWID from the DUT is present in
394 that list. Then verify that the DUT initial config values match
395 those specified for its HWID. Finally, verify that VPD contains all
396 the necessary fields as specified by the board data, and when
397 possible verify that values are legitimate.
398 """
Ricky Liangf7857c12012-09-17 13:34:41 +0800399 def VerifyVpd(ro_vpd_keys, rw_vpd_keys):
Tammo Spalink5c699832012-07-03 17:50:39 +0800400 for key in ro_vpd_keys:
401 if key not in ro_vpd:
Ricky Liangf7857c12012-09-17 13:34:41 +0800402 sys.exit('Missing required RO VPD field: %s' % key)
Tammo Spalink01e11722012-07-24 10:17:54 -0700403 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800404 value = ro_vpd[key]
Ricky Liangf7857c12012-09-17 13:34:41 +0800405 if (known_valid_values is not None) and (value not in known_valid_values):
406 sys.exit('Invalid RO VPD entry : key %r, value %r' % (key, value))
Ricky Liangf7857c12012-09-17 13:34:41 +0800407 for key in rw_vpd_keys:
408 if key not in rw_vpd:
409 sys.exit('Missing required RW VPD field: %s' % key)
410 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
411 value = rw_vpd[key]
412 if (known_valid_values is not None) and (value not in known_valid_values):
413 sys.exit('Invalid RW VPD entry : key %r, value %r' % (key, value))
Andy Cheng0465d132013-03-20 12:12:06 +0800414 event_log.Log('vpd', ro_vpd=FilterDict(ro_vpd), rw_vpd=FilterDict(rw_vpd))
Tammo Spalink5c699832012-07-03 17:50:39 +0800415 map(hwid_tool.Validate.Status, options.status)
Jon Salz0f8a6842012-09-25 11:28:22 +0800416
Jon Salz81350812012-10-11 16:13:22 +0800417 if not options.hwid or not options.probe_results:
418 main_fw_file = crosfw.LoadMainFirmware().GetFileName()
Jon Salz0f8a6842012-09-25 11:28:22 +0800419
420 if options.hwid:
421 hwid_str = options.hwid
422 else:
423 gbb_result = Shell('gbb_utility -g --hwid %s' % main_fw_file).stdout
424 hwid_str = re.findall(r'hardware_id:(.*)', gbb_result)[0].strip()
Tammo Spalink95c43732012-07-25 15:57:14 -0700425 hwid = hwid_tool.ParseHwid(hwid_str)
Tammo Spalink5c699832012-07-03 17:50:39 +0800426 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Jon Salz0f8a6842012-09-25 11:28:22 +0800427 print 'Verifying HWID: %r\n' % hwid.hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700428 device = hw_db.GetDevice(hwid.board)
429 hwid_status = device.GetHwidStatus(hwid.bom, hwid.variant, hwid.volatile)
430 if hwid_status not in options.status:
Tammo Spalink5c699832012-07-03 17:50:39 +0800431 sys.exit('HWID status must be one of [%s], found %r' %
Hung-Te Lin4f5beb12012-08-20 14:48:06 +0800432 (', '.join(options.status), hwid_status))
Jon Salz0f8a6842012-09-25 11:28:22 +0800433 if options.probe_results:
434 # Pull in probe results (including VPD data) from the given file
435 # rather than probing the current system.
436 probe_results = hwid_tool.ProbeResults.Decode(
437 open(options.probe_results).read())
438 ro_vpd = {}
439 rw_vpd = {}
440 for k, v in probe_results.found_volatile_values.items():
Hung-Te Lin56b18402015-01-16 14:52:30 +0800441 match = re.match(r'^vpd\.(ro|rw)\.(\w+)$', k)
Jon Salz0f8a6842012-09-25 11:28:22 +0800442 if match:
443 del probe_results.found_volatile_values[k]
444 (ro_vpd if match.group(1) == 'ro' else rw_vpd)[match.group(2)] = v
445 else:
446 probe_results = Probe()
447 ro_vpd = ReadRoVpd(main_fw_file)
448 rw_vpd = ReadRwVpd(main_fw_file)
Tammo Spalink95c43732012-07-25 15:57:14 -0700449 cooked_components = hw_db.comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800450 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700451 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800452 probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700453 cooked_initial_configs = device.MatchInitialConfigValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800454 probe_results.initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700455 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800456 extant_components=cooked_components.matched,
457 classes_missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700458 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800459 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700460 matched_hwids = device.GetMatchTreeHwids(match_tree)
461 print 'HWID status: %s\n' % hwid_status
462 print 'probed system components:'
463 print YamlWrite(cooked_components.__dict__)
464 print 'missing component classes:'
465 print YamlWrite(probe_results.missing_component_classes)
466 print 'probed volatiles:'
467 print YamlWrite(cooked_volatiles.__dict__)
468 print 'probed initial_configs:'
469 print YamlWrite(cooked_initial_configs)
470 print 'hwid match tree:'
471 print YamlWrite(match_tree)
Andy Cheng0465d132013-03-20 12:12:06 +0800472 event_log.Log(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800473 'probe',
474 found_components=cooked_components.__dict__,
475 missing_component_classes=probe_results.missing_component_classes,
476 volatiles=cooked_volatiles.__dict__,
477 initial_configs=cooked_initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700478 if hwid.hwid not in matched_hwids:
Tammo Spalink5c699832012-07-03 17:50:39 +0800479 err_msg = 'HWID verification FAILED.\n'
Tammo Spalink95c43732012-07-25 15:57:14 -0700480 if cooked_components.unmatched:
Tammo Spalink5c699832012-07-03 17:50:39 +0800481 sys.exit(err_msg + 'some components could not be indentified:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700482 YamlWrite(cooked_components.unmatched))
483 if not match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800484 sys.exit(err_msg + 'no matching boms were found for components:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700485 component_data.Encode())
486 if hwid.bom not in match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800487 sys.exit(err_msg + 'matching boms [%s] do not include target bom %r' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700488 (', '.join(sorted(match_tree)), hwid.bom))
489 err_msg += 'target bom %r matches components' % hwid.bom
490 if hwid.bom not in device.IntersectBomsAndInitialConfigs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800491 cooked_initial_configs):
Tammo Spalink5c699832012-07-03 17:50:39 +0800492 sys.exit(err_msg + ', but failed initial config verification')
Tammo Spalink95c43732012-07-25 15:57:14 -0700493 matched_variants = match_tree.get(hwid.bom, {})
494 if hwid.variant not in matched_variants:
Tammo Spalink5c699832012-07-03 17:50:39 +0800495 sys.exit(err_msg + ', but target variant_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700496 hwid.variant)
497 matched_volatiles = matched_variants.get(hwid.variant, {})
498 if hwid.volatile not in matched_volatiles:
Tammo Spalink5c699832012-07-03 17:50:39 +0800499 sys.exit(err_msg + ', but target volatile_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700500 hwid.volatile)
501 found_status = matched_volatiles.get(hwid.volatile, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800502 sys.exit(err_msg + ', but hwid status %r was unacceptable' % found_status)
Ricky Liangf7857c12012-09-17 13:34:41 +0800503 VerifyVpd(device.vpd_ro_fields, device.vpd_rw_fields)
Andy Cheng0465d132013-03-20 12:12:06 +0800504 event_log.Log('verified_hwid', hwid=hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -0700505 print 'Verification SUCCESS!'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800506
507
508@Command('verify_keys')
Tammo Spalink01e11722012-07-24 10:17:54 -0700509def VerifyKeys(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800510 """Verify keys in firmware and SSD match."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800511
Ricky Lianga70a1202013-03-15 15:03:17 +0800512 return GetGooftool(options).VerifyKeys()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800513
514
515@Command('set_fw_bitmap_locale')
Tammo Spalink01e11722012-07-24 10:17:54 -0700516def SetFirmwareBitmapLocale(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800517 """Use VPD locale value to set firmware bitmap default language."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800518
Ricky Lianga70a1202013-03-15 15:03:17 +0800519 (index, locale) = GetGooftool(options).SetFirmwareBitmapLocale()
Andy Cheng2582d292012-12-04 17:38:28 +0800520 logging.info('Firmware bitmap initial locale set to %d (%s).',
521 index, locale)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800522
523
524@Command('verify_system_time')
Tammo Spalink01e11722012-07-24 10:17:54 -0700525def VerifySystemTime(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800526 """Verify system time is later than release filesystem creation time."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800527
Ricky Lianga70a1202013-03-15 15:03:17 +0800528 return GetGooftool(options).VerifySystemTime()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800529
530
531@Command('verify_rootfs')
Tammo Spalink01e11722012-07-24 10:17:54 -0700532def VerifyRootFs(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800533 """Verify rootfs on SSD is valid by checking hash."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800534
Ricky Lianga70a1202013-03-15 15:03:17 +0800535 return GetGooftool(options).VerifyRootFs()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800536
Hung-Te Lin56b18402015-01-16 14:52:30 +0800537
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800538@Command('verify_tpm')
539def VerifyTPM(options): # pylint: disable=W0613
540 """Verify TPM is cleared."""
541
542 return GetGooftool(options).VerifyTPM()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800543
Hung-Te Lin56b18402015-01-16 14:52:30 +0800544
Hung-Te Lindd708d42014-07-11 17:05:01 +0800545@Command('verify_me_locked')
546def VerifyManagementEngineLocked(options): # pylint: disable=W0613
547 """Verify Managment Engine is locked."""
548
549 return GetGooftool(options).VerifyManagementEngineLocked()
550
Hung-Te Lin56b18402015-01-16 14:52:30 +0800551
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800552@Command('verify_switch_wp')
Andy Chengc92e6f92012-11-20 16:55:53 +0800553def VerifyWPSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800554 """Verify hardware write protection switch is enabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800555
Ricky Lianga70a1202013-03-15 15:03:17 +0800556 GetGooftool(options).VerifyWPSwitch()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800557
558
559@Command('verify_switch_dev')
Tammo Spalink01e11722012-07-24 10:17:54 -0700560def VerifyDevSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800561 """Verify developer switch is disabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800562
Ricky Lianga70a1202013-03-15 15:03:17 +0800563 if GetGooftool(options).CheckDevSwitchForDisabling():
Hung-Te Lind7d34722012-07-26 16:48:35 +0800564 logging.warn('VerifyDevSwitch: No physical switch.')
Andy Cheng0465d132013-03-20 12:12:06 +0800565 event_log.Log('switch_dev', type='virtual switch')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800566
567
Jon Salzadd90d32014-04-29 16:16:27 +0800568@Command('verify_branding')
569def VerifyBranding(options): # pylint: disable=W0613
570 """Verify that branding fields are properly set.
571
572 customization_id, if set in the RO VPD, must be of the correct format.
573
574 rlz_brand_code must be set either in the RO VPD or OEM partition, and must
575 be of the correct format.
576 """
577 return GetGooftool(options).VerifyBranding()
578
579
bowgotsai529139c2015-05-30 01:39:49 +0800580@Command('verify_release_channel')
581def VerifyReleaseChannel(options): # pylint: disable=W0613
582 """Verify that release image channel is correct.
583
584 ChromeOS has four channels: canary, dev, beta and stable.
585 The last three channels support image auto-updates, checks
586 that release image channel is one of them.
587 """
588 return GetGooftool(options).VerifyReleaseChannel()
589
590
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800591@Command('write_protect')
Tammo Spalink01e11722012-07-24 10:17:54 -0700592def EnableFwWp(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800593 """Enable then verify firmware write protection."""
594
Hung-Te Linb21c6682012-08-01 13:53:57 +0800595 def CalculateLegacyRange(fw_type, length, section_data,
596 section_name):
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800597 ro_size = length / 2
598 ro_a = int(section_data[0] / ro_size)
599 ro_b = int((section_data[0] + section_data[1] - 1) / ro_size)
600 if ro_a != ro_b:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800601 raise Error('%s firmware section %s has illegal size' %
Hung-Te Linb21c6682012-08-01 13:53:57 +0800602 (fw_type, section_name))
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800603 ro_offset = ro_a * ro_size
604 return (ro_offset, ro_size)
605
606 def WriteProtect(fw_file_path, fw_type, legacy_section):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800607 """Calculate protection size, then invoke flashrom.
608
609 Our supported chips only allow write protecting half their total
610 size, so we parition the flash chipset space accordingly.
611 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800612
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800613 raw_image = open(fw_file_path, 'rb').read()
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800614 wp_section = 'WP_RO'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800615 image = crosfw.FirmwareImage(raw_image)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800616 if image.has_section(wp_section):
617 section_data = image.get_section_area(wp_section)
618 ro_offset = section_data[0]
619 ro_size = section_data[1]
620 elif image.has_section(legacy_section):
621 section_data = image.get_section_area(legacy_section)
622 (ro_offset, ro_size) = CalculateLegacyRange(
Hung-Te Linb21c6682012-08-01 13:53:57 +0800623 fw_type, len(raw_image), section_data, legacy_section)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800624 else:
625 raise Error('could not find %s firmware section %s or %s' %
626 (fw_type, wp_section, legacy_section))
627
628 logging.debug('write protecting %s [off=%x size=%x]', fw_type,
629 ro_offset, ro_size)
630 crosfw.Flashrom(fw_type).EnableWriteProtection(ro_offset, ro_size)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800631
632 WriteProtect(crosfw.LoadMainFirmware().GetFileName(), 'main', 'RO_SECTION')
Andy Cheng0465d132013-03-20 12:12:06 +0800633 event_log.Log('wp', fw='main')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800634 ec_fw_file = crosfw.LoadEcFirmware().GetFileName()
635 if ec_fw_file is not None:
636 WriteProtect(ec_fw_file, 'ec', 'EC_RO')
Andy Cheng0465d132013-03-20 12:12:06 +0800637 event_log.Log('wp', fw='ec')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800638 else:
639 logging.warning('EC not write protected (seems there is no EC flash).')
640
641
642@Command('clear_gbb_flags')
Andy Chengc92e6f92012-11-20 16:55:53 +0800643def ClearGBBFlags(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800644 """Zero out the GBB flags, in preparation for transition to release state.
645
646 No GBB flags are set in release/shipping state, but they are useful
647 for factory/development. See "gbb_utility --flags" for details.
648 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800649
Ricky Lianga70a1202013-03-15 15:03:17 +0800650 GetGooftool(options).ClearGBBFlags()
Andy Cheng0465d132013-03-20 12:12:06 +0800651 event_log.Log('clear_gbb_flags')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800652
653
Jon Salzaa3a30e2013-05-15 15:56:28 +0800654@Command('clear_factory_vpd_entries')
655def ClearFactoryVPDEntries(options): # pylint: disable=W0613
656 """Clears factory.* items in the RW VPD."""
657 entries = GetGooftool(options).ClearFactoryVPDEntries()
658 event_log.Log('clear_factory_vpd_entries', entries=FilterDict(entries))
659
660
Mattias Nisslercca761b2015-04-15 21:53:04 +0200661@Command('generate_stable_device_secret')
662def GenerateStableDeviceSecret(options): # pylint: disable=W0613
663 """Generates a a fresh stable device secret and stores it in the RO VPD."""
664 GetGooftool(options).GenerateStableDeviceSecret()
665 event_log.Log('generate_stable_device_secret')
666
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800667@Command('wipe_in_place',
668 CmdArg('--fast', action='store_true',
669 help='use non-secure but faster wipe method.'))
670def WipeInPlace(options):
671 """Start factory wipe directly without reboot."""
672
673 GetGooftool(options).WipeInPlace(options.fast)
674
Mattias Nisslercca761b2015-04-15 21:53:04 +0200675
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800676@Command('prepare_wipe',
677 CmdArg('--fast', action='store_true',
678 help='use non-secure but faster wipe method.'))
679def PrepareWipe(options):
680 """Prepare system for transition to release state in next reboot."""
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800681
Ricky Lianga70a1202013-03-15 15:03:17 +0800682 GetGooftool(options).PrepareWipe(options.fast)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800683
Hung-Te Lin56b18402015-01-16 14:52:30 +0800684
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800685@Command('verify',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800686 CmdArg('--no_write_protect', action='store_true',
687 help='Do not check write protection switch state.'),
Ricky Liang43b879b2014-02-24 11:36:55 +0800688 _hwid_version_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700689 _hwid_status_list_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800690 _hwdb_path_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800691 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800692 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800693 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800694 _rma_mode_cmd_arg,
695 _cros_core_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800696def Verify(options):
697 """Verifies if whole factory process is ready for finalization.
698
699 This routine performs all the necessary checks to make sure the
700 device is ready to be finalized, but does not modify state. These
701 checks include dev switch, firmware write protection switch, hwid,
702 system time, keys, and root file system.
703 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800704
Hung-Te Lin6d827542012-07-19 11:50:41 +0800705 if not options.no_write_protect:
Ricky Lianga70a1202013-03-15 15:03:17 +0800706 VerifyWPSwitch(options)
Hung-Te Lindd708d42014-07-11 17:05:01 +0800707 VerifyManagementEngineLocked(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800708 VerifyDevSwitch(options)
709 if options.hwid_version == 2:
Ricky Liang43b879b2014-02-24 11:36:55 +0800710 VerifyHWIDv2(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800711 elif options.hwid_version == 3:
Ricky Liangc662be32013-12-24 11:50:23 +0800712 VerifyHWIDv3(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800713 else:
714 raise Error, 'Invalid HWID version: %r' % options.hwid_version
715 VerifySystemTime(options)
716 VerifyKeys(options)
717 VerifyRootFs(options)
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800718 VerifyTPM(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800719 if options.cros_core:
720 logging.info('VerifyBranding is skipped for ChromeOS Core device.')
721 else:
722 VerifyBranding(options)
bowgotsai529139c2015-05-30 01:39:49 +0800723 VerifyReleaseChannel(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800724
Hung-Te Lin56b18402015-01-16 14:52:30 +0800725
Jon Salzfe9036f2014-01-16 14:11:23 +0800726@Command('untar_stateful_files')
Hung-Te Lin388bce22014-06-03 19:56:40 +0800727def UntarStatefulFiles(unused_options):
Jon Salzfe9036f2014-01-16 14:11:23 +0800728 """Untars stateful files from stateful_files.tar.xz on stateful partition.
729
730 If that file does not exist (which should only be R30 and earlier),
731 this is a no-op.
732 """
733 tar_file = os.path.join(DEVICE_STATEFUL_PATH, 'stateful_files.tar.xz')
734 if os.path.exists(tar_file):
735 Spawn(['tar', 'xf', tar_file], cwd=DEVICE_STATEFUL_PATH,
736 log=True, check_call=True)
737 else:
738 logging.warning('No stateful files at %s', tar_file)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800739
Jon Salz40b9f822014-07-25 16:39:55 +0800740
741@Command('log_source_hashes')
742def LogSourceHashes(options): # pylint: disable=W0613
743 """Logs hashes of source files in the factory toolkit."""
Jon Salze60307f2014-08-05 16:20:00 +0800744 # WARNING: The following line is necessary to validate the integrity
745 # of the factory software. Do not remove or modify it.
746 #
747 # 警告:此行会验证工厂软件的完整性,禁止删除或修改。
Jon Salz40b9f822014-07-25 16:39:55 +0800748 event_log.Log(
749 'source_hashes',
Jon Salz9596ae02014-07-29 14:25:49 +0800750 **file_utils.HashSourceTree(os.path.join(factory.FACTORY_PATH, 'py')))
Jon Salz40b9f822014-07-25 16:39:55 +0800751
752
Tammo Spalink86a61c62012-05-25 15:10:35 +0800753@Command('log_system_details')
Tammo Spalink01e11722012-07-24 10:17:54 -0700754def LogSystemDetails(options): # pylint: disable=W0613
Tammo Spalink86a61c62012-05-25 15:10:35 +0800755 """Write miscellaneous system details to the event log."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800756
Ricky Liang43b879b2014-02-24 11:36:55 +0800757 event_log.Log('system_details', **GetGooftool(options).GetSystemDetails())
Tammo Spalink86a61c62012-05-25 15:10:35 +0800758
759
Jon Salza88b83b2013-05-27 20:00:35 +0800760def CreateReportArchiveBlob(*args, **kwargs):
761 """Creates a report archive and returns it as a blob.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800762
Jon Salza88b83b2013-05-27 20:00:35 +0800763 Args:
764 See CreateReportArchive.
Andy Cheng7a76cb82012-11-19 18:08:19 +0800765
Jon Salza88b83b2013-05-27 20:00:35 +0800766 Returns:
767 An xmlrpclib.Binary object containing a .tar.xz file.
768 """
769 with open(CreateReportArchive(*args, **kwargs)) as f:
770 return xmlrpclib.Binary(f.read())
771
772
773def CreateReportArchive(device_sn=None, add_file=None):
774 """Creates a report archive in a temporary directory.
775
776 Args:
777 device_sn: The device serial number (optional).
778 add_file: A list of files to add (optional).
779
780 Returns:
781 Path to the archive.
782 """
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800783 def NormalizeAsFileName(token):
784 return re.sub(r'\W+', '', token).strip()
Jon Salza88b83b2013-05-27 20:00:35 +0800785
786 target_name = '%s%s.tar.xz' % (
787 time.strftime('%Y%m%dT%H%M%SZ',
788 time.gmtime()),
Hung-Te Lin56b18402015-01-16 14:52:30 +0800789 ('' if device_sn is None else
790 '_' + NormalizeAsFileName(device_sn)))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800791 target_path = os.path.join(gettempdir(), target_name)
Jon Salza88b83b2013-05-27 20:00:35 +0800792
Tammo Spalink86a61c62012-05-25 15:10:35 +0800793 # Intentionally ignoring dotfiles in EVENT_LOG_DIR.
Andy Cheng0465d132013-03-20 12:12:06 +0800794 tar_cmd = 'cd %s ; tar cJf %s *' % (event_log.EVENT_LOG_DIR, target_path)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800795 tar_cmd += ' --add-file %s' % FACTORY_LOG_PATH
Jon Salza88b83b2013-05-27 20:00:35 +0800796 if add_file:
797 for f in add_file:
Jon Salz65266432012-07-30 19:02:49 +0800798 # Require absolute paths since the tar command may change the
799 # directory.
800 if not f.startswith('/'):
801 raise Error('Not an absolute path: %s' % f)
802 if not os.path.exists(f):
803 raise Error('File does not exist: %s' % f)
804 tar_cmd += ' --add-file %s' % pipes.quote(f)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800805 cmd_result = Shell(tar_cmd)
Jon Salzff88c022012-11-03 12:19:58 +0800806
807 if ((cmd_result.status == 1) and
808 all((x == '' or
809 'file changed as we read it' in x or
810 "Removing leading `/' from member names" in x)
811 for x in cmd_result.stderr.split('\n'))):
812 # That's OK. Make sure it's valid though.
Vic Yang85199e72013-01-28 14:33:11 +0800813 Spawn(['tar', 'tfJ', target_path], check_call=True, log=True,
Jon Salzff88c022012-11-03 12:19:58 +0800814 ignore_stdout=True)
815 elif not cmd_result.success:
Tammo Spalink86a61c62012-05-25 15:10:35 +0800816 raise Error('unable to tar event logs, cmd %r failed, stderr: %r' %
817 (tar_cmd, cmd_result.stderr))
Jon Salzff88c022012-11-03 12:19:58 +0800818
Jon Salza88b83b2013-05-27 20:00:35 +0800819 return target_path
820
821_upload_method_cmd_arg = CmdArg(
822 '--upload_method', metavar='METHOD:PARAM',
823 help=('How to perform the upload. METHOD should be one of '
824 '{ftp, shopfloor, ftps, cpfe}.'))
825_add_file_cmd_arg = CmdArg(
826 '--add_file', metavar='FILE', action='append',
827 help='Extra file to include in report (must be an absolute path)')
828
Hung-Te Lin56b18402015-01-16 14:52:30 +0800829
Jon Salza88b83b2013-05-27 20:00:35 +0800830@Command('upload_report',
831 _upload_method_cmd_arg,
832 _add_file_cmd_arg)
833def UploadReport(options):
834 """Create a report containing key device details."""
835 ro_vpd = ReadRoVpd(crosfw.LoadMainFirmware().GetFileName())
836 device_sn = ro_vpd.get('serial_number', None)
837 if device_sn is None:
838 logging.warning('RO_VPD missing device serial number')
839 device_sn = 'MISSING_SN_' + event_log.TimedUuid()
840 target_path = CreateReportArchive(device_sn)
841
Tammo Spalink86a61c62012-05-25 15:10:35 +0800842 if options.upload_method is None or options.upload_method == 'none':
843 logging.warning('REPORT UPLOAD SKIPPED (report left at %s)', target_path)
844 return
845 method, param = options.upload_method.split(':', 1)
846 if method == 'shopfloor':
847 report_upload.ShopFloorUpload(target_path, param)
848 elif method == 'ftp':
Jay Kim360c1dd2012-06-25 10:58:11 -0700849 report_upload.FtpUpload(target_path, 'ftp:' + param)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800850 elif method == 'ftps':
851 report_upload.CurlUrlUpload(target_path, '--ftp-ssl-reqd ftp:%s' % param)
852 elif method == 'cpfe':
Shawn Nematbakhsh3404a092013-01-28 16:49:09 -0800853 report_upload.CpfeUpload(target_path, pipes.quote(param))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800854 else:
855 raise Error('unknown report upload method %r', method)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800856
857
858@Command('finalize',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800859 CmdArg('--no_write_protect', action='store_true',
860 help='Do not enable firmware write protection.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800861 CmdArg('--fast', action='store_true',
862 help='use non-secure but faster wipe method.'),
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800863 CmdArg('--wipe_in_place', action='store_true',
864 help='Start factory wiping in place without reboot.'),
Ricky Liang43b879b2014-02-24 11:36:55 +0800865 _hwid_version_cmd_arg,
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800866 _hwdb_path_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700867 _hwid_status_list_cmd_arg,
Jon Salz65266432012-07-30 19:02:49 +0800868 _upload_method_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800869 _add_file_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800870 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800871 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800872 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800873 _rma_mode_cmd_arg,
874 _cros_core_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800875def Finalize(options):
876 """Verify system readiness and trigger transition into release state.
877
Jon Salzaa3a30e2013-05-15 15:56:28 +0800878 This routine does the following:
879 - Verifies system state (see verify command)
Jon Salzfe9036f2014-01-16 14:11:23 +0800880 - Untars stateful_files.tar.xz, if it exists, in the stateful partition, to
881 initialize files such as the CRX cache
Jon Salzaa3a30e2013-05-15 15:56:28 +0800882 - Modifies firmware bitmaps to match locale
883 - Clears all factory-friendly flags from the GBB
884 - Removes factory-specific entries from RW_VPD (factory.*)
885 - Enables firmware write protection (cannot rollback after this)
886 - Uploads system logs & reports
887 - Sets the necessary boot flags to cause wipe of the factory image on the
888 next boot.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800889 """
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800890 Verify(options)
Jon Salz40b9f822014-07-25 16:39:55 +0800891 LogSourceHashes(options)
Jon Salzfe9036f2014-01-16 14:11:23 +0800892 UntarStatefulFiles(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800893 if options.cros_core:
894 logging.info('SetFirmwareBitmapLocale is skipped for ChromeOS Core device.')
895 else:
896 SetFirmwareBitmapLocale(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800897 ClearGBBFlags(options)
Jon Salzaa3a30e2013-05-15 15:56:28 +0800898 ClearFactoryVPDEntries(options)
Mattias Nisslercca761b2015-04-15 21:53:04 +0200899 GenerateStableDeviceSecret(options)
Hung-Te Lin6d827542012-07-19 11:50:41 +0800900 if options.no_write_protect:
901 logging.warn('WARNING: Firmware Write Protection is SKIPPED.')
Andy Cheng0465d132013-03-20 12:12:06 +0800902 event_log.Log('wp', fw='both', status='skipped')
Hung-Te Lin6d827542012-07-19 11:50:41 +0800903 else:
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800904 EnableFwWp({})
Jon Salza0f58e02012-05-29 19:33:39 +0800905 LogSystemDetails(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800906 UploadReport(options)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800907 if options.wipe_in_place:
908 event_log.Log('wipe_in_place')
909 WipeInPlace(options)
910 else:
911 PrepareWipe(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800912
913
Ricky Liangc662be32013-12-24 11:50:23 +0800914def VerifyHWIDv3(options):
915 """A simple wrapper that calls out to HWID utils to verify version 3 HWID.
Ricky Liang53390232013-03-08 15:37:57 +0800916
Ricky Liangc662be32013-12-24 11:50:23 +0800917 This is mainly for Gooftool to verify v3 HWID during finalize. For testing
918 and development purposes, please use `hwid` command.
Ricky Liang53390232013-03-08 15:37:57 +0800919 """
Ricky Liangc662be32013-12-24 11:50:23 +0800920 db = GetGooftool(options).db
921 encoded_string = options.hwid or hwid_utils.GetHWIDString()
Ricky Liang7905f272013-03-16 01:57:10 +0800922 if options.probe_results:
Ricky Liangc662be32013-12-24 11:50:23 +0800923 probed_results = yaml.load(open(options.probe_results).read())
Ricky Liang7905f272013-03-16 01:57:10 +0800924 else:
Ricky Liangc662be32013-12-24 11:50:23 +0800925 probed_results = yaml.load(Probe(probe_vpd=True).Encode())
926 vpd = hwid_utils.GetVPD(probed_results)
Ricky Liang53390232013-03-08 15:37:57 +0800927
Hung-Te Lin11052952015-03-18 13:48:59 +0800928 event_log.Log('probed_results', probed_results=FilterDict(probed_results))
929 event_log.Log('vpd', vpd=FilterDict(vpd))
Ricky Liang53390232013-03-08 15:37:57 +0800930
Ricky Liangc662be32013-12-24 11:50:23 +0800931 hwid_utils.VerifyHWID(db, encoded_string, probed_results, vpd,
Hung-Te Lin56b18402015-01-16 14:52:30 +0800932 rma_mode=options.rma_mode)
Ricky Liang53390232013-03-08 15:37:57 +0800933
Ricky Liangc662be32013-12-24 11:50:23 +0800934 event_log.Log('verified_hwid', hwid=encoded_string)
Ricky Liang53390232013-03-08 15:37:57 +0800935
936
Ricky Liang59611a62013-06-11 13:47:33 +0800937def ParseDecodedHWID(hwid):
938 """Parse the HWID object into a more compact dict.
939
940 Args:
941 hwid: A decoded HWID object.
942
943 Returns:
944 A dict containing the board name, the binary string, and the list of
945 components.
946 """
947 results = {}
948 results['board'] = hwid.database.board
949 results['binary_string'] = hwid.binary_string
950 results['components'] = collections.defaultdict(list)
951 components = hwid.bom.components
952 for comp_cls in sorted(components):
953 for (comp_name, probed_values, _) in sorted(components[comp_cls]):
954 if not probed_values:
955 db_components = hwid.database.components
956 probed_values = db_components.GetComponentAttributes(
957 comp_cls, comp_name).get('values')
958 results['components'][comp_cls].append(
959 {comp_name: probed_values if probed_values else None})
960 # Convert defaultdict to dict.
961 results['components'] = dict(results['components'])
962 return results
963
964
henryhsu44d793a2013-07-20 00:07:38 +0800965@Command('get_firmware_hash',
966 CmdArg('--file', metavar='FILE', help='Firmware File.'))
967def GetFirmwareHash(options):
henryhsuf6f835c2013-07-20 20:49:25 +0800968 """Get firmware hash from a file"""
henryhsu44d793a2013-07-20 00:07:38 +0800969 if os.path.exists(options.file):
970 hashes = CalculateFirmwareHashes(options.file)
971 for section, value_dict in hashes.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +0800972 print '%s:' % section
henryhsu44d793a2013-07-20 00:07:38 +0800973 for key, value in value_dict.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +0800974 print ' %s: %s' % (key, value)
henryhsu44d793a2013-07-20 00:07:38 +0800975 else:
976 raise Error('File does not exist: %s' % options.file)
977
henryhsuf6f835c2013-07-20 20:49:25 +0800978
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800979def Main():
980 """Run sub-command specified by the command line args."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800981
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800982 options = ParseCmdline(
Ricky Liangc662be32013-12-24 11:50:23 +0800983 ('Perform Google required factory tests. All the HWID-related functions '
984 'provided here are mainly for the deprecated HWID v2. To access HWID '
985 'v3-related utilities, please use `hwid` command.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800986 CmdArg('-l', '--log', metavar='PATH',
987 help='Write logs to this file.'),
Jon Salza4bea382012-10-29 13:00:34 +0800988 CmdArg('--suppress-event-logs', action='store_true',
989 help='Suppress event logging.'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800990 verbosity_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800991 SetupLogging(options.verbosity, options.log)
Andy Cheng0465d132013-03-20 12:12:06 +0800992 event_log.SetGlobalLoggerDefaultPrefix('gooftool')
993 event_log.GetGlobalLogger().suppress = options.suppress_event_logs
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800994 logging.debug('gooftool options: %s', repr(options))
995 try:
996 logging.debug('GOOFTOOL command %r', options.command_name)
997 options.command(options)
998 logging.info('GOOFTOOL command %r SUCCESS', options.command_name)
999 except Error, e:
1000 logging.exception(e)
1001 sys.exit('GOOFTOOL command %r ERROR: %s' % (options.command_name, e))
1002 except Exception, e:
1003 logging.exception(e)
1004 sys.exit('UNCAUGHT RUNTIME EXCEPTION %s' % e)
1005
1006
1007if __name__ == '__main__':
1008 Main()