blob: 2559789bfd44b2bbb405e089f6baeb06191cf410 [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
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800150_cutoff_args_cmd_arg = CmdArg(
151 '--cutoff_args',
152 help='Battery cutoff arguments to be passed to battery_cutoff.sh '
153 'after wiping. Should be the following format: '
154 '[--method shutdown|reboot|battery_cutoff] '
155 '[--check-ac connect_ac|remove_ac] '
156 '[--min-battery-percent <minimum battery percentage>] '
157 '[--max-battery-percent <maximum battery percentage>] '
158 '[--min-battery-voltage <minimum battery voltage>] '
159 '[--max-battery-voltage <maximum battery voltage>]')
160
161_shopfloor_url_args_cmd_arg = CmdArg(
162 '--shopfloor_url',
163 help='Shopfloor server url to be informed when in-place wipe is done. '
164 'After in-place wipe, a XML-RPC request will be sent to the '
165 'given url to indicate the completion of wipe.')
166
167_station_ip_cmd_arg = CmdArg(
168 '--station_ip',
169 help='IP of remote station')
170
171_station_port_cmd_arg = CmdArg(
172 '--station_port',
173 help='Port on remote station')
174
175_wipe_finish_token_cmd_arg = CmdArg(
176 '--wipe_finish_token',
177 help='Required token when notifying station after wipe finished')
178
Tammo Spalink95c43732012-07-25 15:57:14 -0700179@Command('best_match_hwids',
Tammo Spalink8fab5312012-05-28 18:33:30 +0800180 _hwdb_path_cmd_arg,
181 CmdArg('-b', '--board', metavar='BOARD',
Tammo Spalink95c43732012-07-25 15:57:14 -0700182 help='optional BOARD name, needed only if data is present '
183 'for more than one'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800184 CmdArg('--bom', metavar='BOM', help='BOM name'),
185 CmdArg('--variant', metavar='VARIANT', help='VARIANT code'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800186 CmdArg('--optimistic', action='store_true',
187 help='do not probe; assume singletons match'),
Tammo Spalink95c43732012-07-25 15:57:14 -0700188 CmdArg('--comps', nargs='*', default=[],
189 help='list of canonical component names'),
190 CmdArg('--missing', nargs='*', default=[],
191 help='list component classes to be assumed missing'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800192 CmdArg('--status', nargs='*', default=['supported'],
Tammo Spalink95c43732012-07-25 15:57:14 -0700193 help='consider only HWIDs within this list of status values'))
194def BestMatchHwids(options):
Ricky Liangc662be32013-12-24 11:50:23 +0800195 """Determine a list of possible HWIDs using provided args and probing.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800196
197 VOLATILE can always be determined by probing. To get a unique
198 result, VARIANT must be specified for all cases where the matching
199 BOM has more than one associated variant code, otherwise all HWID
200 variants will be returned. Both VARIANT and BOM information can
Tammo Spalink95c43732012-07-25 15:57:14 -0700201 alternatively be specified using the --stdin_comps argument, which
202 allows specifying a list of canonical names (one per line) on stdin,
203 one per line. Based on what is known from BOM and stdin_comps,
204 determine a list of components to probe for, and use those probe
205 results to resolve a list of matching HWIDs. If no boms,
206 components, or variant codes are specified, then a list of all HWIDs
Andy Cheng8ece7382012-08-22 16:25:42 +0800207 that match probeable components will be returned.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800208
209 Returns (on stdout): A list of HWIDs that match the available probe
210 results and argument contraints, one per line.
Tammo Spalink70b48a52012-08-08 16:54:51 -0700211
212 Example:
213
214 // Three ways to specify a keyboard (assuming it is a variant component)
215 gooftool best_match_hwids --missing keyboard
216 gooftool best_match_hwids --variant A or
217 gooftool best_match_hwids --comps us_kbd
Tammo Spalink8fab5312012-05-28 18:33:30 +0800218 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800219
Tammo Spalink5c699832012-07-03 17:50:39 +0800220 map(hwid_tool.Validate.Status, options.status)
Tammo Spalink95c43732012-07-25 15:57:14 -0700221 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Tammo Spalink5c699832012-07-03 17:50:39 +0800222 comp_db = hw_db.comp_db
Tammo Spalink3a7e9022012-06-27 14:08:40 +0800223 device = hw_db.GetDevice(options.board)
Tammo Spalink5c699832012-07-03 17:50:39 +0800224 component_spec = hwid_tool.ComponentSpec.New()
Tammo Spalink8fab5312012-05-28 18:33:30 +0800225 if options.bom:
Tammo Spalink5c699832012-07-03 17:50:39 +0800226 device.BomExists(options.bom)
Tammo Spalink01e11722012-07-24 10:17:54 -0700227 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800228 component_spec, device.boms[options.bom].primary)
Tammo Spalink8fab5312012-05-28 18:33:30 +0800229 if options.variant:
Tammo Spalink5c699832012-07-03 17:50:39 +0800230 device.VariantExists(options.variant)
231 variant_spec = device.variants[options.variant]
Tammo Spalink01e11722012-07-24 10:17:54 -0700232 if hwid_tool.ComponentSpecsConflict(component_spec, variant_spec):
Tammo Spalink95c43732012-07-25 15:57:14 -0700233 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700234 % YamlWrite(sorted(
235 hwid_tool.ComponentSpecClasses(component_spec) &
236 hwid_tool.ComponentSpecClasses(variant_spec))))
Tammo Spalink01e11722012-07-24 10:17:54 -0700237 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800238 component_spec, variant_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700239 if options.comps or options.missing:
240 map(comp_db.CompExists, options.comps)
241 map(comp_db.CompClassExists, options.missing)
242 extra_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800243 components=options.comps,
244 missing=options.missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700245 print 'cmdline asserted components:\n%s' % extra_comp_spec.Encode()
246 if hwid_tool.ComponentSpecsConflict(component_spec, extra_comp_spec):
247 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700248 % YamlWrite(sorted(
249 hwid_tool.ComponentSpecClasses(component_spec) &
250 hwid_tool.ComponentSpecClasses(extra_comp_spec))))
Tammo Spalink95c43732012-07-25 15:57:14 -0700251 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800252 component_spec, extra_comp_spec)
Tammo Spalink01e11722012-07-24 10:17:54 -0700253 spec_classes = hwid_tool.ComponentSpecClasses(component_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700254 missing_classes = set(comp_db.all_comp_classes) - spec_classes
Tammo Spalink5c699832012-07-03 17:50:39 +0800255 if missing_classes and not options.optimistic:
Andy Cheng8ece7382012-08-22 16:25:42 +0800256 non_probeable_missing = missing_classes - PROBEABLE_COMPONENT_CLASSES
257 if non_probeable_missing:
Tammo Spalink95c43732012-07-25 15:57:14 -0700258 sys.exit('FAILURE: these classes are necessary, were not specified '
Tammo Spalink70b48a52012-08-08 16:54:51 -0700259 'as inputs, and cannot be probed for:\n%s'
260 'This problem can often be addressed by specifying all of '
261 'the missing components on the command line (see the command '
Andy Cheng8ece7382012-08-22 16:25:42 +0800262 'help).' % YamlWrite(list(non_probeable_missing)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700263 print 'probing for missing classes:'
264 print YamlWrite(list(missing_classes))
265 probe_results = Probe(target_comp_classes=list(missing_classes),
266 probe_volatile=False, probe_initial_config=False)
267 cooked_components = comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800268 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700269 if cooked_components.unmatched:
270 sys.exit('ERROR: some probed components are unrecognized:\n%s'
271 % YamlWrite(cooked_components.unmatched))
272 probed_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800273 components=cooked_components.matched,
274 missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700275 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800276 component_spec, probed_comp_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700277 print YamlWrite({'component data used for matching': {
Hung-Te Lin56b18402015-01-16 14:52:30 +0800278 'missing component classes': component_spec.classes_missing,
279 'found components': component_spec.components}})
Tammo Spalink95c43732012-07-25 15:57:14 -0700280 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800281 extant_components=hwid_tool.ComponentSpecCompClassMap(
282 component_spec).keys(),
283 classes_missing=component_spec.classes_missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700284 match_tree = device.BuildMatchTree(component_data)
285 if not match_tree:
286 sys.exit('FAILURE: NO matching BOMs found')
287 print 'potential BOMs/VARIANTs:'
288 potential_variants = set()
289 potential_volatiles = set()
290 for bom_name, variant_tree in match_tree.items():
291 print ' BOM: %-8s VARIANTS: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800292 bom_name, ', '.join(sorted(variant_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700293 for variant_code in variant_tree:
294 potential_variants.add(variant_code)
295 for volatile_code in device.volatiles:
296 status = device.GetHwidStatus(bom_name, variant_code, volatile_code)
297 if status in options.status:
298 potential_volatiles.add(volatile_code)
299 print ''
300 if len(potential_variants) == 0:
301 sys.exit('FAILURE: no matching VARIANTs found')
302 if len(potential_volatiles) == 0:
303 sys.exit('FAILURE: no VOLATILEs found for potential matching BOMs/VARIANTS '
304 '(with specified status)')
Tammo Spalink394e4492012-08-01 10:20:30 -0700305 if (options.optimistic and
306 len(match_tree) == 1 and
307 len(potential_variants) == 1 and
308 len(potential_volatiles) == 1):
309 print ('MATCHING HWID: %s' % device.FmtHwid(match_tree.keys().pop(),
310 potential_variants.pop(),
311 potential_volatiles.pop()))
Tammo Spalink5c699832012-07-03 17:50:39 +0800312 return
Tammo Spalink95c43732012-07-25 15:57:14 -0700313 print ('probing VOLATILEs to resolve potential matches: %s\n' %
314 ', '.join(sorted(potential_volatiles)))
315 vol_probe_results = Probe(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800316 target_comp_classes=[],
317 probe_volatile=True,
318 probe_initial_config=False)
Tammo Spalink95c43732012-07-25 15:57:14 -0700319 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800320 vol_probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700321 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800322 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700323 matched_hwids = device.GetMatchTreeHwids(match_tree)
324 if matched_hwids:
325 for hwid in matched_hwids:
Ricky Liang02f3bd72012-09-21 14:33:01 +0800326 if matched_hwids[hwid] in options.status:
327 print 'MATCHING HWID: %s' % hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700328 return
329 print 'exact HWID matching failed, but the following BOMs match: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800330 ', '.join(sorted(match_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700331 if options.optimistic and len(match_tree) == 1:
332 bom_name = set(match_tree).pop()
Tammo Spalink5c699832012-07-03 17:50:39 +0800333 bom = device.boms[bom_name]
Tammo Spalink95c43732012-07-25 15:57:14 -0700334 variant_matches = match_tree[bom_name]
Tammo Spalink5c699832012-07-03 17:50:39 +0800335 if len(variant_matches) == 1:
336 var_code = set(variant_matches).pop()
337 elif len(bom.variants) == 1:
338 var_code = set(bom.variants).pop()
339 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700340 sys.exit('FAILURE: NO matching HWIDs found; optimistic matching failed '
341 'because there were too many variants to choose from for BOM %r'
342 % bom_name)
343 hwids = [device.FmtHwid(bom_name, var_code, vol_code)
344 for vol_code in device.volatiles
345 if device.GetHwidStatus(bom_name, var_code, vol_code)
346 in options.status]
347 for hwid in hwids:
348 print 'MATCHING HWID: %s' % hwid
Tammo Spalink5c699832012-07-03 17:50:39 +0800349 return
350 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700351 print ('optimistic matching not attempted because either it was '
352 'not requested, or because the number of BOMs was <> 1\n')
353 sys.exit('FAILURE: NO matching HWIDs found')
Tammo Spalink8fab5312012-05-28 18:33:30 +0800354
355
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800356@Command('probe',
357 CmdArg('--comps', nargs='*',
358 help='List of keys from the component_db registry.'),
Ricky Liangb30da672013-06-14 12:36:34 +0800359 CmdArg('--fast_fw_probe', action='store_true',
360 help='Do a fast probe for EC and main firmware versions only. '
361 'This implies --no_vol and --no_ic.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800362 CmdArg('--no_vol', action='store_true',
363 help='Do not probe volatile data.'),
364 CmdArg('--no_ic', action='store_true',
Jon Salz0f8a6842012-09-25 11:28:22 +0800365 help='Do not probe initial_config data.'),
366 CmdArg('--include_vpd', action='store_true',
367 help='Include VPD data in volatiles.'))
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800368def RunProbe(options):
369 """Print yaml-formatted breakdown of probed device properties."""
Ricky Lianga70a1202013-03-15 15:03:17 +0800370 print GetGooftool(options).Probe(
371 target_comp_classes=options.comps,
Ricky Liangb30da672013-06-14 12:36:34 +0800372 fast_fw_probe=options.fast_fw_probe,
Ricky Lianga70a1202013-03-15 15:03:17 +0800373 probe_volatile=not options.no_vol,
374 probe_initial_config=not options.no_ic,
375 probe_vpd=options.include_vpd).Encode()
Ricky Liang53390232013-03-08 15:37:57 +0800376
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800377
Tammo Spalink214caf42012-05-28 10:45:00 +0800378@Command('verify_components',
379 _hwdb_path_cmd_arg,
Tammo Spalink5c699832012-07-03 17:50:39 +0800380 CmdArg('target_comps', nargs='*'))
Tammo Spalink214caf42012-05-28 10:45:00 +0800381def VerifyComponents(options):
Andy Cheng8ece7382012-08-22 16:25:42 +0800382 """Verify that probeable components all match entries in the component_db.
Tammo Spalink214caf42012-05-28 10:45:00 +0800383
Tammo Spalink5c699832012-07-03 17:50:39 +0800384 Probe for each component class in the target_comps and verify
Tammo Spalink214caf42012-05-28 10:45:00 +0800385 that a corresponding match exists in the component_db -- make sure
386 that these components are present, that they have been approved, but
387 do not check against any specific BOM/HWID configurations.
388 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800389
Andy Chengc531e2f2012-10-15 19:09:17 +0800390 try:
Ricky Lianga70a1202013-03-15 15:03:17 +0800391 result = GetGooftool(options).VerifyComponents(
Andy Chengc531e2f2012-10-15 19:09:17 +0800392 options.target_comps)
393 except ValueError, e:
394 sys.exit(e)
395
Ricky Liang53390232013-03-08 15:37:57 +0800396 PrintVerifyComponentsResults(result)
397
398
399def PrintVerifyComponentsResults(result):
400 """Prints out the results of VerifyComponents method call.
401
402 Groups the results into two groups: 'matches' and 'errors', and prints out
403 their values.
404 """
Andy Chengc531e2f2012-10-15 19:09:17 +0800405 # group by matches and errors
Tammo Spalink214caf42012-05-28 10:45:00 +0800406 matches = []
Andy Chengc531e2f2012-10-15 19:09:17 +0800407 errors = []
408 for result_list in result.values():
409 for component_name, _, error in result_list:
410 if component_name:
411 matches.append(component_name)
Tammo Spalink214caf42012-05-28 10:45:00 +0800412 else:
Andy Chengc531e2f2012-10-15 19:09:17 +0800413 errors.append(error)
414
Andy Cheng228a8c92012-08-27 10:53:57 +0800415 if matches:
416 print 'found probeable components:\n %s' % '\n '.join(matches)
Tammo Spalink214caf42012-05-28 10:45:00 +0800417 if errors:
Andy Cheng228a8c92012-08-27 10:53:57 +0800418 print '\nerrors:\n %s' % '\n '.join(errors)
419 sys.exit('\ncomponent verification FAILURE')
Tammo Spalink214caf42012-05-28 10:45:00 +0800420 else:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800421 print '\ncomponent verification SUCCESS'
Tammo Spalink214caf42012-05-28 10:45:00 +0800422
423
Ricky Liang43b879b2014-02-24 11:36:55 +0800424@Command('verify_hwid_v2',
Tammo Spalink95c43732012-07-25 15:57:14 -0700425 _hwid_status_list_cmd_arg,
Jon Salz0f8a6842012-09-25 11:28:22 +0800426 _hwdb_path_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800427 _probe_results_cmd_arg,
428 _hwid_cmd_arg)
Ricky Liang43b879b2014-02-24 11:36:55 +0800429def VerifyHWIDv2(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800430 """Verify system HWID properties match probed device properties.
431
432 First probe components, volatile and initial_config parameters for
433 the DUT. Then use the available device data to produce a list of
434 candidate HWIDs. Then verify the HWID from the DUT is present in
435 that list. Then verify that the DUT initial config values match
436 those specified for its HWID. Finally, verify that VPD contains all
437 the necessary fields as specified by the board data, and when
438 possible verify that values are legitimate.
439 """
Ricky Liangf7857c12012-09-17 13:34:41 +0800440 def VerifyVpd(ro_vpd_keys, rw_vpd_keys):
Tammo Spalink5c699832012-07-03 17:50:39 +0800441 for key in ro_vpd_keys:
442 if key not in ro_vpd:
Ricky Liangf7857c12012-09-17 13:34:41 +0800443 sys.exit('Missing required RO VPD field: %s' % key)
Tammo Spalink01e11722012-07-24 10:17:54 -0700444 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800445 value = ro_vpd[key]
Ricky Liangf7857c12012-09-17 13:34:41 +0800446 if (known_valid_values is not None) and (value not in known_valid_values):
447 sys.exit('Invalid RO VPD entry : key %r, value %r' % (key, value))
Ricky Liangf7857c12012-09-17 13:34:41 +0800448 for key in rw_vpd_keys:
449 if key not in rw_vpd:
450 sys.exit('Missing required RW VPD field: %s' % key)
451 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
452 value = rw_vpd[key]
453 if (known_valid_values is not None) and (value not in known_valid_values):
454 sys.exit('Invalid RW VPD entry : key %r, value %r' % (key, value))
Andy Cheng0465d132013-03-20 12:12:06 +0800455 event_log.Log('vpd', ro_vpd=FilterDict(ro_vpd), rw_vpd=FilterDict(rw_vpd))
Tammo Spalink5c699832012-07-03 17:50:39 +0800456 map(hwid_tool.Validate.Status, options.status)
Jon Salz0f8a6842012-09-25 11:28:22 +0800457
Jon Salz0f8a6842012-09-25 11:28:22 +0800458 if options.hwid:
459 hwid_str = options.hwid
460 else:
Hung-Te Lin74346d72016-01-07 22:16:57 +0800461 main_fw_file = crosfw.LoadMainFirmware().GetFileName()
Jon Salz0f8a6842012-09-25 11:28:22 +0800462 gbb_result = Shell('gbb_utility -g --hwid %s' % main_fw_file).stdout
463 hwid_str = re.findall(r'hardware_id:(.*)', gbb_result)[0].strip()
Tammo Spalink95c43732012-07-25 15:57:14 -0700464 hwid = hwid_tool.ParseHwid(hwid_str)
Tammo Spalink5c699832012-07-03 17:50:39 +0800465 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Jon Salz0f8a6842012-09-25 11:28:22 +0800466 print 'Verifying HWID: %r\n' % hwid.hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700467 device = hw_db.GetDevice(hwid.board)
468 hwid_status = device.GetHwidStatus(hwid.bom, hwid.variant, hwid.volatile)
469 if hwid_status not in options.status:
Tammo Spalink5c699832012-07-03 17:50:39 +0800470 sys.exit('HWID status must be one of [%s], found %r' %
Hung-Te Lin4f5beb12012-08-20 14:48:06 +0800471 (', '.join(options.status), hwid_status))
Jon Salz0f8a6842012-09-25 11:28:22 +0800472 if options.probe_results:
473 # Pull in probe results (including VPD data) from the given file
474 # rather than probing the current system.
475 probe_results = hwid_tool.ProbeResults.Decode(
476 open(options.probe_results).read())
477 ro_vpd = {}
478 rw_vpd = {}
479 for k, v in probe_results.found_volatile_values.items():
Hung-Te Lin56b18402015-01-16 14:52:30 +0800480 match = re.match(r'^vpd\.(ro|rw)\.(\w+)$', k)
Jon Salz0f8a6842012-09-25 11:28:22 +0800481 if match:
482 del probe_results.found_volatile_values[k]
483 (ro_vpd if match.group(1) == 'ro' else rw_vpd)[match.group(2)] = v
484 else:
485 probe_results = Probe()
Hung-Te Lin74346d72016-01-07 22:16:57 +0800486 ro_vpd = ReadRoVpd()
487 rw_vpd = ReadRwVpd()
Tammo Spalink95c43732012-07-25 15:57:14 -0700488 cooked_components = hw_db.comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800489 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700490 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800491 probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700492 cooked_initial_configs = device.MatchInitialConfigValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800493 probe_results.initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700494 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800495 extant_components=cooked_components.matched,
496 classes_missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700497 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800498 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700499 matched_hwids = device.GetMatchTreeHwids(match_tree)
500 print 'HWID status: %s\n' % hwid_status
501 print 'probed system components:'
502 print YamlWrite(cooked_components.__dict__)
503 print 'missing component classes:'
504 print YamlWrite(probe_results.missing_component_classes)
505 print 'probed volatiles:'
506 print YamlWrite(cooked_volatiles.__dict__)
507 print 'probed initial_configs:'
508 print YamlWrite(cooked_initial_configs)
509 print 'hwid match tree:'
510 print YamlWrite(match_tree)
Andy Cheng0465d132013-03-20 12:12:06 +0800511 event_log.Log(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800512 'probe',
513 found_components=cooked_components.__dict__,
514 missing_component_classes=probe_results.missing_component_classes,
515 volatiles=cooked_volatiles.__dict__,
516 initial_configs=cooked_initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700517 if hwid.hwid not in matched_hwids:
Tammo Spalink5c699832012-07-03 17:50:39 +0800518 err_msg = 'HWID verification FAILED.\n'
Tammo Spalink95c43732012-07-25 15:57:14 -0700519 if cooked_components.unmatched:
Tammo Spalink5c699832012-07-03 17:50:39 +0800520 sys.exit(err_msg + 'some components could not be indentified:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700521 YamlWrite(cooked_components.unmatched))
522 if not match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800523 sys.exit(err_msg + 'no matching boms were found for components:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700524 component_data.Encode())
525 if hwid.bom not in match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800526 sys.exit(err_msg + 'matching boms [%s] do not include target bom %r' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700527 (', '.join(sorted(match_tree)), hwid.bom))
528 err_msg += 'target bom %r matches components' % hwid.bom
529 if hwid.bom not in device.IntersectBomsAndInitialConfigs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800530 cooked_initial_configs):
Tammo Spalink5c699832012-07-03 17:50:39 +0800531 sys.exit(err_msg + ', but failed initial config verification')
Tammo Spalink95c43732012-07-25 15:57:14 -0700532 matched_variants = match_tree.get(hwid.bom, {})
533 if hwid.variant not in matched_variants:
Tammo Spalink5c699832012-07-03 17:50:39 +0800534 sys.exit(err_msg + ', but target variant_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700535 hwid.variant)
536 matched_volatiles = matched_variants.get(hwid.variant, {})
537 if hwid.volatile not in matched_volatiles:
Tammo Spalink5c699832012-07-03 17:50:39 +0800538 sys.exit(err_msg + ', but target volatile_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700539 hwid.volatile)
540 found_status = matched_volatiles.get(hwid.volatile, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800541 sys.exit(err_msg + ', but hwid status %r was unacceptable' % found_status)
Ricky Liangf7857c12012-09-17 13:34:41 +0800542 VerifyVpd(device.vpd_ro_fields, device.vpd_rw_fields)
Andy Cheng0465d132013-03-20 12:12:06 +0800543 event_log.Log('verified_hwid', hwid=hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -0700544 print 'Verification SUCCESS!'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800545
546
Hung-Te Line1d80f62016-03-31 14:58:13 +0800547@Command('verify_keys',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800548 _release_rootfs_cmd_arg,
549 _firmware_path_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700550def VerifyKeys(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800551 """Verify keys in firmware and SSD match."""
Hung-Te Line1d80f62016-03-31 14:58:13 +0800552 return GetGooftool(options).VerifyKeys(
Hung-Te Lincdb96522016-04-15 16:51:10 +0800553 options.release_rootfs, options.firmware_path)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800554
555
556@Command('set_fw_bitmap_locale')
Tammo Spalink01e11722012-07-24 10:17:54 -0700557def SetFirmwareBitmapLocale(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800558 """Use VPD locale value to set firmware bitmap default language."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800559
Ricky Lianga70a1202013-03-15 15:03:17 +0800560 (index, locale) = GetGooftool(options).SetFirmwareBitmapLocale()
Andy Cheng2582d292012-12-04 17:38:28 +0800561 logging.info('Firmware bitmap initial locale set to %d (%s).',
562 index, locale)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800563
564
Hung-Te Line1d80f62016-03-31 14:58:13 +0800565@Command('verify_system_time',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800566 _release_rootfs_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700567def VerifySystemTime(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800568 """Verify system time is later than release filesystem creation time."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800569
Hung-Te Lincdb96522016-04-15 16:51:10 +0800570 return GetGooftool(options).VerifySystemTime(options.release_rootfs)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800571
572
Hung-Te Line1d80f62016-03-31 14:58:13 +0800573@Command('verify_rootfs',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800574 _release_rootfs_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700575def VerifyRootFs(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800576 """Verify rootfs on SSD is valid by checking hash."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800577
Hung-Te Line1d80f62016-03-31 14:58:13 +0800578 return GetGooftool(options).VerifyRootFs(options.release_rootfs)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800579
Hung-Te Lin56b18402015-01-16 14:52:30 +0800580
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800581@Command('verify_tpm')
582def VerifyTPM(options): # pylint: disable=W0613
583 """Verify TPM is cleared."""
584
585 return GetGooftool(options).VerifyTPM()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800586
Hung-Te Lin56b18402015-01-16 14:52:30 +0800587
Hung-Te Lindd708d42014-07-11 17:05:01 +0800588@Command('verify_me_locked')
589def VerifyManagementEngineLocked(options): # pylint: disable=W0613
590 """Verify Managment Engine is locked."""
591
592 return GetGooftool(options).VerifyManagementEngineLocked()
593
Hung-Te Lin56b18402015-01-16 14:52:30 +0800594
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800595@Command('verify_switch_wp')
Andy Chengc92e6f92012-11-20 16:55:53 +0800596def VerifyWPSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800597 """Verify hardware write protection switch is enabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800598
Ricky Lianga70a1202013-03-15 15:03:17 +0800599 GetGooftool(options).VerifyWPSwitch()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800600
601
602@Command('verify_switch_dev')
Tammo Spalink01e11722012-07-24 10:17:54 -0700603def VerifyDevSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800604 """Verify developer switch is disabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800605
Ricky Lianga70a1202013-03-15 15:03:17 +0800606 if GetGooftool(options).CheckDevSwitchForDisabling():
Hung-Te Lind7d34722012-07-26 16:48:35 +0800607 logging.warn('VerifyDevSwitch: No physical switch.')
Andy Cheng0465d132013-03-20 12:12:06 +0800608 event_log.Log('switch_dev', type='virtual switch')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800609
610
Jon Salzadd90d32014-04-29 16:16:27 +0800611@Command('verify_branding')
612def VerifyBranding(options): # pylint: disable=W0613
613 """Verify that branding fields are properly set.
614
615 customization_id, if set in the RO VPD, must be of the correct format.
616
617 rlz_brand_code must be set either in the RO VPD or OEM partition, and must
618 be of the correct format.
619 """
620 return GetGooftool(options).VerifyBranding()
621
622
bowgotsai13820f42015-09-10 23:18:04 +0800623@Command('verify_release_channel',
624 _enforced_release_channels_cmd_arg)
bowgotsai529139c2015-05-30 01:39:49 +0800625def VerifyReleaseChannel(options): # pylint: disable=W0613
626 """Verify that release image channel is correct.
627
628 ChromeOS has four channels: canary, dev, beta and stable.
629 The last three channels support image auto-updates, checks
630 that release image channel is one of them.
631 """
bowgotsai13820f42015-09-10 23:18:04 +0800632 return GetGooftool(options).VerifyReleaseChannel(
633 options.enforced_release_channels)
bowgotsai529139c2015-05-30 01:39:49 +0800634
635
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800636@Command('write_protect')
Tammo Spalink01e11722012-07-24 10:17:54 -0700637def EnableFwWp(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800638 """Enable then verify firmware write protection."""
639
Hung-Te Linb21c6682012-08-01 13:53:57 +0800640 def CalculateLegacyRange(fw_type, length, section_data,
641 section_name):
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800642 ro_size = length / 2
643 ro_a = int(section_data[0] / ro_size)
644 ro_b = int((section_data[0] + section_data[1] - 1) / ro_size)
645 if ro_a != ro_b:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800646 raise Error('%s firmware section %s has illegal size' %
Hung-Te Linb21c6682012-08-01 13:53:57 +0800647 (fw_type, section_name))
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800648 ro_offset = ro_a * ro_size
649 return (ro_offset, ro_size)
650
651 def WriteProtect(fw_file_path, fw_type, legacy_section):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800652 """Calculate protection size, then invoke flashrom.
653
654 Our supported chips only allow write protecting half their total
655 size, so we parition the flash chipset space accordingly.
656 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800657
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800658 raw_image = open(fw_file_path, 'rb').read()
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800659 wp_section = 'WP_RO'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800660 image = crosfw.FirmwareImage(raw_image)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800661 if image.has_section(wp_section):
662 section_data = image.get_section_area(wp_section)
663 ro_offset = section_data[0]
664 ro_size = section_data[1]
665 elif image.has_section(legacy_section):
666 section_data = image.get_section_area(legacy_section)
667 (ro_offset, ro_size) = CalculateLegacyRange(
Hung-Te Linb21c6682012-08-01 13:53:57 +0800668 fw_type, len(raw_image), section_data, legacy_section)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800669 else:
670 raise Error('could not find %s firmware section %s or %s' %
671 (fw_type, wp_section, legacy_section))
672
673 logging.debug('write protecting %s [off=%x size=%x]', fw_type,
674 ro_offset, ro_size)
675 crosfw.Flashrom(fw_type).EnableWriteProtection(ro_offset, ro_size)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800676
677 WriteProtect(crosfw.LoadMainFirmware().GetFileName(), 'main', 'RO_SECTION')
Andy Cheng0465d132013-03-20 12:12:06 +0800678 event_log.Log('wp', fw='main')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800679 ec_fw_file = crosfw.LoadEcFirmware().GetFileName()
680 if ec_fw_file is not None:
681 WriteProtect(ec_fw_file, 'ec', 'EC_RO')
Andy Cheng0465d132013-03-20 12:12:06 +0800682 event_log.Log('wp', fw='ec')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800683 else:
684 logging.warning('EC not write protected (seems there is no EC flash).')
685
686
687@Command('clear_gbb_flags')
Andy Chengc92e6f92012-11-20 16:55:53 +0800688def ClearGBBFlags(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800689 """Zero out the GBB flags, in preparation for transition to release state.
690
691 No GBB flags are set in release/shipping state, but they are useful
692 for factory/development. See "gbb_utility --flags" for details.
693 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800694
Ricky Lianga70a1202013-03-15 15:03:17 +0800695 GetGooftool(options).ClearGBBFlags()
Andy Cheng0465d132013-03-20 12:12:06 +0800696 event_log.Log('clear_gbb_flags')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800697
698
Jon Salzaa3a30e2013-05-15 15:56:28 +0800699@Command('clear_factory_vpd_entries')
700def ClearFactoryVPDEntries(options): # pylint: disable=W0613
701 """Clears factory.* items in the RW VPD."""
702 entries = GetGooftool(options).ClearFactoryVPDEntries()
703 event_log.Log('clear_factory_vpd_entries', entries=FilterDict(entries))
704
705
Mattias Nisslercca761b2015-04-15 21:53:04 +0200706@Command('generate_stable_device_secret')
707def GenerateStableDeviceSecret(options): # pylint: disable=W0613
708 """Generates a a fresh stable device secret and stores it in the RO VPD."""
709 GetGooftool(options).GenerateStableDeviceSecret()
710 event_log.Log('generate_stable_device_secret')
711
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800712
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800713@Command('wipe_in_place',
714 CmdArg('--fast', action='store_true',
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800715 help='use non-secure but faster wipe method.'),
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800716 _cutoff_args_cmd_arg,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800717 _shopfloor_url_args_cmd_arg,
718 _station_ip_cmd_arg,
719 _station_port_cmd_arg,
720 _wipe_finish_token_cmd_arg)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800721def WipeInPlace(options):
722 """Start factory wipe directly without reboot."""
723
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800724 GetGooftool(options).WipeInPlace(options.fast,
725 options.cutoff_args,
726 options.shopfloor_url,
727 options.station_ip,
728 options.station_port,
729 options.wipe_finish_token)
Mattias Nisslercca761b2015-04-15 21:53:04 +0200730
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800731@Command('wipe_init',
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800732 CmdArg('--wipe_args', help='arguments for clobber-state'),
733 CmdArg('--state_dev', help='path to stateful partition device'),
734 CmdArg('--root_disk', help='path to primary device'),
735 CmdArg('--old_root', help='path to old root'),
736 _cutoff_args_cmd_arg,
737 _shopfloor_url_args_cmd_arg,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800738 _release_rootfs_cmd_arg,
739 _station_ip_cmd_arg,
740 _station_port_cmd_arg,
741 _wipe_finish_token_cmd_arg)
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800742def WipeInit(options):
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800743 GetGooftool(options).WipeInit(options.wipe_args,
744 options.cutoff_args,
745 options.shopfloor_url,
746 options.state_dev,
747 options.release_rootfs,
748 options.root_disk,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800749 options.old_root,
750 options.station_ip,
751 options.station_port,
752 options.wipe_finish_token)
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800753
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800754@Command('prepare_wipe',
755 CmdArg('--fast', action='store_true',
756 help='use non-secure but faster wipe method.'))
757def PrepareWipe(options):
758 """Prepare system for transition to release state in next reboot."""
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800759
Ricky Lianga70a1202013-03-15 15:03:17 +0800760 GetGooftool(options).PrepareWipe(options.fast)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800761
Hung-Te Lin56b18402015-01-16 14:52:30 +0800762
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800763@Command('verify',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800764 CmdArg('--no_write_protect', action='store_true',
765 help='Do not check write protection switch state.'),
Ricky Liang43b879b2014-02-24 11:36:55 +0800766 _hwid_version_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700767 _hwid_status_list_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800768 _hwdb_path_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800769 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800770 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800771 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800772 _rma_mode_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800773 _cros_core_cmd_arg,
Hung-Te Lincdb96522016-04-15 16:51:10 +0800774 _release_rootfs_cmd_arg,
775 _firmware_path_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800776 _enforced_release_channels_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800777def Verify(options):
778 """Verifies if whole factory process is ready for finalization.
779
780 This routine performs all the necessary checks to make sure the
781 device is ready to be finalized, but does not modify state. These
782 checks include dev switch, firmware write protection switch, hwid,
783 system time, keys, and root file system.
784 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800785
Hung-Te Lin6d827542012-07-19 11:50:41 +0800786 if not options.no_write_protect:
Ricky Lianga70a1202013-03-15 15:03:17 +0800787 VerifyWPSwitch(options)
Hung-Te Lindd708d42014-07-11 17:05:01 +0800788 VerifyManagementEngineLocked(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800789 VerifyDevSwitch(options)
790 if options.hwid_version == 2:
Ricky Liang43b879b2014-02-24 11:36:55 +0800791 VerifyHWIDv2(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800792 elif options.hwid_version == 3:
Ricky Liangc662be32013-12-24 11:50:23 +0800793 VerifyHWIDv3(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800794 else:
795 raise Error, 'Invalid HWID version: %r' % options.hwid_version
796 VerifySystemTime(options)
797 VerifyKeys(options)
798 VerifyRootFs(options)
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800799 VerifyTPM(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800800 if options.cros_core:
801 logging.info('VerifyBranding is skipped for ChromeOS Core device.')
802 else:
803 VerifyBranding(options)
bowgotsai529139c2015-05-30 01:39:49 +0800804 VerifyReleaseChannel(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800805
Hung-Te Lin56b18402015-01-16 14:52:30 +0800806
Jon Salzfe9036f2014-01-16 14:11:23 +0800807@Command('untar_stateful_files')
Hung-Te Lin388bce22014-06-03 19:56:40 +0800808def UntarStatefulFiles(unused_options):
Jon Salzfe9036f2014-01-16 14:11:23 +0800809 """Untars stateful files from stateful_files.tar.xz on stateful partition.
810
811 If that file does not exist (which should only be R30 and earlier),
812 this is a no-op.
813 """
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +0800814 tar_file = os.path.join(paths.DEVICE_STATEFUL_PATH, 'stateful_files.tar.xz')
Jon Salzfe9036f2014-01-16 14:11:23 +0800815 if os.path.exists(tar_file):
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +0800816 Spawn(['tar', 'xf', tar_file], cwd=paths.DEVICE_STATEFUL_PATH,
Jon Salzfe9036f2014-01-16 14:11:23 +0800817 log=True, check_call=True)
818 else:
819 logging.warning('No stateful files at %s', tar_file)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800820
Jon Salz40b9f822014-07-25 16:39:55 +0800821
822@Command('log_source_hashes')
823def LogSourceHashes(options): # pylint: disable=W0613
824 """Logs hashes of source files in the factory toolkit."""
Jon Salze60307f2014-08-05 16:20:00 +0800825 # WARNING: The following line is necessary to validate the integrity
826 # of the factory software. Do not remove or modify it.
827 #
828 # 警告:此行会验证工厂软件的完整性,禁止删除或修改。
Wei-Han Chena5c01a02016-04-23 19:27:19 +0800829 factory_par = sys_utils.GetRunningFactoryPythonArchivePath()
830 if factory_par:
831 event_log.Log(
832 'source_hashes',
833 **file_utils.HashPythonArchive(factory_par))
834 else:
835 event_log.Log(
836 'source_hashes',
837 **file_utils.HashSourceTree(os.path.join(paths.FACTORY_PATH, 'py')))
Jon Salz40b9f822014-07-25 16:39:55 +0800838
839
Tammo Spalink86a61c62012-05-25 15:10:35 +0800840@Command('log_system_details')
Tammo Spalink01e11722012-07-24 10:17:54 -0700841def LogSystemDetails(options): # pylint: disable=W0613
Tammo Spalink86a61c62012-05-25 15:10:35 +0800842 """Write miscellaneous system details to the event log."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800843
Ricky Liang43b879b2014-02-24 11:36:55 +0800844 event_log.Log('system_details', **GetGooftool(options).GetSystemDetails())
Tammo Spalink86a61c62012-05-25 15:10:35 +0800845
846
Jon Salza88b83b2013-05-27 20:00:35 +0800847def CreateReportArchiveBlob(*args, **kwargs):
848 """Creates a report archive and returns it as a blob.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800849
Jon Salza88b83b2013-05-27 20:00:35 +0800850 Args:
851 See CreateReportArchive.
Andy Cheng7a76cb82012-11-19 18:08:19 +0800852
Jon Salza88b83b2013-05-27 20:00:35 +0800853 Returns:
854 An xmlrpclib.Binary object containing a .tar.xz file.
855 """
856 with open(CreateReportArchive(*args, **kwargs)) as f:
857 return xmlrpclib.Binary(f.read())
858
859
860def CreateReportArchive(device_sn=None, add_file=None):
861 """Creates a report archive in a temporary directory.
862
863 Args:
864 device_sn: The device serial number (optional).
865 add_file: A list of files to add (optional).
866
867 Returns:
868 Path to the archive.
869 """
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800870 def NormalizeAsFileName(token):
871 return re.sub(r'\W+', '', token).strip()
Jon Salza88b83b2013-05-27 20:00:35 +0800872
873 target_name = '%s%s.tar.xz' % (
874 time.strftime('%Y%m%dT%H%M%SZ',
875 time.gmtime()),
Hung-Te Lin56b18402015-01-16 14:52:30 +0800876 ('' if device_sn is None else
877 '_' + NormalizeAsFileName(device_sn)))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800878 target_path = os.path.join(gettempdir(), target_name)
Jon Salza88b83b2013-05-27 20:00:35 +0800879
Tammo Spalink86a61c62012-05-25 15:10:35 +0800880 # Intentionally ignoring dotfiles in EVENT_LOG_DIR.
Andy Cheng0465d132013-03-20 12:12:06 +0800881 tar_cmd = 'cd %s ; tar cJf %s *' % (event_log.EVENT_LOG_DIR, target_path)
Joel Kitching4b1b6c02016-05-10 14:34:30 +0800882 tar_cmd += ' --add-file %s' % paths.GetFactoryLogPath()
Jon Salza88b83b2013-05-27 20:00:35 +0800883 if add_file:
884 for f in add_file:
Jon Salz65266432012-07-30 19:02:49 +0800885 # Require absolute paths since the tar command may change the
886 # directory.
887 if not f.startswith('/'):
888 raise Error('Not an absolute path: %s' % f)
889 if not os.path.exists(f):
890 raise Error('File does not exist: %s' % f)
891 tar_cmd += ' --add-file %s' % pipes.quote(f)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800892 cmd_result = Shell(tar_cmd)
Jon Salzff88c022012-11-03 12:19:58 +0800893
894 if ((cmd_result.status == 1) and
895 all((x == '' or
896 'file changed as we read it' in x or
897 "Removing leading `/' from member names" in x)
898 for x in cmd_result.stderr.split('\n'))):
899 # That's OK. Make sure it's valid though.
Vic Yang85199e72013-01-28 14:33:11 +0800900 Spawn(['tar', 'tfJ', target_path], check_call=True, log=True,
Jon Salzff88c022012-11-03 12:19:58 +0800901 ignore_stdout=True)
902 elif not cmd_result.success:
Tammo Spalink86a61c62012-05-25 15:10:35 +0800903 raise Error('unable to tar event logs, cmd %r failed, stderr: %r' %
904 (tar_cmd, cmd_result.stderr))
Jon Salzff88c022012-11-03 12:19:58 +0800905
Jon Salza88b83b2013-05-27 20:00:35 +0800906 return target_path
907
908_upload_method_cmd_arg = CmdArg(
909 '--upload_method', metavar='METHOD:PARAM',
910 help=('How to perform the upload. METHOD should be one of '
911 '{ftp, shopfloor, ftps, cpfe}.'))
912_add_file_cmd_arg = CmdArg(
913 '--add_file', metavar='FILE', action='append',
914 help='Extra file to include in report (must be an absolute path)')
915
Hung-Te Lin56b18402015-01-16 14:52:30 +0800916
Jon Salza88b83b2013-05-27 20:00:35 +0800917@Command('upload_report',
918 _upload_method_cmd_arg,
919 _add_file_cmd_arg)
920def UploadReport(options):
921 """Create a report containing key device details."""
Hung-Te Lin74346d72016-01-07 22:16:57 +0800922 ro_vpd = ReadRoVpd()
Jon Salza88b83b2013-05-27 20:00:35 +0800923 device_sn = ro_vpd.get('serial_number', None)
924 if device_sn is None:
925 logging.warning('RO_VPD missing device serial number')
926 device_sn = 'MISSING_SN_' + event_log.TimedUuid()
927 target_path = CreateReportArchive(device_sn)
928
Tammo Spalink86a61c62012-05-25 15:10:35 +0800929 if options.upload_method is None or options.upload_method == 'none':
930 logging.warning('REPORT UPLOAD SKIPPED (report left at %s)', target_path)
931 return
932 method, param = options.upload_method.split(':', 1)
933 if method == 'shopfloor':
934 report_upload.ShopFloorUpload(target_path, param)
935 elif method == 'ftp':
Jay Kim360c1dd2012-06-25 10:58:11 -0700936 report_upload.FtpUpload(target_path, 'ftp:' + param)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800937 elif method == 'ftps':
938 report_upload.CurlUrlUpload(target_path, '--ftp-ssl-reqd ftp:%s' % param)
939 elif method == 'cpfe':
Shawn Nematbakhsh3404a092013-01-28 16:49:09 -0800940 report_upload.CpfeUpload(target_path, pipes.quote(param))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800941 else:
942 raise Error('unknown report upload method %r', method)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800943
944
945@Command('finalize',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800946 CmdArg('--no_write_protect', action='store_true',
947 help='Do not enable firmware write protection.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800948 CmdArg('--fast', action='store_true',
949 help='use non-secure but faster wipe method.'),
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800950 CmdArg('--wipe_in_place', action='store_true',
951 help='Start factory wiping in place without reboot.'),
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800952 _cutoff_args_cmd_arg,
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800953 _shopfloor_url_args_cmd_arg,
Ricky Liang43b879b2014-02-24 11:36:55 +0800954 _hwid_version_cmd_arg,
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800955 _hwdb_path_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700956 _hwid_status_list_cmd_arg,
Jon Salz65266432012-07-30 19:02:49 +0800957 _upload_method_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800958 _add_file_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800959 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800960 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800961 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800962 _rma_mode_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800963 _cros_core_cmd_arg,
Hung-Te Lincdb96522016-04-15 16:51:10 +0800964 _release_rootfs_cmd_arg,
965 _firmware_path_cmd_arg,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800966 _enforced_release_channels_cmd_arg,
967 _station_ip_cmd_arg,
968 _station_port_cmd_arg,
969 _wipe_finish_token_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800970def Finalize(options):
971 """Verify system readiness and trigger transition into release state.
972
Jon Salzaa3a30e2013-05-15 15:56:28 +0800973 This routine does the following:
974 - Verifies system state (see verify command)
Jon Salzfe9036f2014-01-16 14:11:23 +0800975 - Untars stateful_files.tar.xz, if it exists, in the stateful partition, to
976 initialize files such as the CRX cache
Jon Salzaa3a30e2013-05-15 15:56:28 +0800977 - Modifies firmware bitmaps to match locale
978 - Clears all factory-friendly flags from the GBB
979 - Removes factory-specific entries from RW_VPD (factory.*)
980 - Enables firmware write protection (cannot rollback after this)
981 - Uploads system logs & reports
982 - Sets the necessary boot flags to cause wipe of the factory image on the
983 next boot.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800984 """
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800985 Verify(options)
Jon Salz40b9f822014-07-25 16:39:55 +0800986 LogSourceHashes(options)
Jon Salzfe9036f2014-01-16 14:11:23 +0800987 UntarStatefulFiles(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800988 if options.cros_core:
989 logging.info('SetFirmwareBitmapLocale is skipped for ChromeOS Core device.')
990 else:
991 SetFirmwareBitmapLocale(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800992 ClearGBBFlags(options)
Jon Salzaa3a30e2013-05-15 15:56:28 +0800993 ClearFactoryVPDEntries(options)
Mattias Nisslercca761b2015-04-15 21:53:04 +0200994 GenerateStableDeviceSecret(options)
Hung-Te Lin6d827542012-07-19 11:50:41 +0800995 if options.no_write_protect:
996 logging.warn('WARNING: Firmware Write Protection is SKIPPED.')
Andy Cheng0465d132013-03-20 12:12:06 +0800997 event_log.Log('wp', fw='both', status='skipped')
Hung-Te Lin6d827542012-07-19 11:50:41 +0800998 else:
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800999 EnableFwWp({})
Jon Salza0f58e02012-05-29 19:33:39 +08001000 LogSystemDetails(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001001 UploadReport(options)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +08001002 if options.wipe_in_place:
1003 event_log.Log('wipe_in_place')
Wei-Han Chen0a3320e2016-04-23 01:32:07 +08001004 # WipeInPlace(options)
1005 wipe_args = []
Wei-Han Chen1f02f8f2016-05-31 11:05:24 +08001006 if options.cutoff_args:
1007 wipe_args += ['--cutoff_args', options.cutoff_args]
1008 if options.shopfloor_url:
1009 wipe_args += ['--shopfloor_url', options.shopfloor_url]
Wei-Han Chen0a3320e2016-04-23 01:32:07 +08001010 if options.fast:
1011 wipe_args += ['--fast']
Wei-Han Chenbe1355a2016-04-24 19:31:03 +08001012 if options.station_ip:
1013 wipe_args += ['--station_ip', options.station_ip]
1014 if options.station_port:
1015 wipe_args += ['--station_port', options.station_port]
1016 if options.wipe_finish_token:
1017 wipe_args += ['--wipe_finish_token', options.wipe_finish_token]
Wei-Han Chen0a3320e2016-04-23 01:32:07 +08001018 ExecFactoryPar('gooftool', 'wipe_in_place', *wipe_args)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +08001019 else:
1020 PrepareWipe(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001021
1022
Ricky Liangc662be32013-12-24 11:50:23 +08001023def VerifyHWIDv3(options):
1024 """A simple wrapper that calls out to HWID utils to verify version 3 HWID.
Ricky Liang53390232013-03-08 15:37:57 +08001025
Ricky Liangc662be32013-12-24 11:50:23 +08001026 This is mainly for Gooftool to verify v3 HWID during finalize. For testing
1027 and development purposes, please use `hwid` command.
Ricky Liang53390232013-03-08 15:37:57 +08001028 """
Ricky Liangc662be32013-12-24 11:50:23 +08001029 db = GetGooftool(options).db
1030 encoded_string = options.hwid or hwid_utils.GetHWIDString()
Ricky Liang7905f272013-03-16 01:57:10 +08001031 if options.probe_results:
Ricky Liangc662be32013-12-24 11:50:23 +08001032 probed_results = yaml.load(open(options.probe_results).read())
Ricky Liang7905f272013-03-16 01:57:10 +08001033 else:
Ricky Liangc662be32013-12-24 11:50:23 +08001034 probed_results = yaml.load(Probe(probe_vpd=True).Encode())
1035 vpd = hwid_utils.GetVPD(probed_results)
Ricky Liang53390232013-03-08 15:37:57 +08001036
Hung-Te Lin11052952015-03-18 13:48:59 +08001037 event_log.Log('probed_results', probed_results=FilterDict(probed_results))
1038 event_log.Log('vpd', vpd=FilterDict(vpd))
Ricky Liang53390232013-03-08 15:37:57 +08001039
Ricky Liangc662be32013-12-24 11:50:23 +08001040 hwid_utils.VerifyHWID(db, encoded_string, probed_results, vpd,
Hung-Te Lin56b18402015-01-16 14:52:30 +08001041 rma_mode=options.rma_mode)
Ricky Liang53390232013-03-08 15:37:57 +08001042
Ricky Liangc662be32013-12-24 11:50:23 +08001043 event_log.Log('verified_hwid', hwid=encoded_string)
Ricky Liang53390232013-03-08 15:37:57 +08001044
1045
Ricky Liang59611a62013-06-11 13:47:33 +08001046def ParseDecodedHWID(hwid):
1047 """Parse the HWID object into a more compact dict.
1048
1049 Args:
1050 hwid: A decoded HWID object.
1051
1052 Returns:
1053 A dict containing the board name, the binary string, and the list of
1054 components.
1055 """
1056 results = {}
1057 results['board'] = hwid.database.board
1058 results['binary_string'] = hwid.binary_string
1059 results['components'] = collections.defaultdict(list)
1060 components = hwid.bom.components
1061 for comp_cls in sorted(components):
1062 for (comp_name, probed_values, _) in sorted(components[comp_cls]):
1063 if not probed_values:
1064 db_components = hwid.database.components
1065 probed_values = db_components.GetComponentAttributes(
1066 comp_cls, comp_name).get('values')
1067 results['components'][comp_cls].append(
1068 {comp_name: probed_values if probed_values else None})
1069 # Convert defaultdict to dict.
1070 results['components'] = dict(results['components'])
1071 return results
1072
1073
henryhsu44d793a2013-07-20 00:07:38 +08001074@Command('get_firmware_hash',
1075 CmdArg('--file', metavar='FILE', help='Firmware File.'))
1076def GetFirmwareHash(options):
henryhsuf6f835c2013-07-20 20:49:25 +08001077 """Get firmware hash from a file"""
henryhsu44d793a2013-07-20 00:07:38 +08001078 if os.path.exists(options.file):
1079 hashes = CalculateFirmwareHashes(options.file)
1080 for section, value_dict in hashes.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +08001081 print '%s:' % section
henryhsu44d793a2013-07-20 00:07:38 +08001082 for key, value in value_dict.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +08001083 print ' %s: %s' % (key, value)
henryhsu44d793a2013-07-20 00:07:38 +08001084 else:
1085 raise Error('File does not exist: %s' % options.file)
1086
henryhsuf6f835c2013-07-20 20:49:25 +08001087
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001088def Main():
1089 """Run sub-command specified by the command line args."""
Andy Cheng7a76cb82012-11-19 18:08:19 +08001090
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001091 options = ParseCmdline(
Ricky Liangc662be32013-12-24 11:50:23 +08001092 ('Perform Google required factory tests. All the HWID-related functions '
1093 'provided here are mainly for the deprecated HWID v2. To access HWID '
1094 'v3-related utilities, please use `hwid` command.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001095 CmdArg('-l', '--log', metavar='PATH',
1096 help='Write logs to this file.'),
Jon Salza4bea382012-10-29 13:00:34 +08001097 CmdArg('--suppress-event-logs', action='store_true',
1098 help='Suppress event logging.'),
Wei-Han Chenaff56232016-04-16 09:17:59 +08001099 CmdArg('--phase', default=None,
1100 help=('override phase for phase checking (defaults to the current '
1101 'as returned by the "factory phase" command)')),
Tammo Spalink8fab5312012-05-28 18:33:30 +08001102 verbosity_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001103 SetupLogging(options.verbosity, options.log)
Andy Cheng0465d132013-03-20 12:12:06 +08001104 event_log.SetGlobalLoggerDefaultPrefix('gooftool')
1105 event_log.GetGlobalLogger().suppress = options.suppress_event_logs
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001106 logging.debug('gooftool options: %s', repr(options))
Wei-Han Chenaff56232016-04-16 09:17:59 +08001107
1108 phase.OverridePhase(options.phase)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001109 try:
1110 logging.debug('GOOFTOOL command %r', options.command_name)
1111 options.command(options)
1112 logging.info('GOOFTOOL command %r SUCCESS', options.command_name)
1113 except Error, e:
1114 logging.exception(e)
1115 sys.exit('GOOFTOOL command %r ERROR: %s' % (options.command_name, e))
1116 except Exception, e:
1117 logging.exception(e)
1118 sys.exit('UNCAUGHT RUNTIME EXCEPTION %s' % e)
1119
1120
1121if __name__ == '__main__':
1122 Main()