blob: a51e870a618c161746d6e60160b23c82e47d69da [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
Hung-Te Lin0e0f9362015-11-18 18:18:05 +080051from cros.factory.utils.debug_utils import SetupLogging
Jon Salzff88c022012-11-03 12:19:58 +080052from cros.factory.utils.process_utils import Spawn
Joel Kitchingd3bc2662014-12-16 16:03:32 -080053from cros.factory.utils.type_utils import Error
Tammo Spalink86a61c62012-05-25 15:10:35 +080054
Tammo Spalink5c699832012-07-03 17:50:39 +080055
Tammo Spalink5c699832012-07-03 17:50:39 +080056# TODO(tammo): Replace calls to sys.exit with raise Exit, and maybe
57# treat that specially (as a smoot exit, as opposed to the more
58# verbose output for generic Error).
59
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080060_global_gooftool = None
61_gooftool_lock = threading.Lock()
Tammo Spalink5c699832012-07-03 17:50:39 +080062
Hung-Te Lin56b18402015-01-16 14:52:30 +080063
Ricky Lianga70a1202013-03-15 15:03:17 +080064def GetGooftool(options):
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080065 global _global_gooftool # pylint: disable=W0603
Ricky Lianga70a1202013-03-15 15:03:17 +080066
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080067 if _global_gooftool is None:
68 with _gooftool_lock:
Ricky Liang43b879b2014-02-24 11:36:55 +080069 hwid_version = getattr(options, 'hwid_version', 3)
70 if hwid_version == 2:
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080071 hwdb_path = getattr(options, 'hwdb_path', None)
72 component_db = (
73 hwid_tool.HardwareDb(options.hwdb_path).comp_db if hwdb_path
74 else None)
75 _global_gooftool = Gooftool(hwid_version=2, component_db=component_db)
Ricky Liang43b879b2014-02-24 11:36:55 +080076 elif hwid_version == 3:
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080077 board = getattr(options, 'board', None)
78 hwdb_path = getattr(options, 'hwdb_path', None)
79 _global_gooftool = Gooftool(hwid_version=3, board=board,
80 hwdb_path=hwdb_path)
81 else:
82 raise Error, 'Invalid HWID version: %r' % options.hwid_version
83
84 return _global_gooftool
Ricky Lianga70a1202013-03-15 15:03:17 +080085
Hung-Te Lin56b18402015-01-16 14:52:30 +080086
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080087@Command('write_hwid',
88 CmdArg('hwid', metavar='HWID', help='HWID string'))
Andy Chengc92e6f92012-11-20 16:55:53 +080089def WriteHWID(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080090 """Write specified HWID value into the system BB."""
Andy Cheng7a76cb82012-11-19 18:08:19 +080091
Tammo Spalink95c43732012-07-25 15:57:14 -070092 logging.info('writing hwid string %r', options.hwid)
Ricky Lianga70a1202013-03-15 15:03:17 +080093 GetGooftool(options).WriteHWID(options.hwid)
Andy Cheng0465d132013-03-20 12:12:06 +080094 event_log.Log('write_hwid', hwid=options.hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -070095 print 'Wrote HWID: %r' % options.hwid
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080096
97
Ricky Liang53390232013-03-08 15:37:57 +080098_board_cmd_arg = CmdArg(
99 '--board', metavar='BOARD',
100 default=None, help='Board name to test.')
101
Tammo Spalink8fab5312012-05-28 18:33:30 +0800102_hwdb_path_cmd_arg = CmdArg(
103 '--hwdb_path', metavar='PATH',
Ricky Liangeede7922013-06-19 10:18:41 +0800104 default=common.DEFAULT_HWID_DATA_PATH,
Tammo Spalink8fab5312012-05-28 18:33:30 +0800105 help='Path to the HWID database.')
106
Tammo Spalink95c43732012-07-25 15:57:14 -0700107_hwid_status_list_cmd_arg = CmdArg(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800108 '--status', nargs='*', default=['supported'],
109 help='allow only HWIDs with these status values')
Tammo Spalink95c43732012-07-25 15:57:14 -0700110
Jon Salzce124fb2012-10-02 17:42:03 +0800111_probe_results_cmd_arg = CmdArg(
112 '--probe_results', metavar='RESULTS.yaml',
Ricky Liangc662be32013-12-24 11:50:23 +0800113 help=('Output from "gooftool probe --include_vpd" (used instead of '
Jon Salzce124fb2012-10-02 17:42:03 +0800114 'probing this system).'))
115
Ricky Liang53390232013-03-08 15:37:57 +0800116_device_info_cmd_arg = CmdArg(
Ricky Liangf89f73a2013-03-19 05:00:24 +0800117 '--device_info', metavar='DEVICE_INFO.yaml', default=None,
Ricky Liang53390232013-03-08 15:37:57 +0800118 help='A dict of device info to use instead of fetching from shopfllor '
119 'server.')
120
Jon Salzce124fb2012-10-02 17:42:03 +0800121_hwid_cmd_arg = CmdArg(
122 '--hwid', metavar='HWID',
Ricky Lianga70a1202013-03-15 15:03:17 +0800123 help='HWID to verify (instead of the currently set HWID of this system).')
Jon Salzce124fb2012-10-02 17:42:03 +0800124
Bernie Thompson3c11c872013-07-22 18:22:45 -0700125_rma_mode_cmd_arg = CmdArg(
126 '--rma_mode', action='store_true',
127 help='Enable RMA mode, do not check for deprecated components.')
Tammo Spalink95c43732012-07-25 15:57:14 -0700128
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800129_cros_core_cmd_arg = CmdArg(
130 '--cros_core', action='store_true',
131 help='Finalize for ChromeOS Core devices (may add or remove few test '
132 'items. For example, branding verification or firmware bitmap '
133 'locale settings).')
134
Ricky Liang43b879b2014-02-24 11:36:55 +0800135_hwid_version_cmd_arg = CmdArg(
136 '-i', '--hwid-version', default=3, choices=(2, 3), type=int,
137 help='Version of HWID to operate on. (default: %(default)s)')
138
bowgotsai13820f42015-09-10 23:18:04 +0800139_enforced_release_channels_cmd_arg = CmdArg(
140 '--enforced_release_channels', nargs='*', default=None,
141 help='Enforced release image channels.')
142
Hung-Te Lincdb96522016-04-15 16:51:10 +0800143_release_rootfs_cmd_arg = CmdArg(
144 '--release_rootfs', help='Location of release image rootfs partition.')
145
146_firmware_path_cmd_arg = CmdArg(
147 '--firmware_path', help='Location of firmware image partition.')
Ricky Liang43b879b2014-02-24 11:36:55 +0800148
Tammo Spalink95c43732012-07-25 15:57:14 -0700149@Command('best_match_hwids',
Tammo Spalink8fab5312012-05-28 18:33:30 +0800150 _hwdb_path_cmd_arg,
151 CmdArg('-b', '--board', metavar='BOARD',
Tammo Spalink95c43732012-07-25 15:57:14 -0700152 help='optional BOARD name, needed only if data is present '
153 'for more than one'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800154 CmdArg('--bom', metavar='BOM', help='BOM name'),
155 CmdArg('--variant', metavar='VARIANT', help='VARIANT code'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800156 CmdArg('--optimistic', action='store_true',
157 help='do not probe; assume singletons match'),
Tammo Spalink95c43732012-07-25 15:57:14 -0700158 CmdArg('--comps', nargs='*', default=[],
159 help='list of canonical component names'),
160 CmdArg('--missing', nargs='*', default=[],
161 help='list component classes to be assumed missing'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800162 CmdArg('--status', nargs='*', default=['supported'],
Tammo Spalink95c43732012-07-25 15:57:14 -0700163 help='consider only HWIDs within this list of status values'))
164def BestMatchHwids(options):
Ricky Liangc662be32013-12-24 11:50:23 +0800165 """Determine a list of possible HWIDs using provided args and probing.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800166
167 VOLATILE can always be determined by probing. To get a unique
168 result, VARIANT must be specified for all cases where the matching
169 BOM has more than one associated variant code, otherwise all HWID
170 variants will be returned. Both VARIANT and BOM information can
Tammo Spalink95c43732012-07-25 15:57:14 -0700171 alternatively be specified using the --stdin_comps argument, which
172 allows specifying a list of canonical names (one per line) on stdin,
173 one per line. Based on what is known from BOM and stdin_comps,
174 determine a list of components to probe for, and use those probe
175 results to resolve a list of matching HWIDs. If no boms,
176 components, or variant codes are specified, then a list of all HWIDs
Andy Cheng8ece7382012-08-22 16:25:42 +0800177 that match probeable components will be returned.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800178
179 Returns (on stdout): A list of HWIDs that match the available probe
180 results and argument contraints, one per line.
Tammo Spalink70b48a52012-08-08 16:54:51 -0700181
182 Example:
183
184 // Three ways to specify a keyboard (assuming it is a variant component)
185 gooftool best_match_hwids --missing keyboard
186 gooftool best_match_hwids --variant A or
187 gooftool best_match_hwids --comps us_kbd
Tammo Spalink8fab5312012-05-28 18:33:30 +0800188 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800189
Tammo Spalink5c699832012-07-03 17:50:39 +0800190 map(hwid_tool.Validate.Status, options.status)
Tammo Spalink95c43732012-07-25 15:57:14 -0700191 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Tammo Spalink5c699832012-07-03 17:50:39 +0800192 comp_db = hw_db.comp_db
Tammo Spalink3a7e9022012-06-27 14:08:40 +0800193 device = hw_db.GetDevice(options.board)
Tammo Spalink5c699832012-07-03 17:50:39 +0800194 component_spec = hwid_tool.ComponentSpec.New()
Tammo Spalink8fab5312012-05-28 18:33:30 +0800195 if options.bom:
Tammo Spalink5c699832012-07-03 17:50:39 +0800196 device.BomExists(options.bom)
Tammo Spalink01e11722012-07-24 10:17:54 -0700197 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800198 component_spec, device.boms[options.bom].primary)
Tammo Spalink8fab5312012-05-28 18:33:30 +0800199 if options.variant:
Tammo Spalink5c699832012-07-03 17:50:39 +0800200 device.VariantExists(options.variant)
201 variant_spec = device.variants[options.variant]
Tammo Spalink01e11722012-07-24 10:17:54 -0700202 if hwid_tool.ComponentSpecsConflict(component_spec, variant_spec):
Tammo Spalink95c43732012-07-25 15:57:14 -0700203 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700204 % YamlWrite(sorted(
205 hwid_tool.ComponentSpecClasses(component_spec) &
206 hwid_tool.ComponentSpecClasses(variant_spec))))
Tammo Spalink01e11722012-07-24 10:17:54 -0700207 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800208 component_spec, variant_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700209 if options.comps or options.missing:
210 map(comp_db.CompExists, options.comps)
211 map(comp_db.CompClassExists, options.missing)
212 extra_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800213 components=options.comps,
214 missing=options.missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700215 print 'cmdline asserted components:\n%s' % extra_comp_spec.Encode()
216 if hwid_tool.ComponentSpecsConflict(component_spec, extra_comp_spec):
217 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700218 % YamlWrite(sorted(
219 hwid_tool.ComponentSpecClasses(component_spec) &
220 hwid_tool.ComponentSpecClasses(extra_comp_spec))))
Tammo Spalink95c43732012-07-25 15:57:14 -0700221 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800222 component_spec, extra_comp_spec)
Tammo Spalink01e11722012-07-24 10:17:54 -0700223 spec_classes = hwid_tool.ComponentSpecClasses(component_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700224 missing_classes = set(comp_db.all_comp_classes) - spec_classes
Tammo Spalink5c699832012-07-03 17:50:39 +0800225 if missing_classes and not options.optimistic:
Andy Cheng8ece7382012-08-22 16:25:42 +0800226 non_probeable_missing = missing_classes - PROBEABLE_COMPONENT_CLASSES
227 if non_probeable_missing:
Tammo Spalink95c43732012-07-25 15:57:14 -0700228 sys.exit('FAILURE: these classes are necessary, were not specified '
Tammo Spalink70b48a52012-08-08 16:54:51 -0700229 'as inputs, and cannot be probed for:\n%s'
230 'This problem can often be addressed by specifying all of '
231 'the missing components on the command line (see the command '
Andy Cheng8ece7382012-08-22 16:25:42 +0800232 'help).' % YamlWrite(list(non_probeable_missing)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700233 print 'probing for missing classes:'
234 print YamlWrite(list(missing_classes))
235 probe_results = Probe(target_comp_classes=list(missing_classes),
236 probe_volatile=False, probe_initial_config=False)
237 cooked_components = comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800238 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700239 if cooked_components.unmatched:
240 sys.exit('ERROR: some probed components are unrecognized:\n%s'
241 % YamlWrite(cooked_components.unmatched))
242 probed_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800243 components=cooked_components.matched,
244 missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700245 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800246 component_spec, probed_comp_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700247 print YamlWrite({'component data used for matching': {
Hung-Te Lin56b18402015-01-16 14:52:30 +0800248 'missing component classes': component_spec.classes_missing,
249 'found components': component_spec.components}})
Tammo Spalink95c43732012-07-25 15:57:14 -0700250 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800251 extant_components=hwid_tool.ComponentSpecCompClassMap(
252 component_spec).keys(),
253 classes_missing=component_spec.classes_missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700254 match_tree = device.BuildMatchTree(component_data)
255 if not match_tree:
256 sys.exit('FAILURE: NO matching BOMs found')
257 print 'potential BOMs/VARIANTs:'
258 potential_variants = set()
259 potential_volatiles = set()
260 for bom_name, variant_tree in match_tree.items():
261 print ' BOM: %-8s VARIANTS: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800262 bom_name, ', '.join(sorted(variant_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700263 for variant_code in variant_tree:
264 potential_variants.add(variant_code)
265 for volatile_code in device.volatiles:
266 status = device.GetHwidStatus(bom_name, variant_code, volatile_code)
267 if status in options.status:
268 potential_volatiles.add(volatile_code)
269 print ''
270 if len(potential_variants) == 0:
271 sys.exit('FAILURE: no matching VARIANTs found')
272 if len(potential_volatiles) == 0:
273 sys.exit('FAILURE: no VOLATILEs found for potential matching BOMs/VARIANTS '
274 '(with specified status)')
Tammo Spalink394e4492012-08-01 10:20:30 -0700275 if (options.optimistic and
276 len(match_tree) == 1 and
277 len(potential_variants) == 1 and
278 len(potential_volatiles) == 1):
279 print ('MATCHING HWID: %s' % device.FmtHwid(match_tree.keys().pop(),
280 potential_variants.pop(),
281 potential_volatiles.pop()))
Tammo Spalink5c699832012-07-03 17:50:39 +0800282 return
Tammo Spalink95c43732012-07-25 15:57:14 -0700283 print ('probing VOLATILEs to resolve potential matches: %s\n' %
284 ', '.join(sorted(potential_volatiles)))
285 vol_probe_results = Probe(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800286 target_comp_classes=[],
287 probe_volatile=True,
288 probe_initial_config=False)
Tammo Spalink95c43732012-07-25 15:57:14 -0700289 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800290 vol_probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700291 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800292 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700293 matched_hwids = device.GetMatchTreeHwids(match_tree)
294 if matched_hwids:
295 for hwid in matched_hwids:
Ricky Liang02f3bd72012-09-21 14:33:01 +0800296 if matched_hwids[hwid] in options.status:
297 print 'MATCHING HWID: %s' % hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700298 return
299 print 'exact HWID matching failed, but the following BOMs match: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800300 ', '.join(sorted(match_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700301 if options.optimistic and len(match_tree) == 1:
302 bom_name = set(match_tree).pop()
Tammo Spalink5c699832012-07-03 17:50:39 +0800303 bom = device.boms[bom_name]
Tammo Spalink95c43732012-07-25 15:57:14 -0700304 variant_matches = match_tree[bom_name]
Tammo Spalink5c699832012-07-03 17:50:39 +0800305 if len(variant_matches) == 1:
306 var_code = set(variant_matches).pop()
307 elif len(bom.variants) == 1:
308 var_code = set(bom.variants).pop()
309 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700310 sys.exit('FAILURE: NO matching HWIDs found; optimistic matching failed '
311 'because there were too many variants to choose from for BOM %r'
312 % bom_name)
313 hwids = [device.FmtHwid(bom_name, var_code, vol_code)
314 for vol_code in device.volatiles
315 if device.GetHwidStatus(bom_name, var_code, vol_code)
316 in options.status]
317 for hwid in hwids:
318 print 'MATCHING HWID: %s' % hwid
Tammo Spalink5c699832012-07-03 17:50:39 +0800319 return
320 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700321 print ('optimistic matching not attempted because either it was '
322 'not requested, or because the number of BOMs was <> 1\n')
323 sys.exit('FAILURE: NO matching HWIDs found')
Tammo Spalink8fab5312012-05-28 18:33:30 +0800324
325
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800326@Command('probe',
327 CmdArg('--comps', nargs='*',
328 help='List of keys from the component_db registry.'),
Ricky Liangb30da672013-06-14 12:36:34 +0800329 CmdArg('--fast_fw_probe', action='store_true',
330 help='Do a fast probe for EC and main firmware versions only. '
331 'This implies --no_vol and --no_ic.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800332 CmdArg('--no_vol', action='store_true',
333 help='Do not probe volatile data.'),
334 CmdArg('--no_ic', action='store_true',
Jon Salz0f8a6842012-09-25 11:28:22 +0800335 help='Do not probe initial_config data.'),
336 CmdArg('--include_vpd', action='store_true',
337 help='Include VPD data in volatiles.'))
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800338def RunProbe(options):
339 """Print yaml-formatted breakdown of probed device properties."""
Ricky Lianga70a1202013-03-15 15:03:17 +0800340 print GetGooftool(options).Probe(
341 target_comp_classes=options.comps,
Ricky Liangb30da672013-06-14 12:36:34 +0800342 fast_fw_probe=options.fast_fw_probe,
Ricky Lianga70a1202013-03-15 15:03:17 +0800343 probe_volatile=not options.no_vol,
344 probe_initial_config=not options.no_ic,
345 probe_vpd=options.include_vpd).Encode()
Ricky Liang53390232013-03-08 15:37:57 +0800346
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800347
Tammo Spalink214caf42012-05-28 10:45:00 +0800348@Command('verify_components',
349 _hwdb_path_cmd_arg,
Tammo Spalink5c699832012-07-03 17:50:39 +0800350 CmdArg('target_comps', nargs='*'))
Tammo Spalink214caf42012-05-28 10:45:00 +0800351def VerifyComponents(options):
Andy Cheng8ece7382012-08-22 16:25:42 +0800352 """Verify that probeable components all match entries in the component_db.
Tammo Spalink214caf42012-05-28 10:45:00 +0800353
Tammo Spalink5c699832012-07-03 17:50:39 +0800354 Probe for each component class in the target_comps and verify
Tammo Spalink214caf42012-05-28 10:45:00 +0800355 that a corresponding match exists in the component_db -- make sure
356 that these components are present, that they have been approved, but
357 do not check against any specific BOM/HWID configurations.
358 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800359
Andy Chengc531e2f2012-10-15 19:09:17 +0800360 try:
Ricky Lianga70a1202013-03-15 15:03:17 +0800361 result = GetGooftool(options).VerifyComponents(
Andy Chengc531e2f2012-10-15 19:09:17 +0800362 options.target_comps)
363 except ValueError, e:
364 sys.exit(e)
365
Ricky Liang53390232013-03-08 15:37:57 +0800366 PrintVerifyComponentsResults(result)
367
368
369def PrintVerifyComponentsResults(result):
370 """Prints out the results of VerifyComponents method call.
371
372 Groups the results into two groups: 'matches' and 'errors', and prints out
373 their values.
374 """
Andy Chengc531e2f2012-10-15 19:09:17 +0800375 # group by matches and errors
Tammo Spalink214caf42012-05-28 10:45:00 +0800376 matches = []
Andy Chengc531e2f2012-10-15 19:09:17 +0800377 errors = []
378 for result_list in result.values():
379 for component_name, _, error in result_list:
380 if component_name:
381 matches.append(component_name)
Tammo Spalink214caf42012-05-28 10:45:00 +0800382 else:
Andy Chengc531e2f2012-10-15 19:09:17 +0800383 errors.append(error)
384
Andy Cheng228a8c92012-08-27 10:53:57 +0800385 if matches:
386 print 'found probeable components:\n %s' % '\n '.join(matches)
Tammo Spalink214caf42012-05-28 10:45:00 +0800387 if errors:
Andy Cheng228a8c92012-08-27 10:53:57 +0800388 print '\nerrors:\n %s' % '\n '.join(errors)
389 sys.exit('\ncomponent verification FAILURE')
Tammo Spalink214caf42012-05-28 10:45:00 +0800390 else:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800391 print '\ncomponent verification SUCCESS'
Tammo Spalink214caf42012-05-28 10:45:00 +0800392
393
Ricky Liang43b879b2014-02-24 11:36:55 +0800394@Command('verify_hwid_v2',
Tammo Spalink95c43732012-07-25 15:57:14 -0700395 _hwid_status_list_cmd_arg,
Jon Salz0f8a6842012-09-25 11:28:22 +0800396 _hwdb_path_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800397 _probe_results_cmd_arg,
398 _hwid_cmd_arg)
Ricky Liang43b879b2014-02-24 11:36:55 +0800399def VerifyHWIDv2(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800400 """Verify system HWID properties match probed device properties.
401
402 First probe components, volatile and initial_config parameters for
403 the DUT. Then use the available device data to produce a list of
404 candidate HWIDs. Then verify the HWID from the DUT is present in
405 that list. Then verify that the DUT initial config values match
406 those specified for its HWID. Finally, verify that VPD contains all
407 the necessary fields as specified by the board data, and when
408 possible verify that values are legitimate.
409 """
Ricky Liangf7857c12012-09-17 13:34:41 +0800410 def VerifyVpd(ro_vpd_keys, rw_vpd_keys):
Tammo Spalink5c699832012-07-03 17:50:39 +0800411 for key in ro_vpd_keys:
412 if key not in ro_vpd:
Ricky Liangf7857c12012-09-17 13:34:41 +0800413 sys.exit('Missing required RO VPD field: %s' % key)
Tammo Spalink01e11722012-07-24 10:17:54 -0700414 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800415 value = ro_vpd[key]
Ricky Liangf7857c12012-09-17 13:34:41 +0800416 if (known_valid_values is not None) and (value not in known_valid_values):
417 sys.exit('Invalid RO VPD entry : key %r, value %r' % (key, value))
Ricky Liangf7857c12012-09-17 13:34:41 +0800418 for key in rw_vpd_keys:
419 if key not in rw_vpd:
420 sys.exit('Missing required RW VPD field: %s' % key)
421 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
422 value = rw_vpd[key]
423 if (known_valid_values is not None) and (value not in known_valid_values):
424 sys.exit('Invalid RW VPD entry : key %r, value %r' % (key, value))
Andy Cheng0465d132013-03-20 12:12:06 +0800425 event_log.Log('vpd', ro_vpd=FilterDict(ro_vpd), rw_vpd=FilterDict(rw_vpd))
Tammo Spalink5c699832012-07-03 17:50:39 +0800426 map(hwid_tool.Validate.Status, options.status)
Jon Salz0f8a6842012-09-25 11:28:22 +0800427
Jon Salz0f8a6842012-09-25 11:28:22 +0800428 if options.hwid:
429 hwid_str = options.hwid
430 else:
Hung-Te Lin74346d72016-01-07 22:16:57 +0800431 main_fw_file = crosfw.LoadMainFirmware().GetFileName()
Jon Salz0f8a6842012-09-25 11:28:22 +0800432 gbb_result = Shell('gbb_utility -g --hwid %s' % main_fw_file).stdout
433 hwid_str = re.findall(r'hardware_id:(.*)', gbb_result)[0].strip()
Tammo Spalink95c43732012-07-25 15:57:14 -0700434 hwid = hwid_tool.ParseHwid(hwid_str)
Tammo Spalink5c699832012-07-03 17:50:39 +0800435 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Jon Salz0f8a6842012-09-25 11:28:22 +0800436 print 'Verifying HWID: %r\n' % hwid.hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700437 device = hw_db.GetDevice(hwid.board)
438 hwid_status = device.GetHwidStatus(hwid.bom, hwid.variant, hwid.volatile)
439 if hwid_status not in options.status:
Tammo Spalink5c699832012-07-03 17:50:39 +0800440 sys.exit('HWID status must be one of [%s], found %r' %
Hung-Te Lin4f5beb12012-08-20 14:48:06 +0800441 (', '.join(options.status), hwid_status))
Jon Salz0f8a6842012-09-25 11:28:22 +0800442 if options.probe_results:
443 # Pull in probe results (including VPD data) from the given file
444 # rather than probing the current system.
445 probe_results = hwid_tool.ProbeResults.Decode(
446 open(options.probe_results).read())
447 ro_vpd = {}
448 rw_vpd = {}
449 for k, v in probe_results.found_volatile_values.items():
Hung-Te Lin56b18402015-01-16 14:52:30 +0800450 match = re.match(r'^vpd\.(ro|rw)\.(\w+)$', k)
Jon Salz0f8a6842012-09-25 11:28:22 +0800451 if match:
452 del probe_results.found_volatile_values[k]
453 (ro_vpd if match.group(1) == 'ro' else rw_vpd)[match.group(2)] = v
454 else:
455 probe_results = Probe()
Hung-Te Lin74346d72016-01-07 22:16:57 +0800456 ro_vpd = ReadRoVpd()
457 rw_vpd = ReadRwVpd()
Tammo Spalink95c43732012-07-25 15:57:14 -0700458 cooked_components = hw_db.comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800459 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700460 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800461 probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700462 cooked_initial_configs = device.MatchInitialConfigValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800463 probe_results.initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700464 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800465 extant_components=cooked_components.matched,
466 classes_missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700467 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800468 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700469 matched_hwids = device.GetMatchTreeHwids(match_tree)
470 print 'HWID status: %s\n' % hwid_status
471 print 'probed system components:'
472 print YamlWrite(cooked_components.__dict__)
473 print 'missing component classes:'
474 print YamlWrite(probe_results.missing_component_classes)
475 print 'probed volatiles:'
476 print YamlWrite(cooked_volatiles.__dict__)
477 print 'probed initial_configs:'
478 print YamlWrite(cooked_initial_configs)
479 print 'hwid match tree:'
480 print YamlWrite(match_tree)
Andy Cheng0465d132013-03-20 12:12:06 +0800481 event_log.Log(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800482 'probe',
483 found_components=cooked_components.__dict__,
484 missing_component_classes=probe_results.missing_component_classes,
485 volatiles=cooked_volatiles.__dict__,
486 initial_configs=cooked_initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700487 if hwid.hwid not in matched_hwids:
Tammo Spalink5c699832012-07-03 17:50:39 +0800488 err_msg = 'HWID verification FAILED.\n'
Tammo Spalink95c43732012-07-25 15:57:14 -0700489 if cooked_components.unmatched:
Tammo Spalink5c699832012-07-03 17:50:39 +0800490 sys.exit(err_msg + 'some components could not be indentified:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700491 YamlWrite(cooked_components.unmatched))
492 if not match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800493 sys.exit(err_msg + 'no matching boms were found for components:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700494 component_data.Encode())
495 if hwid.bom not in match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800496 sys.exit(err_msg + 'matching boms [%s] do not include target bom %r' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700497 (', '.join(sorted(match_tree)), hwid.bom))
498 err_msg += 'target bom %r matches components' % hwid.bom
499 if hwid.bom not in device.IntersectBomsAndInitialConfigs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800500 cooked_initial_configs):
Tammo Spalink5c699832012-07-03 17:50:39 +0800501 sys.exit(err_msg + ', but failed initial config verification')
Tammo Spalink95c43732012-07-25 15:57:14 -0700502 matched_variants = match_tree.get(hwid.bom, {})
503 if hwid.variant not in matched_variants:
Tammo Spalink5c699832012-07-03 17:50:39 +0800504 sys.exit(err_msg + ', but target variant_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700505 hwid.variant)
506 matched_volatiles = matched_variants.get(hwid.variant, {})
507 if hwid.volatile not in matched_volatiles:
Tammo Spalink5c699832012-07-03 17:50:39 +0800508 sys.exit(err_msg + ', but target volatile_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700509 hwid.volatile)
510 found_status = matched_volatiles.get(hwid.volatile, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800511 sys.exit(err_msg + ', but hwid status %r was unacceptable' % found_status)
Ricky Liangf7857c12012-09-17 13:34:41 +0800512 VerifyVpd(device.vpd_ro_fields, device.vpd_rw_fields)
Andy Cheng0465d132013-03-20 12:12:06 +0800513 event_log.Log('verified_hwid', hwid=hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -0700514 print 'Verification SUCCESS!'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800515
516
Hung-Te Line1d80f62016-03-31 14:58:13 +0800517@Command('verify_keys',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800518 _release_rootfs_cmd_arg,
519 _firmware_path_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700520def VerifyKeys(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800521 """Verify keys in firmware and SSD match."""
Hung-Te Line1d80f62016-03-31 14:58:13 +0800522 return GetGooftool(options).VerifyKeys(
Hung-Te Lincdb96522016-04-15 16:51:10 +0800523 options.release_rootfs, options.firmware_path)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800524
525
526@Command('set_fw_bitmap_locale')
Tammo Spalink01e11722012-07-24 10:17:54 -0700527def SetFirmwareBitmapLocale(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800528 """Use VPD locale value to set firmware bitmap default language."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800529
Ricky Lianga70a1202013-03-15 15:03:17 +0800530 (index, locale) = GetGooftool(options).SetFirmwareBitmapLocale()
Andy Cheng2582d292012-12-04 17:38:28 +0800531 logging.info('Firmware bitmap initial locale set to %d (%s).',
532 index, locale)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800533
534
Hung-Te Line1d80f62016-03-31 14:58:13 +0800535@Command('verify_system_time',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800536 _release_rootfs_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700537def VerifySystemTime(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800538 """Verify system time is later than release filesystem creation time."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800539
Hung-Te Lincdb96522016-04-15 16:51:10 +0800540 return GetGooftool(options).VerifySystemTime(options.release_rootfs)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800541
542
Hung-Te Line1d80f62016-03-31 14:58:13 +0800543@Command('verify_rootfs',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800544 _release_rootfs_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700545def VerifyRootFs(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800546 """Verify rootfs on SSD is valid by checking hash."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800547
Hung-Te Line1d80f62016-03-31 14:58:13 +0800548 return GetGooftool(options).VerifyRootFs(options.release_rootfs)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800549
Hung-Te Lin56b18402015-01-16 14:52:30 +0800550
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800551@Command('verify_tpm')
552def VerifyTPM(options): # pylint: disable=W0613
553 """Verify TPM is cleared."""
554
555 return GetGooftool(options).VerifyTPM()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800556
Hung-Te Lin56b18402015-01-16 14:52:30 +0800557
Hung-Te Lindd708d42014-07-11 17:05:01 +0800558@Command('verify_me_locked')
559def VerifyManagementEngineLocked(options): # pylint: disable=W0613
560 """Verify Managment Engine is locked."""
561
562 return GetGooftool(options).VerifyManagementEngineLocked()
563
Hung-Te Lin56b18402015-01-16 14:52:30 +0800564
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800565@Command('verify_switch_wp')
Andy Chengc92e6f92012-11-20 16:55:53 +0800566def VerifyWPSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800567 """Verify hardware write protection switch is enabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800568
Ricky Lianga70a1202013-03-15 15:03:17 +0800569 GetGooftool(options).VerifyWPSwitch()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800570
571
572@Command('verify_switch_dev')
Tammo Spalink01e11722012-07-24 10:17:54 -0700573def VerifyDevSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800574 """Verify developer switch is disabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800575
Ricky Lianga70a1202013-03-15 15:03:17 +0800576 if GetGooftool(options).CheckDevSwitchForDisabling():
Hung-Te Lind7d34722012-07-26 16:48:35 +0800577 logging.warn('VerifyDevSwitch: No physical switch.')
Andy Cheng0465d132013-03-20 12:12:06 +0800578 event_log.Log('switch_dev', type='virtual switch')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800579
580
Jon Salzadd90d32014-04-29 16:16:27 +0800581@Command('verify_branding')
582def VerifyBranding(options): # pylint: disable=W0613
583 """Verify that branding fields are properly set.
584
585 customization_id, if set in the RO VPD, must be of the correct format.
586
587 rlz_brand_code must be set either in the RO VPD or OEM partition, and must
588 be of the correct format.
589 """
590 return GetGooftool(options).VerifyBranding()
591
592
bowgotsai13820f42015-09-10 23:18:04 +0800593@Command('verify_release_channel',
594 _enforced_release_channels_cmd_arg)
bowgotsai529139c2015-05-30 01:39:49 +0800595def VerifyReleaseChannel(options): # pylint: disable=W0613
596 """Verify that release image channel is correct.
597
598 ChromeOS has four channels: canary, dev, beta and stable.
599 The last three channels support image auto-updates, checks
600 that release image channel is one of them.
601 """
bowgotsai13820f42015-09-10 23:18:04 +0800602 return GetGooftool(options).VerifyReleaseChannel(
603 options.enforced_release_channels)
bowgotsai529139c2015-05-30 01:39:49 +0800604
605
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800606@Command('write_protect')
Tammo Spalink01e11722012-07-24 10:17:54 -0700607def EnableFwWp(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800608 """Enable then verify firmware write protection."""
609
Hung-Te Linb21c6682012-08-01 13:53:57 +0800610 def CalculateLegacyRange(fw_type, length, section_data,
611 section_name):
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800612 ro_size = length / 2
613 ro_a = int(section_data[0] / ro_size)
614 ro_b = int((section_data[0] + section_data[1] - 1) / ro_size)
615 if ro_a != ro_b:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800616 raise Error('%s firmware section %s has illegal size' %
Hung-Te Linb21c6682012-08-01 13:53:57 +0800617 (fw_type, section_name))
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800618 ro_offset = ro_a * ro_size
619 return (ro_offset, ro_size)
620
621 def WriteProtect(fw_file_path, fw_type, legacy_section):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800622 """Calculate protection size, then invoke flashrom.
623
624 Our supported chips only allow write protecting half their total
625 size, so we parition the flash chipset space accordingly.
626 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800627
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800628 raw_image = open(fw_file_path, 'rb').read()
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800629 wp_section = 'WP_RO'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800630 image = crosfw.FirmwareImage(raw_image)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800631 if image.has_section(wp_section):
632 section_data = image.get_section_area(wp_section)
633 ro_offset = section_data[0]
634 ro_size = section_data[1]
635 elif image.has_section(legacy_section):
636 section_data = image.get_section_area(legacy_section)
637 (ro_offset, ro_size) = CalculateLegacyRange(
Hung-Te Linb21c6682012-08-01 13:53:57 +0800638 fw_type, len(raw_image), section_data, legacy_section)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800639 else:
640 raise Error('could not find %s firmware section %s or %s' %
641 (fw_type, wp_section, legacy_section))
642
643 logging.debug('write protecting %s [off=%x size=%x]', fw_type,
644 ro_offset, ro_size)
645 crosfw.Flashrom(fw_type).EnableWriteProtection(ro_offset, ro_size)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800646
647 WriteProtect(crosfw.LoadMainFirmware().GetFileName(), 'main', 'RO_SECTION')
Andy Cheng0465d132013-03-20 12:12:06 +0800648 event_log.Log('wp', fw='main')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800649 ec_fw_file = crosfw.LoadEcFirmware().GetFileName()
650 if ec_fw_file is not None:
651 WriteProtect(ec_fw_file, 'ec', 'EC_RO')
Andy Cheng0465d132013-03-20 12:12:06 +0800652 event_log.Log('wp', fw='ec')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800653 else:
654 logging.warning('EC not write protected (seems there is no EC flash).')
655
656
657@Command('clear_gbb_flags')
Andy Chengc92e6f92012-11-20 16:55:53 +0800658def ClearGBBFlags(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800659 """Zero out the GBB flags, in preparation for transition to release state.
660
661 No GBB flags are set in release/shipping state, but they are useful
662 for factory/development. See "gbb_utility --flags" for details.
663 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800664
Ricky Lianga70a1202013-03-15 15:03:17 +0800665 GetGooftool(options).ClearGBBFlags()
Andy Cheng0465d132013-03-20 12:12:06 +0800666 event_log.Log('clear_gbb_flags')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800667
668
Jon Salzaa3a30e2013-05-15 15:56:28 +0800669@Command('clear_factory_vpd_entries')
670def ClearFactoryVPDEntries(options): # pylint: disable=W0613
671 """Clears factory.* items in the RW VPD."""
672 entries = GetGooftool(options).ClearFactoryVPDEntries()
673 event_log.Log('clear_factory_vpd_entries', entries=FilterDict(entries))
674
675
Mattias Nisslercca761b2015-04-15 21:53:04 +0200676@Command('generate_stable_device_secret')
677def GenerateStableDeviceSecret(options): # pylint: disable=W0613
678 """Generates a a fresh stable device secret and stores it in the RO VPD."""
679 GetGooftool(options).GenerateStableDeviceSecret()
680 event_log.Log('generate_stable_device_secret')
681
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800682_cutoff_args_cmd_arg = CmdArg(
683 '--cutoff_args',
684 help='Battery cutoff arguments to be passed to battery_cutoff.sh '
685 'after wiping. Should be the following format: '
Shun-Hsing Ouccbeab12016-05-13 11:58:45 +0800686 '[--method shutdown|reboot|battery_cutoff] '
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800687 '[--check-ac connect_ac|remove_ac] '
688 '[--min-battery-percent <minimum battery percentage>] '
689 '[--max-battery-percent <maximum battery percentage>] '
690 '[--min-battery-voltage <minimum battery voltage>] '
691 '[--max-battery-voltage <maximum battery voltage>]')
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800692_shopfloor_url_args_cmd_arg = CmdArg(
693 '--shopfloor_url',
694 help='Shopfloor server url to be informed when in-place wipe is done. '
695 'After in-place wipe, a XML-RPC request will be sent to the '
696 'given url to indicate the completion of wipe.')
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800697@Command('wipe_in_place',
698 CmdArg('--fast', action='store_true',
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800699 help='use non-secure but faster wipe method.'),
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800700 _cutoff_args_cmd_arg,
701 _shopfloor_url_args_cmd_arg)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800702def WipeInPlace(options):
703 """Start factory wipe directly without reboot."""
704
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800705 GetGooftool(options).WipeInPlace(options.fast, options.cutoff_args,
706 options.shopfloor_url)
Mattias Nisslercca761b2015-04-15 21:53:04 +0200707
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800708@Command('wipe_init',
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800709 CmdArg('--wipe_args', help='arguments for clobber-state'),
710 CmdArg('--state_dev', help='path to stateful partition device'),
711 CmdArg('--root_disk', help='path to primary device'),
712 CmdArg('--old_root', help='path to old root'),
713 _cutoff_args_cmd_arg,
714 _shopfloor_url_args_cmd_arg,
715 _release_rootfs_cmd_arg)
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800716def WipeInit(options):
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800717 GetGooftool(options).WipeInit(options.wipe_args,
718 options.cutoff_args,
719 options.shopfloor_url,
720 options.state_dev,
721 options.release_rootfs,
722 options.root_disk,
723 options.old_root)
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800724
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800725@Command('prepare_wipe',
726 CmdArg('--fast', action='store_true',
727 help='use non-secure but faster wipe method.'))
728def PrepareWipe(options):
729 """Prepare system for transition to release state in next reboot."""
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800730
Ricky Lianga70a1202013-03-15 15:03:17 +0800731 GetGooftool(options).PrepareWipe(options.fast)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800732
Hung-Te Lin56b18402015-01-16 14:52:30 +0800733
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800734@Command('verify',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800735 CmdArg('--no_write_protect', action='store_true',
736 help='Do not check write protection switch state.'),
Ricky Liang43b879b2014-02-24 11:36:55 +0800737 _hwid_version_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700738 _hwid_status_list_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800739 _hwdb_path_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800740 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800741 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800742 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800743 _rma_mode_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800744 _cros_core_cmd_arg,
Hung-Te Lincdb96522016-04-15 16:51:10 +0800745 _release_rootfs_cmd_arg,
746 _firmware_path_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800747 _enforced_release_channels_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800748def Verify(options):
749 """Verifies if whole factory process is ready for finalization.
750
751 This routine performs all the necessary checks to make sure the
752 device is ready to be finalized, but does not modify state. These
753 checks include dev switch, firmware write protection switch, hwid,
754 system time, keys, and root file system.
755 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800756
Hung-Te Lin6d827542012-07-19 11:50:41 +0800757 if not options.no_write_protect:
Ricky Lianga70a1202013-03-15 15:03:17 +0800758 VerifyWPSwitch(options)
Hung-Te Lindd708d42014-07-11 17:05:01 +0800759 VerifyManagementEngineLocked(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800760 VerifyDevSwitch(options)
761 if options.hwid_version == 2:
Ricky Liang43b879b2014-02-24 11:36:55 +0800762 VerifyHWIDv2(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800763 elif options.hwid_version == 3:
Ricky Liangc662be32013-12-24 11:50:23 +0800764 VerifyHWIDv3(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800765 else:
766 raise Error, 'Invalid HWID version: %r' % options.hwid_version
767 VerifySystemTime(options)
768 VerifyKeys(options)
769 VerifyRootFs(options)
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800770 VerifyTPM(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800771 if options.cros_core:
772 logging.info('VerifyBranding is skipped for ChromeOS Core device.')
773 else:
774 VerifyBranding(options)
bowgotsai529139c2015-05-30 01:39:49 +0800775 VerifyReleaseChannel(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800776
Hung-Te Lin56b18402015-01-16 14:52:30 +0800777
Jon Salzfe9036f2014-01-16 14:11:23 +0800778@Command('untar_stateful_files')
Hung-Te Lin388bce22014-06-03 19:56:40 +0800779def UntarStatefulFiles(unused_options):
Jon Salzfe9036f2014-01-16 14:11:23 +0800780 """Untars stateful files from stateful_files.tar.xz on stateful partition.
781
782 If that file does not exist (which should only be R30 and earlier),
783 this is a no-op.
784 """
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +0800785 tar_file = os.path.join(paths.DEVICE_STATEFUL_PATH, 'stateful_files.tar.xz')
Jon Salzfe9036f2014-01-16 14:11:23 +0800786 if os.path.exists(tar_file):
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +0800787 Spawn(['tar', 'xf', tar_file], cwd=paths.DEVICE_STATEFUL_PATH,
Jon Salzfe9036f2014-01-16 14:11:23 +0800788 log=True, check_call=True)
789 else:
790 logging.warning('No stateful files at %s', tar_file)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800791
Jon Salz40b9f822014-07-25 16:39:55 +0800792
793@Command('log_source_hashes')
794def LogSourceHashes(options): # pylint: disable=W0613
795 """Logs hashes of source files in the factory toolkit."""
Jon Salze60307f2014-08-05 16:20:00 +0800796 # WARNING: The following line is necessary to validate the integrity
797 # of the factory software. Do not remove or modify it.
798 #
799 # 警告:此行会验证工厂软件的完整性,禁止删除或修改。
Jon Salz40b9f822014-07-25 16:39:55 +0800800 event_log.Log(
801 'source_hashes',
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +0800802 **file_utils.HashSourceTree(os.path.join(paths.FACTORY_PATH, 'py')))
Jon Salz40b9f822014-07-25 16:39:55 +0800803
804
Tammo Spalink86a61c62012-05-25 15:10:35 +0800805@Command('log_system_details')
Tammo Spalink01e11722012-07-24 10:17:54 -0700806def LogSystemDetails(options): # pylint: disable=W0613
Tammo Spalink86a61c62012-05-25 15:10:35 +0800807 """Write miscellaneous system details to the event log."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800808
Ricky Liang43b879b2014-02-24 11:36:55 +0800809 event_log.Log('system_details', **GetGooftool(options).GetSystemDetails())
Tammo Spalink86a61c62012-05-25 15:10:35 +0800810
811
Jon Salza88b83b2013-05-27 20:00:35 +0800812def CreateReportArchiveBlob(*args, **kwargs):
813 """Creates a report archive and returns it as a blob.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800814
Jon Salza88b83b2013-05-27 20:00:35 +0800815 Args:
816 See CreateReportArchive.
Andy Cheng7a76cb82012-11-19 18:08:19 +0800817
Jon Salza88b83b2013-05-27 20:00:35 +0800818 Returns:
819 An xmlrpclib.Binary object containing a .tar.xz file.
820 """
821 with open(CreateReportArchive(*args, **kwargs)) as f:
822 return xmlrpclib.Binary(f.read())
823
824
825def CreateReportArchive(device_sn=None, add_file=None):
826 """Creates a report archive in a temporary directory.
827
828 Args:
829 device_sn: The device serial number (optional).
830 add_file: A list of files to add (optional).
831
832 Returns:
833 Path to the archive.
834 """
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800835 def NormalizeAsFileName(token):
836 return re.sub(r'\W+', '', token).strip()
Jon Salza88b83b2013-05-27 20:00:35 +0800837
838 target_name = '%s%s.tar.xz' % (
839 time.strftime('%Y%m%dT%H%M%SZ',
840 time.gmtime()),
Hung-Te Lin56b18402015-01-16 14:52:30 +0800841 ('' if device_sn is None else
842 '_' + NormalizeAsFileName(device_sn)))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800843 target_path = os.path.join(gettempdir(), target_name)
Jon Salza88b83b2013-05-27 20:00:35 +0800844
Tammo Spalink86a61c62012-05-25 15:10:35 +0800845 # Intentionally ignoring dotfiles in EVENT_LOG_DIR.
Andy Cheng0465d132013-03-20 12:12:06 +0800846 tar_cmd = 'cd %s ; tar cJf %s *' % (event_log.EVENT_LOG_DIR, target_path)
Joel Kitching4b1b6c02016-05-10 14:34:30 +0800847 tar_cmd += ' --add-file %s' % paths.GetFactoryLogPath()
Jon Salza88b83b2013-05-27 20:00:35 +0800848 if add_file:
849 for f in add_file:
Jon Salz65266432012-07-30 19:02:49 +0800850 # Require absolute paths since the tar command may change the
851 # directory.
852 if not f.startswith('/'):
853 raise Error('Not an absolute path: %s' % f)
854 if not os.path.exists(f):
855 raise Error('File does not exist: %s' % f)
856 tar_cmd += ' --add-file %s' % pipes.quote(f)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800857 cmd_result = Shell(tar_cmd)
Jon Salzff88c022012-11-03 12:19:58 +0800858
859 if ((cmd_result.status == 1) and
860 all((x == '' or
861 'file changed as we read it' in x or
862 "Removing leading `/' from member names" in x)
863 for x in cmd_result.stderr.split('\n'))):
864 # That's OK. Make sure it's valid though.
Vic Yang85199e72013-01-28 14:33:11 +0800865 Spawn(['tar', 'tfJ', target_path], check_call=True, log=True,
Jon Salzff88c022012-11-03 12:19:58 +0800866 ignore_stdout=True)
867 elif not cmd_result.success:
Tammo Spalink86a61c62012-05-25 15:10:35 +0800868 raise Error('unable to tar event logs, cmd %r failed, stderr: %r' %
869 (tar_cmd, cmd_result.stderr))
Jon Salzff88c022012-11-03 12:19:58 +0800870
Jon Salza88b83b2013-05-27 20:00:35 +0800871 return target_path
872
873_upload_method_cmd_arg = CmdArg(
874 '--upload_method', metavar='METHOD:PARAM',
875 help=('How to perform the upload. METHOD should be one of '
876 '{ftp, shopfloor, ftps, cpfe}.'))
877_add_file_cmd_arg = CmdArg(
878 '--add_file', metavar='FILE', action='append',
879 help='Extra file to include in report (must be an absolute path)')
880
Hung-Te Lin56b18402015-01-16 14:52:30 +0800881
Jon Salza88b83b2013-05-27 20:00:35 +0800882@Command('upload_report',
883 _upload_method_cmd_arg,
884 _add_file_cmd_arg)
885def UploadReport(options):
886 """Create a report containing key device details."""
Hung-Te Lin74346d72016-01-07 22:16:57 +0800887 ro_vpd = ReadRoVpd()
Jon Salza88b83b2013-05-27 20:00:35 +0800888 device_sn = ro_vpd.get('serial_number', None)
889 if device_sn is None:
890 logging.warning('RO_VPD missing device serial number')
891 device_sn = 'MISSING_SN_' + event_log.TimedUuid()
892 target_path = CreateReportArchive(device_sn)
893
Tammo Spalink86a61c62012-05-25 15:10:35 +0800894 if options.upload_method is None or options.upload_method == 'none':
895 logging.warning('REPORT UPLOAD SKIPPED (report left at %s)', target_path)
896 return
897 method, param = options.upload_method.split(':', 1)
898 if method == 'shopfloor':
899 report_upload.ShopFloorUpload(target_path, param)
900 elif method == 'ftp':
Jay Kim360c1dd2012-06-25 10:58:11 -0700901 report_upload.FtpUpload(target_path, 'ftp:' + param)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800902 elif method == 'ftps':
903 report_upload.CurlUrlUpload(target_path, '--ftp-ssl-reqd ftp:%s' % param)
904 elif method == 'cpfe':
Shawn Nematbakhsh3404a092013-01-28 16:49:09 -0800905 report_upload.CpfeUpload(target_path, pipes.quote(param))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800906 else:
907 raise Error('unknown report upload method %r', method)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800908
909
910@Command('finalize',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800911 CmdArg('--no_write_protect', action='store_true',
912 help='Do not enable firmware write protection.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800913 CmdArg('--fast', action='store_true',
914 help='use non-secure but faster wipe method.'),
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800915 CmdArg('--wipe_in_place', action='store_true',
916 help='Start factory wiping in place without reboot.'),
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800917 _cutoff_args_cmd_arg,
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800918 _shopfloor_url_args_cmd_arg,
Ricky Liang43b879b2014-02-24 11:36:55 +0800919 _hwid_version_cmd_arg,
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800920 _hwdb_path_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700921 _hwid_status_list_cmd_arg,
Jon Salz65266432012-07-30 19:02:49 +0800922 _upload_method_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800923 _add_file_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800924 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800925 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800926 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800927 _rma_mode_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800928 _cros_core_cmd_arg,
Hung-Te Lincdb96522016-04-15 16:51:10 +0800929 _release_rootfs_cmd_arg,
930 _firmware_path_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800931 _enforced_release_channels_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800932def Finalize(options):
933 """Verify system readiness and trigger transition into release state.
934
Jon Salzaa3a30e2013-05-15 15:56:28 +0800935 This routine does the following:
936 - Verifies system state (see verify command)
Jon Salzfe9036f2014-01-16 14:11:23 +0800937 - Untars stateful_files.tar.xz, if it exists, in the stateful partition, to
938 initialize files such as the CRX cache
Jon Salzaa3a30e2013-05-15 15:56:28 +0800939 - Modifies firmware bitmaps to match locale
940 - Clears all factory-friendly flags from the GBB
941 - Removes factory-specific entries from RW_VPD (factory.*)
942 - Enables firmware write protection (cannot rollback after this)
943 - Uploads system logs & reports
944 - Sets the necessary boot flags to cause wipe of the factory image on the
945 next boot.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800946 """
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800947 Verify(options)
Jon Salz40b9f822014-07-25 16:39:55 +0800948 LogSourceHashes(options)
Jon Salzfe9036f2014-01-16 14:11:23 +0800949 UntarStatefulFiles(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800950 if options.cros_core:
951 logging.info('SetFirmwareBitmapLocale is skipped for ChromeOS Core device.')
952 else:
953 SetFirmwareBitmapLocale(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800954 ClearGBBFlags(options)
Jon Salzaa3a30e2013-05-15 15:56:28 +0800955 ClearFactoryVPDEntries(options)
Mattias Nisslercca761b2015-04-15 21:53:04 +0200956 GenerateStableDeviceSecret(options)
Hung-Te Lin6d827542012-07-19 11:50:41 +0800957 if options.no_write_protect:
958 logging.warn('WARNING: Firmware Write Protection is SKIPPED.')
Andy Cheng0465d132013-03-20 12:12:06 +0800959 event_log.Log('wp', fw='both', status='skipped')
Hung-Te Lin6d827542012-07-19 11:50:41 +0800960 else:
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800961 EnableFwWp({})
Jon Salza0f58e02012-05-29 19:33:39 +0800962 LogSystemDetails(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800963 UploadReport(options)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800964 if options.wipe_in_place:
965 event_log.Log('wipe_in_place')
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800966 # WipeInPlace(options)
967 wipe_args = []
968 wipe_args += ['--cutoff_args', options.cutoff_args]
969 wipe_args += ['--shopfloor_url', options.shopfloor_url]
970 if options.fast:
971 wipe_args += ['--fast']
972 ExecFactoryPar('gooftool', 'wipe_in_place', *wipe_args)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800973 else:
974 PrepareWipe(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800975
976
Ricky Liangc662be32013-12-24 11:50:23 +0800977def VerifyHWIDv3(options):
978 """A simple wrapper that calls out to HWID utils to verify version 3 HWID.
Ricky Liang53390232013-03-08 15:37:57 +0800979
Ricky Liangc662be32013-12-24 11:50:23 +0800980 This is mainly for Gooftool to verify v3 HWID during finalize. For testing
981 and development purposes, please use `hwid` command.
Ricky Liang53390232013-03-08 15:37:57 +0800982 """
Ricky Liangc662be32013-12-24 11:50:23 +0800983 db = GetGooftool(options).db
984 encoded_string = options.hwid or hwid_utils.GetHWIDString()
Ricky Liang7905f272013-03-16 01:57:10 +0800985 if options.probe_results:
Ricky Liangc662be32013-12-24 11:50:23 +0800986 probed_results = yaml.load(open(options.probe_results).read())
Ricky Liang7905f272013-03-16 01:57:10 +0800987 else:
Ricky Liangc662be32013-12-24 11:50:23 +0800988 probed_results = yaml.load(Probe(probe_vpd=True).Encode())
989 vpd = hwid_utils.GetVPD(probed_results)
Ricky Liang53390232013-03-08 15:37:57 +0800990
Hung-Te Lin11052952015-03-18 13:48:59 +0800991 event_log.Log('probed_results', probed_results=FilterDict(probed_results))
992 event_log.Log('vpd', vpd=FilterDict(vpd))
Ricky Liang53390232013-03-08 15:37:57 +0800993
Ricky Liangc662be32013-12-24 11:50:23 +0800994 hwid_utils.VerifyHWID(db, encoded_string, probed_results, vpd,
Hung-Te Lin56b18402015-01-16 14:52:30 +0800995 rma_mode=options.rma_mode)
Ricky Liang53390232013-03-08 15:37:57 +0800996
Ricky Liangc662be32013-12-24 11:50:23 +0800997 event_log.Log('verified_hwid', hwid=encoded_string)
Ricky Liang53390232013-03-08 15:37:57 +0800998
999
Ricky Liang59611a62013-06-11 13:47:33 +08001000def ParseDecodedHWID(hwid):
1001 """Parse the HWID object into a more compact dict.
1002
1003 Args:
1004 hwid: A decoded HWID object.
1005
1006 Returns:
1007 A dict containing the board name, the binary string, and the list of
1008 components.
1009 """
1010 results = {}
1011 results['board'] = hwid.database.board
1012 results['binary_string'] = hwid.binary_string
1013 results['components'] = collections.defaultdict(list)
1014 components = hwid.bom.components
1015 for comp_cls in sorted(components):
1016 for (comp_name, probed_values, _) in sorted(components[comp_cls]):
1017 if not probed_values:
1018 db_components = hwid.database.components
1019 probed_values = db_components.GetComponentAttributes(
1020 comp_cls, comp_name).get('values')
1021 results['components'][comp_cls].append(
1022 {comp_name: probed_values if probed_values else None})
1023 # Convert defaultdict to dict.
1024 results['components'] = dict(results['components'])
1025 return results
1026
1027
henryhsu44d793a2013-07-20 00:07:38 +08001028@Command('get_firmware_hash',
1029 CmdArg('--file', metavar='FILE', help='Firmware File.'))
1030def GetFirmwareHash(options):
henryhsuf6f835c2013-07-20 20:49:25 +08001031 """Get firmware hash from a file"""
henryhsu44d793a2013-07-20 00:07:38 +08001032 if os.path.exists(options.file):
1033 hashes = CalculateFirmwareHashes(options.file)
1034 for section, value_dict in hashes.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +08001035 print '%s:' % section
henryhsu44d793a2013-07-20 00:07:38 +08001036 for key, value in value_dict.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +08001037 print ' %s: %s' % (key, value)
henryhsu44d793a2013-07-20 00:07:38 +08001038 else:
1039 raise Error('File does not exist: %s' % options.file)
1040
henryhsuf6f835c2013-07-20 20:49:25 +08001041
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001042def Main():
1043 """Run sub-command specified by the command line args."""
Andy Cheng7a76cb82012-11-19 18:08:19 +08001044
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001045 options = ParseCmdline(
Ricky Liangc662be32013-12-24 11:50:23 +08001046 ('Perform Google required factory tests. All the HWID-related functions '
1047 'provided here are mainly for the deprecated HWID v2. To access HWID '
1048 'v3-related utilities, please use `hwid` command.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001049 CmdArg('-l', '--log', metavar='PATH',
1050 help='Write logs to this file.'),
Jon Salza4bea382012-10-29 13:00:34 +08001051 CmdArg('--suppress-event-logs', action='store_true',
1052 help='Suppress event logging.'),
Wei-Han Chenaff56232016-04-16 09:17:59 +08001053 CmdArg('--phase', default=None,
1054 help=('override phase for phase checking (defaults to the current '
1055 'as returned by the "factory phase" command)')),
Tammo Spalink8fab5312012-05-28 18:33:30 +08001056 verbosity_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001057 SetupLogging(options.verbosity, options.log)
Andy Cheng0465d132013-03-20 12:12:06 +08001058 event_log.SetGlobalLoggerDefaultPrefix('gooftool')
1059 event_log.GetGlobalLogger().suppress = options.suppress_event_logs
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001060 logging.debug('gooftool options: %s', repr(options))
Wei-Han Chenaff56232016-04-16 09:17:59 +08001061
1062 phase.OverridePhase(options.phase)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001063 try:
1064 logging.debug('GOOFTOOL command %r', options.command_name)
1065 options.command(options)
1066 logging.info('GOOFTOOL command %r SUCCESS', options.command_name)
1067 except Error, e:
1068 logging.exception(e)
1069 sys.exit('GOOFTOOL command %r ERROR: %s' % (options.command_name, e))
1070 except Exception, e:
1071 logging.exception(e)
1072 sys.exit('UNCAUGHT RUNTIME EXCEPTION %s' % e)
1073
1074
1075if __name__ == '__main__':
1076 Main()