blob: aadcee77b1c97436aadc35785b073ca08b7368c9 [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
Hung-Te Lin604e0c22015-11-24 15:17:07 +080040from cros.factory.hwid.v2 import hwid_tool
41from cros.factory.hwid.v2.yaml_datastore import YamlWrite
42from cros.factory.hwid.v3 import common
43from cros.factory.hwid.v3 import hwid_utils
Hung-Te Lin91492a12014-11-25 18:56:30 +080044from cros.factory.test import event_log
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +080045from cros.factory.test.env import paths
Wei-Han Chenaff56232016-04-16 09:17:59 +080046from cros.factory.test.rules import phase
Hung-Te Lin3f096842016-01-13 17:37:06 +080047from cros.factory.test.rules.privacy import FilterDict
Hung-Te Lin03bf7ab2016-06-16 17:26:19 +080048from cros.factory.utils.argparse_utils import CmdArg
Hung-Te Lin03bf7ab2016-06-16 17:26:19 +080049from cros.factory.utils.argparse_utils import ParseCmdline
50from cros.factory.utils.argparse_utils import verbosity_cmd_arg
Ting Shen18a06382016-08-30 16:18:21 +080051from cros.factory.utils import argparse_utils
Jon Salz40b9f822014-07-25 16:39:55 +080052from cros.factory.utils import file_utils
Wei-Han Chena5c01a02016-04-23 19:27:19 +080053from cros.factory.utils import sys_utils
Chun-Ta Lin53cbbd52016-06-08 21:42:19 +080054from cros.factory.utils import time_utils
Hung-Te Lin0e0f9362015-11-18 18:18:05 +080055from cros.factory.utils.debug_utils import SetupLogging
Jon Salzff88c022012-11-03 12:19:58 +080056from cros.factory.utils.process_utils import Spawn
Joel Kitchingd3bc2662014-12-16 16:03:32 -080057from cros.factory.utils.type_utils import Error
Tammo Spalink86a61c62012-05-25 15:10:35 +080058
Tammo Spalink5c699832012-07-03 17:50:39 +080059
Tammo Spalink5c699832012-07-03 17:50:39 +080060# TODO(tammo): Replace calls to sys.exit with raise Exit, and maybe
61# treat that specially (as a smoot exit, as opposed to the more
62# verbose output for generic Error).
63
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080064_global_gooftool = None
65_gooftool_lock = threading.Lock()
Tammo Spalink5c699832012-07-03 17:50:39 +080066
Hung-Te Lin56b18402015-01-16 14:52:30 +080067
Ricky Lianga70a1202013-03-15 15:03:17 +080068def GetGooftool(options):
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080069 global _global_gooftool # pylint: disable=W0603
Ricky Lianga70a1202013-03-15 15:03:17 +080070
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080071 if _global_gooftool is None:
72 with _gooftool_lock:
Ricky Liang43b879b2014-02-24 11:36:55 +080073 hwid_version = getattr(options, 'hwid_version', 3)
74 if hwid_version == 2:
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080075 hwdb_path = getattr(options, 'hwdb_path', None)
76 component_db = (
77 hwid_tool.HardwareDb(options.hwdb_path).comp_db if hwdb_path
78 else None)
79 _global_gooftool = Gooftool(hwid_version=2, component_db=component_db)
Ricky Liang43b879b2014-02-24 11:36:55 +080080 elif hwid_version == 3:
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080081 board = getattr(options, 'board', None)
82 hwdb_path = getattr(options, 'hwdb_path', None)
83 _global_gooftool = Gooftool(hwid_version=3, board=board,
84 hwdb_path=hwdb_path)
85 else:
86 raise Error, 'Invalid HWID version: %r' % options.hwid_version
87
88 return _global_gooftool
Ricky Lianga70a1202013-03-15 15:03:17 +080089
Hung-Te Lin56b18402015-01-16 14:52:30 +080090
Ting Shen18a06382016-08-30 16:18:21 +080091def Command(cmd_name, *args, **kwargs):
92 """ Decorator for commands in gooftool.
93
94 This is similar to argparse_utils.Command, but all gooftool commands
95 can be waived during `gooftool finalize` or `gooftool verify` using
96 --waive_list option.
97 """
98 def Decorate(fun):
99 def CommandWithWaiveCheck(options):
100 waive_list = vars(options).get('waive_list', [])
101 if phase.GetPhase() >= phase.PVT_DOGFOOD and waive_list != []:
102 raise Error(
103 'waive_list should be empty for phase %s' % phase.GetPhase())
104
105 try:
106 fun(options)
107 except Exception as e:
108 if cmd_name in waive_list:
109 logging.exception(e)
110 else:
111 raise
112
113 return argparse_utils.Command(cmd_name, *args, **kwargs)(
114 CommandWithWaiveCheck)
115 return Decorate
116
117
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800118@Command('write_hwid',
119 CmdArg('hwid', metavar='HWID', help='HWID string'))
Andy Chengc92e6f92012-11-20 16:55:53 +0800120def WriteHWID(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800121 """Write specified HWID value into the system BB."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800122
Tammo Spalink95c43732012-07-25 15:57:14 -0700123 logging.info('writing hwid string %r', options.hwid)
Ricky Lianga70a1202013-03-15 15:03:17 +0800124 GetGooftool(options).WriteHWID(options.hwid)
Andy Cheng0465d132013-03-20 12:12:06 +0800125 event_log.Log('write_hwid', hwid=options.hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -0700126 print 'Wrote HWID: %r' % options.hwid
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800127
128
Ricky Liang53390232013-03-08 15:37:57 +0800129_board_cmd_arg = CmdArg(
130 '--board', metavar='BOARD',
131 default=None, help='Board name to test.')
132
Tammo Spalink8fab5312012-05-28 18:33:30 +0800133_hwdb_path_cmd_arg = CmdArg(
134 '--hwdb_path', metavar='PATH',
Ricky Liangeede7922013-06-19 10:18:41 +0800135 default=common.DEFAULT_HWID_DATA_PATH,
Tammo Spalink8fab5312012-05-28 18:33:30 +0800136 help='Path to the HWID database.')
137
Tammo Spalink95c43732012-07-25 15:57:14 -0700138_hwid_status_list_cmd_arg = CmdArg(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800139 '--status', nargs='*', default=['supported'],
140 help='allow only HWIDs with these status values')
Tammo Spalink95c43732012-07-25 15:57:14 -0700141
Jon Salzce124fb2012-10-02 17:42:03 +0800142_probe_results_cmd_arg = CmdArg(
143 '--probe_results', metavar='RESULTS.yaml',
Ricky Liangc662be32013-12-24 11:50:23 +0800144 help=('Output from "gooftool probe --include_vpd" (used instead of '
Jon Salzce124fb2012-10-02 17:42:03 +0800145 'probing this system).'))
146
Ricky Liang53390232013-03-08 15:37:57 +0800147_device_info_cmd_arg = CmdArg(
Ricky Liangf89f73a2013-03-19 05:00:24 +0800148 '--device_info', metavar='DEVICE_INFO.yaml', default=None,
Ricky Liang53390232013-03-08 15:37:57 +0800149 help='A dict of device info to use instead of fetching from shopfllor '
150 'server.')
151
Jon Salzce124fb2012-10-02 17:42:03 +0800152_hwid_cmd_arg = CmdArg(
153 '--hwid', metavar='HWID',
Ricky Lianga70a1202013-03-15 15:03:17 +0800154 help='HWID to verify (instead of the currently set HWID of this system).')
Jon Salzce124fb2012-10-02 17:42:03 +0800155
Bernie Thompson3c11c872013-07-22 18:22:45 -0700156_rma_mode_cmd_arg = CmdArg(
157 '--rma_mode', action='store_true',
158 help='Enable RMA mode, do not check for deprecated components.')
Tammo Spalink95c43732012-07-25 15:57:14 -0700159
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800160_cros_core_cmd_arg = CmdArg(
161 '--cros_core', action='store_true',
162 help='Finalize for ChromeOS Core devices (may add or remove few test '
163 'items. For example, branding verification or firmware bitmap '
164 'locale settings).')
165
Ricky Liang43b879b2014-02-24 11:36:55 +0800166_hwid_version_cmd_arg = CmdArg(
167 '-i', '--hwid-version', default=3, choices=(2, 3), type=int,
168 help='Version of HWID to operate on. (default: %(default)s)')
169
bowgotsai13820f42015-09-10 23:18:04 +0800170_enforced_release_channels_cmd_arg = CmdArg(
171 '--enforced_release_channels', nargs='*', default=None,
172 help='Enforced release image channels.')
173
Hung-Te Lincdb96522016-04-15 16:51:10 +0800174_release_rootfs_cmd_arg = CmdArg(
175 '--release_rootfs', help='Location of release image rootfs partition.')
176
177_firmware_path_cmd_arg = CmdArg(
178 '--firmware_path', help='Location of firmware image partition.')
Ricky Liang43b879b2014-02-24 11:36:55 +0800179
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800180_cutoff_args_cmd_arg = CmdArg(
181 '--cutoff_args',
182 help='Battery cutoff arguments to be passed to battery_cutoff.sh '
183 'after wiping. Should be the following format: '
184 '[--method shutdown|reboot|battery_cutoff] '
185 '[--check-ac connect_ac|remove_ac] '
186 '[--min-battery-percent <minimum battery percentage>] '
187 '[--max-battery-percent <maximum battery percentage>] '
188 '[--min-battery-voltage <minimum battery voltage>] '
189 '[--max-battery-voltage <maximum battery voltage>]')
190
191_shopfloor_url_args_cmd_arg = CmdArg(
192 '--shopfloor_url',
193 help='Shopfloor server url to be informed when in-place wipe is done. '
194 'After in-place wipe, a XML-RPC request will be sent to the '
195 'given url to indicate the completion of wipe.')
196
197_station_ip_cmd_arg = CmdArg(
198 '--station_ip',
199 help='IP of remote station')
200
201_station_port_cmd_arg = CmdArg(
202 '--station_port',
203 help='Port on remote station')
204
205_wipe_finish_token_cmd_arg = CmdArg(
206 '--wipe_finish_token',
207 help='Required token when notifying station after wipe finished')
208
Ting Shen18a06382016-08-30 16:18:21 +0800209_waive_list_cmd_arg = CmdArg(
210 '--waive_list', nargs='*', default=[], metavar='SUBCMD',
211 help='A list of waived checks, serperated by whitespace.'
212 'Each item should be a sub-command of gooftool.'
213 'e.g. "gooftool verify --waive_list verify_tpm clear_gbb_flags".')
214
Tammo Spalink95c43732012-07-25 15:57:14 -0700215@Command('best_match_hwids',
Tammo Spalink8fab5312012-05-28 18:33:30 +0800216 _hwdb_path_cmd_arg,
217 CmdArg('-b', '--board', metavar='BOARD',
Tammo Spalink95c43732012-07-25 15:57:14 -0700218 help='optional BOARD name, needed only if data is present '
219 'for more than one'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800220 CmdArg('--bom', metavar='BOM', help='BOM name'),
221 CmdArg('--variant', metavar='VARIANT', help='VARIANT code'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800222 CmdArg('--optimistic', action='store_true',
223 help='do not probe; assume singletons match'),
Tammo Spalink95c43732012-07-25 15:57:14 -0700224 CmdArg('--comps', nargs='*', default=[],
225 help='list of canonical component names'),
226 CmdArg('--missing', nargs='*', default=[],
227 help='list component classes to be assumed missing'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800228 CmdArg('--status', nargs='*', default=['supported'],
Tammo Spalink95c43732012-07-25 15:57:14 -0700229 help='consider only HWIDs within this list of status values'))
230def BestMatchHwids(options):
Ricky Liangc662be32013-12-24 11:50:23 +0800231 """Determine a list of possible HWIDs using provided args and probing.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800232
233 VOLATILE can always be determined by probing. To get a unique
234 result, VARIANT must be specified for all cases where the matching
235 BOM has more than one associated variant code, otherwise all HWID
236 variants will be returned. Both VARIANT and BOM information can
Tammo Spalink95c43732012-07-25 15:57:14 -0700237 alternatively be specified using the --stdin_comps argument, which
238 allows specifying a list of canonical names (one per line) on stdin,
239 one per line. Based on what is known from BOM and stdin_comps,
240 determine a list of components to probe for, and use those probe
241 results to resolve a list of matching HWIDs. If no boms,
242 components, or variant codes are specified, then a list of all HWIDs
Andy Cheng8ece7382012-08-22 16:25:42 +0800243 that match probeable components will be returned.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800244
245 Returns (on stdout): A list of HWIDs that match the available probe
246 results and argument contraints, one per line.
Tammo Spalink70b48a52012-08-08 16:54:51 -0700247
248 Example:
249
250 // Three ways to specify a keyboard (assuming it is a variant component)
251 gooftool best_match_hwids --missing keyboard
252 gooftool best_match_hwids --variant A or
253 gooftool best_match_hwids --comps us_kbd
Tammo Spalink8fab5312012-05-28 18:33:30 +0800254 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800255
Tammo Spalink5c699832012-07-03 17:50:39 +0800256 map(hwid_tool.Validate.Status, options.status)
Tammo Spalink95c43732012-07-25 15:57:14 -0700257 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Tammo Spalink5c699832012-07-03 17:50:39 +0800258 comp_db = hw_db.comp_db
Tammo Spalink3a7e9022012-06-27 14:08:40 +0800259 device = hw_db.GetDevice(options.board)
Tammo Spalink5c699832012-07-03 17:50:39 +0800260 component_spec = hwid_tool.ComponentSpec.New()
Tammo Spalink8fab5312012-05-28 18:33:30 +0800261 if options.bom:
Tammo Spalink5c699832012-07-03 17:50:39 +0800262 device.BomExists(options.bom)
Tammo Spalink01e11722012-07-24 10:17:54 -0700263 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800264 component_spec, device.boms[options.bom].primary)
Tammo Spalink8fab5312012-05-28 18:33:30 +0800265 if options.variant:
Tammo Spalink5c699832012-07-03 17:50:39 +0800266 device.VariantExists(options.variant)
267 variant_spec = device.variants[options.variant]
Tammo Spalink01e11722012-07-24 10:17:54 -0700268 if hwid_tool.ComponentSpecsConflict(component_spec, variant_spec):
Tammo Spalink95c43732012-07-25 15:57:14 -0700269 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700270 % YamlWrite(sorted(
271 hwid_tool.ComponentSpecClasses(component_spec) &
272 hwid_tool.ComponentSpecClasses(variant_spec))))
Tammo Spalink01e11722012-07-24 10:17:54 -0700273 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800274 component_spec, variant_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700275 if options.comps or options.missing:
276 map(comp_db.CompExists, options.comps)
277 map(comp_db.CompClassExists, options.missing)
278 extra_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800279 components=options.comps,
280 missing=options.missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700281 print 'cmdline asserted components:\n%s' % extra_comp_spec.Encode()
282 if hwid_tool.ComponentSpecsConflict(component_spec, extra_comp_spec):
283 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700284 % YamlWrite(sorted(
285 hwid_tool.ComponentSpecClasses(component_spec) &
286 hwid_tool.ComponentSpecClasses(extra_comp_spec))))
Tammo Spalink95c43732012-07-25 15:57:14 -0700287 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800288 component_spec, extra_comp_spec)
Tammo Spalink01e11722012-07-24 10:17:54 -0700289 spec_classes = hwid_tool.ComponentSpecClasses(component_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700290 missing_classes = set(comp_db.all_comp_classes) - spec_classes
Tammo Spalink5c699832012-07-03 17:50:39 +0800291 if missing_classes and not options.optimistic:
Andy Cheng8ece7382012-08-22 16:25:42 +0800292 non_probeable_missing = missing_classes - PROBEABLE_COMPONENT_CLASSES
293 if non_probeable_missing:
Tammo Spalink95c43732012-07-25 15:57:14 -0700294 sys.exit('FAILURE: these classes are necessary, were not specified '
Tammo Spalink70b48a52012-08-08 16:54:51 -0700295 'as inputs, and cannot be probed for:\n%s'
296 'This problem can often be addressed by specifying all of '
297 'the missing components on the command line (see the command '
Andy Cheng8ece7382012-08-22 16:25:42 +0800298 'help).' % YamlWrite(list(non_probeable_missing)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700299 print 'probing for missing classes:'
300 print YamlWrite(list(missing_classes))
301 probe_results = Probe(target_comp_classes=list(missing_classes),
302 probe_volatile=False, probe_initial_config=False)
303 cooked_components = comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800304 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700305 if cooked_components.unmatched:
306 sys.exit('ERROR: some probed components are unrecognized:\n%s'
307 % YamlWrite(cooked_components.unmatched))
308 probed_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800309 components=cooked_components.matched,
310 missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700311 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800312 component_spec, probed_comp_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700313 print YamlWrite({'component data used for matching': {
Hung-Te Lin56b18402015-01-16 14:52:30 +0800314 'missing component classes': component_spec.classes_missing,
315 'found components': component_spec.components}})
Tammo Spalink95c43732012-07-25 15:57:14 -0700316 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800317 extant_components=hwid_tool.ComponentSpecCompClassMap(
318 component_spec).keys(),
319 classes_missing=component_spec.classes_missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700320 match_tree = device.BuildMatchTree(component_data)
321 if not match_tree:
322 sys.exit('FAILURE: NO matching BOMs found')
323 print 'potential BOMs/VARIANTs:'
324 potential_variants = set()
325 potential_volatiles = set()
326 for bom_name, variant_tree in match_tree.items():
327 print ' BOM: %-8s VARIANTS: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800328 bom_name, ', '.join(sorted(variant_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700329 for variant_code in variant_tree:
330 potential_variants.add(variant_code)
331 for volatile_code in device.volatiles:
332 status = device.GetHwidStatus(bom_name, variant_code, volatile_code)
333 if status in options.status:
334 potential_volatiles.add(volatile_code)
335 print ''
336 if len(potential_variants) == 0:
337 sys.exit('FAILURE: no matching VARIANTs found')
338 if len(potential_volatiles) == 0:
339 sys.exit('FAILURE: no VOLATILEs found for potential matching BOMs/VARIANTS '
340 '(with specified status)')
Tammo Spalink394e4492012-08-01 10:20:30 -0700341 if (options.optimistic and
342 len(match_tree) == 1 and
343 len(potential_variants) == 1 and
344 len(potential_volatiles) == 1):
345 print ('MATCHING HWID: %s' % device.FmtHwid(match_tree.keys().pop(),
346 potential_variants.pop(),
347 potential_volatiles.pop()))
Tammo Spalink5c699832012-07-03 17:50:39 +0800348 return
Tammo Spalink95c43732012-07-25 15:57:14 -0700349 print ('probing VOLATILEs to resolve potential matches: %s\n' %
350 ', '.join(sorted(potential_volatiles)))
351 vol_probe_results = Probe(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800352 target_comp_classes=[],
353 probe_volatile=True,
354 probe_initial_config=False)
Tammo Spalink95c43732012-07-25 15:57:14 -0700355 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800356 vol_probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700357 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800358 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700359 matched_hwids = device.GetMatchTreeHwids(match_tree)
360 if matched_hwids:
361 for hwid in matched_hwids:
Ricky Liang02f3bd72012-09-21 14:33:01 +0800362 if matched_hwids[hwid] in options.status:
363 print 'MATCHING HWID: %s' % hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700364 return
365 print 'exact HWID matching failed, but the following BOMs match: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800366 ', '.join(sorted(match_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700367 if options.optimistic and len(match_tree) == 1:
368 bom_name = set(match_tree).pop()
Tammo Spalink5c699832012-07-03 17:50:39 +0800369 bom = device.boms[bom_name]
Tammo Spalink95c43732012-07-25 15:57:14 -0700370 variant_matches = match_tree[bom_name]
Tammo Spalink5c699832012-07-03 17:50:39 +0800371 if len(variant_matches) == 1:
372 var_code = set(variant_matches).pop()
373 elif len(bom.variants) == 1:
374 var_code = set(bom.variants).pop()
375 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700376 sys.exit('FAILURE: NO matching HWIDs found; optimistic matching failed '
377 'because there were too many variants to choose from for BOM %r'
378 % bom_name)
379 hwids = [device.FmtHwid(bom_name, var_code, vol_code)
380 for vol_code in device.volatiles
381 if device.GetHwidStatus(bom_name, var_code, vol_code)
382 in options.status]
383 for hwid in hwids:
384 print 'MATCHING HWID: %s' % hwid
Tammo Spalink5c699832012-07-03 17:50:39 +0800385 return
386 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700387 print ('optimistic matching not attempted because either it was '
388 'not requested, or because the number of BOMs was <> 1\n')
389 sys.exit('FAILURE: NO matching HWIDs found')
Tammo Spalink8fab5312012-05-28 18:33:30 +0800390
391
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800392@Command('probe',
393 CmdArg('--comps', nargs='*',
394 help='List of keys from the component_db registry.'),
Ricky Liangb30da672013-06-14 12:36:34 +0800395 CmdArg('--fast_fw_probe', action='store_true',
396 help='Do a fast probe for EC and main firmware versions only. '
397 'This implies --no_vol and --no_ic.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800398 CmdArg('--no_vol', action='store_true',
399 help='Do not probe volatile data.'),
400 CmdArg('--no_ic', action='store_true',
Jon Salz0f8a6842012-09-25 11:28:22 +0800401 help='Do not probe initial_config data.'),
402 CmdArg('--include_vpd', action='store_true',
403 help='Include VPD data in volatiles.'))
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800404def RunProbe(options):
405 """Print yaml-formatted breakdown of probed device properties."""
Ricky Lianga70a1202013-03-15 15:03:17 +0800406 print GetGooftool(options).Probe(
407 target_comp_classes=options.comps,
Ricky Liangb30da672013-06-14 12:36:34 +0800408 fast_fw_probe=options.fast_fw_probe,
Ricky Lianga70a1202013-03-15 15:03:17 +0800409 probe_volatile=not options.no_vol,
410 probe_initial_config=not options.no_ic,
411 probe_vpd=options.include_vpd).Encode()
Ricky Liang53390232013-03-08 15:37:57 +0800412
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800413
Tammo Spalink214caf42012-05-28 10:45:00 +0800414@Command('verify_components',
415 _hwdb_path_cmd_arg,
Tammo Spalink5c699832012-07-03 17:50:39 +0800416 CmdArg('target_comps', nargs='*'))
Tammo Spalink214caf42012-05-28 10:45:00 +0800417def VerifyComponents(options):
Andy Cheng8ece7382012-08-22 16:25:42 +0800418 """Verify that probeable components all match entries in the component_db.
Tammo Spalink214caf42012-05-28 10:45:00 +0800419
Tammo Spalink5c699832012-07-03 17:50:39 +0800420 Probe for each component class in the target_comps and verify
Tammo Spalink214caf42012-05-28 10:45:00 +0800421 that a corresponding match exists in the component_db -- make sure
422 that these components are present, that they have been approved, but
423 do not check against any specific BOM/HWID configurations.
424 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800425
Andy Chengc531e2f2012-10-15 19:09:17 +0800426 try:
Ricky Lianga70a1202013-03-15 15:03:17 +0800427 result = GetGooftool(options).VerifyComponents(
Andy Chengc531e2f2012-10-15 19:09:17 +0800428 options.target_comps)
429 except ValueError, e:
430 sys.exit(e)
431
Ricky Liang53390232013-03-08 15:37:57 +0800432 PrintVerifyComponentsResults(result)
433
434
435def PrintVerifyComponentsResults(result):
436 """Prints out the results of VerifyComponents method call.
437
438 Groups the results into two groups: 'matches' and 'errors', and prints out
439 their values.
440 """
Andy Chengc531e2f2012-10-15 19:09:17 +0800441 # group by matches and errors
Tammo Spalink214caf42012-05-28 10:45:00 +0800442 matches = []
Andy Chengc531e2f2012-10-15 19:09:17 +0800443 errors = []
444 for result_list in result.values():
445 for component_name, _, error in result_list:
446 if component_name:
447 matches.append(component_name)
Tammo Spalink214caf42012-05-28 10:45:00 +0800448 else:
Andy Chengc531e2f2012-10-15 19:09:17 +0800449 errors.append(error)
450
Andy Cheng228a8c92012-08-27 10:53:57 +0800451 if matches:
452 print 'found probeable components:\n %s' % '\n '.join(matches)
Tammo Spalink214caf42012-05-28 10:45:00 +0800453 if errors:
Andy Cheng228a8c92012-08-27 10:53:57 +0800454 print '\nerrors:\n %s' % '\n '.join(errors)
455 sys.exit('\ncomponent verification FAILURE')
Tammo Spalink214caf42012-05-28 10:45:00 +0800456 else:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800457 print '\ncomponent verification SUCCESS'
Tammo Spalink214caf42012-05-28 10:45:00 +0800458
459
Ricky Liang43b879b2014-02-24 11:36:55 +0800460@Command('verify_hwid_v2',
Tammo Spalink95c43732012-07-25 15:57:14 -0700461 _hwid_status_list_cmd_arg,
Jon Salz0f8a6842012-09-25 11:28:22 +0800462 _hwdb_path_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800463 _probe_results_cmd_arg,
464 _hwid_cmd_arg)
Ricky Liang43b879b2014-02-24 11:36:55 +0800465def VerifyHWIDv2(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800466 """Verify system HWID properties match probed device properties.
467
468 First probe components, volatile and initial_config parameters for
469 the DUT. Then use the available device data to produce a list of
470 candidate HWIDs. Then verify the HWID from the DUT is present in
471 that list. Then verify that the DUT initial config values match
472 those specified for its HWID. Finally, verify that VPD contains all
473 the necessary fields as specified by the board data, and when
474 possible verify that values are legitimate.
475 """
Ricky Liangf7857c12012-09-17 13:34:41 +0800476 def VerifyVpd(ro_vpd_keys, rw_vpd_keys):
Tammo Spalink5c699832012-07-03 17:50:39 +0800477 for key in ro_vpd_keys:
478 if key not in ro_vpd:
Ricky Liangf7857c12012-09-17 13:34:41 +0800479 sys.exit('Missing required RO VPD field: %s' % key)
Tammo Spalink01e11722012-07-24 10:17:54 -0700480 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800481 value = ro_vpd[key]
Ricky Liangf7857c12012-09-17 13:34:41 +0800482 if (known_valid_values is not None) and (value not in known_valid_values):
483 sys.exit('Invalid RO VPD entry : key %r, value %r' % (key, value))
Ricky Liangf7857c12012-09-17 13:34:41 +0800484 for key in rw_vpd_keys:
485 if key not in rw_vpd:
486 sys.exit('Missing required RW VPD field: %s' % key)
487 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
488 value = rw_vpd[key]
489 if (known_valid_values is not None) and (value not in known_valid_values):
490 sys.exit('Invalid RW VPD entry : key %r, value %r' % (key, value))
Andy Cheng0465d132013-03-20 12:12:06 +0800491 event_log.Log('vpd', ro_vpd=FilterDict(ro_vpd), rw_vpd=FilterDict(rw_vpd))
Tammo Spalink5c699832012-07-03 17:50:39 +0800492 map(hwid_tool.Validate.Status, options.status)
Jon Salz0f8a6842012-09-25 11:28:22 +0800493
Jon Salz0f8a6842012-09-25 11:28:22 +0800494 if options.hwid:
495 hwid_str = options.hwid
496 else:
Hung-Te Lin74346d72016-01-07 22:16:57 +0800497 main_fw_file = crosfw.LoadMainFirmware().GetFileName()
Jon Salz0f8a6842012-09-25 11:28:22 +0800498 gbb_result = Shell('gbb_utility -g --hwid %s' % main_fw_file).stdout
499 hwid_str = re.findall(r'hardware_id:(.*)', gbb_result)[0].strip()
Tammo Spalink95c43732012-07-25 15:57:14 -0700500 hwid = hwid_tool.ParseHwid(hwid_str)
Tammo Spalink5c699832012-07-03 17:50:39 +0800501 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Jon Salz0f8a6842012-09-25 11:28:22 +0800502 print 'Verifying HWID: %r\n' % hwid.hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700503 device = hw_db.GetDevice(hwid.board)
504 hwid_status = device.GetHwidStatus(hwid.bom, hwid.variant, hwid.volatile)
505 if hwid_status not in options.status:
Tammo Spalink5c699832012-07-03 17:50:39 +0800506 sys.exit('HWID status must be one of [%s], found %r' %
Hung-Te Lin4f5beb12012-08-20 14:48:06 +0800507 (', '.join(options.status), hwid_status))
Jon Salz0f8a6842012-09-25 11:28:22 +0800508 if options.probe_results:
509 # Pull in probe results (including VPD data) from the given file
510 # rather than probing the current system.
511 probe_results = hwid_tool.ProbeResults.Decode(
512 open(options.probe_results).read())
513 ro_vpd = {}
514 rw_vpd = {}
515 for k, v in probe_results.found_volatile_values.items():
Hung-Te Lin56b18402015-01-16 14:52:30 +0800516 match = re.match(r'^vpd\.(ro|rw)\.(\w+)$', k)
Jon Salz0f8a6842012-09-25 11:28:22 +0800517 if match:
518 del probe_results.found_volatile_values[k]
519 (ro_vpd if match.group(1) == 'ro' else rw_vpd)[match.group(2)] = v
520 else:
521 probe_results = Probe()
Hung-Te Lin74346d72016-01-07 22:16:57 +0800522 ro_vpd = ReadRoVpd()
523 rw_vpd = ReadRwVpd()
Tammo Spalink95c43732012-07-25 15:57:14 -0700524 cooked_components = hw_db.comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800525 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700526 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800527 probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700528 cooked_initial_configs = device.MatchInitialConfigValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800529 probe_results.initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700530 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800531 extant_components=cooked_components.matched,
532 classes_missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700533 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800534 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700535 matched_hwids = device.GetMatchTreeHwids(match_tree)
536 print 'HWID status: %s\n' % hwid_status
537 print 'probed system components:'
538 print YamlWrite(cooked_components.__dict__)
539 print 'missing component classes:'
540 print YamlWrite(probe_results.missing_component_classes)
541 print 'probed volatiles:'
542 print YamlWrite(cooked_volatiles.__dict__)
543 print 'probed initial_configs:'
544 print YamlWrite(cooked_initial_configs)
545 print 'hwid match tree:'
546 print YamlWrite(match_tree)
Andy Cheng0465d132013-03-20 12:12:06 +0800547 event_log.Log(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800548 'probe',
549 found_components=cooked_components.__dict__,
550 missing_component_classes=probe_results.missing_component_classes,
551 volatiles=cooked_volatiles.__dict__,
552 initial_configs=cooked_initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700553 if hwid.hwid not in matched_hwids:
Tammo Spalink5c699832012-07-03 17:50:39 +0800554 err_msg = 'HWID verification FAILED.\n'
Tammo Spalink95c43732012-07-25 15:57:14 -0700555 if cooked_components.unmatched:
Tammo Spalink5c699832012-07-03 17:50:39 +0800556 sys.exit(err_msg + 'some components could not be indentified:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700557 YamlWrite(cooked_components.unmatched))
558 if not match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800559 sys.exit(err_msg + 'no matching boms were found for components:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700560 component_data.Encode())
561 if hwid.bom not in match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800562 sys.exit(err_msg + 'matching boms [%s] do not include target bom %r' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700563 (', '.join(sorted(match_tree)), hwid.bom))
564 err_msg += 'target bom %r matches components' % hwid.bom
565 if hwid.bom not in device.IntersectBomsAndInitialConfigs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800566 cooked_initial_configs):
Tammo Spalink5c699832012-07-03 17:50:39 +0800567 sys.exit(err_msg + ', but failed initial config verification')
Tammo Spalink95c43732012-07-25 15:57:14 -0700568 matched_variants = match_tree.get(hwid.bom, {})
569 if hwid.variant not in matched_variants:
Tammo Spalink5c699832012-07-03 17:50:39 +0800570 sys.exit(err_msg + ', but target variant_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700571 hwid.variant)
572 matched_volatiles = matched_variants.get(hwid.variant, {})
573 if hwid.volatile not in matched_volatiles:
Tammo Spalink5c699832012-07-03 17:50:39 +0800574 sys.exit(err_msg + ', but target volatile_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700575 hwid.volatile)
576 found_status = matched_volatiles.get(hwid.volatile, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800577 sys.exit(err_msg + ', but hwid status %r was unacceptable' % found_status)
Ricky Liangf7857c12012-09-17 13:34:41 +0800578 VerifyVpd(device.vpd_ro_fields, device.vpd_rw_fields)
Andy Cheng0465d132013-03-20 12:12:06 +0800579 event_log.Log('verified_hwid', hwid=hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -0700580 print 'Verification SUCCESS!'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800581
582
Hung-Te Line1d80f62016-03-31 14:58:13 +0800583@Command('verify_keys',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800584 _release_rootfs_cmd_arg,
585 _firmware_path_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700586def VerifyKeys(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800587 """Verify keys in firmware and SSD match."""
Hung-Te Line1d80f62016-03-31 14:58:13 +0800588 return GetGooftool(options).VerifyKeys(
Hung-Te Lincdb96522016-04-15 16:51:10 +0800589 options.release_rootfs, options.firmware_path)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800590
591
592@Command('set_fw_bitmap_locale')
Tammo Spalink01e11722012-07-24 10:17:54 -0700593def SetFirmwareBitmapLocale(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800594 """Use VPD locale value to set firmware bitmap default language."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800595
Ricky Lianga70a1202013-03-15 15:03:17 +0800596 (index, locale) = GetGooftool(options).SetFirmwareBitmapLocale()
Andy Cheng2582d292012-12-04 17:38:28 +0800597 logging.info('Firmware bitmap initial locale set to %d (%s).',
598 index, locale)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800599
600
Hung-Te Line1d80f62016-03-31 14:58:13 +0800601@Command('verify_system_time',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800602 _release_rootfs_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700603def VerifySystemTime(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800604 """Verify system time is later than release filesystem creation time."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800605
Hung-Te Lincdb96522016-04-15 16:51:10 +0800606 return GetGooftool(options).VerifySystemTime(options.release_rootfs)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800607
608
Hung-Te Line1d80f62016-03-31 14:58:13 +0800609@Command('verify_rootfs',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800610 _release_rootfs_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700611def VerifyRootFs(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800612 """Verify rootfs on SSD is valid by checking hash."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800613
Hung-Te Line1d80f62016-03-31 14:58:13 +0800614 return GetGooftool(options).VerifyRootFs(options.release_rootfs)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800615
Hung-Te Lin56b18402015-01-16 14:52:30 +0800616
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800617@Command('verify_tpm')
618def VerifyTPM(options): # pylint: disable=W0613
619 """Verify TPM is cleared."""
620
621 return GetGooftool(options).VerifyTPM()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800622
Hung-Te Lin56b18402015-01-16 14:52:30 +0800623
Hung-Te Lindd708d42014-07-11 17:05:01 +0800624@Command('verify_me_locked')
625def VerifyManagementEngineLocked(options): # pylint: disable=W0613
626 """Verify Managment Engine is locked."""
627
628 return GetGooftool(options).VerifyManagementEngineLocked()
629
Hung-Te Lin56b18402015-01-16 14:52:30 +0800630
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800631@Command('verify_switch_wp')
Andy Chengc92e6f92012-11-20 16:55:53 +0800632def VerifyWPSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800633 """Verify hardware write protection switch is enabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800634
Ricky Lianga70a1202013-03-15 15:03:17 +0800635 GetGooftool(options).VerifyWPSwitch()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800636
637
638@Command('verify_switch_dev')
Tammo Spalink01e11722012-07-24 10:17:54 -0700639def VerifyDevSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800640 """Verify developer switch is disabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800641
Ricky Lianga70a1202013-03-15 15:03:17 +0800642 if GetGooftool(options).CheckDevSwitchForDisabling():
Hung-Te Lind7d34722012-07-26 16:48:35 +0800643 logging.warn('VerifyDevSwitch: No physical switch.')
Andy Cheng0465d132013-03-20 12:12:06 +0800644 event_log.Log('switch_dev', type='virtual switch')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800645
646
Jon Salzadd90d32014-04-29 16:16:27 +0800647@Command('verify_branding')
648def VerifyBranding(options): # pylint: disable=W0613
649 """Verify that branding fields are properly set.
650
651 customization_id, if set in the RO VPD, must be of the correct format.
652
653 rlz_brand_code must be set either in the RO VPD or OEM partition, and must
654 be of the correct format.
655 """
656 return GetGooftool(options).VerifyBranding()
657
658
bowgotsai13820f42015-09-10 23:18:04 +0800659@Command('verify_release_channel',
660 _enforced_release_channels_cmd_arg)
bowgotsai529139c2015-05-30 01:39:49 +0800661def VerifyReleaseChannel(options): # pylint: disable=W0613
662 """Verify that release image channel is correct.
663
664 ChromeOS has four channels: canary, dev, beta and stable.
665 The last three channels support image auto-updates, checks
666 that release image channel is one of them.
667 """
bowgotsai13820f42015-09-10 23:18:04 +0800668 return GetGooftool(options).VerifyReleaseChannel(
669 options.enforced_release_channels)
bowgotsai529139c2015-05-30 01:39:49 +0800670
671
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800672@Command('write_protect')
Tammo Spalink01e11722012-07-24 10:17:54 -0700673def EnableFwWp(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800674 """Enable then verify firmware write protection."""
675
Hung-Te Linb21c6682012-08-01 13:53:57 +0800676 def CalculateLegacyRange(fw_type, length, section_data,
677 section_name):
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800678 ro_size = length / 2
679 ro_a = int(section_data[0] / ro_size)
680 ro_b = int((section_data[0] + section_data[1] - 1) / ro_size)
681 if ro_a != ro_b:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800682 raise Error('%s firmware section %s has illegal size' %
Hung-Te Linb21c6682012-08-01 13:53:57 +0800683 (fw_type, section_name))
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800684 ro_offset = ro_a * ro_size
685 return (ro_offset, ro_size)
686
687 def WriteProtect(fw_file_path, fw_type, legacy_section):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800688 """Calculate protection size, then invoke flashrom.
689
690 Our supported chips only allow write protecting half their total
691 size, so we parition the flash chipset space accordingly.
692 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800693
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800694 raw_image = open(fw_file_path, 'rb').read()
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800695 wp_section = 'WP_RO'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800696 image = crosfw.FirmwareImage(raw_image)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800697 if image.has_section(wp_section):
698 section_data = image.get_section_area(wp_section)
699 ro_offset = section_data[0]
700 ro_size = section_data[1]
701 elif image.has_section(legacy_section):
702 section_data = image.get_section_area(legacy_section)
703 (ro_offset, ro_size) = CalculateLegacyRange(
Hung-Te Linb21c6682012-08-01 13:53:57 +0800704 fw_type, len(raw_image), section_data, legacy_section)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800705 else:
706 raise Error('could not find %s firmware section %s or %s' %
707 (fw_type, wp_section, legacy_section))
708
709 logging.debug('write protecting %s [off=%x size=%x]', fw_type,
710 ro_offset, ro_size)
711 crosfw.Flashrom(fw_type).EnableWriteProtection(ro_offset, ro_size)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800712
713 WriteProtect(crosfw.LoadMainFirmware().GetFileName(), 'main', 'RO_SECTION')
Andy Cheng0465d132013-03-20 12:12:06 +0800714 event_log.Log('wp', fw='main')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800715 ec_fw_file = crosfw.LoadEcFirmware().GetFileName()
716 if ec_fw_file is not None:
717 WriteProtect(ec_fw_file, 'ec', 'EC_RO')
Andy Cheng0465d132013-03-20 12:12:06 +0800718 event_log.Log('wp', fw='ec')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800719 else:
720 logging.warning('EC not write protected (seems there is no EC flash).')
721
722
723@Command('clear_gbb_flags')
Andy Chengc92e6f92012-11-20 16:55:53 +0800724def ClearGBBFlags(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800725 """Zero out the GBB flags, in preparation for transition to release state.
726
727 No GBB flags are set in release/shipping state, but they are useful
728 for factory/development. See "gbb_utility --flags" for details.
729 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800730
Ricky Lianga70a1202013-03-15 15:03:17 +0800731 GetGooftool(options).ClearGBBFlags()
Andy Cheng0465d132013-03-20 12:12:06 +0800732 event_log.Log('clear_gbb_flags')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800733
734
Jon Salzaa3a30e2013-05-15 15:56:28 +0800735@Command('clear_factory_vpd_entries')
736def ClearFactoryVPDEntries(options): # pylint: disable=W0613
737 """Clears factory.* items in the RW VPD."""
738 entries = GetGooftool(options).ClearFactoryVPDEntries()
739 event_log.Log('clear_factory_vpd_entries', entries=FilterDict(entries))
740
741
Mattias Nisslercca761b2015-04-15 21:53:04 +0200742@Command('generate_stable_device_secret')
743def GenerateStableDeviceSecret(options): # pylint: disable=W0613
744 """Generates a a fresh stable device secret and stores it in the RO VPD."""
745 GetGooftool(options).GenerateStableDeviceSecret()
746 event_log.Log('generate_stable_device_secret')
747
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800748
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800749@Command('wipe_in_place',
750 CmdArg('--fast', action='store_true',
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800751 help='use non-secure but faster wipe method.'),
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800752 _cutoff_args_cmd_arg,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800753 _shopfloor_url_args_cmd_arg,
754 _station_ip_cmd_arg,
755 _station_port_cmd_arg,
756 _wipe_finish_token_cmd_arg)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800757def WipeInPlace(options):
758 """Start factory wipe directly without reboot."""
759
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800760 GetGooftool(options).WipeInPlace(options.fast,
761 options.cutoff_args,
762 options.shopfloor_url,
763 options.station_ip,
764 options.station_port,
765 options.wipe_finish_token)
Mattias Nisslercca761b2015-04-15 21:53:04 +0200766
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800767@Command('wipe_init',
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800768 CmdArg('--wipe_args', help='arguments for clobber-state'),
769 CmdArg('--state_dev', help='path to stateful partition device'),
770 CmdArg('--root_disk', help='path to primary device'),
771 CmdArg('--old_root', help='path to old root'),
772 _cutoff_args_cmd_arg,
773 _shopfloor_url_args_cmd_arg,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800774 _release_rootfs_cmd_arg,
775 _station_ip_cmd_arg,
776 _station_port_cmd_arg,
777 _wipe_finish_token_cmd_arg)
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800778def WipeInit(options):
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800779 GetGooftool(options).WipeInit(options.wipe_args,
780 options.cutoff_args,
781 options.shopfloor_url,
782 options.state_dev,
783 options.release_rootfs,
784 options.root_disk,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800785 options.old_root,
786 options.station_ip,
787 options.station_port,
788 options.wipe_finish_token)
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800789
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800790@Command('prepare_wipe',
791 CmdArg('--fast', action='store_true',
792 help='use non-secure but faster wipe method.'))
793def PrepareWipe(options):
794 """Prepare system for transition to release state in next reboot."""
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800795
Ricky Lianga70a1202013-03-15 15:03:17 +0800796 GetGooftool(options).PrepareWipe(options.fast)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800797
Hung-Te Lin56b18402015-01-16 14:52:30 +0800798
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800799@Command('verify',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800800 CmdArg('--no_write_protect', action='store_true',
801 help='Do not check write protection switch state.'),
Ricky Liang43b879b2014-02-24 11:36:55 +0800802 _hwid_version_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700803 _hwid_status_list_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800804 _hwdb_path_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800805 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800806 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800807 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800808 _rma_mode_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800809 _cros_core_cmd_arg,
Hung-Te Lincdb96522016-04-15 16:51:10 +0800810 _release_rootfs_cmd_arg,
811 _firmware_path_cmd_arg,
Ting Shen18a06382016-08-30 16:18:21 +0800812 _enforced_release_channels_cmd_arg,
813 _waive_list_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800814def Verify(options):
815 """Verifies if whole factory process is ready for finalization.
816
817 This routine performs all the necessary checks to make sure the
818 device is ready to be finalized, but does not modify state. These
819 checks include dev switch, firmware write protection switch, hwid,
820 system time, keys, and root file system.
821 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800822
Hung-Te Lin6d827542012-07-19 11:50:41 +0800823 if not options.no_write_protect:
Ricky Lianga70a1202013-03-15 15:03:17 +0800824 VerifyWPSwitch(options)
Hung-Te Lindd708d42014-07-11 17:05:01 +0800825 VerifyManagementEngineLocked(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800826 VerifyDevSwitch(options)
827 if options.hwid_version == 2:
Ricky Liang43b879b2014-02-24 11:36:55 +0800828 VerifyHWIDv2(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800829 elif options.hwid_version == 3:
Ricky Liangc662be32013-12-24 11:50:23 +0800830 VerifyHWIDv3(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800831 else:
832 raise Error, 'Invalid HWID version: %r' % options.hwid_version
833 VerifySystemTime(options)
834 VerifyKeys(options)
835 VerifyRootFs(options)
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800836 VerifyTPM(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800837 if options.cros_core:
838 logging.info('VerifyBranding is skipped for ChromeOS Core device.')
839 else:
840 VerifyBranding(options)
bowgotsai529139c2015-05-30 01:39:49 +0800841 VerifyReleaseChannel(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800842
Hung-Te Lin56b18402015-01-16 14:52:30 +0800843
Jon Salzfe9036f2014-01-16 14:11:23 +0800844@Command('untar_stateful_files')
Hung-Te Lin388bce22014-06-03 19:56:40 +0800845def UntarStatefulFiles(unused_options):
Jon Salzfe9036f2014-01-16 14:11:23 +0800846 """Untars stateful files from stateful_files.tar.xz on stateful partition.
847
848 If that file does not exist (which should only be R30 and earlier),
849 this is a no-op.
850 """
Hung-Te Lin2333f3f2016-08-24 17:56:48 +0800851 # Path to stateful partition on device.
852 device_stateful_path = '/mnt/stateful_partition'
853 tar_file = os.path.join(device_stateful_path, 'stateful_files.tar.xz')
Jon Salzfe9036f2014-01-16 14:11:23 +0800854 if os.path.exists(tar_file):
Hung-Te Lin2333f3f2016-08-24 17:56:48 +0800855 Spawn(['tar', 'xf', tar_file], cwd=device_stateful_path,
Jon Salzfe9036f2014-01-16 14:11:23 +0800856 log=True, check_call=True)
857 else:
858 logging.warning('No stateful files at %s', tar_file)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800859
Jon Salz40b9f822014-07-25 16:39:55 +0800860
861@Command('log_source_hashes')
862def LogSourceHashes(options): # pylint: disable=W0613
863 """Logs hashes of source files in the factory toolkit."""
Jon Salze60307f2014-08-05 16:20:00 +0800864 # WARNING: The following line is necessary to validate the integrity
865 # of the factory software. Do not remove or modify it.
866 #
867 # 警告:此行会验证工厂软件的完整性,禁止删除或修改。
Wei-Han Chena5c01a02016-04-23 19:27:19 +0800868 factory_par = sys_utils.GetRunningFactoryPythonArchivePath()
869 if factory_par:
870 event_log.Log(
871 'source_hashes',
872 **file_utils.HashPythonArchive(factory_par))
873 else:
874 event_log.Log(
875 'source_hashes',
876 **file_utils.HashSourceTree(os.path.join(paths.FACTORY_PATH, 'py')))
Jon Salz40b9f822014-07-25 16:39:55 +0800877
878
Tammo Spalink86a61c62012-05-25 15:10:35 +0800879@Command('log_system_details')
Tammo Spalink01e11722012-07-24 10:17:54 -0700880def LogSystemDetails(options): # pylint: disable=W0613
Tammo Spalink86a61c62012-05-25 15:10:35 +0800881 """Write miscellaneous system details to the event log."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800882
Ricky Liang43b879b2014-02-24 11:36:55 +0800883 event_log.Log('system_details', **GetGooftool(options).GetSystemDetails())
Tammo Spalink86a61c62012-05-25 15:10:35 +0800884
885
Jon Salza88b83b2013-05-27 20:00:35 +0800886def CreateReportArchiveBlob(*args, **kwargs):
887 """Creates a report archive and returns it as a blob.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800888
Jon Salza88b83b2013-05-27 20:00:35 +0800889 Args:
890 See CreateReportArchive.
Andy Cheng7a76cb82012-11-19 18:08:19 +0800891
Jon Salza88b83b2013-05-27 20:00:35 +0800892 Returns:
893 An xmlrpclib.Binary object containing a .tar.xz file.
894 """
895 with open(CreateReportArchive(*args, **kwargs)) as f:
896 return xmlrpclib.Binary(f.read())
897
898
899def CreateReportArchive(device_sn=None, add_file=None):
900 """Creates a report archive in a temporary directory.
901
902 Args:
903 device_sn: The device serial number (optional).
904 add_file: A list of files to add (optional).
905
906 Returns:
907 Path to the archive.
908 """
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800909 def NormalizeAsFileName(token):
910 return re.sub(r'\W+', '', token).strip()
Jon Salza88b83b2013-05-27 20:00:35 +0800911
912 target_name = '%s%s.tar.xz' % (
913 time.strftime('%Y%m%dT%H%M%SZ',
914 time.gmtime()),
Hung-Te Lin56b18402015-01-16 14:52:30 +0800915 ('' if device_sn is None else
916 '_' + NormalizeAsFileName(device_sn)))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800917 target_path = os.path.join(gettempdir(), target_name)
Jon Salza88b83b2013-05-27 20:00:35 +0800918
Tammo Spalink86a61c62012-05-25 15:10:35 +0800919 # Intentionally ignoring dotfiles in EVENT_LOG_DIR.
Andy Cheng0465d132013-03-20 12:12:06 +0800920 tar_cmd = 'cd %s ; tar cJf %s *' % (event_log.EVENT_LOG_DIR, target_path)
Joel Kitching4b1b6c02016-05-10 14:34:30 +0800921 tar_cmd += ' --add-file %s' % paths.GetFactoryLogPath()
Jon Salza88b83b2013-05-27 20:00:35 +0800922 if add_file:
923 for f in add_file:
Jon Salz65266432012-07-30 19:02:49 +0800924 # Require absolute paths since the tar command may change the
925 # directory.
926 if not f.startswith('/'):
927 raise Error('Not an absolute path: %s' % f)
928 if not os.path.exists(f):
929 raise Error('File does not exist: %s' % f)
930 tar_cmd += ' --add-file %s' % pipes.quote(f)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800931 cmd_result = Shell(tar_cmd)
Jon Salzff88c022012-11-03 12:19:58 +0800932
933 if ((cmd_result.status == 1) and
934 all((x == '' or
935 'file changed as we read it' in x or
936 "Removing leading `/' from member names" in x)
937 for x in cmd_result.stderr.split('\n'))):
938 # That's OK. Make sure it's valid though.
Vic Yang85199e72013-01-28 14:33:11 +0800939 Spawn(['tar', 'tfJ', target_path], check_call=True, log=True,
Jon Salzff88c022012-11-03 12:19:58 +0800940 ignore_stdout=True)
941 elif not cmd_result.success:
Tammo Spalink86a61c62012-05-25 15:10:35 +0800942 raise Error('unable to tar event logs, cmd %r failed, stderr: %r' %
943 (tar_cmd, cmd_result.stderr))
Jon Salzff88c022012-11-03 12:19:58 +0800944
Jon Salza88b83b2013-05-27 20:00:35 +0800945 return target_path
946
947_upload_method_cmd_arg = CmdArg(
948 '--upload_method', metavar='METHOD:PARAM',
949 help=('How to perform the upload. METHOD should be one of '
950 '{ftp, shopfloor, ftps, cpfe}.'))
951_add_file_cmd_arg = CmdArg(
952 '--add_file', metavar='FILE', action='append',
953 help='Extra file to include in report (must be an absolute path)')
954
Hung-Te Lin56b18402015-01-16 14:52:30 +0800955
Jon Salza88b83b2013-05-27 20:00:35 +0800956@Command('upload_report',
957 _upload_method_cmd_arg,
958 _add_file_cmd_arg)
959def UploadReport(options):
960 """Create a report containing key device details."""
Hung-Te Lin74346d72016-01-07 22:16:57 +0800961 ro_vpd = ReadRoVpd()
Jon Salza88b83b2013-05-27 20:00:35 +0800962 device_sn = ro_vpd.get('serial_number', None)
963 if device_sn is None:
964 logging.warning('RO_VPD missing device serial number')
Chun-Ta Lin53cbbd52016-06-08 21:42:19 +0800965 device_sn = 'MISSING_SN_' + time_utils.TimedUUID()
Jon Salza88b83b2013-05-27 20:00:35 +0800966 target_path = CreateReportArchive(device_sn)
967
Tammo Spalink86a61c62012-05-25 15:10:35 +0800968 if options.upload_method is None or options.upload_method == 'none':
969 logging.warning('REPORT UPLOAD SKIPPED (report left at %s)', target_path)
970 return
971 method, param = options.upload_method.split(':', 1)
972 if method == 'shopfloor':
973 report_upload.ShopFloorUpload(target_path, param)
974 elif method == 'ftp':
Jay Kim360c1dd2012-06-25 10:58:11 -0700975 report_upload.FtpUpload(target_path, 'ftp:' + param)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800976 elif method == 'ftps':
977 report_upload.CurlUrlUpload(target_path, '--ftp-ssl-reqd ftp:%s' % param)
978 elif method == 'cpfe':
Shawn Nematbakhsh3404a092013-01-28 16:49:09 -0800979 report_upload.CpfeUpload(target_path, pipes.quote(param))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800980 else:
981 raise Error('unknown report upload method %r', method)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800982
983
984@Command('finalize',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800985 CmdArg('--no_write_protect', action='store_true',
986 help='Do not enable firmware write protection.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800987 CmdArg('--fast', action='store_true',
988 help='use non-secure but faster wipe method.'),
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800989 CmdArg('--wipe_in_place', action='store_true',
990 help='Start factory wiping in place without reboot.'),
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800991 _cutoff_args_cmd_arg,
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800992 _shopfloor_url_args_cmd_arg,
Ricky Liang43b879b2014-02-24 11:36:55 +0800993 _hwid_version_cmd_arg,
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800994 _hwdb_path_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700995 _hwid_status_list_cmd_arg,
Jon Salz65266432012-07-30 19:02:49 +0800996 _upload_method_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800997 _add_file_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800998 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800999 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +08001000 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +08001001 _rma_mode_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +08001002 _cros_core_cmd_arg,
Hung-Te Lincdb96522016-04-15 16:51:10 +08001003 _release_rootfs_cmd_arg,
1004 _firmware_path_cmd_arg,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +08001005 _enforced_release_channels_cmd_arg,
1006 _station_ip_cmd_arg,
1007 _station_port_cmd_arg,
Ting Shen18a06382016-08-30 16:18:21 +08001008 _wipe_finish_token_cmd_arg,
1009 _waive_list_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001010def Finalize(options):
1011 """Verify system readiness and trigger transition into release state.
1012
Jon Salzaa3a30e2013-05-15 15:56:28 +08001013 This routine does the following:
1014 - Verifies system state (see verify command)
Jon Salzfe9036f2014-01-16 14:11:23 +08001015 - Untars stateful_files.tar.xz, if it exists, in the stateful partition, to
1016 initialize files such as the CRX cache
Jon Salzaa3a30e2013-05-15 15:56:28 +08001017 - Modifies firmware bitmaps to match locale
1018 - Clears all factory-friendly flags from the GBB
1019 - Removes factory-specific entries from RW_VPD (factory.*)
1020 - Enables firmware write protection (cannot rollback after this)
1021 - Uploads system logs & reports
1022 - Sets the necessary boot flags to cause wipe of the factory image on the
1023 next boot.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001024 """
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001025 Verify(options)
Jon Salz40b9f822014-07-25 16:39:55 +08001026 LogSourceHashes(options)
Jon Salzfe9036f2014-01-16 14:11:23 +08001027 UntarStatefulFiles(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +08001028 if options.cros_core:
1029 logging.info('SetFirmwareBitmapLocale is skipped for ChromeOS Core device.')
1030 else:
1031 SetFirmwareBitmapLocale(options)
Ricky Lianga70a1202013-03-15 15:03:17 +08001032 ClearGBBFlags(options)
Jon Salzaa3a30e2013-05-15 15:56:28 +08001033 ClearFactoryVPDEntries(options)
Mattias Nisslercca761b2015-04-15 21:53:04 +02001034 GenerateStableDeviceSecret(options)
Hung-Te Lin6d827542012-07-19 11:50:41 +08001035 if options.no_write_protect:
1036 logging.warn('WARNING: Firmware Write Protection is SKIPPED.')
Andy Cheng0465d132013-03-20 12:12:06 +08001037 event_log.Log('wp', fw='both', status='skipped')
Hung-Te Lin6d827542012-07-19 11:50:41 +08001038 else:
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001039 EnableFwWp({})
Jon Salza0f58e02012-05-29 19:33:39 +08001040 LogSystemDetails(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001041 UploadReport(options)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +08001042 if options.wipe_in_place:
1043 event_log.Log('wipe_in_place')
Wei-Han Chen0a3320e2016-04-23 01:32:07 +08001044 # WipeInPlace(options)
1045 wipe_args = []
Wei-Han Chen1f02f8f2016-05-31 11:05:24 +08001046 if options.cutoff_args:
1047 wipe_args += ['--cutoff_args', options.cutoff_args]
1048 if options.shopfloor_url:
1049 wipe_args += ['--shopfloor_url', options.shopfloor_url]
Wei-Han Chen0a3320e2016-04-23 01:32:07 +08001050 if options.fast:
1051 wipe_args += ['--fast']
Wei-Han Chenbe1355a2016-04-24 19:31:03 +08001052 if options.station_ip:
1053 wipe_args += ['--station_ip', options.station_ip]
1054 if options.station_port:
1055 wipe_args += ['--station_port', options.station_port]
1056 if options.wipe_finish_token:
1057 wipe_args += ['--wipe_finish_token', options.wipe_finish_token]
Wei-Han Chen0a3320e2016-04-23 01:32:07 +08001058 ExecFactoryPar('gooftool', 'wipe_in_place', *wipe_args)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +08001059 else:
1060 PrepareWipe(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001061
1062
Ricky Liangc662be32013-12-24 11:50:23 +08001063def VerifyHWIDv3(options):
1064 """A simple wrapper that calls out to HWID utils to verify version 3 HWID.
Ricky Liang53390232013-03-08 15:37:57 +08001065
Ricky Liangc662be32013-12-24 11:50:23 +08001066 This is mainly for Gooftool to verify v3 HWID during finalize. For testing
1067 and development purposes, please use `hwid` command.
Ricky Liang53390232013-03-08 15:37:57 +08001068 """
Ricky Liangc662be32013-12-24 11:50:23 +08001069 db = GetGooftool(options).db
1070 encoded_string = options.hwid or hwid_utils.GetHWIDString()
Ricky Liang7905f272013-03-16 01:57:10 +08001071 if options.probe_results:
Ricky Liangc662be32013-12-24 11:50:23 +08001072 probed_results = yaml.load(open(options.probe_results).read())
Ricky Liang7905f272013-03-16 01:57:10 +08001073 else:
Ricky Liangc662be32013-12-24 11:50:23 +08001074 probed_results = yaml.load(Probe(probe_vpd=True).Encode())
1075 vpd = hwid_utils.GetVPD(probed_results)
Ricky Liang53390232013-03-08 15:37:57 +08001076
Hung-Te Lin11052952015-03-18 13:48:59 +08001077 event_log.Log('probed_results', probed_results=FilterDict(probed_results))
1078 event_log.Log('vpd', vpd=FilterDict(vpd))
Ricky Liang53390232013-03-08 15:37:57 +08001079
Ricky Liangc662be32013-12-24 11:50:23 +08001080 hwid_utils.VerifyHWID(db, encoded_string, probed_results, vpd,
Hung-Te Lin56b18402015-01-16 14:52:30 +08001081 rma_mode=options.rma_mode)
Ricky Liang53390232013-03-08 15:37:57 +08001082
Ricky Liangc662be32013-12-24 11:50:23 +08001083 event_log.Log('verified_hwid', hwid=encoded_string)
Ricky Liang53390232013-03-08 15:37:57 +08001084
1085
Ricky Liang59611a62013-06-11 13:47:33 +08001086def ParseDecodedHWID(hwid):
1087 """Parse the HWID object into a more compact dict.
1088
1089 Args:
1090 hwid: A decoded HWID object.
1091
1092 Returns:
1093 A dict containing the board name, the binary string, and the list of
1094 components.
1095 """
1096 results = {}
1097 results['board'] = hwid.database.board
1098 results['binary_string'] = hwid.binary_string
1099 results['components'] = collections.defaultdict(list)
1100 components = hwid.bom.components
1101 for comp_cls in sorted(components):
1102 for (comp_name, probed_values, _) in sorted(components[comp_cls]):
1103 if not probed_values:
1104 db_components = hwid.database.components
1105 probed_values = db_components.GetComponentAttributes(
1106 comp_cls, comp_name).get('values')
1107 results['components'][comp_cls].append(
1108 {comp_name: probed_values if probed_values else None})
1109 # Convert defaultdict to dict.
1110 results['components'] = dict(results['components'])
1111 return results
1112
1113
henryhsu44d793a2013-07-20 00:07:38 +08001114@Command('get_firmware_hash',
1115 CmdArg('--file', metavar='FILE', help='Firmware File.'))
1116def GetFirmwareHash(options):
henryhsuf6f835c2013-07-20 20:49:25 +08001117 """Get firmware hash from a file"""
henryhsu44d793a2013-07-20 00:07:38 +08001118 if os.path.exists(options.file):
1119 hashes = CalculateFirmwareHashes(options.file)
1120 for section, value_dict in hashes.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +08001121 print '%s:' % section
henryhsu44d793a2013-07-20 00:07:38 +08001122 for key, value in value_dict.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +08001123 print ' %s: %s' % (key, value)
henryhsu44d793a2013-07-20 00:07:38 +08001124 else:
1125 raise Error('File does not exist: %s' % options.file)
1126
henryhsuf6f835c2013-07-20 20:49:25 +08001127
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001128def Main():
1129 """Run sub-command specified by the command line args."""
Andy Cheng7a76cb82012-11-19 18:08:19 +08001130
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001131 options = ParseCmdline(
Ricky Liangc662be32013-12-24 11:50:23 +08001132 ('Perform Google required factory tests. All the HWID-related functions '
1133 'provided here are mainly for the deprecated HWID v2. To access HWID '
1134 'v3-related utilities, please use `hwid` command.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001135 CmdArg('-l', '--log', metavar='PATH',
1136 help='Write logs to this file.'),
Jon Salza4bea382012-10-29 13:00:34 +08001137 CmdArg('--suppress-event-logs', action='store_true',
1138 help='Suppress event logging.'),
Wei-Han Chenaff56232016-04-16 09:17:59 +08001139 CmdArg('--phase', default=None,
1140 help=('override phase for phase checking (defaults to the current '
1141 'as returned by the "factory phase" command)')),
Tammo Spalink8fab5312012-05-28 18:33:30 +08001142 verbosity_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001143 SetupLogging(options.verbosity, options.log)
Andy Cheng0465d132013-03-20 12:12:06 +08001144 event_log.SetGlobalLoggerDefaultPrefix('gooftool')
1145 event_log.GetGlobalLogger().suppress = options.suppress_event_logs
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001146 logging.debug('gooftool options: %s', repr(options))
Wei-Han Chenaff56232016-04-16 09:17:59 +08001147
1148 phase.OverridePhase(options.phase)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001149 try:
1150 logging.debug('GOOFTOOL command %r', options.command_name)
1151 options.command(options)
1152 logging.info('GOOFTOOL command %r SUCCESS', options.command_name)
1153 except Error, e:
1154 logging.exception(e)
1155 sys.exit('GOOFTOOL command %r ERROR: %s' % (options.command_name, e))
1156 except Exception, e:
1157 logging.exception(e)
1158 sys.exit('UNCAUGHT RUNTIME EXCEPTION %s' % e)
1159
1160
1161if __name__ == '__main__':
1162 Main()