blob: a439fc81c32473b2febf5901b0fcffa8175c3748 [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
49from cros.factory.utils.argparse_utils import Command
50from cros.factory.utils.argparse_utils import ParseCmdline
51from cros.factory.utils.argparse_utils import verbosity_cmd_arg
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
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080091@Command('write_hwid',
92 CmdArg('hwid', metavar='HWID', help='HWID string'))
Andy Chengc92e6f92012-11-20 16:55:53 +080093def WriteHWID(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080094 """Write specified HWID value into the system BB."""
Andy Cheng7a76cb82012-11-19 18:08:19 +080095
Tammo Spalink95c43732012-07-25 15:57:14 -070096 logging.info('writing hwid string %r', options.hwid)
Ricky Lianga70a1202013-03-15 15:03:17 +080097 GetGooftool(options).WriteHWID(options.hwid)
Andy Cheng0465d132013-03-20 12:12:06 +080098 event_log.Log('write_hwid', hwid=options.hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -070099 print 'Wrote HWID: %r' % options.hwid
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800100
101
Ricky Liang53390232013-03-08 15:37:57 +0800102_board_cmd_arg = CmdArg(
103 '--board', metavar='BOARD',
104 default=None, help='Board name to test.')
105
Tammo Spalink8fab5312012-05-28 18:33:30 +0800106_hwdb_path_cmd_arg = CmdArg(
107 '--hwdb_path', metavar='PATH',
Ricky Liangeede7922013-06-19 10:18:41 +0800108 default=common.DEFAULT_HWID_DATA_PATH,
Tammo Spalink8fab5312012-05-28 18:33:30 +0800109 help='Path to the HWID database.')
110
Tammo Spalink95c43732012-07-25 15:57:14 -0700111_hwid_status_list_cmd_arg = CmdArg(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800112 '--status', nargs='*', default=['supported'],
113 help='allow only HWIDs with these status values')
Tammo Spalink95c43732012-07-25 15:57:14 -0700114
Jon Salzce124fb2012-10-02 17:42:03 +0800115_probe_results_cmd_arg = CmdArg(
116 '--probe_results', metavar='RESULTS.yaml',
Ricky Liangc662be32013-12-24 11:50:23 +0800117 help=('Output from "gooftool probe --include_vpd" (used instead of '
Jon Salzce124fb2012-10-02 17:42:03 +0800118 'probing this system).'))
119
Ricky Liang53390232013-03-08 15:37:57 +0800120_device_info_cmd_arg = CmdArg(
Ricky Liangf89f73a2013-03-19 05:00:24 +0800121 '--device_info', metavar='DEVICE_INFO.yaml', default=None,
Ricky Liang53390232013-03-08 15:37:57 +0800122 help='A dict of device info to use instead of fetching from shopfllor '
123 'server.')
124
Jon Salzce124fb2012-10-02 17:42:03 +0800125_hwid_cmd_arg = CmdArg(
126 '--hwid', metavar='HWID',
Ricky Lianga70a1202013-03-15 15:03:17 +0800127 help='HWID to verify (instead of the currently set HWID of this system).')
Jon Salzce124fb2012-10-02 17:42:03 +0800128
Bernie Thompson3c11c872013-07-22 18:22:45 -0700129_rma_mode_cmd_arg = CmdArg(
130 '--rma_mode', action='store_true',
131 help='Enable RMA mode, do not check for deprecated components.')
Tammo Spalink95c43732012-07-25 15:57:14 -0700132
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800133_cros_core_cmd_arg = CmdArg(
134 '--cros_core', action='store_true',
135 help='Finalize for ChromeOS Core devices (may add or remove few test '
136 'items. For example, branding verification or firmware bitmap '
137 'locale settings).')
138
Ricky Liang43b879b2014-02-24 11:36:55 +0800139_hwid_version_cmd_arg = CmdArg(
140 '-i', '--hwid-version', default=3, choices=(2, 3), type=int,
141 help='Version of HWID to operate on. (default: %(default)s)')
142
bowgotsai13820f42015-09-10 23:18:04 +0800143_enforced_release_channels_cmd_arg = CmdArg(
144 '--enforced_release_channels', nargs='*', default=None,
145 help='Enforced release image channels.')
146
Hung-Te Lincdb96522016-04-15 16:51:10 +0800147_release_rootfs_cmd_arg = CmdArg(
148 '--release_rootfs', help='Location of release image rootfs partition.')
149
150_firmware_path_cmd_arg = CmdArg(
151 '--firmware_path', help='Location of firmware image partition.')
Ricky Liang43b879b2014-02-24 11:36:55 +0800152
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800153_cutoff_args_cmd_arg = CmdArg(
154 '--cutoff_args',
155 help='Battery cutoff arguments to be passed to battery_cutoff.sh '
156 'after wiping. Should be the following format: '
157 '[--method shutdown|reboot|battery_cutoff] '
158 '[--check-ac connect_ac|remove_ac] '
159 '[--min-battery-percent <minimum battery percentage>] '
160 '[--max-battery-percent <maximum battery percentage>] '
161 '[--min-battery-voltage <minimum battery voltage>] '
162 '[--max-battery-voltage <maximum battery voltage>]')
163
164_shopfloor_url_args_cmd_arg = CmdArg(
165 '--shopfloor_url',
166 help='Shopfloor server url to be informed when in-place wipe is done. '
167 'After in-place wipe, a XML-RPC request will be sent to the '
168 'given url to indicate the completion of wipe.')
169
170_station_ip_cmd_arg = CmdArg(
171 '--station_ip',
172 help='IP of remote station')
173
174_station_port_cmd_arg = CmdArg(
175 '--station_port',
176 help='Port on remote station')
177
178_wipe_finish_token_cmd_arg = CmdArg(
179 '--wipe_finish_token',
180 help='Required token when notifying station after wipe finished')
181
Tammo Spalink95c43732012-07-25 15:57:14 -0700182@Command('best_match_hwids',
Tammo Spalink8fab5312012-05-28 18:33:30 +0800183 _hwdb_path_cmd_arg,
184 CmdArg('-b', '--board', metavar='BOARD',
Tammo Spalink95c43732012-07-25 15:57:14 -0700185 help='optional BOARD name, needed only if data is present '
186 'for more than one'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800187 CmdArg('--bom', metavar='BOM', help='BOM name'),
188 CmdArg('--variant', metavar='VARIANT', help='VARIANT code'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800189 CmdArg('--optimistic', action='store_true',
190 help='do not probe; assume singletons match'),
Tammo Spalink95c43732012-07-25 15:57:14 -0700191 CmdArg('--comps', nargs='*', default=[],
192 help='list of canonical component names'),
193 CmdArg('--missing', nargs='*', default=[],
194 help='list component classes to be assumed missing'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800195 CmdArg('--status', nargs='*', default=['supported'],
Tammo Spalink95c43732012-07-25 15:57:14 -0700196 help='consider only HWIDs within this list of status values'))
197def BestMatchHwids(options):
Ricky Liangc662be32013-12-24 11:50:23 +0800198 """Determine a list of possible HWIDs using provided args and probing.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800199
200 VOLATILE can always be determined by probing. To get a unique
201 result, VARIANT must be specified for all cases where the matching
202 BOM has more than one associated variant code, otherwise all HWID
203 variants will be returned. Both VARIANT and BOM information can
Tammo Spalink95c43732012-07-25 15:57:14 -0700204 alternatively be specified using the --stdin_comps argument, which
205 allows specifying a list of canonical names (one per line) on stdin,
206 one per line. Based on what is known from BOM and stdin_comps,
207 determine a list of components to probe for, and use those probe
208 results to resolve a list of matching HWIDs. If no boms,
209 components, or variant codes are specified, then a list of all HWIDs
Andy Cheng8ece7382012-08-22 16:25:42 +0800210 that match probeable components will be returned.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800211
212 Returns (on stdout): A list of HWIDs that match the available probe
213 results and argument contraints, one per line.
Tammo Spalink70b48a52012-08-08 16:54:51 -0700214
215 Example:
216
217 // Three ways to specify a keyboard (assuming it is a variant component)
218 gooftool best_match_hwids --missing keyboard
219 gooftool best_match_hwids --variant A or
220 gooftool best_match_hwids --comps us_kbd
Tammo Spalink8fab5312012-05-28 18:33:30 +0800221 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800222
Tammo Spalink5c699832012-07-03 17:50:39 +0800223 map(hwid_tool.Validate.Status, options.status)
Tammo Spalink95c43732012-07-25 15:57:14 -0700224 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Tammo Spalink5c699832012-07-03 17:50:39 +0800225 comp_db = hw_db.comp_db
Tammo Spalink3a7e9022012-06-27 14:08:40 +0800226 device = hw_db.GetDevice(options.board)
Tammo Spalink5c699832012-07-03 17:50:39 +0800227 component_spec = hwid_tool.ComponentSpec.New()
Tammo Spalink8fab5312012-05-28 18:33:30 +0800228 if options.bom:
Tammo Spalink5c699832012-07-03 17:50:39 +0800229 device.BomExists(options.bom)
Tammo Spalink01e11722012-07-24 10:17:54 -0700230 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800231 component_spec, device.boms[options.bom].primary)
Tammo Spalink8fab5312012-05-28 18:33:30 +0800232 if options.variant:
Tammo Spalink5c699832012-07-03 17:50:39 +0800233 device.VariantExists(options.variant)
234 variant_spec = device.variants[options.variant]
Tammo Spalink01e11722012-07-24 10:17:54 -0700235 if hwid_tool.ComponentSpecsConflict(component_spec, variant_spec):
Tammo Spalink95c43732012-07-25 15:57:14 -0700236 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700237 % YamlWrite(sorted(
238 hwid_tool.ComponentSpecClasses(component_spec) &
239 hwid_tool.ComponentSpecClasses(variant_spec))))
Tammo Spalink01e11722012-07-24 10:17:54 -0700240 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800241 component_spec, variant_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700242 if options.comps or options.missing:
243 map(comp_db.CompExists, options.comps)
244 map(comp_db.CompClassExists, options.missing)
245 extra_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800246 components=options.comps,
247 missing=options.missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700248 print 'cmdline asserted components:\n%s' % extra_comp_spec.Encode()
249 if hwid_tool.ComponentSpecsConflict(component_spec, extra_comp_spec):
250 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700251 % YamlWrite(sorted(
252 hwid_tool.ComponentSpecClasses(component_spec) &
253 hwid_tool.ComponentSpecClasses(extra_comp_spec))))
Tammo Spalink95c43732012-07-25 15:57:14 -0700254 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800255 component_spec, extra_comp_spec)
Tammo Spalink01e11722012-07-24 10:17:54 -0700256 spec_classes = hwid_tool.ComponentSpecClasses(component_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700257 missing_classes = set(comp_db.all_comp_classes) - spec_classes
Tammo Spalink5c699832012-07-03 17:50:39 +0800258 if missing_classes and not options.optimistic:
Andy Cheng8ece7382012-08-22 16:25:42 +0800259 non_probeable_missing = missing_classes - PROBEABLE_COMPONENT_CLASSES
260 if non_probeable_missing:
Tammo Spalink95c43732012-07-25 15:57:14 -0700261 sys.exit('FAILURE: these classes are necessary, were not specified '
Tammo Spalink70b48a52012-08-08 16:54:51 -0700262 'as inputs, and cannot be probed for:\n%s'
263 'This problem can often be addressed by specifying all of '
264 'the missing components on the command line (see the command '
Andy Cheng8ece7382012-08-22 16:25:42 +0800265 'help).' % YamlWrite(list(non_probeable_missing)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700266 print 'probing for missing classes:'
267 print YamlWrite(list(missing_classes))
268 probe_results = Probe(target_comp_classes=list(missing_classes),
269 probe_volatile=False, probe_initial_config=False)
270 cooked_components = comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800271 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700272 if cooked_components.unmatched:
273 sys.exit('ERROR: some probed components are unrecognized:\n%s'
274 % YamlWrite(cooked_components.unmatched))
275 probed_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800276 components=cooked_components.matched,
277 missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700278 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800279 component_spec, probed_comp_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700280 print YamlWrite({'component data used for matching': {
Hung-Te Lin56b18402015-01-16 14:52:30 +0800281 'missing component classes': component_spec.classes_missing,
282 'found components': component_spec.components}})
Tammo Spalink95c43732012-07-25 15:57:14 -0700283 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800284 extant_components=hwid_tool.ComponentSpecCompClassMap(
285 component_spec).keys(),
286 classes_missing=component_spec.classes_missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700287 match_tree = device.BuildMatchTree(component_data)
288 if not match_tree:
289 sys.exit('FAILURE: NO matching BOMs found')
290 print 'potential BOMs/VARIANTs:'
291 potential_variants = set()
292 potential_volatiles = set()
293 for bom_name, variant_tree in match_tree.items():
294 print ' BOM: %-8s VARIANTS: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800295 bom_name, ', '.join(sorted(variant_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700296 for variant_code in variant_tree:
297 potential_variants.add(variant_code)
298 for volatile_code in device.volatiles:
299 status = device.GetHwidStatus(bom_name, variant_code, volatile_code)
300 if status in options.status:
301 potential_volatiles.add(volatile_code)
302 print ''
303 if len(potential_variants) == 0:
304 sys.exit('FAILURE: no matching VARIANTs found')
305 if len(potential_volatiles) == 0:
306 sys.exit('FAILURE: no VOLATILEs found for potential matching BOMs/VARIANTS '
307 '(with specified status)')
Tammo Spalink394e4492012-08-01 10:20:30 -0700308 if (options.optimistic and
309 len(match_tree) == 1 and
310 len(potential_variants) == 1 and
311 len(potential_volatiles) == 1):
312 print ('MATCHING HWID: %s' % device.FmtHwid(match_tree.keys().pop(),
313 potential_variants.pop(),
314 potential_volatiles.pop()))
Tammo Spalink5c699832012-07-03 17:50:39 +0800315 return
Tammo Spalink95c43732012-07-25 15:57:14 -0700316 print ('probing VOLATILEs to resolve potential matches: %s\n' %
317 ', '.join(sorted(potential_volatiles)))
318 vol_probe_results = Probe(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800319 target_comp_classes=[],
320 probe_volatile=True,
321 probe_initial_config=False)
Tammo Spalink95c43732012-07-25 15:57:14 -0700322 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800323 vol_probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700324 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800325 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700326 matched_hwids = device.GetMatchTreeHwids(match_tree)
327 if matched_hwids:
328 for hwid in matched_hwids:
Ricky Liang02f3bd72012-09-21 14:33:01 +0800329 if matched_hwids[hwid] in options.status:
330 print 'MATCHING HWID: %s' % hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700331 return
332 print 'exact HWID matching failed, but the following BOMs match: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800333 ', '.join(sorted(match_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700334 if options.optimistic and len(match_tree) == 1:
335 bom_name = set(match_tree).pop()
Tammo Spalink5c699832012-07-03 17:50:39 +0800336 bom = device.boms[bom_name]
Tammo Spalink95c43732012-07-25 15:57:14 -0700337 variant_matches = match_tree[bom_name]
Tammo Spalink5c699832012-07-03 17:50:39 +0800338 if len(variant_matches) == 1:
339 var_code = set(variant_matches).pop()
340 elif len(bom.variants) == 1:
341 var_code = set(bom.variants).pop()
342 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700343 sys.exit('FAILURE: NO matching HWIDs found; optimistic matching failed '
344 'because there were too many variants to choose from for BOM %r'
345 % bom_name)
346 hwids = [device.FmtHwid(bom_name, var_code, vol_code)
347 for vol_code in device.volatiles
348 if device.GetHwidStatus(bom_name, var_code, vol_code)
349 in options.status]
350 for hwid in hwids:
351 print 'MATCHING HWID: %s' % hwid
Tammo Spalink5c699832012-07-03 17:50:39 +0800352 return
353 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700354 print ('optimistic matching not attempted because either it was '
355 'not requested, or because the number of BOMs was <> 1\n')
356 sys.exit('FAILURE: NO matching HWIDs found')
Tammo Spalink8fab5312012-05-28 18:33:30 +0800357
358
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800359@Command('probe',
360 CmdArg('--comps', nargs='*',
361 help='List of keys from the component_db registry.'),
Ricky Liangb30da672013-06-14 12:36:34 +0800362 CmdArg('--fast_fw_probe', action='store_true',
363 help='Do a fast probe for EC and main firmware versions only. '
364 'This implies --no_vol and --no_ic.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800365 CmdArg('--no_vol', action='store_true',
366 help='Do not probe volatile data.'),
367 CmdArg('--no_ic', action='store_true',
Jon Salz0f8a6842012-09-25 11:28:22 +0800368 help='Do not probe initial_config data.'),
369 CmdArg('--include_vpd', action='store_true',
370 help='Include VPD data in volatiles.'))
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800371def RunProbe(options):
372 """Print yaml-formatted breakdown of probed device properties."""
Ricky Lianga70a1202013-03-15 15:03:17 +0800373 print GetGooftool(options).Probe(
374 target_comp_classes=options.comps,
Ricky Liangb30da672013-06-14 12:36:34 +0800375 fast_fw_probe=options.fast_fw_probe,
Ricky Lianga70a1202013-03-15 15:03:17 +0800376 probe_volatile=not options.no_vol,
377 probe_initial_config=not options.no_ic,
378 probe_vpd=options.include_vpd).Encode()
Ricky Liang53390232013-03-08 15:37:57 +0800379
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800380
Tammo Spalink214caf42012-05-28 10:45:00 +0800381@Command('verify_components',
382 _hwdb_path_cmd_arg,
Tammo Spalink5c699832012-07-03 17:50:39 +0800383 CmdArg('target_comps', nargs='*'))
Tammo Spalink214caf42012-05-28 10:45:00 +0800384def VerifyComponents(options):
Andy Cheng8ece7382012-08-22 16:25:42 +0800385 """Verify that probeable components all match entries in the component_db.
Tammo Spalink214caf42012-05-28 10:45:00 +0800386
Tammo Spalink5c699832012-07-03 17:50:39 +0800387 Probe for each component class in the target_comps and verify
Tammo Spalink214caf42012-05-28 10:45:00 +0800388 that a corresponding match exists in the component_db -- make sure
389 that these components are present, that they have been approved, but
390 do not check against any specific BOM/HWID configurations.
391 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800392
Andy Chengc531e2f2012-10-15 19:09:17 +0800393 try:
Ricky Lianga70a1202013-03-15 15:03:17 +0800394 result = GetGooftool(options).VerifyComponents(
Andy Chengc531e2f2012-10-15 19:09:17 +0800395 options.target_comps)
396 except ValueError, e:
397 sys.exit(e)
398
Ricky Liang53390232013-03-08 15:37:57 +0800399 PrintVerifyComponentsResults(result)
400
401
402def PrintVerifyComponentsResults(result):
403 """Prints out the results of VerifyComponents method call.
404
405 Groups the results into two groups: 'matches' and 'errors', and prints out
406 their values.
407 """
Andy Chengc531e2f2012-10-15 19:09:17 +0800408 # group by matches and errors
Tammo Spalink214caf42012-05-28 10:45:00 +0800409 matches = []
Andy Chengc531e2f2012-10-15 19:09:17 +0800410 errors = []
411 for result_list in result.values():
412 for component_name, _, error in result_list:
413 if component_name:
414 matches.append(component_name)
Tammo Spalink214caf42012-05-28 10:45:00 +0800415 else:
Andy Chengc531e2f2012-10-15 19:09:17 +0800416 errors.append(error)
417
Andy Cheng228a8c92012-08-27 10:53:57 +0800418 if matches:
419 print 'found probeable components:\n %s' % '\n '.join(matches)
Tammo Spalink214caf42012-05-28 10:45:00 +0800420 if errors:
Andy Cheng228a8c92012-08-27 10:53:57 +0800421 print '\nerrors:\n %s' % '\n '.join(errors)
422 sys.exit('\ncomponent verification FAILURE')
Tammo Spalink214caf42012-05-28 10:45:00 +0800423 else:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800424 print '\ncomponent verification SUCCESS'
Tammo Spalink214caf42012-05-28 10:45:00 +0800425
426
Ricky Liang43b879b2014-02-24 11:36:55 +0800427@Command('verify_hwid_v2',
Tammo Spalink95c43732012-07-25 15:57:14 -0700428 _hwid_status_list_cmd_arg,
Jon Salz0f8a6842012-09-25 11:28:22 +0800429 _hwdb_path_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800430 _probe_results_cmd_arg,
431 _hwid_cmd_arg)
Ricky Liang43b879b2014-02-24 11:36:55 +0800432def VerifyHWIDv2(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800433 """Verify system HWID properties match probed device properties.
434
435 First probe components, volatile and initial_config parameters for
436 the DUT. Then use the available device data to produce a list of
437 candidate HWIDs. Then verify the HWID from the DUT is present in
438 that list. Then verify that the DUT initial config values match
439 those specified for its HWID. Finally, verify that VPD contains all
440 the necessary fields as specified by the board data, and when
441 possible verify that values are legitimate.
442 """
Ricky Liangf7857c12012-09-17 13:34:41 +0800443 def VerifyVpd(ro_vpd_keys, rw_vpd_keys):
Tammo Spalink5c699832012-07-03 17:50:39 +0800444 for key in ro_vpd_keys:
445 if key not in ro_vpd:
Ricky Liangf7857c12012-09-17 13:34:41 +0800446 sys.exit('Missing required RO VPD field: %s' % key)
Tammo Spalink01e11722012-07-24 10:17:54 -0700447 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800448 value = ro_vpd[key]
Ricky Liangf7857c12012-09-17 13:34:41 +0800449 if (known_valid_values is not None) and (value not in known_valid_values):
450 sys.exit('Invalid RO VPD entry : key %r, value %r' % (key, value))
Ricky Liangf7857c12012-09-17 13:34:41 +0800451 for key in rw_vpd_keys:
452 if key not in rw_vpd:
453 sys.exit('Missing required RW VPD field: %s' % key)
454 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
455 value = rw_vpd[key]
456 if (known_valid_values is not None) and (value not in known_valid_values):
457 sys.exit('Invalid RW VPD entry : key %r, value %r' % (key, value))
Andy Cheng0465d132013-03-20 12:12:06 +0800458 event_log.Log('vpd', ro_vpd=FilterDict(ro_vpd), rw_vpd=FilterDict(rw_vpd))
Tammo Spalink5c699832012-07-03 17:50:39 +0800459 map(hwid_tool.Validate.Status, options.status)
Jon Salz0f8a6842012-09-25 11:28:22 +0800460
Jon Salz0f8a6842012-09-25 11:28:22 +0800461 if options.hwid:
462 hwid_str = options.hwid
463 else:
Hung-Te Lin74346d72016-01-07 22:16:57 +0800464 main_fw_file = crosfw.LoadMainFirmware().GetFileName()
Jon Salz0f8a6842012-09-25 11:28:22 +0800465 gbb_result = Shell('gbb_utility -g --hwid %s' % main_fw_file).stdout
466 hwid_str = re.findall(r'hardware_id:(.*)', gbb_result)[0].strip()
Tammo Spalink95c43732012-07-25 15:57:14 -0700467 hwid = hwid_tool.ParseHwid(hwid_str)
Tammo Spalink5c699832012-07-03 17:50:39 +0800468 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Jon Salz0f8a6842012-09-25 11:28:22 +0800469 print 'Verifying HWID: %r\n' % hwid.hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700470 device = hw_db.GetDevice(hwid.board)
471 hwid_status = device.GetHwidStatus(hwid.bom, hwid.variant, hwid.volatile)
472 if hwid_status not in options.status:
Tammo Spalink5c699832012-07-03 17:50:39 +0800473 sys.exit('HWID status must be one of [%s], found %r' %
Hung-Te Lin4f5beb12012-08-20 14:48:06 +0800474 (', '.join(options.status), hwid_status))
Jon Salz0f8a6842012-09-25 11:28:22 +0800475 if options.probe_results:
476 # Pull in probe results (including VPD data) from the given file
477 # rather than probing the current system.
478 probe_results = hwid_tool.ProbeResults.Decode(
479 open(options.probe_results).read())
480 ro_vpd = {}
481 rw_vpd = {}
482 for k, v in probe_results.found_volatile_values.items():
Hung-Te Lin56b18402015-01-16 14:52:30 +0800483 match = re.match(r'^vpd\.(ro|rw)\.(\w+)$', k)
Jon Salz0f8a6842012-09-25 11:28:22 +0800484 if match:
485 del probe_results.found_volatile_values[k]
486 (ro_vpd if match.group(1) == 'ro' else rw_vpd)[match.group(2)] = v
487 else:
488 probe_results = Probe()
Hung-Te Lin74346d72016-01-07 22:16:57 +0800489 ro_vpd = ReadRoVpd()
490 rw_vpd = ReadRwVpd()
Tammo Spalink95c43732012-07-25 15:57:14 -0700491 cooked_components = hw_db.comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800492 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700493 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800494 probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700495 cooked_initial_configs = device.MatchInitialConfigValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800496 probe_results.initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700497 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800498 extant_components=cooked_components.matched,
499 classes_missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700500 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800501 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700502 matched_hwids = device.GetMatchTreeHwids(match_tree)
503 print 'HWID status: %s\n' % hwid_status
504 print 'probed system components:'
505 print YamlWrite(cooked_components.__dict__)
506 print 'missing component classes:'
507 print YamlWrite(probe_results.missing_component_classes)
508 print 'probed volatiles:'
509 print YamlWrite(cooked_volatiles.__dict__)
510 print 'probed initial_configs:'
511 print YamlWrite(cooked_initial_configs)
512 print 'hwid match tree:'
513 print YamlWrite(match_tree)
Andy Cheng0465d132013-03-20 12:12:06 +0800514 event_log.Log(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800515 'probe',
516 found_components=cooked_components.__dict__,
517 missing_component_classes=probe_results.missing_component_classes,
518 volatiles=cooked_volatiles.__dict__,
519 initial_configs=cooked_initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700520 if hwid.hwid not in matched_hwids:
Tammo Spalink5c699832012-07-03 17:50:39 +0800521 err_msg = 'HWID verification FAILED.\n'
Tammo Spalink95c43732012-07-25 15:57:14 -0700522 if cooked_components.unmatched:
Tammo Spalink5c699832012-07-03 17:50:39 +0800523 sys.exit(err_msg + 'some components could not be indentified:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700524 YamlWrite(cooked_components.unmatched))
525 if not match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800526 sys.exit(err_msg + 'no matching boms were found for components:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700527 component_data.Encode())
528 if hwid.bom not in match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800529 sys.exit(err_msg + 'matching boms [%s] do not include target bom %r' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700530 (', '.join(sorted(match_tree)), hwid.bom))
531 err_msg += 'target bom %r matches components' % hwid.bom
532 if hwid.bom not in device.IntersectBomsAndInitialConfigs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800533 cooked_initial_configs):
Tammo Spalink5c699832012-07-03 17:50:39 +0800534 sys.exit(err_msg + ', but failed initial config verification')
Tammo Spalink95c43732012-07-25 15:57:14 -0700535 matched_variants = match_tree.get(hwid.bom, {})
536 if hwid.variant not in matched_variants:
Tammo Spalink5c699832012-07-03 17:50:39 +0800537 sys.exit(err_msg + ', but target variant_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700538 hwid.variant)
539 matched_volatiles = matched_variants.get(hwid.variant, {})
540 if hwid.volatile not in matched_volatiles:
Tammo Spalink5c699832012-07-03 17:50:39 +0800541 sys.exit(err_msg + ', but target volatile_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700542 hwid.volatile)
543 found_status = matched_volatiles.get(hwid.volatile, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800544 sys.exit(err_msg + ', but hwid status %r was unacceptable' % found_status)
Ricky Liangf7857c12012-09-17 13:34:41 +0800545 VerifyVpd(device.vpd_ro_fields, device.vpd_rw_fields)
Andy Cheng0465d132013-03-20 12:12:06 +0800546 event_log.Log('verified_hwid', hwid=hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -0700547 print 'Verification SUCCESS!'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800548
549
Hung-Te Line1d80f62016-03-31 14:58:13 +0800550@Command('verify_keys',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800551 _release_rootfs_cmd_arg,
552 _firmware_path_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700553def VerifyKeys(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800554 """Verify keys in firmware and SSD match."""
Hung-Te Line1d80f62016-03-31 14:58:13 +0800555 return GetGooftool(options).VerifyKeys(
Hung-Te Lincdb96522016-04-15 16:51:10 +0800556 options.release_rootfs, options.firmware_path)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800557
558
559@Command('set_fw_bitmap_locale')
Tammo Spalink01e11722012-07-24 10:17:54 -0700560def SetFirmwareBitmapLocale(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800561 """Use VPD locale value to set firmware bitmap default language."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800562
Ricky Lianga70a1202013-03-15 15:03:17 +0800563 (index, locale) = GetGooftool(options).SetFirmwareBitmapLocale()
Andy Cheng2582d292012-12-04 17:38:28 +0800564 logging.info('Firmware bitmap initial locale set to %d (%s).',
565 index, locale)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800566
567
Hung-Te Line1d80f62016-03-31 14:58:13 +0800568@Command('verify_system_time',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800569 _release_rootfs_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700570def VerifySystemTime(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800571 """Verify system time is later than release filesystem creation time."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800572
Hung-Te Lincdb96522016-04-15 16:51:10 +0800573 return GetGooftool(options).VerifySystemTime(options.release_rootfs)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800574
575
Hung-Te Line1d80f62016-03-31 14:58:13 +0800576@Command('verify_rootfs',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800577 _release_rootfs_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700578def VerifyRootFs(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800579 """Verify rootfs on SSD is valid by checking hash."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800580
Hung-Te Line1d80f62016-03-31 14:58:13 +0800581 return GetGooftool(options).VerifyRootFs(options.release_rootfs)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800582
Hung-Te Lin56b18402015-01-16 14:52:30 +0800583
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800584@Command('verify_tpm')
585def VerifyTPM(options): # pylint: disable=W0613
586 """Verify TPM is cleared."""
587
588 return GetGooftool(options).VerifyTPM()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800589
Hung-Te Lin56b18402015-01-16 14:52:30 +0800590
Hung-Te Lindd708d42014-07-11 17:05:01 +0800591@Command('verify_me_locked')
592def VerifyManagementEngineLocked(options): # pylint: disable=W0613
593 """Verify Managment Engine is locked."""
594
595 return GetGooftool(options).VerifyManagementEngineLocked()
596
Hung-Te Lin56b18402015-01-16 14:52:30 +0800597
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800598@Command('verify_switch_wp')
Andy Chengc92e6f92012-11-20 16:55:53 +0800599def VerifyWPSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800600 """Verify hardware write protection switch is enabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800601
Ricky Lianga70a1202013-03-15 15:03:17 +0800602 GetGooftool(options).VerifyWPSwitch()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800603
604
605@Command('verify_switch_dev')
Tammo Spalink01e11722012-07-24 10:17:54 -0700606def VerifyDevSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800607 """Verify developer switch is disabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800608
Ricky Lianga70a1202013-03-15 15:03:17 +0800609 if GetGooftool(options).CheckDevSwitchForDisabling():
Hung-Te Lind7d34722012-07-26 16:48:35 +0800610 logging.warn('VerifyDevSwitch: No physical switch.')
Andy Cheng0465d132013-03-20 12:12:06 +0800611 event_log.Log('switch_dev', type='virtual switch')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800612
613
Jon Salzadd90d32014-04-29 16:16:27 +0800614@Command('verify_branding')
615def VerifyBranding(options): # pylint: disable=W0613
616 """Verify that branding fields are properly set.
617
618 customization_id, if set in the RO VPD, must be of the correct format.
619
620 rlz_brand_code must be set either in the RO VPD or OEM partition, and must
621 be of the correct format.
622 """
623 return GetGooftool(options).VerifyBranding()
624
625
bowgotsai13820f42015-09-10 23:18:04 +0800626@Command('verify_release_channel',
627 _enforced_release_channels_cmd_arg)
bowgotsai529139c2015-05-30 01:39:49 +0800628def VerifyReleaseChannel(options): # pylint: disable=W0613
629 """Verify that release image channel is correct.
630
631 ChromeOS has four channels: canary, dev, beta and stable.
632 The last three channels support image auto-updates, checks
633 that release image channel is one of them.
634 """
bowgotsai13820f42015-09-10 23:18:04 +0800635 return GetGooftool(options).VerifyReleaseChannel(
636 options.enforced_release_channels)
bowgotsai529139c2015-05-30 01:39:49 +0800637
638
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800639@Command('write_protect')
Tammo Spalink01e11722012-07-24 10:17:54 -0700640def EnableFwWp(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800641 """Enable then verify firmware write protection."""
642
Hung-Te Linb21c6682012-08-01 13:53:57 +0800643 def CalculateLegacyRange(fw_type, length, section_data,
644 section_name):
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800645 ro_size = length / 2
646 ro_a = int(section_data[0] / ro_size)
647 ro_b = int((section_data[0] + section_data[1] - 1) / ro_size)
648 if ro_a != ro_b:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800649 raise Error('%s firmware section %s has illegal size' %
Hung-Te Linb21c6682012-08-01 13:53:57 +0800650 (fw_type, section_name))
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800651 ro_offset = ro_a * ro_size
652 return (ro_offset, ro_size)
653
654 def WriteProtect(fw_file_path, fw_type, legacy_section):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800655 """Calculate protection size, then invoke flashrom.
656
657 Our supported chips only allow write protecting half their total
658 size, so we parition the flash chipset space accordingly.
659 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800660
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800661 raw_image = open(fw_file_path, 'rb').read()
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800662 wp_section = 'WP_RO'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800663 image = crosfw.FirmwareImage(raw_image)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800664 if image.has_section(wp_section):
665 section_data = image.get_section_area(wp_section)
666 ro_offset = section_data[0]
667 ro_size = section_data[1]
668 elif image.has_section(legacy_section):
669 section_data = image.get_section_area(legacy_section)
670 (ro_offset, ro_size) = CalculateLegacyRange(
Hung-Te Linb21c6682012-08-01 13:53:57 +0800671 fw_type, len(raw_image), section_data, legacy_section)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800672 else:
673 raise Error('could not find %s firmware section %s or %s' %
674 (fw_type, wp_section, legacy_section))
675
676 logging.debug('write protecting %s [off=%x size=%x]', fw_type,
677 ro_offset, ro_size)
678 crosfw.Flashrom(fw_type).EnableWriteProtection(ro_offset, ro_size)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800679
680 WriteProtect(crosfw.LoadMainFirmware().GetFileName(), 'main', 'RO_SECTION')
Andy Cheng0465d132013-03-20 12:12:06 +0800681 event_log.Log('wp', fw='main')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800682 ec_fw_file = crosfw.LoadEcFirmware().GetFileName()
683 if ec_fw_file is not None:
684 WriteProtect(ec_fw_file, 'ec', 'EC_RO')
Andy Cheng0465d132013-03-20 12:12:06 +0800685 event_log.Log('wp', fw='ec')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800686 else:
687 logging.warning('EC not write protected (seems there is no EC flash).')
688
689
690@Command('clear_gbb_flags')
Andy Chengc92e6f92012-11-20 16:55:53 +0800691def ClearGBBFlags(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800692 """Zero out the GBB flags, in preparation for transition to release state.
693
694 No GBB flags are set in release/shipping state, but they are useful
695 for factory/development. See "gbb_utility --flags" for details.
696 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800697
Ricky Lianga70a1202013-03-15 15:03:17 +0800698 GetGooftool(options).ClearGBBFlags()
Andy Cheng0465d132013-03-20 12:12:06 +0800699 event_log.Log('clear_gbb_flags')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800700
701
Jon Salzaa3a30e2013-05-15 15:56:28 +0800702@Command('clear_factory_vpd_entries')
703def ClearFactoryVPDEntries(options): # pylint: disable=W0613
704 """Clears factory.* items in the RW VPD."""
705 entries = GetGooftool(options).ClearFactoryVPDEntries()
706 event_log.Log('clear_factory_vpd_entries', entries=FilterDict(entries))
707
708
Mattias Nisslercca761b2015-04-15 21:53:04 +0200709@Command('generate_stable_device_secret')
710def GenerateStableDeviceSecret(options): # pylint: disable=W0613
711 """Generates a a fresh stable device secret and stores it in the RO VPD."""
712 GetGooftool(options).GenerateStableDeviceSecret()
713 event_log.Log('generate_stable_device_secret')
714
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800715
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800716@Command('wipe_in_place',
717 CmdArg('--fast', action='store_true',
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800718 help='use non-secure but faster wipe method.'),
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800719 _cutoff_args_cmd_arg,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800720 _shopfloor_url_args_cmd_arg,
721 _station_ip_cmd_arg,
722 _station_port_cmd_arg,
723 _wipe_finish_token_cmd_arg)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800724def WipeInPlace(options):
725 """Start factory wipe directly without reboot."""
726
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800727 GetGooftool(options).WipeInPlace(options.fast,
728 options.cutoff_args,
729 options.shopfloor_url,
730 options.station_ip,
731 options.station_port,
732 options.wipe_finish_token)
Mattias Nisslercca761b2015-04-15 21:53:04 +0200733
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800734@Command('wipe_init',
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800735 CmdArg('--wipe_args', help='arguments for clobber-state'),
736 CmdArg('--state_dev', help='path to stateful partition device'),
737 CmdArg('--root_disk', help='path to primary device'),
738 CmdArg('--old_root', help='path to old root'),
739 _cutoff_args_cmd_arg,
740 _shopfloor_url_args_cmd_arg,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800741 _release_rootfs_cmd_arg,
742 _station_ip_cmd_arg,
743 _station_port_cmd_arg,
744 _wipe_finish_token_cmd_arg)
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800745def WipeInit(options):
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800746 GetGooftool(options).WipeInit(options.wipe_args,
747 options.cutoff_args,
748 options.shopfloor_url,
749 options.state_dev,
750 options.release_rootfs,
751 options.root_disk,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800752 options.old_root,
753 options.station_ip,
754 options.station_port,
755 options.wipe_finish_token)
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800756
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800757@Command('prepare_wipe',
758 CmdArg('--fast', action='store_true',
759 help='use non-secure but faster wipe method.'))
760def PrepareWipe(options):
761 """Prepare system for transition to release state in next reboot."""
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800762
Ricky Lianga70a1202013-03-15 15:03:17 +0800763 GetGooftool(options).PrepareWipe(options.fast)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800764
Hung-Te Lin56b18402015-01-16 14:52:30 +0800765
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800766@Command('verify',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800767 CmdArg('--no_write_protect', action='store_true',
768 help='Do not check write protection switch state.'),
Ricky Liang43b879b2014-02-24 11:36:55 +0800769 _hwid_version_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700770 _hwid_status_list_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800771 _hwdb_path_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800772 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800773 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800774 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800775 _rma_mode_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800776 _cros_core_cmd_arg,
Hung-Te Lincdb96522016-04-15 16:51:10 +0800777 _release_rootfs_cmd_arg,
778 _firmware_path_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800779 _enforced_release_channels_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800780def Verify(options):
781 """Verifies if whole factory process is ready for finalization.
782
783 This routine performs all the necessary checks to make sure the
784 device is ready to be finalized, but does not modify state. These
785 checks include dev switch, firmware write protection switch, hwid,
786 system time, keys, and root file system.
787 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800788
Hung-Te Lin6d827542012-07-19 11:50:41 +0800789 if not options.no_write_protect:
Ricky Lianga70a1202013-03-15 15:03:17 +0800790 VerifyWPSwitch(options)
Hung-Te Lindd708d42014-07-11 17:05:01 +0800791 VerifyManagementEngineLocked(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800792 VerifyDevSwitch(options)
793 if options.hwid_version == 2:
Ricky Liang43b879b2014-02-24 11:36:55 +0800794 VerifyHWIDv2(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800795 elif options.hwid_version == 3:
Ricky Liangc662be32013-12-24 11:50:23 +0800796 VerifyHWIDv3(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800797 else:
798 raise Error, 'Invalid HWID version: %r' % options.hwid_version
799 VerifySystemTime(options)
800 VerifyKeys(options)
801 VerifyRootFs(options)
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800802 VerifyTPM(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800803 if options.cros_core:
804 logging.info('VerifyBranding is skipped for ChromeOS Core device.')
805 else:
806 VerifyBranding(options)
bowgotsai529139c2015-05-30 01:39:49 +0800807 VerifyReleaseChannel(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800808
Hung-Te Lin56b18402015-01-16 14:52:30 +0800809
Jon Salzfe9036f2014-01-16 14:11:23 +0800810@Command('untar_stateful_files')
Hung-Te Lin388bce22014-06-03 19:56:40 +0800811def UntarStatefulFiles(unused_options):
Jon Salzfe9036f2014-01-16 14:11:23 +0800812 """Untars stateful files from stateful_files.tar.xz on stateful partition.
813
814 If that file does not exist (which should only be R30 and earlier),
815 this is a no-op.
816 """
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +0800817 tar_file = os.path.join(paths.DEVICE_STATEFUL_PATH, 'stateful_files.tar.xz')
Jon Salzfe9036f2014-01-16 14:11:23 +0800818 if os.path.exists(tar_file):
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +0800819 Spawn(['tar', 'xf', tar_file], cwd=paths.DEVICE_STATEFUL_PATH,
Jon Salzfe9036f2014-01-16 14:11:23 +0800820 log=True, check_call=True)
821 else:
822 logging.warning('No stateful files at %s', tar_file)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800823
Jon Salz40b9f822014-07-25 16:39:55 +0800824
825@Command('log_source_hashes')
826def LogSourceHashes(options): # pylint: disable=W0613
827 """Logs hashes of source files in the factory toolkit."""
Jon Salze60307f2014-08-05 16:20:00 +0800828 # WARNING: The following line is necessary to validate the integrity
829 # of the factory software. Do not remove or modify it.
830 #
831 # 警告:此行会验证工厂软件的完整性,禁止删除或修改。
Wei-Han Chena5c01a02016-04-23 19:27:19 +0800832 factory_par = sys_utils.GetRunningFactoryPythonArchivePath()
833 if factory_par:
834 event_log.Log(
835 'source_hashes',
836 **file_utils.HashPythonArchive(factory_par))
837 else:
838 event_log.Log(
839 'source_hashes',
840 **file_utils.HashSourceTree(os.path.join(paths.FACTORY_PATH, 'py')))
Jon Salz40b9f822014-07-25 16:39:55 +0800841
842
Tammo Spalink86a61c62012-05-25 15:10:35 +0800843@Command('log_system_details')
Tammo Spalink01e11722012-07-24 10:17:54 -0700844def LogSystemDetails(options): # pylint: disable=W0613
Tammo Spalink86a61c62012-05-25 15:10:35 +0800845 """Write miscellaneous system details to the event log."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800846
Ricky Liang43b879b2014-02-24 11:36:55 +0800847 event_log.Log('system_details', **GetGooftool(options).GetSystemDetails())
Tammo Spalink86a61c62012-05-25 15:10:35 +0800848
849
Jon Salza88b83b2013-05-27 20:00:35 +0800850def CreateReportArchiveBlob(*args, **kwargs):
851 """Creates a report archive and returns it as a blob.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800852
Jon Salza88b83b2013-05-27 20:00:35 +0800853 Args:
854 See CreateReportArchive.
Andy Cheng7a76cb82012-11-19 18:08:19 +0800855
Jon Salza88b83b2013-05-27 20:00:35 +0800856 Returns:
857 An xmlrpclib.Binary object containing a .tar.xz file.
858 """
859 with open(CreateReportArchive(*args, **kwargs)) as f:
860 return xmlrpclib.Binary(f.read())
861
862
863def CreateReportArchive(device_sn=None, add_file=None):
864 """Creates a report archive in a temporary directory.
865
866 Args:
867 device_sn: The device serial number (optional).
868 add_file: A list of files to add (optional).
869
870 Returns:
871 Path to the archive.
872 """
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800873 def NormalizeAsFileName(token):
874 return re.sub(r'\W+', '', token).strip()
Jon Salza88b83b2013-05-27 20:00:35 +0800875
876 target_name = '%s%s.tar.xz' % (
877 time.strftime('%Y%m%dT%H%M%SZ',
878 time.gmtime()),
Hung-Te Lin56b18402015-01-16 14:52:30 +0800879 ('' if device_sn is None else
880 '_' + NormalizeAsFileName(device_sn)))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800881 target_path = os.path.join(gettempdir(), target_name)
Jon Salza88b83b2013-05-27 20:00:35 +0800882
Tammo Spalink86a61c62012-05-25 15:10:35 +0800883 # Intentionally ignoring dotfiles in EVENT_LOG_DIR.
Andy Cheng0465d132013-03-20 12:12:06 +0800884 tar_cmd = 'cd %s ; tar cJf %s *' % (event_log.EVENT_LOG_DIR, target_path)
Joel Kitching4b1b6c02016-05-10 14:34:30 +0800885 tar_cmd += ' --add-file %s' % paths.GetFactoryLogPath()
Jon Salza88b83b2013-05-27 20:00:35 +0800886 if add_file:
887 for f in add_file:
Jon Salz65266432012-07-30 19:02:49 +0800888 # Require absolute paths since the tar command may change the
889 # directory.
890 if not f.startswith('/'):
891 raise Error('Not an absolute path: %s' % f)
892 if not os.path.exists(f):
893 raise Error('File does not exist: %s' % f)
894 tar_cmd += ' --add-file %s' % pipes.quote(f)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800895 cmd_result = Shell(tar_cmd)
Jon Salzff88c022012-11-03 12:19:58 +0800896
897 if ((cmd_result.status == 1) and
898 all((x == '' or
899 'file changed as we read it' in x or
900 "Removing leading `/' from member names" in x)
901 for x in cmd_result.stderr.split('\n'))):
902 # That's OK. Make sure it's valid though.
Vic Yang85199e72013-01-28 14:33:11 +0800903 Spawn(['tar', 'tfJ', target_path], check_call=True, log=True,
Jon Salzff88c022012-11-03 12:19:58 +0800904 ignore_stdout=True)
905 elif not cmd_result.success:
Tammo Spalink86a61c62012-05-25 15:10:35 +0800906 raise Error('unable to tar event logs, cmd %r failed, stderr: %r' %
907 (tar_cmd, cmd_result.stderr))
Jon Salzff88c022012-11-03 12:19:58 +0800908
Jon Salza88b83b2013-05-27 20:00:35 +0800909 return target_path
910
911_upload_method_cmd_arg = CmdArg(
912 '--upload_method', metavar='METHOD:PARAM',
913 help=('How to perform the upload. METHOD should be one of '
914 '{ftp, shopfloor, ftps, cpfe}.'))
915_add_file_cmd_arg = CmdArg(
916 '--add_file', metavar='FILE', action='append',
917 help='Extra file to include in report (must be an absolute path)')
918
Hung-Te Lin56b18402015-01-16 14:52:30 +0800919
Jon Salza88b83b2013-05-27 20:00:35 +0800920@Command('upload_report',
921 _upload_method_cmd_arg,
922 _add_file_cmd_arg)
923def UploadReport(options):
924 """Create a report containing key device details."""
Hung-Te Lin74346d72016-01-07 22:16:57 +0800925 ro_vpd = ReadRoVpd()
Jon Salza88b83b2013-05-27 20:00:35 +0800926 device_sn = ro_vpd.get('serial_number', None)
927 if device_sn is None:
928 logging.warning('RO_VPD missing device serial number')
Chun-Ta Lin53cbbd52016-06-08 21:42:19 +0800929 device_sn = 'MISSING_SN_' + time_utils.TimedUUID()
Jon Salza88b83b2013-05-27 20:00:35 +0800930 target_path = CreateReportArchive(device_sn)
931
Tammo Spalink86a61c62012-05-25 15:10:35 +0800932 if options.upload_method is None or options.upload_method == 'none':
933 logging.warning('REPORT UPLOAD SKIPPED (report left at %s)', target_path)
934 return
935 method, param = options.upload_method.split(':', 1)
936 if method == 'shopfloor':
937 report_upload.ShopFloorUpload(target_path, param)
938 elif method == 'ftp':
Jay Kim360c1dd2012-06-25 10:58:11 -0700939 report_upload.FtpUpload(target_path, 'ftp:' + param)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800940 elif method == 'ftps':
941 report_upload.CurlUrlUpload(target_path, '--ftp-ssl-reqd ftp:%s' % param)
942 elif method == 'cpfe':
Shawn Nematbakhsh3404a092013-01-28 16:49:09 -0800943 report_upload.CpfeUpload(target_path, pipes.quote(param))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800944 else:
945 raise Error('unknown report upload method %r', method)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800946
947
948@Command('finalize',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800949 CmdArg('--no_write_protect', action='store_true',
950 help='Do not enable firmware write protection.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800951 CmdArg('--fast', action='store_true',
952 help='use non-secure but faster wipe method.'),
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800953 CmdArg('--wipe_in_place', action='store_true',
954 help='Start factory wiping in place without reboot.'),
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800955 _cutoff_args_cmd_arg,
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800956 _shopfloor_url_args_cmd_arg,
Ricky Liang43b879b2014-02-24 11:36:55 +0800957 _hwid_version_cmd_arg,
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800958 _hwdb_path_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700959 _hwid_status_list_cmd_arg,
Jon Salz65266432012-07-30 19:02:49 +0800960 _upload_method_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800961 _add_file_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800962 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800963 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800964 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800965 _rma_mode_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800966 _cros_core_cmd_arg,
Hung-Te Lincdb96522016-04-15 16:51:10 +0800967 _release_rootfs_cmd_arg,
968 _firmware_path_cmd_arg,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800969 _enforced_release_channels_cmd_arg,
970 _station_ip_cmd_arg,
971 _station_port_cmd_arg,
972 _wipe_finish_token_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800973def Finalize(options):
974 """Verify system readiness and trigger transition into release state.
975
Jon Salzaa3a30e2013-05-15 15:56:28 +0800976 This routine does the following:
977 - Verifies system state (see verify command)
Jon Salzfe9036f2014-01-16 14:11:23 +0800978 - Untars stateful_files.tar.xz, if it exists, in the stateful partition, to
979 initialize files such as the CRX cache
Jon Salzaa3a30e2013-05-15 15:56:28 +0800980 - Modifies firmware bitmaps to match locale
981 - Clears all factory-friendly flags from the GBB
982 - Removes factory-specific entries from RW_VPD (factory.*)
983 - Enables firmware write protection (cannot rollback after this)
984 - Uploads system logs & reports
985 - Sets the necessary boot flags to cause wipe of the factory image on the
986 next boot.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800987 """
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800988 Verify(options)
Jon Salz40b9f822014-07-25 16:39:55 +0800989 LogSourceHashes(options)
Jon Salzfe9036f2014-01-16 14:11:23 +0800990 UntarStatefulFiles(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800991 if options.cros_core:
992 logging.info('SetFirmwareBitmapLocale is skipped for ChromeOS Core device.')
993 else:
994 SetFirmwareBitmapLocale(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800995 ClearGBBFlags(options)
Jon Salzaa3a30e2013-05-15 15:56:28 +0800996 ClearFactoryVPDEntries(options)
Mattias Nisslercca761b2015-04-15 21:53:04 +0200997 GenerateStableDeviceSecret(options)
Hung-Te Lin6d827542012-07-19 11:50:41 +0800998 if options.no_write_protect:
999 logging.warn('WARNING: Firmware Write Protection is SKIPPED.')
Andy Cheng0465d132013-03-20 12:12:06 +08001000 event_log.Log('wp', fw='both', status='skipped')
Hung-Te Lin6d827542012-07-19 11:50:41 +08001001 else:
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001002 EnableFwWp({})
Jon Salza0f58e02012-05-29 19:33:39 +08001003 LogSystemDetails(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001004 UploadReport(options)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +08001005 if options.wipe_in_place:
1006 event_log.Log('wipe_in_place')
Wei-Han Chen0a3320e2016-04-23 01:32:07 +08001007 # WipeInPlace(options)
1008 wipe_args = []
Wei-Han Chen1f02f8f2016-05-31 11:05:24 +08001009 if options.cutoff_args:
1010 wipe_args += ['--cutoff_args', options.cutoff_args]
1011 if options.shopfloor_url:
1012 wipe_args += ['--shopfloor_url', options.shopfloor_url]
Wei-Han Chen0a3320e2016-04-23 01:32:07 +08001013 if options.fast:
1014 wipe_args += ['--fast']
Wei-Han Chenbe1355a2016-04-24 19:31:03 +08001015 if options.station_ip:
1016 wipe_args += ['--station_ip', options.station_ip]
1017 if options.station_port:
1018 wipe_args += ['--station_port', options.station_port]
1019 if options.wipe_finish_token:
1020 wipe_args += ['--wipe_finish_token', options.wipe_finish_token]
Wei-Han Chen0a3320e2016-04-23 01:32:07 +08001021 ExecFactoryPar('gooftool', 'wipe_in_place', *wipe_args)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +08001022 else:
1023 PrepareWipe(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001024
1025
Ricky Liangc662be32013-12-24 11:50:23 +08001026def VerifyHWIDv3(options):
1027 """A simple wrapper that calls out to HWID utils to verify version 3 HWID.
Ricky Liang53390232013-03-08 15:37:57 +08001028
Ricky Liangc662be32013-12-24 11:50:23 +08001029 This is mainly for Gooftool to verify v3 HWID during finalize. For testing
1030 and development purposes, please use `hwid` command.
Ricky Liang53390232013-03-08 15:37:57 +08001031 """
Ricky Liangc662be32013-12-24 11:50:23 +08001032 db = GetGooftool(options).db
1033 encoded_string = options.hwid or hwid_utils.GetHWIDString()
Ricky Liang7905f272013-03-16 01:57:10 +08001034 if options.probe_results:
Ricky Liangc662be32013-12-24 11:50:23 +08001035 probed_results = yaml.load(open(options.probe_results).read())
Ricky Liang7905f272013-03-16 01:57:10 +08001036 else:
Ricky Liangc662be32013-12-24 11:50:23 +08001037 probed_results = yaml.load(Probe(probe_vpd=True).Encode())
1038 vpd = hwid_utils.GetVPD(probed_results)
Ricky Liang53390232013-03-08 15:37:57 +08001039
Hung-Te Lin11052952015-03-18 13:48:59 +08001040 event_log.Log('probed_results', probed_results=FilterDict(probed_results))
1041 event_log.Log('vpd', vpd=FilterDict(vpd))
Ricky Liang53390232013-03-08 15:37:57 +08001042
Ricky Liangc662be32013-12-24 11:50:23 +08001043 hwid_utils.VerifyHWID(db, encoded_string, probed_results, vpd,
Hung-Te Lin56b18402015-01-16 14:52:30 +08001044 rma_mode=options.rma_mode)
Ricky Liang53390232013-03-08 15:37:57 +08001045
Ricky Liangc662be32013-12-24 11:50:23 +08001046 event_log.Log('verified_hwid', hwid=encoded_string)
Ricky Liang53390232013-03-08 15:37:57 +08001047
1048
Ricky Liang59611a62013-06-11 13:47:33 +08001049def ParseDecodedHWID(hwid):
1050 """Parse the HWID object into a more compact dict.
1051
1052 Args:
1053 hwid: A decoded HWID object.
1054
1055 Returns:
1056 A dict containing the board name, the binary string, and the list of
1057 components.
1058 """
1059 results = {}
1060 results['board'] = hwid.database.board
1061 results['binary_string'] = hwid.binary_string
1062 results['components'] = collections.defaultdict(list)
1063 components = hwid.bom.components
1064 for comp_cls in sorted(components):
1065 for (comp_name, probed_values, _) in sorted(components[comp_cls]):
1066 if not probed_values:
1067 db_components = hwid.database.components
1068 probed_values = db_components.GetComponentAttributes(
1069 comp_cls, comp_name).get('values')
1070 results['components'][comp_cls].append(
1071 {comp_name: probed_values if probed_values else None})
1072 # Convert defaultdict to dict.
1073 results['components'] = dict(results['components'])
1074 return results
1075
1076
henryhsu44d793a2013-07-20 00:07:38 +08001077@Command('get_firmware_hash',
1078 CmdArg('--file', metavar='FILE', help='Firmware File.'))
1079def GetFirmwareHash(options):
henryhsuf6f835c2013-07-20 20:49:25 +08001080 """Get firmware hash from a file"""
henryhsu44d793a2013-07-20 00:07:38 +08001081 if os.path.exists(options.file):
1082 hashes = CalculateFirmwareHashes(options.file)
1083 for section, value_dict in hashes.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +08001084 print '%s:' % section
henryhsu44d793a2013-07-20 00:07:38 +08001085 for key, value in value_dict.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +08001086 print ' %s: %s' % (key, value)
henryhsu44d793a2013-07-20 00:07:38 +08001087 else:
1088 raise Error('File does not exist: %s' % options.file)
1089
henryhsuf6f835c2013-07-20 20:49:25 +08001090
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001091def Main():
1092 """Run sub-command specified by the command line args."""
Andy Cheng7a76cb82012-11-19 18:08:19 +08001093
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001094 options = ParseCmdline(
Ricky Liangc662be32013-12-24 11:50:23 +08001095 ('Perform Google required factory tests. All the HWID-related functions '
1096 'provided here are mainly for the deprecated HWID v2. To access HWID '
1097 'v3-related utilities, please use `hwid` command.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001098 CmdArg('-l', '--log', metavar='PATH',
1099 help='Write logs to this file.'),
Jon Salza4bea382012-10-29 13:00:34 +08001100 CmdArg('--suppress-event-logs', action='store_true',
1101 help='Suppress event logging.'),
Wei-Han Chenaff56232016-04-16 09:17:59 +08001102 CmdArg('--phase', default=None,
1103 help=('override phase for phase checking (defaults to the current '
1104 'as returned by the "factory phase" command)')),
Tammo Spalink8fab5312012-05-28 18:33:30 +08001105 verbosity_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001106 SetupLogging(options.verbosity, options.log)
Andy Cheng0465d132013-03-20 12:12:06 +08001107 event_log.SetGlobalLoggerDefaultPrefix('gooftool')
1108 event_log.GetGlobalLogger().suppress = options.suppress_event_logs
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001109 logging.debug('gooftool options: %s', repr(options))
Wei-Han Chenaff56232016-04-16 09:17:59 +08001110
1111 phase.OverridePhase(options.phase)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001112 try:
1113 logging.debug('GOOFTOOL command %r', options.command_name)
1114 options.command(options)
1115 logging.info('GOOFTOOL command %r SUCCESS', options.command_name)
1116 except Error, e:
1117 logging.exception(e)
1118 sys.exit('GOOFTOOL command %r ERROR: %s' % (options.command_name, e))
1119 except Exception, e:
1120 logging.exception(e)
1121 sys.exit('UNCAUGHT RUNTIME EXCEPTION %s' % e)
1122
1123
1124if __name__ == '__main__':
1125 Main()