blob: e87cd7f1750f1272f62e6eb22c16d8d95ba826b8 [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
bowgotsai13820f42015-09-10 23:18:04 +0800137_enforced_release_channels_cmd_arg = CmdArg(
138 '--enforced_release_channels', nargs='*', default=None,
139 help='Enforced release image channels.')
140
Ricky Liang43b879b2014-02-24 11:36:55 +0800141
Tammo Spalink95c43732012-07-25 15:57:14 -0700142@Command('best_match_hwids',
Tammo Spalink8fab5312012-05-28 18:33:30 +0800143 _hwdb_path_cmd_arg,
144 CmdArg('-b', '--board', metavar='BOARD',
Tammo Spalink95c43732012-07-25 15:57:14 -0700145 help='optional BOARD name, needed only if data is present '
146 'for more than one'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800147 CmdArg('--bom', metavar='BOM', help='BOM name'),
148 CmdArg('--variant', metavar='VARIANT', help='VARIANT code'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800149 CmdArg('--optimistic', action='store_true',
150 help='do not probe; assume singletons match'),
Tammo Spalink95c43732012-07-25 15:57:14 -0700151 CmdArg('--comps', nargs='*', default=[],
152 help='list of canonical component names'),
153 CmdArg('--missing', nargs='*', default=[],
154 help='list component classes to be assumed missing'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800155 CmdArg('--status', nargs='*', default=['supported'],
Tammo Spalink95c43732012-07-25 15:57:14 -0700156 help='consider only HWIDs within this list of status values'))
157def BestMatchHwids(options):
Ricky Liangc662be32013-12-24 11:50:23 +0800158 """Determine a list of possible HWIDs using provided args and probing.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800159
160 VOLATILE can always be determined by probing. To get a unique
161 result, VARIANT must be specified for all cases where the matching
162 BOM has more than one associated variant code, otherwise all HWID
163 variants will be returned. Both VARIANT and BOM information can
Tammo Spalink95c43732012-07-25 15:57:14 -0700164 alternatively be specified using the --stdin_comps argument, which
165 allows specifying a list of canonical names (one per line) on stdin,
166 one per line. Based on what is known from BOM and stdin_comps,
167 determine a list of components to probe for, and use those probe
168 results to resolve a list of matching HWIDs. If no boms,
169 components, or variant codes are specified, then a list of all HWIDs
Andy Cheng8ece7382012-08-22 16:25:42 +0800170 that match probeable components will be returned.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800171
172 Returns (on stdout): A list of HWIDs that match the available probe
173 results and argument contraints, one per line.
Tammo Spalink70b48a52012-08-08 16:54:51 -0700174
175 Example:
176
177 // Three ways to specify a keyboard (assuming it is a variant component)
178 gooftool best_match_hwids --missing keyboard
179 gooftool best_match_hwids --variant A or
180 gooftool best_match_hwids --comps us_kbd
Tammo Spalink8fab5312012-05-28 18:33:30 +0800181 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800182
Tammo Spalink5c699832012-07-03 17:50:39 +0800183 map(hwid_tool.Validate.Status, options.status)
Tammo Spalink95c43732012-07-25 15:57:14 -0700184 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Tammo Spalink5c699832012-07-03 17:50:39 +0800185 comp_db = hw_db.comp_db
Tammo Spalink3a7e9022012-06-27 14:08:40 +0800186 device = hw_db.GetDevice(options.board)
Tammo Spalink5c699832012-07-03 17:50:39 +0800187 component_spec = hwid_tool.ComponentSpec.New()
Tammo Spalink8fab5312012-05-28 18:33:30 +0800188 if options.bom:
Tammo Spalink5c699832012-07-03 17:50:39 +0800189 device.BomExists(options.bom)
Tammo Spalink01e11722012-07-24 10:17:54 -0700190 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800191 component_spec, device.boms[options.bom].primary)
Tammo Spalink8fab5312012-05-28 18:33:30 +0800192 if options.variant:
Tammo Spalink5c699832012-07-03 17:50:39 +0800193 device.VariantExists(options.variant)
194 variant_spec = device.variants[options.variant]
Tammo Spalink01e11722012-07-24 10:17:54 -0700195 if hwid_tool.ComponentSpecsConflict(component_spec, variant_spec):
Tammo Spalink95c43732012-07-25 15:57:14 -0700196 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700197 % YamlWrite(sorted(
198 hwid_tool.ComponentSpecClasses(component_spec) &
199 hwid_tool.ComponentSpecClasses(variant_spec))))
Tammo Spalink01e11722012-07-24 10:17:54 -0700200 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800201 component_spec, variant_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700202 if options.comps or options.missing:
203 map(comp_db.CompExists, options.comps)
204 map(comp_db.CompClassExists, options.missing)
205 extra_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800206 components=options.comps,
207 missing=options.missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700208 print 'cmdline asserted components:\n%s' % extra_comp_spec.Encode()
209 if hwid_tool.ComponentSpecsConflict(component_spec, extra_comp_spec):
210 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700211 % YamlWrite(sorted(
212 hwid_tool.ComponentSpecClasses(component_spec) &
213 hwid_tool.ComponentSpecClasses(extra_comp_spec))))
Tammo Spalink95c43732012-07-25 15:57:14 -0700214 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800215 component_spec, extra_comp_spec)
Tammo Spalink01e11722012-07-24 10:17:54 -0700216 spec_classes = hwid_tool.ComponentSpecClasses(component_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700217 missing_classes = set(comp_db.all_comp_classes) - spec_classes
Tammo Spalink5c699832012-07-03 17:50:39 +0800218 if missing_classes and not options.optimistic:
Andy Cheng8ece7382012-08-22 16:25:42 +0800219 non_probeable_missing = missing_classes - PROBEABLE_COMPONENT_CLASSES
220 if non_probeable_missing:
Tammo Spalink95c43732012-07-25 15:57:14 -0700221 sys.exit('FAILURE: these classes are necessary, were not specified '
Tammo Spalink70b48a52012-08-08 16:54:51 -0700222 'as inputs, and cannot be probed for:\n%s'
223 'This problem can often be addressed by specifying all of '
224 'the missing components on the command line (see the command '
Andy Cheng8ece7382012-08-22 16:25:42 +0800225 'help).' % YamlWrite(list(non_probeable_missing)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700226 print 'probing for missing classes:'
227 print YamlWrite(list(missing_classes))
228 probe_results = Probe(target_comp_classes=list(missing_classes),
229 probe_volatile=False, probe_initial_config=False)
230 cooked_components = comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800231 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700232 if cooked_components.unmatched:
233 sys.exit('ERROR: some probed components are unrecognized:\n%s'
234 % YamlWrite(cooked_components.unmatched))
235 probed_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800236 components=cooked_components.matched,
237 missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700238 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800239 component_spec, probed_comp_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700240 print YamlWrite({'component data used for matching': {
Hung-Te Lin56b18402015-01-16 14:52:30 +0800241 'missing component classes': component_spec.classes_missing,
242 'found components': component_spec.components}})
Tammo Spalink95c43732012-07-25 15:57:14 -0700243 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800244 extant_components=hwid_tool.ComponentSpecCompClassMap(
245 component_spec).keys(),
246 classes_missing=component_spec.classes_missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700247 match_tree = device.BuildMatchTree(component_data)
248 if not match_tree:
249 sys.exit('FAILURE: NO matching BOMs found')
250 print 'potential BOMs/VARIANTs:'
251 potential_variants = set()
252 potential_volatiles = set()
253 for bom_name, variant_tree in match_tree.items():
254 print ' BOM: %-8s VARIANTS: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800255 bom_name, ', '.join(sorted(variant_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700256 for variant_code in variant_tree:
257 potential_variants.add(variant_code)
258 for volatile_code in device.volatiles:
259 status = device.GetHwidStatus(bom_name, variant_code, volatile_code)
260 if status in options.status:
261 potential_volatiles.add(volatile_code)
262 print ''
263 if len(potential_variants) == 0:
264 sys.exit('FAILURE: no matching VARIANTs found')
265 if len(potential_volatiles) == 0:
266 sys.exit('FAILURE: no VOLATILEs found for potential matching BOMs/VARIANTS '
267 '(with specified status)')
Tammo Spalink394e4492012-08-01 10:20:30 -0700268 if (options.optimistic and
269 len(match_tree) == 1 and
270 len(potential_variants) == 1 and
271 len(potential_volatiles) == 1):
272 print ('MATCHING HWID: %s' % device.FmtHwid(match_tree.keys().pop(),
273 potential_variants.pop(),
274 potential_volatiles.pop()))
Tammo Spalink5c699832012-07-03 17:50:39 +0800275 return
Tammo Spalink95c43732012-07-25 15:57:14 -0700276 print ('probing VOLATILEs to resolve potential matches: %s\n' %
277 ', '.join(sorted(potential_volatiles)))
278 vol_probe_results = Probe(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800279 target_comp_classes=[],
280 probe_volatile=True,
281 probe_initial_config=False)
Tammo Spalink95c43732012-07-25 15:57:14 -0700282 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800283 vol_probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700284 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800285 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700286 matched_hwids = device.GetMatchTreeHwids(match_tree)
287 if matched_hwids:
288 for hwid in matched_hwids:
Ricky Liang02f3bd72012-09-21 14:33:01 +0800289 if matched_hwids[hwid] in options.status:
290 print 'MATCHING HWID: %s' % hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700291 return
292 print 'exact HWID matching failed, but the following BOMs match: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800293 ', '.join(sorted(match_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700294 if options.optimistic and len(match_tree) == 1:
295 bom_name = set(match_tree).pop()
Tammo Spalink5c699832012-07-03 17:50:39 +0800296 bom = device.boms[bom_name]
Tammo Spalink95c43732012-07-25 15:57:14 -0700297 variant_matches = match_tree[bom_name]
Tammo Spalink5c699832012-07-03 17:50:39 +0800298 if len(variant_matches) == 1:
299 var_code = set(variant_matches).pop()
300 elif len(bom.variants) == 1:
301 var_code = set(bom.variants).pop()
302 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700303 sys.exit('FAILURE: NO matching HWIDs found; optimistic matching failed '
304 'because there were too many variants to choose from for BOM %r'
305 % bom_name)
306 hwids = [device.FmtHwid(bom_name, var_code, vol_code)
307 for vol_code in device.volatiles
308 if device.GetHwidStatus(bom_name, var_code, vol_code)
309 in options.status]
310 for hwid in hwids:
311 print 'MATCHING HWID: %s' % hwid
Tammo Spalink5c699832012-07-03 17:50:39 +0800312 return
313 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700314 print ('optimistic matching not attempted because either it was '
315 'not requested, or because the number of BOMs was <> 1\n')
316 sys.exit('FAILURE: NO matching HWIDs found')
Tammo Spalink8fab5312012-05-28 18:33:30 +0800317
318
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800319@Command('probe',
320 CmdArg('--comps', nargs='*',
321 help='List of keys from the component_db registry.'),
Ricky Liangb30da672013-06-14 12:36:34 +0800322 CmdArg('--fast_fw_probe', action='store_true',
323 help='Do a fast probe for EC and main firmware versions only. '
324 'This implies --no_vol and --no_ic.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800325 CmdArg('--no_vol', action='store_true',
326 help='Do not probe volatile data.'),
327 CmdArg('--no_ic', action='store_true',
Jon Salz0f8a6842012-09-25 11:28:22 +0800328 help='Do not probe initial_config data.'),
329 CmdArg('--include_vpd', action='store_true',
330 help='Include VPD data in volatiles.'))
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800331def RunProbe(options):
332 """Print yaml-formatted breakdown of probed device properties."""
Ricky Lianga70a1202013-03-15 15:03:17 +0800333 print GetGooftool(options).Probe(
334 target_comp_classes=options.comps,
Ricky Liangb30da672013-06-14 12:36:34 +0800335 fast_fw_probe=options.fast_fw_probe,
Ricky Lianga70a1202013-03-15 15:03:17 +0800336 probe_volatile=not options.no_vol,
337 probe_initial_config=not options.no_ic,
338 probe_vpd=options.include_vpd).Encode()
Ricky Liang53390232013-03-08 15:37:57 +0800339
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800340
Tammo Spalink214caf42012-05-28 10:45:00 +0800341@Command('verify_components',
342 _hwdb_path_cmd_arg,
Tammo Spalink5c699832012-07-03 17:50:39 +0800343 CmdArg('target_comps', nargs='*'))
Tammo Spalink214caf42012-05-28 10:45:00 +0800344def VerifyComponents(options):
Andy Cheng8ece7382012-08-22 16:25:42 +0800345 """Verify that probeable components all match entries in the component_db.
Tammo Spalink214caf42012-05-28 10:45:00 +0800346
Tammo Spalink5c699832012-07-03 17:50:39 +0800347 Probe for each component class in the target_comps and verify
Tammo Spalink214caf42012-05-28 10:45:00 +0800348 that a corresponding match exists in the component_db -- make sure
349 that these components are present, that they have been approved, but
350 do not check against any specific BOM/HWID configurations.
351 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800352
Andy Chengc531e2f2012-10-15 19:09:17 +0800353 try:
Ricky Lianga70a1202013-03-15 15:03:17 +0800354 result = GetGooftool(options).VerifyComponents(
Andy Chengc531e2f2012-10-15 19:09:17 +0800355 options.target_comps)
356 except ValueError, e:
357 sys.exit(e)
358
Ricky Liang53390232013-03-08 15:37:57 +0800359 PrintVerifyComponentsResults(result)
360
361
362def PrintVerifyComponentsResults(result):
363 """Prints out the results of VerifyComponents method call.
364
365 Groups the results into two groups: 'matches' and 'errors', and prints out
366 their values.
367 """
Andy Chengc531e2f2012-10-15 19:09:17 +0800368 # group by matches and errors
Tammo Spalink214caf42012-05-28 10:45:00 +0800369 matches = []
Andy Chengc531e2f2012-10-15 19:09:17 +0800370 errors = []
371 for result_list in result.values():
372 for component_name, _, error in result_list:
373 if component_name:
374 matches.append(component_name)
Tammo Spalink214caf42012-05-28 10:45:00 +0800375 else:
Andy Chengc531e2f2012-10-15 19:09:17 +0800376 errors.append(error)
377
Andy Cheng228a8c92012-08-27 10:53:57 +0800378 if matches:
379 print 'found probeable components:\n %s' % '\n '.join(matches)
Tammo Spalink214caf42012-05-28 10:45:00 +0800380 if errors:
Andy Cheng228a8c92012-08-27 10:53:57 +0800381 print '\nerrors:\n %s' % '\n '.join(errors)
382 sys.exit('\ncomponent verification FAILURE')
Tammo Spalink214caf42012-05-28 10:45:00 +0800383 else:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800384 print '\ncomponent verification SUCCESS'
Tammo Spalink214caf42012-05-28 10:45:00 +0800385
386
Ricky Liang43b879b2014-02-24 11:36:55 +0800387@Command('verify_hwid_v2',
Tammo Spalink95c43732012-07-25 15:57:14 -0700388 _hwid_status_list_cmd_arg,
Jon Salz0f8a6842012-09-25 11:28:22 +0800389 _hwdb_path_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800390 _probe_results_cmd_arg,
391 _hwid_cmd_arg)
Ricky Liang43b879b2014-02-24 11:36:55 +0800392def VerifyHWIDv2(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800393 """Verify system HWID properties match probed device properties.
394
395 First probe components, volatile and initial_config parameters for
396 the DUT. Then use the available device data to produce a list of
397 candidate HWIDs. Then verify the HWID from the DUT is present in
398 that list. Then verify that the DUT initial config values match
399 those specified for its HWID. Finally, verify that VPD contains all
400 the necessary fields as specified by the board data, and when
401 possible verify that values are legitimate.
402 """
Ricky Liangf7857c12012-09-17 13:34:41 +0800403 def VerifyVpd(ro_vpd_keys, rw_vpd_keys):
Tammo Spalink5c699832012-07-03 17:50:39 +0800404 for key in ro_vpd_keys:
405 if key not in ro_vpd:
Ricky Liangf7857c12012-09-17 13:34:41 +0800406 sys.exit('Missing required RO VPD field: %s' % key)
Tammo Spalink01e11722012-07-24 10:17:54 -0700407 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800408 value = ro_vpd[key]
Ricky Liangf7857c12012-09-17 13:34:41 +0800409 if (known_valid_values is not None) and (value not in known_valid_values):
410 sys.exit('Invalid RO VPD entry : key %r, value %r' % (key, value))
Ricky Liangf7857c12012-09-17 13:34:41 +0800411 for key in rw_vpd_keys:
412 if key not in rw_vpd:
413 sys.exit('Missing required RW VPD field: %s' % key)
414 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
415 value = rw_vpd[key]
416 if (known_valid_values is not None) and (value not in known_valid_values):
417 sys.exit('Invalid RW VPD entry : key %r, value %r' % (key, value))
Andy Cheng0465d132013-03-20 12:12:06 +0800418 event_log.Log('vpd', ro_vpd=FilterDict(ro_vpd), rw_vpd=FilterDict(rw_vpd))
Tammo Spalink5c699832012-07-03 17:50:39 +0800419 map(hwid_tool.Validate.Status, options.status)
Jon Salz0f8a6842012-09-25 11:28:22 +0800420
Jon Salz81350812012-10-11 16:13:22 +0800421 if not options.hwid or not options.probe_results:
422 main_fw_file = crosfw.LoadMainFirmware().GetFileName()
Jon Salz0f8a6842012-09-25 11:28:22 +0800423
424 if options.hwid:
425 hwid_str = options.hwid
426 else:
427 gbb_result = Shell('gbb_utility -g --hwid %s' % main_fw_file).stdout
428 hwid_str = re.findall(r'hardware_id:(.*)', gbb_result)[0].strip()
Tammo Spalink95c43732012-07-25 15:57:14 -0700429 hwid = hwid_tool.ParseHwid(hwid_str)
Tammo Spalink5c699832012-07-03 17:50:39 +0800430 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Jon Salz0f8a6842012-09-25 11:28:22 +0800431 print 'Verifying HWID: %r\n' % hwid.hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700432 device = hw_db.GetDevice(hwid.board)
433 hwid_status = device.GetHwidStatus(hwid.bom, hwid.variant, hwid.volatile)
434 if hwid_status not in options.status:
Tammo Spalink5c699832012-07-03 17:50:39 +0800435 sys.exit('HWID status must be one of [%s], found %r' %
Hung-Te Lin4f5beb12012-08-20 14:48:06 +0800436 (', '.join(options.status), hwid_status))
Jon Salz0f8a6842012-09-25 11:28:22 +0800437 if options.probe_results:
438 # Pull in probe results (including VPD data) from the given file
439 # rather than probing the current system.
440 probe_results = hwid_tool.ProbeResults.Decode(
441 open(options.probe_results).read())
442 ro_vpd = {}
443 rw_vpd = {}
444 for k, v in probe_results.found_volatile_values.items():
Hung-Te Lin56b18402015-01-16 14:52:30 +0800445 match = re.match(r'^vpd\.(ro|rw)\.(\w+)$', k)
Jon Salz0f8a6842012-09-25 11:28:22 +0800446 if match:
447 del probe_results.found_volatile_values[k]
448 (ro_vpd if match.group(1) == 'ro' else rw_vpd)[match.group(2)] = v
449 else:
450 probe_results = Probe()
451 ro_vpd = ReadRoVpd(main_fw_file)
452 rw_vpd = ReadRwVpd(main_fw_file)
Tammo Spalink95c43732012-07-25 15:57:14 -0700453 cooked_components = hw_db.comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800454 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700455 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800456 probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700457 cooked_initial_configs = device.MatchInitialConfigValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800458 probe_results.initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700459 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800460 extant_components=cooked_components.matched,
461 classes_missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700462 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800463 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700464 matched_hwids = device.GetMatchTreeHwids(match_tree)
465 print 'HWID status: %s\n' % hwid_status
466 print 'probed system components:'
467 print YamlWrite(cooked_components.__dict__)
468 print 'missing component classes:'
469 print YamlWrite(probe_results.missing_component_classes)
470 print 'probed volatiles:'
471 print YamlWrite(cooked_volatiles.__dict__)
472 print 'probed initial_configs:'
473 print YamlWrite(cooked_initial_configs)
474 print 'hwid match tree:'
475 print YamlWrite(match_tree)
Andy Cheng0465d132013-03-20 12:12:06 +0800476 event_log.Log(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800477 'probe',
478 found_components=cooked_components.__dict__,
479 missing_component_classes=probe_results.missing_component_classes,
480 volatiles=cooked_volatiles.__dict__,
481 initial_configs=cooked_initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700482 if hwid.hwid not in matched_hwids:
Tammo Spalink5c699832012-07-03 17:50:39 +0800483 err_msg = 'HWID verification FAILED.\n'
Tammo Spalink95c43732012-07-25 15:57:14 -0700484 if cooked_components.unmatched:
Tammo Spalink5c699832012-07-03 17:50:39 +0800485 sys.exit(err_msg + 'some components could not be indentified:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700486 YamlWrite(cooked_components.unmatched))
487 if not match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800488 sys.exit(err_msg + 'no matching boms were found for components:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700489 component_data.Encode())
490 if hwid.bom not in match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800491 sys.exit(err_msg + 'matching boms [%s] do not include target bom %r' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700492 (', '.join(sorted(match_tree)), hwid.bom))
493 err_msg += 'target bom %r matches components' % hwid.bom
494 if hwid.bom not in device.IntersectBomsAndInitialConfigs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800495 cooked_initial_configs):
Tammo Spalink5c699832012-07-03 17:50:39 +0800496 sys.exit(err_msg + ', but failed initial config verification')
Tammo Spalink95c43732012-07-25 15:57:14 -0700497 matched_variants = match_tree.get(hwid.bom, {})
498 if hwid.variant not in matched_variants:
Tammo Spalink5c699832012-07-03 17:50:39 +0800499 sys.exit(err_msg + ', but target variant_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700500 hwid.variant)
501 matched_volatiles = matched_variants.get(hwid.variant, {})
502 if hwid.volatile not in matched_volatiles:
Tammo Spalink5c699832012-07-03 17:50:39 +0800503 sys.exit(err_msg + ', but target volatile_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700504 hwid.volatile)
505 found_status = matched_volatiles.get(hwid.volatile, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800506 sys.exit(err_msg + ', but hwid status %r was unacceptable' % found_status)
Ricky Liangf7857c12012-09-17 13:34:41 +0800507 VerifyVpd(device.vpd_ro_fields, device.vpd_rw_fields)
Andy Cheng0465d132013-03-20 12:12:06 +0800508 event_log.Log('verified_hwid', hwid=hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -0700509 print 'Verification SUCCESS!'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800510
511
512@Command('verify_keys')
Tammo Spalink01e11722012-07-24 10:17:54 -0700513def VerifyKeys(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800514 """Verify keys in firmware and SSD match."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800515
Ricky Lianga70a1202013-03-15 15:03:17 +0800516 return GetGooftool(options).VerifyKeys()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800517
518
519@Command('set_fw_bitmap_locale')
Tammo Spalink01e11722012-07-24 10:17:54 -0700520def SetFirmwareBitmapLocale(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800521 """Use VPD locale value to set firmware bitmap default language."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800522
Ricky Lianga70a1202013-03-15 15:03:17 +0800523 (index, locale) = GetGooftool(options).SetFirmwareBitmapLocale()
Andy Cheng2582d292012-12-04 17:38:28 +0800524 logging.info('Firmware bitmap initial locale set to %d (%s).',
525 index, locale)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800526
527
528@Command('verify_system_time')
Tammo Spalink01e11722012-07-24 10:17:54 -0700529def VerifySystemTime(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800530 """Verify system time is later than release filesystem creation time."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800531
Ricky Lianga70a1202013-03-15 15:03:17 +0800532 return GetGooftool(options).VerifySystemTime()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800533
534
535@Command('verify_rootfs')
Tammo Spalink01e11722012-07-24 10:17:54 -0700536def VerifyRootFs(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800537 """Verify rootfs on SSD is valid by checking hash."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800538
Ricky Lianga70a1202013-03-15 15:03:17 +0800539 return GetGooftool(options).VerifyRootFs()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800540
Hung-Te Lin56b18402015-01-16 14:52:30 +0800541
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800542@Command('verify_tpm')
543def VerifyTPM(options): # pylint: disable=W0613
544 """Verify TPM is cleared."""
545
546 return GetGooftool(options).VerifyTPM()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800547
Hung-Te Lin56b18402015-01-16 14:52:30 +0800548
Hung-Te Lindd708d42014-07-11 17:05:01 +0800549@Command('verify_me_locked')
550def VerifyManagementEngineLocked(options): # pylint: disable=W0613
551 """Verify Managment Engine is locked."""
552
553 return GetGooftool(options).VerifyManagementEngineLocked()
554
Hung-Te Lin56b18402015-01-16 14:52:30 +0800555
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800556@Command('verify_switch_wp')
Andy Chengc92e6f92012-11-20 16:55:53 +0800557def VerifyWPSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800558 """Verify hardware write protection switch is enabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800559
Ricky Lianga70a1202013-03-15 15:03:17 +0800560 GetGooftool(options).VerifyWPSwitch()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800561
562
563@Command('verify_switch_dev')
Tammo Spalink01e11722012-07-24 10:17:54 -0700564def VerifyDevSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800565 """Verify developer switch is disabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800566
Ricky Lianga70a1202013-03-15 15:03:17 +0800567 if GetGooftool(options).CheckDevSwitchForDisabling():
Hung-Te Lind7d34722012-07-26 16:48:35 +0800568 logging.warn('VerifyDevSwitch: No physical switch.')
Andy Cheng0465d132013-03-20 12:12:06 +0800569 event_log.Log('switch_dev', type='virtual switch')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800570
571
Jon Salzadd90d32014-04-29 16:16:27 +0800572@Command('verify_branding')
573def VerifyBranding(options): # pylint: disable=W0613
574 """Verify that branding fields are properly set.
575
576 customization_id, if set in the RO VPD, must be of the correct format.
577
578 rlz_brand_code must be set either in the RO VPD or OEM partition, and must
579 be of the correct format.
580 """
581 return GetGooftool(options).VerifyBranding()
582
583
bowgotsai13820f42015-09-10 23:18:04 +0800584@Command('verify_release_channel',
585 _enforced_release_channels_cmd_arg)
bowgotsai529139c2015-05-30 01:39:49 +0800586def VerifyReleaseChannel(options): # pylint: disable=W0613
587 """Verify that release image channel is correct.
588
589 ChromeOS has four channels: canary, dev, beta and stable.
590 The last three channels support image auto-updates, checks
591 that release image channel is one of them.
592 """
bowgotsai13820f42015-09-10 23:18:04 +0800593 return GetGooftool(options).VerifyReleaseChannel(
594 options.enforced_release_channels)
bowgotsai529139c2015-05-30 01:39:49 +0800595
596
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800597@Command('write_protect')
Tammo Spalink01e11722012-07-24 10:17:54 -0700598def EnableFwWp(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800599 """Enable then verify firmware write protection."""
600
Hung-Te Linb21c6682012-08-01 13:53:57 +0800601 def CalculateLegacyRange(fw_type, length, section_data,
602 section_name):
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800603 ro_size = length / 2
604 ro_a = int(section_data[0] / ro_size)
605 ro_b = int((section_data[0] + section_data[1] - 1) / ro_size)
606 if ro_a != ro_b:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800607 raise Error('%s firmware section %s has illegal size' %
Hung-Te Linb21c6682012-08-01 13:53:57 +0800608 (fw_type, section_name))
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800609 ro_offset = ro_a * ro_size
610 return (ro_offset, ro_size)
611
612 def WriteProtect(fw_file_path, fw_type, legacy_section):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800613 """Calculate protection size, then invoke flashrom.
614
615 Our supported chips only allow write protecting half their total
616 size, so we parition the flash chipset space accordingly.
617 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800618
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800619 raw_image = open(fw_file_path, 'rb').read()
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800620 wp_section = 'WP_RO'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800621 image = crosfw.FirmwareImage(raw_image)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800622 if image.has_section(wp_section):
623 section_data = image.get_section_area(wp_section)
624 ro_offset = section_data[0]
625 ro_size = section_data[1]
626 elif image.has_section(legacy_section):
627 section_data = image.get_section_area(legacy_section)
628 (ro_offset, ro_size) = CalculateLegacyRange(
Hung-Te Linb21c6682012-08-01 13:53:57 +0800629 fw_type, len(raw_image), section_data, legacy_section)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800630 else:
631 raise Error('could not find %s firmware section %s or %s' %
632 (fw_type, wp_section, legacy_section))
633
634 logging.debug('write protecting %s [off=%x size=%x]', fw_type,
635 ro_offset, ro_size)
636 crosfw.Flashrom(fw_type).EnableWriteProtection(ro_offset, ro_size)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800637
638 WriteProtect(crosfw.LoadMainFirmware().GetFileName(), 'main', 'RO_SECTION')
Andy Cheng0465d132013-03-20 12:12:06 +0800639 event_log.Log('wp', fw='main')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800640 ec_fw_file = crosfw.LoadEcFirmware().GetFileName()
641 if ec_fw_file is not None:
642 WriteProtect(ec_fw_file, 'ec', 'EC_RO')
Andy Cheng0465d132013-03-20 12:12:06 +0800643 event_log.Log('wp', fw='ec')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800644 else:
645 logging.warning('EC not write protected (seems there is no EC flash).')
646
647
648@Command('clear_gbb_flags')
Andy Chengc92e6f92012-11-20 16:55:53 +0800649def ClearGBBFlags(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800650 """Zero out the GBB flags, in preparation for transition to release state.
651
652 No GBB flags are set in release/shipping state, but they are useful
653 for factory/development. See "gbb_utility --flags" for details.
654 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800655
Ricky Lianga70a1202013-03-15 15:03:17 +0800656 GetGooftool(options).ClearGBBFlags()
Andy Cheng0465d132013-03-20 12:12:06 +0800657 event_log.Log('clear_gbb_flags')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800658
659
Jon Salzaa3a30e2013-05-15 15:56:28 +0800660@Command('clear_factory_vpd_entries')
661def ClearFactoryVPDEntries(options): # pylint: disable=W0613
662 """Clears factory.* items in the RW VPD."""
663 entries = GetGooftool(options).ClearFactoryVPDEntries()
664 event_log.Log('clear_factory_vpd_entries', entries=FilterDict(entries))
665
666
Mattias Nisslercca761b2015-04-15 21:53:04 +0200667@Command('generate_stable_device_secret')
668def GenerateStableDeviceSecret(options): # pylint: disable=W0613
669 """Generates a a fresh stable device secret and stores it in the RO VPD."""
670 GetGooftool(options).GenerateStableDeviceSecret()
671 event_log.Log('generate_stable_device_secret')
672
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800673@Command('wipe_in_place',
674 CmdArg('--fast', action='store_true',
675 help='use non-secure but faster wipe method.'))
676def WipeInPlace(options):
677 """Start factory wipe directly without reboot."""
678
679 GetGooftool(options).WipeInPlace(options.fast)
680
Mattias Nisslercca761b2015-04-15 21:53:04 +0200681
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800682@Command('prepare_wipe',
683 CmdArg('--fast', action='store_true',
684 help='use non-secure but faster wipe method.'))
685def PrepareWipe(options):
686 """Prepare system for transition to release state in next reboot."""
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800687
Ricky Lianga70a1202013-03-15 15:03:17 +0800688 GetGooftool(options).PrepareWipe(options.fast)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800689
Hung-Te Lin56b18402015-01-16 14:52:30 +0800690
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800691@Command('verify',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800692 CmdArg('--no_write_protect', action='store_true',
693 help='Do not check write protection switch state.'),
Ricky Liang43b879b2014-02-24 11:36:55 +0800694 _hwid_version_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700695 _hwid_status_list_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800696 _hwdb_path_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800697 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800698 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800699 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800700 _rma_mode_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800701 _cros_core_cmd_arg,
702 _enforced_release_channels_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800703def Verify(options):
704 """Verifies if whole factory process is ready for finalization.
705
706 This routine performs all the necessary checks to make sure the
707 device is ready to be finalized, but does not modify state. These
708 checks include dev switch, firmware write protection switch, hwid,
709 system time, keys, and root file system.
710 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800711
Hung-Te Lin6d827542012-07-19 11:50:41 +0800712 if not options.no_write_protect:
Ricky Lianga70a1202013-03-15 15:03:17 +0800713 VerifyWPSwitch(options)
Hung-Te Lindd708d42014-07-11 17:05:01 +0800714 VerifyManagementEngineLocked(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800715 VerifyDevSwitch(options)
716 if options.hwid_version == 2:
Ricky Liang43b879b2014-02-24 11:36:55 +0800717 VerifyHWIDv2(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800718 elif options.hwid_version == 3:
Ricky Liangc662be32013-12-24 11:50:23 +0800719 VerifyHWIDv3(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800720 else:
721 raise Error, 'Invalid HWID version: %r' % options.hwid_version
722 VerifySystemTime(options)
723 VerifyKeys(options)
724 VerifyRootFs(options)
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800725 VerifyTPM(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800726 if options.cros_core:
727 logging.info('VerifyBranding is skipped for ChromeOS Core device.')
728 else:
729 VerifyBranding(options)
bowgotsai529139c2015-05-30 01:39:49 +0800730 VerifyReleaseChannel(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800731
Hung-Te Lin56b18402015-01-16 14:52:30 +0800732
Jon Salzfe9036f2014-01-16 14:11:23 +0800733@Command('untar_stateful_files')
Hung-Te Lin388bce22014-06-03 19:56:40 +0800734def UntarStatefulFiles(unused_options):
Jon Salzfe9036f2014-01-16 14:11:23 +0800735 """Untars stateful files from stateful_files.tar.xz on stateful partition.
736
737 If that file does not exist (which should only be R30 and earlier),
738 this is a no-op.
739 """
740 tar_file = os.path.join(DEVICE_STATEFUL_PATH, 'stateful_files.tar.xz')
741 if os.path.exists(tar_file):
742 Spawn(['tar', 'xf', tar_file], cwd=DEVICE_STATEFUL_PATH,
743 log=True, check_call=True)
744 else:
745 logging.warning('No stateful files at %s', tar_file)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800746
Jon Salz40b9f822014-07-25 16:39:55 +0800747
748@Command('log_source_hashes')
749def LogSourceHashes(options): # pylint: disable=W0613
750 """Logs hashes of source files in the factory toolkit."""
Jon Salze60307f2014-08-05 16:20:00 +0800751 # WARNING: The following line is necessary to validate the integrity
752 # of the factory software. Do not remove or modify it.
753 #
754 # 警告:此行会验证工厂软件的完整性,禁止删除或修改。
Jon Salz40b9f822014-07-25 16:39:55 +0800755 event_log.Log(
756 'source_hashes',
Jon Salz9596ae02014-07-29 14:25:49 +0800757 **file_utils.HashSourceTree(os.path.join(factory.FACTORY_PATH, 'py')))
Jon Salz40b9f822014-07-25 16:39:55 +0800758
759
Tammo Spalink86a61c62012-05-25 15:10:35 +0800760@Command('log_system_details')
Tammo Spalink01e11722012-07-24 10:17:54 -0700761def LogSystemDetails(options): # pylint: disable=W0613
Tammo Spalink86a61c62012-05-25 15:10:35 +0800762 """Write miscellaneous system details to the event log."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800763
Ricky Liang43b879b2014-02-24 11:36:55 +0800764 event_log.Log('system_details', **GetGooftool(options).GetSystemDetails())
Tammo Spalink86a61c62012-05-25 15:10:35 +0800765
766
Jon Salza88b83b2013-05-27 20:00:35 +0800767def CreateReportArchiveBlob(*args, **kwargs):
768 """Creates a report archive and returns it as a blob.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800769
Jon Salza88b83b2013-05-27 20:00:35 +0800770 Args:
771 See CreateReportArchive.
Andy Cheng7a76cb82012-11-19 18:08:19 +0800772
Jon Salza88b83b2013-05-27 20:00:35 +0800773 Returns:
774 An xmlrpclib.Binary object containing a .tar.xz file.
775 """
776 with open(CreateReportArchive(*args, **kwargs)) as f:
777 return xmlrpclib.Binary(f.read())
778
779
780def CreateReportArchive(device_sn=None, add_file=None):
781 """Creates a report archive in a temporary directory.
782
783 Args:
784 device_sn: The device serial number (optional).
785 add_file: A list of files to add (optional).
786
787 Returns:
788 Path to the archive.
789 """
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800790 def NormalizeAsFileName(token):
791 return re.sub(r'\W+', '', token).strip()
Jon Salza88b83b2013-05-27 20:00:35 +0800792
793 target_name = '%s%s.tar.xz' % (
794 time.strftime('%Y%m%dT%H%M%SZ',
795 time.gmtime()),
Hung-Te Lin56b18402015-01-16 14:52:30 +0800796 ('' if device_sn is None else
797 '_' + NormalizeAsFileName(device_sn)))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800798 target_path = os.path.join(gettempdir(), target_name)
Jon Salza88b83b2013-05-27 20:00:35 +0800799
Tammo Spalink86a61c62012-05-25 15:10:35 +0800800 # Intentionally ignoring dotfiles in EVENT_LOG_DIR.
Andy Cheng0465d132013-03-20 12:12:06 +0800801 tar_cmd = 'cd %s ; tar cJf %s *' % (event_log.EVENT_LOG_DIR, target_path)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800802 tar_cmd += ' --add-file %s' % FACTORY_LOG_PATH
Jon Salza88b83b2013-05-27 20:00:35 +0800803 if add_file:
804 for f in add_file:
Jon Salz65266432012-07-30 19:02:49 +0800805 # Require absolute paths since the tar command may change the
806 # directory.
807 if not f.startswith('/'):
808 raise Error('Not an absolute path: %s' % f)
809 if not os.path.exists(f):
810 raise Error('File does not exist: %s' % f)
811 tar_cmd += ' --add-file %s' % pipes.quote(f)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800812 cmd_result = Shell(tar_cmd)
Jon Salzff88c022012-11-03 12:19:58 +0800813
814 if ((cmd_result.status == 1) and
815 all((x == '' or
816 'file changed as we read it' in x or
817 "Removing leading `/' from member names" in x)
818 for x in cmd_result.stderr.split('\n'))):
819 # That's OK. Make sure it's valid though.
Vic Yang85199e72013-01-28 14:33:11 +0800820 Spawn(['tar', 'tfJ', target_path], check_call=True, log=True,
Jon Salzff88c022012-11-03 12:19:58 +0800821 ignore_stdout=True)
822 elif not cmd_result.success:
Tammo Spalink86a61c62012-05-25 15:10:35 +0800823 raise Error('unable to tar event logs, cmd %r failed, stderr: %r' %
824 (tar_cmd, cmd_result.stderr))
Jon Salzff88c022012-11-03 12:19:58 +0800825
Jon Salza88b83b2013-05-27 20:00:35 +0800826 return target_path
827
828_upload_method_cmd_arg = CmdArg(
829 '--upload_method', metavar='METHOD:PARAM',
830 help=('How to perform the upload. METHOD should be one of '
831 '{ftp, shopfloor, ftps, cpfe}.'))
832_add_file_cmd_arg = CmdArg(
833 '--add_file', metavar='FILE', action='append',
834 help='Extra file to include in report (must be an absolute path)')
835
Hung-Te Lin56b18402015-01-16 14:52:30 +0800836
Jon Salza88b83b2013-05-27 20:00:35 +0800837@Command('upload_report',
838 _upload_method_cmd_arg,
839 _add_file_cmd_arg)
840def UploadReport(options):
841 """Create a report containing key device details."""
842 ro_vpd = ReadRoVpd(crosfw.LoadMainFirmware().GetFileName())
843 device_sn = ro_vpd.get('serial_number', None)
844 if device_sn is None:
845 logging.warning('RO_VPD missing device serial number')
846 device_sn = 'MISSING_SN_' + event_log.TimedUuid()
847 target_path = CreateReportArchive(device_sn)
848
Tammo Spalink86a61c62012-05-25 15:10:35 +0800849 if options.upload_method is None or options.upload_method == 'none':
850 logging.warning('REPORT UPLOAD SKIPPED (report left at %s)', target_path)
851 return
852 method, param = options.upload_method.split(':', 1)
853 if method == 'shopfloor':
854 report_upload.ShopFloorUpload(target_path, param)
855 elif method == 'ftp':
Jay Kim360c1dd2012-06-25 10:58:11 -0700856 report_upload.FtpUpload(target_path, 'ftp:' + param)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800857 elif method == 'ftps':
858 report_upload.CurlUrlUpload(target_path, '--ftp-ssl-reqd ftp:%s' % param)
859 elif method == 'cpfe':
Shawn Nematbakhsh3404a092013-01-28 16:49:09 -0800860 report_upload.CpfeUpload(target_path, pipes.quote(param))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800861 else:
862 raise Error('unknown report upload method %r', method)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800863
864
865@Command('finalize',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800866 CmdArg('--no_write_protect', action='store_true',
867 help='Do not enable firmware write protection.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800868 CmdArg('--fast', action='store_true',
869 help='use non-secure but faster wipe method.'),
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800870 CmdArg('--wipe_in_place', action='store_true',
871 help='Start factory wiping in place without reboot.'),
Ricky Liang43b879b2014-02-24 11:36:55 +0800872 _hwid_version_cmd_arg,
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800873 _hwdb_path_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700874 _hwid_status_list_cmd_arg,
Jon Salz65266432012-07-30 19:02:49 +0800875 _upload_method_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800876 _add_file_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800877 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800878 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800879 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800880 _rma_mode_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800881 _cros_core_cmd_arg,
882 _enforced_release_channels_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800883def Finalize(options):
884 """Verify system readiness and trigger transition into release state.
885
Jon Salzaa3a30e2013-05-15 15:56:28 +0800886 This routine does the following:
887 - Verifies system state (see verify command)
Jon Salzfe9036f2014-01-16 14:11:23 +0800888 - Untars stateful_files.tar.xz, if it exists, in the stateful partition, to
889 initialize files such as the CRX cache
Jon Salzaa3a30e2013-05-15 15:56:28 +0800890 - Modifies firmware bitmaps to match locale
891 - Clears all factory-friendly flags from the GBB
892 - Removes factory-specific entries from RW_VPD (factory.*)
893 - Enables firmware write protection (cannot rollback after this)
894 - Uploads system logs & reports
895 - Sets the necessary boot flags to cause wipe of the factory image on the
896 next boot.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800897 """
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800898 Verify(options)
Jon Salz40b9f822014-07-25 16:39:55 +0800899 LogSourceHashes(options)
Jon Salzfe9036f2014-01-16 14:11:23 +0800900 UntarStatefulFiles(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800901 if options.cros_core:
902 logging.info('SetFirmwareBitmapLocale is skipped for ChromeOS Core device.')
903 else:
904 SetFirmwareBitmapLocale(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800905 ClearGBBFlags(options)
Jon Salzaa3a30e2013-05-15 15:56:28 +0800906 ClearFactoryVPDEntries(options)
Mattias Nisslercca761b2015-04-15 21:53:04 +0200907 GenerateStableDeviceSecret(options)
Hung-Te Lin6d827542012-07-19 11:50:41 +0800908 if options.no_write_protect:
909 logging.warn('WARNING: Firmware Write Protection is SKIPPED.')
Andy Cheng0465d132013-03-20 12:12:06 +0800910 event_log.Log('wp', fw='both', status='skipped')
Hung-Te Lin6d827542012-07-19 11:50:41 +0800911 else:
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800912 EnableFwWp({})
Jon Salza0f58e02012-05-29 19:33:39 +0800913 LogSystemDetails(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800914 UploadReport(options)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800915 if options.wipe_in_place:
916 event_log.Log('wipe_in_place')
917 WipeInPlace(options)
918 else:
919 PrepareWipe(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800920
921
Ricky Liangc662be32013-12-24 11:50:23 +0800922def VerifyHWIDv3(options):
923 """A simple wrapper that calls out to HWID utils to verify version 3 HWID.
Ricky Liang53390232013-03-08 15:37:57 +0800924
Ricky Liangc662be32013-12-24 11:50:23 +0800925 This is mainly for Gooftool to verify v3 HWID during finalize. For testing
926 and development purposes, please use `hwid` command.
Ricky Liang53390232013-03-08 15:37:57 +0800927 """
Ricky Liangc662be32013-12-24 11:50:23 +0800928 db = GetGooftool(options).db
929 encoded_string = options.hwid or hwid_utils.GetHWIDString()
Ricky Liang7905f272013-03-16 01:57:10 +0800930 if options.probe_results:
Ricky Liangc662be32013-12-24 11:50:23 +0800931 probed_results = yaml.load(open(options.probe_results).read())
Ricky Liang7905f272013-03-16 01:57:10 +0800932 else:
Ricky Liangc662be32013-12-24 11:50:23 +0800933 probed_results = yaml.load(Probe(probe_vpd=True).Encode())
934 vpd = hwid_utils.GetVPD(probed_results)
Ricky Liang53390232013-03-08 15:37:57 +0800935
Hung-Te Lin11052952015-03-18 13:48:59 +0800936 event_log.Log('probed_results', probed_results=FilterDict(probed_results))
937 event_log.Log('vpd', vpd=FilterDict(vpd))
Ricky Liang53390232013-03-08 15:37:57 +0800938
Ricky Liangc662be32013-12-24 11:50:23 +0800939 hwid_utils.VerifyHWID(db, encoded_string, probed_results, vpd,
Hung-Te Lin56b18402015-01-16 14:52:30 +0800940 rma_mode=options.rma_mode)
Ricky Liang53390232013-03-08 15:37:57 +0800941
Ricky Liangc662be32013-12-24 11:50:23 +0800942 event_log.Log('verified_hwid', hwid=encoded_string)
Ricky Liang53390232013-03-08 15:37:57 +0800943
944
Ricky Liang59611a62013-06-11 13:47:33 +0800945def ParseDecodedHWID(hwid):
946 """Parse the HWID object into a more compact dict.
947
948 Args:
949 hwid: A decoded HWID object.
950
951 Returns:
952 A dict containing the board name, the binary string, and the list of
953 components.
954 """
955 results = {}
956 results['board'] = hwid.database.board
957 results['binary_string'] = hwid.binary_string
958 results['components'] = collections.defaultdict(list)
959 components = hwid.bom.components
960 for comp_cls in sorted(components):
961 for (comp_name, probed_values, _) in sorted(components[comp_cls]):
962 if not probed_values:
963 db_components = hwid.database.components
964 probed_values = db_components.GetComponentAttributes(
965 comp_cls, comp_name).get('values')
966 results['components'][comp_cls].append(
967 {comp_name: probed_values if probed_values else None})
968 # Convert defaultdict to dict.
969 results['components'] = dict(results['components'])
970 return results
971
972
henryhsu44d793a2013-07-20 00:07:38 +0800973@Command('get_firmware_hash',
974 CmdArg('--file', metavar='FILE', help='Firmware File.'))
975def GetFirmwareHash(options):
henryhsuf6f835c2013-07-20 20:49:25 +0800976 """Get firmware hash from a file"""
henryhsu44d793a2013-07-20 00:07:38 +0800977 if os.path.exists(options.file):
978 hashes = CalculateFirmwareHashes(options.file)
979 for section, value_dict in hashes.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +0800980 print '%s:' % section
henryhsu44d793a2013-07-20 00:07:38 +0800981 for key, value in value_dict.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +0800982 print ' %s: %s' % (key, value)
henryhsu44d793a2013-07-20 00:07:38 +0800983 else:
984 raise Error('File does not exist: %s' % options.file)
985
henryhsuf6f835c2013-07-20 20:49:25 +0800986
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800987def Main():
988 """Run sub-command specified by the command line args."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800989
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800990 options = ParseCmdline(
Ricky Liangc662be32013-12-24 11:50:23 +0800991 ('Perform Google required factory tests. All the HWID-related functions '
992 'provided here are mainly for the deprecated HWID v2. To access HWID '
993 'v3-related utilities, please use `hwid` command.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800994 CmdArg('-l', '--log', metavar='PATH',
995 help='Write logs to this file.'),
Jon Salza4bea382012-10-29 13:00:34 +0800996 CmdArg('--suppress-event-logs', action='store_true',
997 help='Suppress event logging.'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800998 verbosity_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800999 SetupLogging(options.verbosity, options.log)
Andy Cheng0465d132013-03-20 12:12:06 +08001000 event_log.SetGlobalLoggerDefaultPrefix('gooftool')
1001 event_log.GetGlobalLogger().suppress = options.suppress_event_logs
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001002 logging.debug('gooftool options: %s', repr(options))
1003 try:
1004 logging.debug('GOOFTOOL command %r', options.command_name)
1005 options.command(options)
1006 logging.info('GOOFTOOL command %r SUCCESS', options.command_name)
1007 except Error, e:
1008 logging.exception(e)
1009 sys.exit('GOOFTOOL command %r ERROR: %s' % (options.command_name, e))
1010 except Exception, e:
1011 logging.exception(e)
1012 sys.exit('UNCAUGHT RUNTIME EXCEPTION %s' % e)
1013
1014
1015if __name__ == '__main__':
1016 Main()