blob: 3344dfa3c58d6d17598456c7ff8766e4aae882bb [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
Ricky Liang53390232013-03-08 15:37:57 +080031from cros.factory.gooftool import crosfw
Tammo Spalink01e11722012-07-24 10:17:54 -070032from cros.factory.gooftool import report_upload
Hung-Te Lin84c77fa2016-03-02 17:43:30 +080033from cros.factory.gooftool.core import Gooftool
Wei-Han Chen0a3320e2016-04-23 01:32:07 +080034from cros.factory.gooftool.common import ExecFactoryPar
Hung-Te Lin0e0f9362015-11-18 18:18:05 +080035from cros.factory.gooftool.common import Shell
Andy Cheng8ece7382012-08-22 16:25:42 +080036from cros.factory.gooftool.probe import Probe, PROBEABLE_COMPONENT_CLASSES
Jon Salz0f8a6842012-09-25 11:28:22 +080037from cros.factory.gooftool.probe import ReadRoVpd, ReadRwVpd
henryhsu44d793a2013-07-20 00:07:38 +080038from cros.factory.gooftool.probe import CalculateFirmwareHashes
Jon Salz193d7c62013-03-07 13:40:19 +080039from cros.factory.gooftool.vpd_data import KNOWN_VPD_FIELD_DATA
Tammo Spalinka40293e2012-07-04 14:58:56 +080040from cros.factory.hacked_argparse import CmdArg, Command, ParseCmdline
41from cros.factory.hacked_argparse import verbosity_cmd_arg
Hung-Te Lin604e0c22015-11-24 15:17:07 +080042from cros.factory.hwid.v2 import hwid_tool
43from cros.factory.hwid.v2.yaml_datastore import YamlWrite
44from cros.factory.hwid.v3 import common
45from cros.factory.hwid.v3 import hwid_utils
Hung-Te Lin91492a12014-11-25 18:56:30 +080046from cros.factory.test import event_log
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +080047from cros.factory.test.env import paths
Wei-Han Chenaff56232016-04-16 09:17:59 +080048from cros.factory.test.rules import phase
Hung-Te Lin3f096842016-01-13 17:37:06 +080049from cros.factory.test.rules.privacy import FilterDict
Jon Salz40b9f822014-07-25 16:39:55 +080050from cros.factory.utils import file_utils
Wei-Han Chena5c01a02016-04-23 19:27:19 +080051from cros.factory.utils import sys_utils
Hung-Te Lin0e0f9362015-11-18 18:18:05 +080052from cros.factory.utils.debug_utils import SetupLogging
Jon Salzff88c022012-11-03 12:19:58 +080053from cros.factory.utils.process_utils import Spawn
Joel Kitchingd3bc2662014-12-16 16:03:32 -080054from cros.factory.utils.type_utils import Error
Tammo Spalink86a61c62012-05-25 15:10:35 +080055
Tammo Spalink5c699832012-07-03 17:50:39 +080056
Tammo Spalink5c699832012-07-03 17:50:39 +080057# TODO(tammo): Replace calls to sys.exit with raise Exit, and maybe
58# treat that specially (as a smoot exit, as opposed to the more
59# verbose output for generic Error).
60
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080061_global_gooftool = None
62_gooftool_lock = threading.Lock()
Tammo Spalink5c699832012-07-03 17:50:39 +080063
Hung-Te Lin56b18402015-01-16 14:52:30 +080064
Ricky Lianga70a1202013-03-15 15:03:17 +080065def GetGooftool(options):
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080066 global _global_gooftool # pylint: disable=W0603
Ricky Lianga70a1202013-03-15 15:03:17 +080067
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080068 if _global_gooftool is None:
69 with _gooftool_lock:
Ricky Liang43b879b2014-02-24 11:36:55 +080070 hwid_version = getattr(options, 'hwid_version', 3)
71 if hwid_version == 2:
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080072 hwdb_path = getattr(options, 'hwdb_path', None)
73 component_db = (
74 hwid_tool.HardwareDb(options.hwdb_path).comp_db if hwdb_path
75 else None)
76 _global_gooftool = Gooftool(hwid_version=2, component_db=component_db)
Ricky Liang43b879b2014-02-24 11:36:55 +080077 elif hwid_version == 3:
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080078 board = getattr(options, 'board', None)
79 hwdb_path = getattr(options, 'hwdb_path', None)
80 _global_gooftool = Gooftool(hwid_version=3, board=board,
81 hwdb_path=hwdb_path)
82 else:
83 raise Error, 'Invalid HWID version: %r' % options.hwid_version
84
85 return _global_gooftool
Ricky Lianga70a1202013-03-15 15:03:17 +080086
Hung-Te Lin56b18402015-01-16 14:52:30 +080087
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080088@Command('write_hwid',
89 CmdArg('hwid', metavar='HWID', help='HWID string'))
Andy Chengc92e6f92012-11-20 16:55:53 +080090def WriteHWID(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080091 """Write specified HWID value into the system BB."""
Andy Cheng7a76cb82012-11-19 18:08:19 +080092
Tammo Spalink95c43732012-07-25 15:57:14 -070093 logging.info('writing hwid string %r', options.hwid)
Ricky Lianga70a1202013-03-15 15:03:17 +080094 GetGooftool(options).WriteHWID(options.hwid)
Andy Cheng0465d132013-03-20 12:12:06 +080095 event_log.Log('write_hwid', hwid=options.hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -070096 print 'Wrote HWID: %r' % options.hwid
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080097
98
Ricky Liang53390232013-03-08 15:37:57 +080099_board_cmd_arg = CmdArg(
100 '--board', metavar='BOARD',
101 default=None, help='Board name to test.')
102
Tammo Spalink8fab5312012-05-28 18:33:30 +0800103_hwdb_path_cmd_arg = CmdArg(
104 '--hwdb_path', metavar='PATH',
Ricky Liangeede7922013-06-19 10:18:41 +0800105 default=common.DEFAULT_HWID_DATA_PATH,
Tammo Spalink8fab5312012-05-28 18:33:30 +0800106 help='Path to the HWID database.')
107
Tammo Spalink95c43732012-07-25 15:57:14 -0700108_hwid_status_list_cmd_arg = CmdArg(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800109 '--status', nargs='*', default=['supported'],
110 help='allow only HWIDs with these status values')
Tammo Spalink95c43732012-07-25 15:57:14 -0700111
Jon Salzce124fb2012-10-02 17:42:03 +0800112_probe_results_cmd_arg = CmdArg(
113 '--probe_results', metavar='RESULTS.yaml',
Ricky Liangc662be32013-12-24 11:50:23 +0800114 help=('Output from "gooftool probe --include_vpd" (used instead of '
Jon Salzce124fb2012-10-02 17:42:03 +0800115 'probing this system).'))
116
Ricky Liang53390232013-03-08 15:37:57 +0800117_device_info_cmd_arg = CmdArg(
Ricky Liangf89f73a2013-03-19 05:00:24 +0800118 '--device_info', metavar='DEVICE_INFO.yaml', default=None,
Ricky Liang53390232013-03-08 15:37:57 +0800119 help='A dict of device info to use instead of fetching from shopfllor '
120 'server.')
121
Jon Salzce124fb2012-10-02 17:42:03 +0800122_hwid_cmd_arg = CmdArg(
123 '--hwid', metavar='HWID',
Ricky Lianga70a1202013-03-15 15:03:17 +0800124 help='HWID to verify (instead of the currently set HWID of this system).')
Jon Salzce124fb2012-10-02 17:42:03 +0800125
Bernie Thompson3c11c872013-07-22 18:22:45 -0700126_rma_mode_cmd_arg = CmdArg(
127 '--rma_mode', action='store_true',
128 help='Enable RMA mode, do not check for deprecated components.')
Tammo Spalink95c43732012-07-25 15:57:14 -0700129
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800130_cros_core_cmd_arg = CmdArg(
131 '--cros_core', action='store_true',
132 help='Finalize for ChromeOS Core devices (may add or remove few test '
133 'items. For example, branding verification or firmware bitmap '
134 'locale settings).')
135
Ricky Liang43b879b2014-02-24 11:36:55 +0800136_hwid_version_cmd_arg = CmdArg(
137 '-i', '--hwid-version', default=3, choices=(2, 3), type=int,
138 help='Version of HWID to operate on. (default: %(default)s)')
139
bowgotsai13820f42015-09-10 23:18:04 +0800140_enforced_release_channels_cmd_arg = CmdArg(
141 '--enforced_release_channels', nargs='*', default=None,
142 help='Enforced release image channels.')
143
Hung-Te Lincdb96522016-04-15 16:51:10 +0800144_release_rootfs_cmd_arg = CmdArg(
145 '--release_rootfs', help='Location of release image rootfs partition.')
146
147_firmware_path_cmd_arg = CmdArg(
148 '--firmware_path', help='Location of firmware image partition.')
Ricky Liang43b879b2014-02-24 11:36:55 +0800149
Tammo Spalink95c43732012-07-25 15:57:14 -0700150@Command('best_match_hwids',
Tammo Spalink8fab5312012-05-28 18:33:30 +0800151 _hwdb_path_cmd_arg,
152 CmdArg('-b', '--board', metavar='BOARD',
Tammo Spalink95c43732012-07-25 15:57:14 -0700153 help='optional BOARD name, needed only if data is present '
154 'for more than one'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800155 CmdArg('--bom', metavar='BOM', help='BOM name'),
156 CmdArg('--variant', metavar='VARIANT', help='VARIANT code'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800157 CmdArg('--optimistic', action='store_true',
158 help='do not probe; assume singletons match'),
Tammo Spalink95c43732012-07-25 15:57:14 -0700159 CmdArg('--comps', nargs='*', default=[],
160 help='list of canonical component names'),
161 CmdArg('--missing', nargs='*', default=[],
162 help='list component classes to be assumed missing'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800163 CmdArg('--status', nargs='*', default=['supported'],
Tammo Spalink95c43732012-07-25 15:57:14 -0700164 help='consider only HWIDs within this list of status values'))
165def BestMatchHwids(options):
Ricky Liangc662be32013-12-24 11:50:23 +0800166 """Determine a list of possible HWIDs using provided args and probing.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800167
168 VOLATILE can always be determined by probing. To get a unique
169 result, VARIANT must be specified for all cases where the matching
170 BOM has more than one associated variant code, otherwise all HWID
171 variants will be returned. Both VARIANT and BOM information can
Tammo Spalink95c43732012-07-25 15:57:14 -0700172 alternatively be specified using the --stdin_comps argument, which
173 allows specifying a list of canonical names (one per line) on stdin,
174 one per line. Based on what is known from BOM and stdin_comps,
175 determine a list of components to probe for, and use those probe
176 results to resolve a list of matching HWIDs. If no boms,
177 components, or variant codes are specified, then a list of all HWIDs
Andy Cheng8ece7382012-08-22 16:25:42 +0800178 that match probeable components will be returned.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800179
180 Returns (on stdout): A list of HWIDs that match the available probe
181 results and argument contraints, one per line.
Tammo Spalink70b48a52012-08-08 16:54:51 -0700182
183 Example:
184
185 // Three ways to specify a keyboard (assuming it is a variant component)
186 gooftool best_match_hwids --missing keyboard
187 gooftool best_match_hwids --variant A or
188 gooftool best_match_hwids --comps us_kbd
Tammo Spalink8fab5312012-05-28 18:33:30 +0800189 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800190
Tammo Spalink5c699832012-07-03 17:50:39 +0800191 map(hwid_tool.Validate.Status, options.status)
Tammo Spalink95c43732012-07-25 15:57:14 -0700192 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Tammo Spalink5c699832012-07-03 17:50:39 +0800193 comp_db = hw_db.comp_db
Tammo Spalink3a7e9022012-06-27 14:08:40 +0800194 device = hw_db.GetDevice(options.board)
Tammo Spalink5c699832012-07-03 17:50:39 +0800195 component_spec = hwid_tool.ComponentSpec.New()
Tammo Spalink8fab5312012-05-28 18:33:30 +0800196 if options.bom:
Tammo Spalink5c699832012-07-03 17:50:39 +0800197 device.BomExists(options.bom)
Tammo Spalink01e11722012-07-24 10:17:54 -0700198 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800199 component_spec, device.boms[options.bom].primary)
Tammo Spalink8fab5312012-05-28 18:33:30 +0800200 if options.variant:
Tammo Spalink5c699832012-07-03 17:50:39 +0800201 device.VariantExists(options.variant)
202 variant_spec = device.variants[options.variant]
Tammo Spalink01e11722012-07-24 10:17:54 -0700203 if hwid_tool.ComponentSpecsConflict(component_spec, variant_spec):
Tammo Spalink95c43732012-07-25 15:57:14 -0700204 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700205 % YamlWrite(sorted(
206 hwid_tool.ComponentSpecClasses(component_spec) &
207 hwid_tool.ComponentSpecClasses(variant_spec))))
Tammo Spalink01e11722012-07-24 10:17:54 -0700208 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800209 component_spec, variant_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700210 if options.comps or options.missing:
211 map(comp_db.CompExists, options.comps)
212 map(comp_db.CompClassExists, options.missing)
213 extra_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800214 components=options.comps,
215 missing=options.missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700216 print 'cmdline asserted components:\n%s' % extra_comp_spec.Encode()
217 if hwid_tool.ComponentSpecsConflict(component_spec, extra_comp_spec):
218 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700219 % YamlWrite(sorted(
220 hwid_tool.ComponentSpecClasses(component_spec) &
221 hwid_tool.ComponentSpecClasses(extra_comp_spec))))
Tammo Spalink95c43732012-07-25 15:57:14 -0700222 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800223 component_spec, extra_comp_spec)
Tammo Spalink01e11722012-07-24 10:17:54 -0700224 spec_classes = hwid_tool.ComponentSpecClasses(component_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700225 missing_classes = set(comp_db.all_comp_classes) - spec_classes
Tammo Spalink5c699832012-07-03 17:50:39 +0800226 if missing_classes and not options.optimistic:
Andy Cheng8ece7382012-08-22 16:25:42 +0800227 non_probeable_missing = missing_classes - PROBEABLE_COMPONENT_CLASSES
228 if non_probeable_missing:
Tammo Spalink95c43732012-07-25 15:57:14 -0700229 sys.exit('FAILURE: these classes are necessary, were not specified '
Tammo Spalink70b48a52012-08-08 16:54:51 -0700230 'as inputs, and cannot be probed for:\n%s'
231 'This problem can often be addressed by specifying all of '
232 'the missing components on the command line (see the command '
Andy Cheng8ece7382012-08-22 16:25:42 +0800233 'help).' % YamlWrite(list(non_probeable_missing)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700234 print 'probing for missing classes:'
235 print YamlWrite(list(missing_classes))
236 probe_results = Probe(target_comp_classes=list(missing_classes),
237 probe_volatile=False, probe_initial_config=False)
238 cooked_components = comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800239 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700240 if cooked_components.unmatched:
241 sys.exit('ERROR: some probed components are unrecognized:\n%s'
242 % YamlWrite(cooked_components.unmatched))
243 probed_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800244 components=cooked_components.matched,
245 missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700246 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800247 component_spec, probed_comp_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700248 print YamlWrite({'component data used for matching': {
Hung-Te Lin56b18402015-01-16 14:52:30 +0800249 'missing component classes': component_spec.classes_missing,
250 'found components': component_spec.components}})
Tammo Spalink95c43732012-07-25 15:57:14 -0700251 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800252 extant_components=hwid_tool.ComponentSpecCompClassMap(
253 component_spec).keys(),
254 classes_missing=component_spec.classes_missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700255 match_tree = device.BuildMatchTree(component_data)
256 if not match_tree:
257 sys.exit('FAILURE: NO matching BOMs found')
258 print 'potential BOMs/VARIANTs:'
259 potential_variants = set()
260 potential_volatiles = set()
261 for bom_name, variant_tree in match_tree.items():
262 print ' BOM: %-8s VARIANTS: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800263 bom_name, ', '.join(sorted(variant_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700264 for variant_code in variant_tree:
265 potential_variants.add(variant_code)
266 for volatile_code in device.volatiles:
267 status = device.GetHwidStatus(bom_name, variant_code, volatile_code)
268 if status in options.status:
269 potential_volatiles.add(volatile_code)
270 print ''
271 if len(potential_variants) == 0:
272 sys.exit('FAILURE: no matching VARIANTs found')
273 if len(potential_volatiles) == 0:
274 sys.exit('FAILURE: no VOLATILEs found for potential matching BOMs/VARIANTS '
275 '(with specified status)')
Tammo Spalink394e4492012-08-01 10:20:30 -0700276 if (options.optimistic and
277 len(match_tree) == 1 and
278 len(potential_variants) == 1 and
279 len(potential_volatiles) == 1):
280 print ('MATCHING HWID: %s' % device.FmtHwid(match_tree.keys().pop(),
281 potential_variants.pop(),
282 potential_volatiles.pop()))
Tammo Spalink5c699832012-07-03 17:50:39 +0800283 return
Tammo Spalink95c43732012-07-25 15:57:14 -0700284 print ('probing VOLATILEs to resolve potential matches: %s\n' %
285 ', '.join(sorted(potential_volatiles)))
286 vol_probe_results = Probe(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800287 target_comp_classes=[],
288 probe_volatile=True,
289 probe_initial_config=False)
Tammo Spalink95c43732012-07-25 15:57:14 -0700290 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800291 vol_probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700292 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800293 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700294 matched_hwids = device.GetMatchTreeHwids(match_tree)
295 if matched_hwids:
296 for hwid in matched_hwids:
Ricky Liang02f3bd72012-09-21 14:33:01 +0800297 if matched_hwids[hwid] in options.status:
298 print 'MATCHING HWID: %s' % hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700299 return
300 print 'exact HWID matching failed, but the following BOMs match: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800301 ', '.join(sorted(match_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700302 if options.optimistic and len(match_tree) == 1:
303 bom_name = set(match_tree).pop()
Tammo Spalink5c699832012-07-03 17:50:39 +0800304 bom = device.boms[bom_name]
Tammo Spalink95c43732012-07-25 15:57:14 -0700305 variant_matches = match_tree[bom_name]
Tammo Spalink5c699832012-07-03 17:50:39 +0800306 if len(variant_matches) == 1:
307 var_code = set(variant_matches).pop()
308 elif len(bom.variants) == 1:
309 var_code = set(bom.variants).pop()
310 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700311 sys.exit('FAILURE: NO matching HWIDs found; optimistic matching failed '
312 'because there were too many variants to choose from for BOM %r'
313 % bom_name)
314 hwids = [device.FmtHwid(bom_name, var_code, vol_code)
315 for vol_code in device.volatiles
316 if device.GetHwidStatus(bom_name, var_code, vol_code)
317 in options.status]
318 for hwid in hwids:
319 print 'MATCHING HWID: %s' % hwid
Tammo Spalink5c699832012-07-03 17:50:39 +0800320 return
321 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700322 print ('optimistic matching not attempted because either it was '
323 'not requested, or because the number of BOMs was <> 1\n')
324 sys.exit('FAILURE: NO matching HWIDs found')
Tammo Spalink8fab5312012-05-28 18:33:30 +0800325
326
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800327@Command('probe',
328 CmdArg('--comps', nargs='*',
329 help='List of keys from the component_db registry.'),
Ricky Liangb30da672013-06-14 12:36:34 +0800330 CmdArg('--fast_fw_probe', action='store_true',
331 help='Do a fast probe for EC and main firmware versions only. '
332 'This implies --no_vol and --no_ic.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800333 CmdArg('--no_vol', action='store_true',
334 help='Do not probe volatile data.'),
335 CmdArg('--no_ic', action='store_true',
Jon Salz0f8a6842012-09-25 11:28:22 +0800336 help='Do not probe initial_config data.'),
337 CmdArg('--include_vpd', action='store_true',
338 help='Include VPD data in volatiles.'))
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800339def RunProbe(options):
340 """Print yaml-formatted breakdown of probed device properties."""
Ricky Lianga70a1202013-03-15 15:03:17 +0800341 print GetGooftool(options).Probe(
342 target_comp_classes=options.comps,
Ricky Liangb30da672013-06-14 12:36:34 +0800343 fast_fw_probe=options.fast_fw_probe,
Ricky Lianga70a1202013-03-15 15:03:17 +0800344 probe_volatile=not options.no_vol,
345 probe_initial_config=not options.no_ic,
346 probe_vpd=options.include_vpd).Encode()
Ricky Liang53390232013-03-08 15:37:57 +0800347
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800348
Tammo Spalink214caf42012-05-28 10:45:00 +0800349@Command('verify_components',
350 _hwdb_path_cmd_arg,
Tammo Spalink5c699832012-07-03 17:50:39 +0800351 CmdArg('target_comps', nargs='*'))
Tammo Spalink214caf42012-05-28 10:45:00 +0800352def VerifyComponents(options):
Andy Cheng8ece7382012-08-22 16:25:42 +0800353 """Verify that probeable components all match entries in the component_db.
Tammo Spalink214caf42012-05-28 10:45:00 +0800354
Tammo Spalink5c699832012-07-03 17:50:39 +0800355 Probe for each component class in the target_comps and verify
Tammo Spalink214caf42012-05-28 10:45:00 +0800356 that a corresponding match exists in the component_db -- make sure
357 that these components are present, that they have been approved, but
358 do not check against any specific BOM/HWID configurations.
359 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800360
Andy Chengc531e2f2012-10-15 19:09:17 +0800361 try:
Ricky Lianga70a1202013-03-15 15:03:17 +0800362 result = GetGooftool(options).VerifyComponents(
Andy Chengc531e2f2012-10-15 19:09:17 +0800363 options.target_comps)
364 except ValueError, e:
365 sys.exit(e)
366
Ricky Liang53390232013-03-08 15:37:57 +0800367 PrintVerifyComponentsResults(result)
368
369
370def PrintVerifyComponentsResults(result):
371 """Prints out the results of VerifyComponents method call.
372
373 Groups the results into two groups: 'matches' and 'errors', and prints out
374 their values.
375 """
Andy Chengc531e2f2012-10-15 19:09:17 +0800376 # group by matches and errors
Tammo Spalink214caf42012-05-28 10:45:00 +0800377 matches = []
Andy Chengc531e2f2012-10-15 19:09:17 +0800378 errors = []
379 for result_list in result.values():
380 for component_name, _, error in result_list:
381 if component_name:
382 matches.append(component_name)
Tammo Spalink214caf42012-05-28 10:45:00 +0800383 else:
Andy Chengc531e2f2012-10-15 19:09:17 +0800384 errors.append(error)
385
Andy Cheng228a8c92012-08-27 10:53:57 +0800386 if matches:
387 print 'found probeable components:\n %s' % '\n '.join(matches)
Tammo Spalink214caf42012-05-28 10:45:00 +0800388 if errors:
Andy Cheng228a8c92012-08-27 10:53:57 +0800389 print '\nerrors:\n %s' % '\n '.join(errors)
390 sys.exit('\ncomponent verification FAILURE')
Tammo Spalink214caf42012-05-28 10:45:00 +0800391 else:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800392 print '\ncomponent verification SUCCESS'
Tammo Spalink214caf42012-05-28 10:45:00 +0800393
394
Ricky Liang43b879b2014-02-24 11:36:55 +0800395@Command('verify_hwid_v2',
Tammo Spalink95c43732012-07-25 15:57:14 -0700396 _hwid_status_list_cmd_arg,
Jon Salz0f8a6842012-09-25 11:28:22 +0800397 _hwdb_path_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800398 _probe_results_cmd_arg,
399 _hwid_cmd_arg)
Ricky Liang43b879b2014-02-24 11:36:55 +0800400def VerifyHWIDv2(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800401 """Verify system HWID properties match probed device properties.
402
403 First probe components, volatile and initial_config parameters for
404 the DUT. Then use the available device data to produce a list of
405 candidate HWIDs. Then verify the HWID from the DUT is present in
406 that list. Then verify that the DUT initial config values match
407 those specified for its HWID. Finally, verify that VPD contains all
408 the necessary fields as specified by the board data, and when
409 possible verify that values are legitimate.
410 """
Ricky Liangf7857c12012-09-17 13:34:41 +0800411 def VerifyVpd(ro_vpd_keys, rw_vpd_keys):
Tammo Spalink5c699832012-07-03 17:50:39 +0800412 for key in ro_vpd_keys:
413 if key not in ro_vpd:
Ricky Liangf7857c12012-09-17 13:34:41 +0800414 sys.exit('Missing required RO VPD field: %s' % key)
Tammo Spalink01e11722012-07-24 10:17:54 -0700415 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800416 value = ro_vpd[key]
Ricky Liangf7857c12012-09-17 13:34:41 +0800417 if (known_valid_values is not None) and (value not in known_valid_values):
418 sys.exit('Invalid RO VPD entry : key %r, value %r' % (key, value))
Ricky Liangf7857c12012-09-17 13:34:41 +0800419 for key in rw_vpd_keys:
420 if key not in rw_vpd:
421 sys.exit('Missing required RW VPD field: %s' % key)
422 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
423 value = rw_vpd[key]
424 if (known_valid_values is not None) and (value not in known_valid_values):
425 sys.exit('Invalid RW VPD entry : key %r, value %r' % (key, value))
Andy Cheng0465d132013-03-20 12:12:06 +0800426 event_log.Log('vpd', ro_vpd=FilterDict(ro_vpd), rw_vpd=FilterDict(rw_vpd))
Tammo Spalink5c699832012-07-03 17:50:39 +0800427 map(hwid_tool.Validate.Status, options.status)
Jon Salz0f8a6842012-09-25 11:28:22 +0800428
Jon Salz0f8a6842012-09-25 11:28:22 +0800429 if options.hwid:
430 hwid_str = options.hwid
431 else:
Hung-Te Lin74346d72016-01-07 22:16:57 +0800432 main_fw_file = crosfw.LoadMainFirmware().GetFileName()
Jon Salz0f8a6842012-09-25 11:28:22 +0800433 gbb_result = Shell('gbb_utility -g --hwid %s' % main_fw_file).stdout
434 hwid_str = re.findall(r'hardware_id:(.*)', gbb_result)[0].strip()
Tammo Spalink95c43732012-07-25 15:57:14 -0700435 hwid = hwid_tool.ParseHwid(hwid_str)
Tammo Spalink5c699832012-07-03 17:50:39 +0800436 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Jon Salz0f8a6842012-09-25 11:28:22 +0800437 print 'Verifying HWID: %r\n' % hwid.hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700438 device = hw_db.GetDevice(hwid.board)
439 hwid_status = device.GetHwidStatus(hwid.bom, hwid.variant, hwid.volatile)
440 if hwid_status not in options.status:
Tammo Spalink5c699832012-07-03 17:50:39 +0800441 sys.exit('HWID status must be one of [%s], found %r' %
Hung-Te Lin4f5beb12012-08-20 14:48:06 +0800442 (', '.join(options.status), hwid_status))
Jon Salz0f8a6842012-09-25 11:28:22 +0800443 if options.probe_results:
444 # Pull in probe results (including VPD data) from the given file
445 # rather than probing the current system.
446 probe_results = hwid_tool.ProbeResults.Decode(
447 open(options.probe_results).read())
448 ro_vpd = {}
449 rw_vpd = {}
450 for k, v in probe_results.found_volatile_values.items():
Hung-Te Lin56b18402015-01-16 14:52:30 +0800451 match = re.match(r'^vpd\.(ro|rw)\.(\w+)$', k)
Jon Salz0f8a6842012-09-25 11:28:22 +0800452 if match:
453 del probe_results.found_volatile_values[k]
454 (ro_vpd if match.group(1) == 'ro' else rw_vpd)[match.group(2)] = v
455 else:
456 probe_results = Probe()
Hung-Te Lin74346d72016-01-07 22:16:57 +0800457 ro_vpd = ReadRoVpd()
458 rw_vpd = ReadRwVpd()
Tammo Spalink95c43732012-07-25 15:57:14 -0700459 cooked_components = hw_db.comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800460 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700461 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800462 probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700463 cooked_initial_configs = device.MatchInitialConfigValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800464 probe_results.initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700465 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800466 extant_components=cooked_components.matched,
467 classes_missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700468 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800469 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700470 matched_hwids = device.GetMatchTreeHwids(match_tree)
471 print 'HWID status: %s\n' % hwid_status
472 print 'probed system components:'
473 print YamlWrite(cooked_components.__dict__)
474 print 'missing component classes:'
475 print YamlWrite(probe_results.missing_component_classes)
476 print 'probed volatiles:'
477 print YamlWrite(cooked_volatiles.__dict__)
478 print 'probed initial_configs:'
479 print YamlWrite(cooked_initial_configs)
480 print 'hwid match tree:'
481 print YamlWrite(match_tree)
Andy Cheng0465d132013-03-20 12:12:06 +0800482 event_log.Log(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800483 'probe',
484 found_components=cooked_components.__dict__,
485 missing_component_classes=probe_results.missing_component_classes,
486 volatiles=cooked_volatiles.__dict__,
487 initial_configs=cooked_initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700488 if hwid.hwid not in matched_hwids:
Tammo Spalink5c699832012-07-03 17:50:39 +0800489 err_msg = 'HWID verification FAILED.\n'
Tammo Spalink95c43732012-07-25 15:57:14 -0700490 if cooked_components.unmatched:
Tammo Spalink5c699832012-07-03 17:50:39 +0800491 sys.exit(err_msg + 'some components could not be indentified:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700492 YamlWrite(cooked_components.unmatched))
493 if not match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800494 sys.exit(err_msg + 'no matching boms were found for components:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700495 component_data.Encode())
496 if hwid.bom not in match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800497 sys.exit(err_msg + 'matching boms [%s] do not include target bom %r' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700498 (', '.join(sorted(match_tree)), hwid.bom))
499 err_msg += 'target bom %r matches components' % hwid.bom
500 if hwid.bom not in device.IntersectBomsAndInitialConfigs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800501 cooked_initial_configs):
Tammo Spalink5c699832012-07-03 17:50:39 +0800502 sys.exit(err_msg + ', but failed initial config verification')
Tammo Spalink95c43732012-07-25 15:57:14 -0700503 matched_variants = match_tree.get(hwid.bom, {})
504 if hwid.variant not in matched_variants:
Tammo Spalink5c699832012-07-03 17:50:39 +0800505 sys.exit(err_msg + ', but target variant_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700506 hwid.variant)
507 matched_volatiles = matched_variants.get(hwid.variant, {})
508 if hwid.volatile not in matched_volatiles:
Tammo Spalink5c699832012-07-03 17:50:39 +0800509 sys.exit(err_msg + ', but target volatile_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700510 hwid.volatile)
511 found_status = matched_volatiles.get(hwid.volatile, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800512 sys.exit(err_msg + ', but hwid status %r was unacceptable' % found_status)
Ricky Liangf7857c12012-09-17 13:34:41 +0800513 VerifyVpd(device.vpd_ro_fields, device.vpd_rw_fields)
Andy Cheng0465d132013-03-20 12:12:06 +0800514 event_log.Log('verified_hwid', hwid=hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -0700515 print 'Verification SUCCESS!'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800516
517
Hung-Te Line1d80f62016-03-31 14:58:13 +0800518@Command('verify_keys',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800519 _release_rootfs_cmd_arg,
520 _firmware_path_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700521def VerifyKeys(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800522 """Verify keys in firmware and SSD match."""
Hung-Te Line1d80f62016-03-31 14:58:13 +0800523 return GetGooftool(options).VerifyKeys(
Hung-Te Lincdb96522016-04-15 16:51:10 +0800524 options.release_rootfs, options.firmware_path)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800525
526
527@Command('set_fw_bitmap_locale')
Tammo Spalink01e11722012-07-24 10:17:54 -0700528def SetFirmwareBitmapLocale(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800529 """Use VPD locale value to set firmware bitmap default language."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800530
Ricky Lianga70a1202013-03-15 15:03:17 +0800531 (index, locale) = GetGooftool(options).SetFirmwareBitmapLocale()
Andy Cheng2582d292012-12-04 17:38:28 +0800532 logging.info('Firmware bitmap initial locale set to %d (%s).',
533 index, locale)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800534
535
Hung-Te Line1d80f62016-03-31 14:58:13 +0800536@Command('verify_system_time',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800537 _release_rootfs_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700538def VerifySystemTime(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800539 """Verify system time is later than release filesystem creation time."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800540
Hung-Te Lincdb96522016-04-15 16:51:10 +0800541 return GetGooftool(options).VerifySystemTime(options.release_rootfs)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800542
543
Hung-Te Line1d80f62016-03-31 14:58:13 +0800544@Command('verify_rootfs',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800545 _release_rootfs_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700546def VerifyRootFs(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800547 """Verify rootfs on SSD is valid by checking hash."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800548
Hung-Te Line1d80f62016-03-31 14:58:13 +0800549 return GetGooftool(options).VerifyRootFs(options.release_rootfs)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800550
Hung-Te Lin56b18402015-01-16 14:52:30 +0800551
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800552@Command('verify_tpm')
553def VerifyTPM(options): # pylint: disable=W0613
554 """Verify TPM is cleared."""
555
556 return GetGooftool(options).VerifyTPM()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800557
Hung-Te Lin56b18402015-01-16 14:52:30 +0800558
Hung-Te Lindd708d42014-07-11 17:05:01 +0800559@Command('verify_me_locked')
560def VerifyManagementEngineLocked(options): # pylint: disable=W0613
561 """Verify Managment Engine is locked."""
562
563 return GetGooftool(options).VerifyManagementEngineLocked()
564
Hung-Te Lin56b18402015-01-16 14:52:30 +0800565
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800566@Command('verify_switch_wp')
Andy Chengc92e6f92012-11-20 16:55:53 +0800567def VerifyWPSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800568 """Verify hardware write protection switch is enabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800569
Ricky Lianga70a1202013-03-15 15:03:17 +0800570 GetGooftool(options).VerifyWPSwitch()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800571
572
573@Command('verify_switch_dev')
Tammo Spalink01e11722012-07-24 10:17:54 -0700574def VerifyDevSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800575 """Verify developer switch is disabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800576
Ricky Lianga70a1202013-03-15 15:03:17 +0800577 if GetGooftool(options).CheckDevSwitchForDisabling():
Hung-Te Lind7d34722012-07-26 16:48:35 +0800578 logging.warn('VerifyDevSwitch: No physical switch.')
Andy Cheng0465d132013-03-20 12:12:06 +0800579 event_log.Log('switch_dev', type='virtual switch')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800580
581
Jon Salzadd90d32014-04-29 16:16:27 +0800582@Command('verify_branding')
583def VerifyBranding(options): # pylint: disable=W0613
584 """Verify that branding fields are properly set.
585
586 customization_id, if set in the RO VPD, must be of the correct format.
587
588 rlz_brand_code must be set either in the RO VPD or OEM partition, and must
589 be of the correct format.
590 """
591 return GetGooftool(options).VerifyBranding()
592
593
bowgotsai13820f42015-09-10 23:18:04 +0800594@Command('verify_release_channel',
595 _enforced_release_channels_cmd_arg)
bowgotsai529139c2015-05-30 01:39:49 +0800596def VerifyReleaseChannel(options): # pylint: disable=W0613
597 """Verify that release image channel is correct.
598
599 ChromeOS has four channels: canary, dev, beta and stable.
600 The last three channels support image auto-updates, checks
601 that release image channel is one of them.
602 """
bowgotsai13820f42015-09-10 23:18:04 +0800603 return GetGooftool(options).VerifyReleaseChannel(
604 options.enforced_release_channels)
bowgotsai529139c2015-05-30 01:39:49 +0800605
606
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800607@Command('write_protect')
Tammo Spalink01e11722012-07-24 10:17:54 -0700608def EnableFwWp(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800609 """Enable then verify firmware write protection."""
610
Hung-Te Linb21c6682012-08-01 13:53:57 +0800611 def CalculateLegacyRange(fw_type, length, section_data,
612 section_name):
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800613 ro_size = length / 2
614 ro_a = int(section_data[0] / ro_size)
615 ro_b = int((section_data[0] + section_data[1] - 1) / ro_size)
616 if ro_a != ro_b:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800617 raise Error('%s firmware section %s has illegal size' %
Hung-Te Linb21c6682012-08-01 13:53:57 +0800618 (fw_type, section_name))
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800619 ro_offset = ro_a * ro_size
620 return (ro_offset, ro_size)
621
622 def WriteProtect(fw_file_path, fw_type, legacy_section):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800623 """Calculate protection size, then invoke flashrom.
624
625 Our supported chips only allow write protecting half their total
626 size, so we parition the flash chipset space accordingly.
627 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800628
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800629 raw_image = open(fw_file_path, 'rb').read()
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800630 wp_section = 'WP_RO'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800631 image = crosfw.FirmwareImage(raw_image)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800632 if image.has_section(wp_section):
633 section_data = image.get_section_area(wp_section)
634 ro_offset = section_data[0]
635 ro_size = section_data[1]
636 elif image.has_section(legacy_section):
637 section_data = image.get_section_area(legacy_section)
638 (ro_offset, ro_size) = CalculateLegacyRange(
Hung-Te Linb21c6682012-08-01 13:53:57 +0800639 fw_type, len(raw_image), section_data, legacy_section)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800640 else:
641 raise Error('could not find %s firmware section %s or %s' %
642 (fw_type, wp_section, legacy_section))
643
644 logging.debug('write protecting %s [off=%x size=%x]', fw_type,
645 ro_offset, ro_size)
646 crosfw.Flashrom(fw_type).EnableWriteProtection(ro_offset, ro_size)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800647
648 WriteProtect(crosfw.LoadMainFirmware().GetFileName(), 'main', 'RO_SECTION')
Andy Cheng0465d132013-03-20 12:12:06 +0800649 event_log.Log('wp', fw='main')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800650 ec_fw_file = crosfw.LoadEcFirmware().GetFileName()
651 if ec_fw_file is not None:
652 WriteProtect(ec_fw_file, 'ec', 'EC_RO')
Andy Cheng0465d132013-03-20 12:12:06 +0800653 event_log.Log('wp', fw='ec')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800654 else:
655 logging.warning('EC not write protected (seems there is no EC flash).')
656
657
658@Command('clear_gbb_flags')
Andy Chengc92e6f92012-11-20 16:55:53 +0800659def ClearGBBFlags(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800660 """Zero out the GBB flags, in preparation for transition to release state.
661
662 No GBB flags are set in release/shipping state, but they are useful
663 for factory/development. See "gbb_utility --flags" for details.
664 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800665
Ricky Lianga70a1202013-03-15 15:03:17 +0800666 GetGooftool(options).ClearGBBFlags()
Andy Cheng0465d132013-03-20 12:12:06 +0800667 event_log.Log('clear_gbb_flags')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800668
669
Jon Salzaa3a30e2013-05-15 15:56:28 +0800670@Command('clear_factory_vpd_entries')
671def ClearFactoryVPDEntries(options): # pylint: disable=W0613
672 """Clears factory.* items in the RW VPD."""
673 entries = GetGooftool(options).ClearFactoryVPDEntries()
674 event_log.Log('clear_factory_vpd_entries', entries=FilterDict(entries))
675
676
Mattias Nisslercca761b2015-04-15 21:53:04 +0200677@Command('generate_stable_device_secret')
678def GenerateStableDeviceSecret(options): # pylint: disable=W0613
679 """Generates a a fresh stable device secret and stores it in the RO VPD."""
680 GetGooftool(options).GenerateStableDeviceSecret()
681 event_log.Log('generate_stable_device_secret')
682
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800683_cutoff_args_cmd_arg = CmdArg(
684 '--cutoff_args',
685 help='Battery cutoff arguments to be passed to battery_cutoff.sh '
686 'after wiping. Should be the following format: '
Shun-Hsing Ouccbeab12016-05-13 11:58:45 +0800687 '[--method shutdown|reboot|battery_cutoff] '
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800688 '[--check-ac connect_ac|remove_ac] '
689 '[--min-battery-percent <minimum battery percentage>] '
690 '[--max-battery-percent <maximum battery percentage>] '
691 '[--min-battery-voltage <minimum battery voltage>] '
692 '[--max-battery-voltage <maximum battery voltage>]')
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800693_shopfloor_url_args_cmd_arg = CmdArg(
694 '--shopfloor_url',
695 help='Shopfloor server url to be informed when in-place wipe is done. '
696 'After in-place wipe, a XML-RPC request will be sent to the '
697 'given url to indicate the completion of wipe.')
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800698@Command('wipe_in_place',
699 CmdArg('--fast', action='store_true',
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800700 help='use non-secure but faster wipe method.'),
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800701 _cutoff_args_cmd_arg,
702 _shopfloor_url_args_cmd_arg)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800703def WipeInPlace(options):
704 """Start factory wipe directly without reboot."""
705
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800706 GetGooftool(options).WipeInPlace(options.fast, options.cutoff_args,
707 options.shopfloor_url)
Mattias Nisslercca761b2015-04-15 21:53:04 +0200708
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800709@Command('wipe_init',
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800710 CmdArg('--wipe_args', help='arguments for clobber-state'),
711 CmdArg('--state_dev', help='path to stateful partition device'),
712 CmdArg('--root_disk', help='path to primary device'),
713 CmdArg('--old_root', help='path to old root'),
714 _cutoff_args_cmd_arg,
715 _shopfloor_url_args_cmd_arg,
716 _release_rootfs_cmd_arg)
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800717def WipeInit(options):
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800718 GetGooftool(options).WipeInit(options.wipe_args,
719 options.cutoff_args,
720 options.shopfloor_url,
721 options.state_dev,
722 options.release_rootfs,
723 options.root_disk,
724 options.old_root)
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800725
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800726@Command('prepare_wipe',
727 CmdArg('--fast', action='store_true',
728 help='use non-secure but faster wipe method.'))
729def PrepareWipe(options):
730 """Prepare system for transition to release state in next reboot."""
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800731
Ricky Lianga70a1202013-03-15 15:03:17 +0800732 GetGooftool(options).PrepareWipe(options.fast)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800733
Hung-Te Lin56b18402015-01-16 14:52:30 +0800734
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800735@Command('verify',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800736 CmdArg('--no_write_protect', action='store_true',
737 help='Do not check write protection switch state.'),
Ricky Liang43b879b2014-02-24 11:36:55 +0800738 _hwid_version_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700739 _hwid_status_list_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800740 _hwdb_path_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800741 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800742 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800743 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800744 _rma_mode_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800745 _cros_core_cmd_arg,
Hung-Te Lincdb96522016-04-15 16:51:10 +0800746 _release_rootfs_cmd_arg,
747 _firmware_path_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800748 _enforced_release_channels_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800749def Verify(options):
750 """Verifies if whole factory process is ready for finalization.
751
752 This routine performs all the necessary checks to make sure the
753 device is ready to be finalized, but does not modify state. These
754 checks include dev switch, firmware write protection switch, hwid,
755 system time, keys, and root file system.
756 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800757
Hung-Te Lin6d827542012-07-19 11:50:41 +0800758 if not options.no_write_protect:
Ricky Lianga70a1202013-03-15 15:03:17 +0800759 VerifyWPSwitch(options)
Hung-Te Lindd708d42014-07-11 17:05:01 +0800760 VerifyManagementEngineLocked(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800761 VerifyDevSwitch(options)
762 if options.hwid_version == 2:
Ricky Liang43b879b2014-02-24 11:36:55 +0800763 VerifyHWIDv2(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800764 elif options.hwid_version == 3:
Ricky Liangc662be32013-12-24 11:50:23 +0800765 VerifyHWIDv3(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800766 else:
767 raise Error, 'Invalid HWID version: %r' % options.hwid_version
768 VerifySystemTime(options)
769 VerifyKeys(options)
770 VerifyRootFs(options)
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800771 VerifyTPM(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800772 if options.cros_core:
773 logging.info('VerifyBranding is skipped for ChromeOS Core device.')
774 else:
775 VerifyBranding(options)
bowgotsai529139c2015-05-30 01:39:49 +0800776 VerifyReleaseChannel(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800777
Hung-Te Lin56b18402015-01-16 14:52:30 +0800778
Jon Salzfe9036f2014-01-16 14:11:23 +0800779@Command('untar_stateful_files')
Hung-Te Lin388bce22014-06-03 19:56:40 +0800780def UntarStatefulFiles(unused_options):
Jon Salzfe9036f2014-01-16 14:11:23 +0800781 """Untars stateful files from stateful_files.tar.xz on stateful partition.
782
783 If that file does not exist (which should only be R30 and earlier),
784 this is a no-op.
785 """
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +0800786 tar_file = os.path.join(paths.DEVICE_STATEFUL_PATH, 'stateful_files.tar.xz')
Jon Salzfe9036f2014-01-16 14:11:23 +0800787 if os.path.exists(tar_file):
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +0800788 Spawn(['tar', 'xf', tar_file], cwd=paths.DEVICE_STATEFUL_PATH,
Jon Salzfe9036f2014-01-16 14:11:23 +0800789 log=True, check_call=True)
790 else:
791 logging.warning('No stateful files at %s', tar_file)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800792
Jon Salz40b9f822014-07-25 16:39:55 +0800793
794@Command('log_source_hashes')
795def LogSourceHashes(options): # pylint: disable=W0613
796 """Logs hashes of source files in the factory toolkit."""
Jon Salze60307f2014-08-05 16:20:00 +0800797 # WARNING: The following line is necessary to validate the integrity
798 # of the factory software. Do not remove or modify it.
799 #
800 # 警告:此行会验证工厂软件的完整性,禁止删除或修改。
Wei-Han Chena5c01a02016-04-23 19:27:19 +0800801 factory_par = sys_utils.GetRunningFactoryPythonArchivePath()
802 if factory_par:
803 event_log.Log(
804 'source_hashes',
805 **file_utils.HashPythonArchive(factory_par))
806 else:
807 event_log.Log(
808 'source_hashes',
809 **file_utils.HashSourceTree(os.path.join(paths.FACTORY_PATH, 'py')))
Jon Salz40b9f822014-07-25 16:39:55 +0800810
811
Tammo Spalink86a61c62012-05-25 15:10:35 +0800812@Command('log_system_details')
Tammo Spalink01e11722012-07-24 10:17:54 -0700813def LogSystemDetails(options): # pylint: disable=W0613
Tammo Spalink86a61c62012-05-25 15:10:35 +0800814 """Write miscellaneous system details to the event log."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800815
Ricky Liang43b879b2014-02-24 11:36:55 +0800816 event_log.Log('system_details', **GetGooftool(options).GetSystemDetails())
Tammo Spalink86a61c62012-05-25 15:10:35 +0800817
818
Jon Salza88b83b2013-05-27 20:00:35 +0800819def CreateReportArchiveBlob(*args, **kwargs):
820 """Creates a report archive and returns it as a blob.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800821
Jon Salza88b83b2013-05-27 20:00:35 +0800822 Args:
823 See CreateReportArchive.
Andy Cheng7a76cb82012-11-19 18:08:19 +0800824
Jon Salza88b83b2013-05-27 20:00:35 +0800825 Returns:
826 An xmlrpclib.Binary object containing a .tar.xz file.
827 """
828 with open(CreateReportArchive(*args, **kwargs)) as f:
829 return xmlrpclib.Binary(f.read())
830
831
832def CreateReportArchive(device_sn=None, add_file=None):
833 """Creates a report archive in a temporary directory.
834
835 Args:
836 device_sn: The device serial number (optional).
837 add_file: A list of files to add (optional).
838
839 Returns:
840 Path to the archive.
841 """
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800842 def NormalizeAsFileName(token):
843 return re.sub(r'\W+', '', token).strip()
Jon Salza88b83b2013-05-27 20:00:35 +0800844
845 target_name = '%s%s.tar.xz' % (
846 time.strftime('%Y%m%dT%H%M%SZ',
847 time.gmtime()),
Hung-Te Lin56b18402015-01-16 14:52:30 +0800848 ('' if device_sn is None else
849 '_' + NormalizeAsFileName(device_sn)))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800850 target_path = os.path.join(gettempdir(), target_name)
Jon Salza88b83b2013-05-27 20:00:35 +0800851
Tammo Spalink86a61c62012-05-25 15:10:35 +0800852 # Intentionally ignoring dotfiles in EVENT_LOG_DIR.
Andy Cheng0465d132013-03-20 12:12:06 +0800853 tar_cmd = 'cd %s ; tar cJf %s *' % (event_log.EVENT_LOG_DIR, target_path)
Joel Kitching4b1b6c02016-05-10 14:34:30 +0800854 tar_cmd += ' --add-file %s' % paths.GetFactoryLogPath()
Jon Salza88b83b2013-05-27 20:00:35 +0800855 if add_file:
856 for f in add_file:
Jon Salz65266432012-07-30 19:02:49 +0800857 # Require absolute paths since the tar command may change the
858 # directory.
859 if not f.startswith('/'):
860 raise Error('Not an absolute path: %s' % f)
861 if not os.path.exists(f):
862 raise Error('File does not exist: %s' % f)
863 tar_cmd += ' --add-file %s' % pipes.quote(f)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800864 cmd_result = Shell(tar_cmd)
Jon Salzff88c022012-11-03 12:19:58 +0800865
866 if ((cmd_result.status == 1) and
867 all((x == '' or
868 'file changed as we read it' in x or
869 "Removing leading `/' from member names" in x)
870 for x in cmd_result.stderr.split('\n'))):
871 # That's OK. Make sure it's valid though.
Vic Yang85199e72013-01-28 14:33:11 +0800872 Spawn(['tar', 'tfJ', target_path], check_call=True, log=True,
Jon Salzff88c022012-11-03 12:19:58 +0800873 ignore_stdout=True)
874 elif not cmd_result.success:
Tammo Spalink86a61c62012-05-25 15:10:35 +0800875 raise Error('unable to tar event logs, cmd %r failed, stderr: %r' %
876 (tar_cmd, cmd_result.stderr))
Jon Salzff88c022012-11-03 12:19:58 +0800877
Jon Salza88b83b2013-05-27 20:00:35 +0800878 return target_path
879
880_upload_method_cmd_arg = CmdArg(
881 '--upload_method', metavar='METHOD:PARAM',
882 help=('How to perform the upload. METHOD should be one of '
883 '{ftp, shopfloor, ftps, cpfe}.'))
884_add_file_cmd_arg = CmdArg(
885 '--add_file', metavar='FILE', action='append',
886 help='Extra file to include in report (must be an absolute path)')
887
Hung-Te Lin56b18402015-01-16 14:52:30 +0800888
Jon Salza88b83b2013-05-27 20:00:35 +0800889@Command('upload_report',
890 _upload_method_cmd_arg,
891 _add_file_cmd_arg)
892def UploadReport(options):
893 """Create a report containing key device details."""
Hung-Te Lin74346d72016-01-07 22:16:57 +0800894 ro_vpd = ReadRoVpd()
Jon Salza88b83b2013-05-27 20:00:35 +0800895 device_sn = ro_vpd.get('serial_number', None)
896 if device_sn is None:
897 logging.warning('RO_VPD missing device serial number')
898 device_sn = 'MISSING_SN_' + event_log.TimedUuid()
899 target_path = CreateReportArchive(device_sn)
900
Tammo Spalink86a61c62012-05-25 15:10:35 +0800901 if options.upload_method is None or options.upload_method == 'none':
902 logging.warning('REPORT UPLOAD SKIPPED (report left at %s)', target_path)
903 return
904 method, param = options.upload_method.split(':', 1)
905 if method == 'shopfloor':
906 report_upload.ShopFloorUpload(target_path, param)
907 elif method == 'ftp':
Jay Kim360c1dd2012-06-25 10:58:11 -0700908 report_upload.FtpUpload(target_path, 'ftp:' + param)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800909 elif method == 'ftps':
910 report_upload.CurlUrlUpload(target_path, '--ftp-ssl-reqd ftp:%s' % param)
911 elif method == 'cpfe':
Shawn Nematbakhsh3404a092013-01-28 16:49:09 -0800912 report_upload.CpfeUpload(target_path, pipes.quote(param))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800913 else:
914 raise Error('unknown report upload method %r', method)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800915
916
917@Command('finalize',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800918 CmdArg('--no_write_protect', action='store_true',
919 help='Do not enable firmware write protection.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800920 CmdArg('--fast', action='store_true',
921 help='use non-secure but faster wipe method.'),
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800922 CmdArg('--wipe_in_place', action='store_true',
923 help='Start factory wiping in place without reboot.'),
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800924 _cutoff_args_cmd_arg,
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800925 _shopfloor_url_args_cmd_arg,
Ricky Liang43b879b2014-02-24 11:36:55 +0800926 _hwid_version_cmd_arg,
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800927 _hwdb_path_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700928 _hwid_status_list_cmd_arg,
Jon Salz65266432012-07-30 19:02:49 +0800929 _upload_method_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800930 _add_file_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800931 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800932 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800933 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800934 _rma_mode_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800935 _cros_core_cmd_arg,
Hung-Te Lincdb96522016-04-15 16:51:10 +0800936 _release_rootfs_cmd_arg,
937 _firmware_path_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800938 _enforced_release_channels_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800939def Finalize(options):
940 """Verify system readiness and trigger transition into release state.
941
Jon Salzaa3a30e2013-05-15 15:56:28 +0800942 This routine does the following:
943 - Verifies system state (see verify command)
Jon Salzfe9036f2014-01-16 14:11:23 +0800944 - Untars stateful_files.tar.xz, if it exists, in the stateful partition, to
945 initialize files such as the CRX cache
Jon Salzaa3a30e2013-05-15 15:56:28 +0800946 - Modifies firmware bitmaps to match locale
947 - Clears all factory-friendly flags from the GBB
948 - Removes factory-specific entries from RW_VPD (factory.*)
949 - Enables firmware write protection (cannot rollback after this)
950 - Uploads system logs & reports
951 - Sets the necessary boot flags to cause wipe of the factory image on the
952 next boot.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800953 """
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800954 Verify(options)
Jon Salz40b9f822014-07-25 16:39:55 +0800955 LogSourceHashes(options)
Jon Salzfe9036f2014-01-16 14:11:23 +0800956 UntarStatefulFiles(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800957 if options.cros_core:
958 logging.info('SetFirmwareBitmapLocale is skipped for ChromeOS Core device.')
959 else:
960 SetFirmwareBitmapLocale(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800961 ClearGBBFlags(options)
Jon Salzaa3a30e2013-05-15 15:56:28 +0800962 ClearFactoryVPDEntries(options)
Mattias Nisslercca761b2015-04-15 21:53:04 +0200963 GenerateStableDeviceSecret(options)
Hung-Te Lin6d827542012-07-19 11:50:41 +0800964 if options.no_write_protect:
965 logging.warn('WARNING: Firmware Write Protection is SKIPPED.')
Andy Cheng0465d132013-03-20 12:12:06 +0800966 event_log.Log('wp', fw='both', status='skipped')
Hung-Te Lin6d827542012-07-19 11:50:41 +0800967 else:
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800968 EnableFwWp({})
Jon Salza0f58e02012-05-29 19:33:39 +0800969 LogSystemDetails(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800970 UploadReport(options)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800971 if options.wipe_in_place:
972 event_log.Log('wipe_in_place')
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800973 # WipeInPlace(options)
974 wipe_args = []
975 wipe_args += ['--cutoff_args', options.cutoff_args]
976 wipe_args += ['--shopfloor_url', options.shopfloor_url]
977 if options.fast:
978 wipe_args += ['--fast']
979 ExecFactoryPar('gooftool', 'wipe_in_place', *wipe_args)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800980 else:
981 PrepareWipe(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800982
983
Ricky Liangc662be32013-12-24 11:50:23 +0800984def VerifyHWIDv3(options):
985 """A simple wrapper that calls out to HWID utils to verify version 3 HWID.
Ricky Liang53390232013-03-08 15:37:57 +0800986
Ricky Liangc662be32013-12-24 11:50:23 +0800987 This is mainly for Gooftool to verify v3 HWID during finalize. For testing
988 and development purposes, please use `hwid` command.
Ricky Liang53390232013-03-08 15:37:57 +0800989 """
Ricky Liangc662be32013-12-24 11:50:23 +0800990 db = GetGooftool(options).db
991 encoded_string = options.hwid or hwid_utils.GetHWIDString()
Ricky Liang7905f272013-03-16 01:57:10 +0800992 if options.probe_results:
Ricky Liangc662be32013-12-24 11:50:23 +0800993 probed_results = yaml.load(open(options.probe_results).read())
Ricky Liang7905f272013-03-16 01:57:10 +0800994 else:
Ricky Liangc662be32013-12-24 11:50:23 +0800995 probed_results = yaml.load(Probe(probe_vpd=True).Encode())
996 vpd = hwid_utils.GetVPD(probed_results)
Ricky Liang53390232013-03-08 15:37:57 +0800997
Hung-Te Lin11052952015-03-18 13:48:59 +0800998 event_log.Log('probed_results', probed_results=FilterDict(probed_results))
999 event_log.Log('vpd', vpd=FilterDict(vpd))
Ricky Liang53390232013-03-08 15:37:57 +08001000
Ricky Liangc662be32013-12-24 11:50:23 +08001001 hwid_utils.VerifyHWID(db, encoded_string, probed_results, vpd,
Hung-Te Lin56b18402015-01-16 14:52:30 +08001002 rma_mode=options.rma_mode)
Ricky Liang53390232013-03-08 15:37:57 +08001003
Ricky Liangc662be32013-12-24 11:50:23 +08001004 event_log.Log('verified_hwid', hwid=encoded_string)
Ricky Liang53390232013-03-08 15:37:57 +08001005
1006
Ricky Liang59611a62013-06-11 13:47:33 +08001007def ParseDecodedHWID(hwid):
1008 """Parse the HWID object into a more compact dict.
1009
1010 Args:
1011 hwid: A decoded HWID object.
1012
1013 Returns:
1014 A dict containing the board name, the binary string, and the list of
1015 components.
1016 """
1017 results = {}
1018 results['board'] = hwid.database.board
1019 results['binary_string'] = hwid.binary_string
1020 results['components'] = collections.defaultdict(list)
1021 components = hwid.bom.components
1022 for comp_cls in sorted(components):
1023 for (comp_name, probed_values, _) in sorted(components[comp_cls]):
1024 if not probed_values:
1025 db_components = hwid.database.components
1026 probed_values = db_components.GetComponentAttributes(
1027 comp_cls, comp_name).get('values')
1028 results['components'][comp_cls].append(
1029 {comp_name: probed_values if probed_values else None})
1030 # Convert defaultdict to dict.
1031 results['components'] = dict(results['components'])
1032 return results
1033
1034
henryhsu44d793a2013-07-20 00:07:38 +08001035@Command('get_firmware_hash',
1036 CmdArg('--file', metavar='FILE', help='Firmware File.'))
1037def GetFirmwareHash(options):
henryhsuf6f835c2013-07-20 20:49:25 +08001038 """Get firmware hash from a file"""
henryhsu44d793a2013-07-20 00:07:38 +08001039 if os.path.exists(options.file):
1040 hashes = CalculateFirmwareHashes(options.file)
1041 for section, value_dict in hashes.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +08001042 print '%s:' % section
henryhsu44d793a2013-07-20 00:07:38 +08001043 for key, value in value_dict.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +08001044 print ' %s: %s' % (key, value)
henryhsu44d793a2013-07-20 00:07:38 +08001045 else:
1046 raise Error('File does not exist: %s' % options.file)
1047
henryhsuf6f835c2013-07-20 20:49:25 +08001048
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001049def Main():
1050 """Run sub-command specified by the command line args."""
Andy Cheng7a76cb82012-11-19 18:08:19 +08001051
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001052 options = ParseCmdline(
Ricky Liangc662be32013-12-24 11:50:23 +08001053 ('Perform Google required factory tests. All the HWID-related functions '
1054 'provided here are mainly for the deprecated HWID v2. To access HWID '
1055 'v3-related utilities, please use `hwid` command.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001056 CmdArg('-l', '--log', metavar='PATH',
1057 help='Write logs to this file.'),
Jon Salza4bea382012-10-29 13:00:34 +08001058 CmdArg('--suppress-event-logs', action='store_true',
1059 help='Suppress event logging.'),
Wei-Han Chenaff56232016-04-16 09:17:59 +08001060 CmdArg('--phase', default=None,
1061 help=('override phase for phase checking (defaults to the current '
1062 'as returned by the "factory phase" command)')),
Tammo Spalink8fab5312012-05-28 18:33:30 +08001063 verbosity_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001064 SetupLogging(options.verbosity, options.log)
Andy Cheng0465d132013-03-20 12:12:06 +08001065 event_log.SetGlobalLoggerDefaultPrefix('gooftool')
1066 event_log.GetGlobalLogger().suppress = options.suppress_event_logs
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001067 logging.debug('gooftool options: %s', repr(options))
Wei-Han Chenaff56232016-04-16 09:17:59 +08001068
1069 phase.OverridePhase(options.phase)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001070 try:
1071 logging.debug('GOOFTOOL command %r', options.command_name)
1072 options.command(options)
1073 logging.info('GOOFTOOL command %r SUCCESS', options.command_name)
1074 except Error, e:
1075 logging.exception(e)
1076 sys.exit('GOOFTOOL command %r ERROR: %s' % (options.command_name, e))
1077 except Exception, e:
1078 logging.exception(e)
1079 sys.exit('UNCAUGHT RUNTIME EXCEPTION %s' % e)
1080
1081
1082if __name__ == '__main__':
1083 Main()