blob: cfa5fee2370367ebfd26daa5cd0558bc400c8035 [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
Hung-Te Lin0e0f9362015-11-18 18:18:05 +080054from cros.factory.utils.debug_utils import SetupLogging
Jon Salzff88c022012-11-03 12:19:58 +080055from cros.factory.utils.process_utils import Spawn
Joel Kitchingd3bc2662014-12-16 16:03:32 -080056from cros.factory.utils.type_utils import Error
Tammo Spalink86a61c62012-05-25 15:10:35 +080057
Tammo Spalink5c699832012-07-03 17:50:39 +080058
Tammo Spalink5c699832012-07-03 17:50:39 +080059# TODO(tammo): Replace calls to sys.exit with raise Exit, and maybe
60# treat that specially (as a smoot exit, as opposed to the more
61# verbose output for generic Error).
62
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080063_global_gooftool = None
64_gooftool_lock = threading.Lock()
Tammo Spalink5c699832012-07-03 17:50:39 +080065
Hung-Te Lin56b18402015-01-16 14:52:30 +080066
Ricky Lianga70a1202013-03-15 15:03:17 +080067def GetGooftool(options):
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080068 global _global_gooftool # pylint: disable=W0603
Ricky Lianga70a1202013-03-15 15:03:17 +080069
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080070 if _global_gooftool is None:
71 with _gooftool_lock:
Ricky Liang43b879b2014-02-24 11:36:55 +080072 hwid_version = getattr(options, 'hwid_version', 3)
73 if hwid_version == 2:
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080074 hwdb_path = getattr(options, 'hwdb_path', None)
75 component_db = (
76 hwid_tool.HardwareDb(options.hwdb_path).comp_db if hwdb_path
77 else None)
78 _global_gooftool = Gooftool(hwid_version=2, component_db=component_db)
Ricky Liang43b879b2014-02-24 11:36:55 +080079 elif hwid_version == 3:
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080080 board = getattr(options, 'board', None)
81 hwdb_path = getattr(options, 'hwdb_path', None)
82 _global_gooftool = Gooftool(hwid_version=3, board=board,
83 hwdb_path=hwdb_path)
84 else:
85 raise Error, 'Invalid HWID version: %r' % options.hwid_version
86
87 return _global_gooftool
Ricky Lianga70a1202013-03-15 15:03:17 +080088
Hung-Te Lin56b18402015-01-16 14:52:30 +080089
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080090@Command('write_hwid',
91 CmdArg('hwid', metavar='HWID', help='HWID string'))
Andy Chengc92e6f92012-11-20 16:55:53 +080092def WriteHWID(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080093 """Write specified HWID value into the system BB."""
Andy Cheng7a76cb82012-11-19 18:08:19 +080094
Tammo Spalink95c43732012-07-25 15:57:14 -070095 logging.info('writing hwid string %r', options.hwid)
Ricky Lianga70a1202013-03-15 15:03:17 +080096 GetGooftool(options).WriteHWID(options.hwid)
Andy Cheng0465d132013-03-20 12:12:06 +080097 event_log.Log('write_hwid', hwid=options.hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -070098 print 'Wrote HWID: %r' % options.hwid
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080099
100
Ricky Liang53390232013-03-08 15:37:57 +0800101_board_cmd_arg = CmdArg(
102 '--board', metavar='BOARD',
103 default=None, help='Board name to test.')
104
Tammo Spalink8fab5312012-05-28 18:33:30 +0800105_hwdb_path_cmd_arg = CmdArg(
106 '--hwdb_path', metavar='PATH',
Ricky Liangeede7922013-06-19 10:18:41 +0800107 default=common.DEFAULT_HWID_DATA_PATH,
Tammo Spalink8fab5312012-05-28 18:33:30 +0800108 help='Path to the HWID database.')
109
Tammo Spalink95c43732012-07-25 15:57:14 -0700110_hwid_status_list_cmd_arg = CmdArg(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800111 '--status', nargs='*', default=['supported'],
112 help='allow only HWIDs with these status values')
Tammo Spalink95c43732012-07-25 15:57:14 -0700113
Jon Salzce124fb2012-10-02 17:42:03 +0800114_probe_results_cmd_arg = CmdArg(
115 '--probe_results', metavar='RESULTS.yaml',
Ricky Liangc662be32013-12-24 11:50:23 +0800116 help=('Output from "gooftool probe --include_vpd" (used instead of '
Jon Salzce124fb2012-10-02 17:42:03 +0800117 'probing this system).'))
118
Ricky Liang53390232013-03-08 15:37:57 +0800119_device_info_cmd_arg = CmdArg(
Ricky Liangf89f73a2013-03-19 05:00:24 +0800120 '--device_info', metavar='DEVICE_INFO.yaml', default=None,
Ricky Liang53390232013-03-08 15:37:57 +0800121 help='A dict of device info to use instead of fetching from shopfllor '
122 'server.')
123
Jon Salzce124fb2012-10-02 17:42:03 +0800124_hwid_cmd_arg = CmdArg(
125 '--hwid', metavar='HWID',
Ricky Lianga70a1202013-03-15 15:03:17 +0800126 help='HWID to verify (instead of the currently set HWID of this system).')
Jon Salzce124fb2012-10-02 17:42:03 +0800127
Bernie Thompson3c11c872013-07-22 18:22:45 -0700128_rma_mode_cmd_arg = CmdArg(
129 '--rma_mode', action='store_true',
130 help='Enable RMA mode, do not check for deprecated components.')
Tammo Spalink95c43732012-07-25 15:57:14 -0700131
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800132_cros_core_cmd_arg = CmdArg(
133 '--cros_core', action='store_true',
134 help='Finalize for ChromeOS Core devices (may add or remove few test '
135 'items. For example, branding verification or firmware bitmap '
136 'locale settings).')
137
Ricky Liang43b879b2014-02-24 11:36:55 +0800138_hwid_version_cmd_arg = CmdArg(
139 '-i', '--hwid-version', default=3, choices=(2, 3), type=int,
140 help='Version of HWID to operate on. (default: %(default)s)')
141
bowgotsai13820f42015-09-10 23:18:04 +0800142_enforced_release_channels_cmd_arg = CmdArg(
143 '--enforced_release_channels', nargs='*', default=None,
144 help='Enforced release image channels.')
145
Hung-Te Lincdb96522016-04-15 16:51:10 +0800146_release_rootfs_cmd_arg = CmdArg(
147 '--release_rootfs', help='Location of release image rootfs partition.')
148
149_firmware_path_cmd_arg = CmdArg(
150 '--firmware_path', help='Location of firmware image partition.')
Ricky Liang43b879b2014-02-24 11:36:55 +0800151
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800152_cutoff_args_cmd_arg = CmdArg(
153 '--cutoff_args',
154 help='Battery cutoff arguments to be passed to battery_cutoff.sh '
155 'after wiping. Should be the following format: '
156 '[--method shutdown|reboot|battery_cutoff] '
157 '[--check-ac connect_ac|remove_ac] '
158 '[--min-battery-percent <minimum battery percentage>] '
159 '[--max-battery-percent <maximum battery percentage>] '
160 '[--min-battery-voltage <minimum battery voltage>] '
161 '[--max-battery-voltage <maximum battery voltage>]')
162
163_shopfloor_url_args_cmd_arg = CmdArg(
164 '--shopfloor_url',
165 help='Shopfloor server url to be informed when in-place wipe is done. '
166 'After in-place wipe, a XML-RPC request will be sent to the '
167 'given url to indicate the completion of wipe.')
168
169_station_ip_cmd_arg = CmdArg(
170 '--station_ip',
171 help='IP of remote station')
172
173_station_port_cmd_arg = CmdArg(
174 '--station_port',
175 help='Port on remote station')
176
177_wipe_finish_token_cmd_arg = CmdArg(
178 '--wipe_finish_token',
179 help='Required token when notifying station after wipe finished')
180
Tammo Spalink95c43732012-07-25 15:57:14 -0700181@Command('best_match_hwids',
Tammo Spalink8fab5312012-05-28 18:33:30 +0800182 _hwdb_path_cmd_arg,
183 CmdArg('-b', '--board', metavar='BOARD',
Tammo Spalink95c43732012-07-25 15:57:14 -0700184 help='optional BOARD name, needed only if data is present '
185 'for more than one'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800186 CmdArg('--bom', metavar='BOM', help='BOM name'),
187 CmdArg('--variant', metavar='VARIANT', help='VARIANT code'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800188 CmdArg('--optimistic', action='store_true',
189 help='do not probe; assume singletons match'),
Tammo Spalink95c43732012-07-25 15:57:14 -0700190 CmdArg('--comps', nargs='*', default=[],
191 help='list of canonical component names'),
192 CmdArg('--missing', nargs='*', default=[],
193 help='list component classes to be assumed missing'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800194 CmdArg('--status', nargs='*', default=['supported'],
Tammo Spalink95c43732012-07-25 15:57:14 -0700195 help='consider only HWIDs within this list of status values'))
196def BestMatchHwids(options):
Ricky Liangc662be32013-12-24 11:50:23 +0800197 """Determine a list of possible HWIDs using provided args and probing.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800198
199 VOLATILE can always be determined by probing. To get a unique
200 result, VARIANT must be specified for all cases where the matching
201 BOM has more than one associated variant code, otherwise all HWID
202 variants will be returned. Both VARIANT and BOM information can
Tammo Spalink95c43732012-07-25 15:57:14 -0700203 alternatively be specified using the --stdin_comps argument, which
204 allows specifying a list of canonical names (one per line) on stdin,
205 one per line. Based on what is known from BOM and stdin_comps,
206 determine a list of components to probe for, and use those probe
207 results to resolve a list of matching HWIDs. If no boms,
208 components, or variant codes are specified, then a list of all HWIDs
Andy Cheng8ece7382012-08-22 16:25:42 +0800209 that match probeable components will be returned.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800210
211 Returns (on stdout): A list of HWIDs that match the available probe
212 results and argument contraints, one per line.
Tammo Spalink70b48a52012-08-08 16:54:51 -0700213
214 Example:
215
216 // Three ways to specify a keyboard (assuming it is a variant component)
217 gooftool best_match_hwids --missing keyboard
218 gooftool best_match_hwids --variant A or
219 gooftool best_match_hwids --comps us_kbd
Tammo Spalink8fab5312012-05-28 18:33:30 +0800220 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800221
Tammo Spalink5c699832012-07-03 17:50:39 +0800222 map(hwid_tool.Validate.Status, options.status)
Tammo Spalink95c43732012-07-25 15:57:14 -0700223 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Tammo Spalink5c699832012-07-03 17:50:39 +0800224 comp_db = hw_db.comp_db
Tammo Spalink3a7e9022012-06-27 14:08:40 +0800225 device = hw_db.GetDevice(options.board)
Tammo Spalink5c699832012-07-03 17:50:39 +0800226 component_spec = hwid_tool.ComponentSpec.New()
Tammo Spalink8fab5312012-05-28 18:33:30 +0800227 if options.bom:
Tammo Spalink5c699832012-07-03 17:50:39 +0800228 device.BomExists(options.bom)
Tammo Spalink01e11722012-07-24 10:17:54 -0700229 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800230 component_spec, device.boms[options.bom].primary)
Tammo Spalink8fab5312012-05-28 18:33:30 +0800231 if options.variant:
Tammo Spalink5c699832012-07-03 17:50:39 +0800232 device.VariantExists(options.variant)
233 variant_spec = device.variants[options.variant]
Tammo Spalink01e11722012-07-24 10:17:54 -0700234 if hwid_tool.ComponentSpecsConflict(component_spec, variant_spec):
Tammo Spalink95c43732012-07-25 15:57:14 -0700235 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700236 % YamlWrite(sorted(
237 hwid_tool.ComponentSpecClasses(component_spec) &
238 hwid_tool.ComponentSpecClasses(variant_spec))))
Tammo Spalink01e11722012-07-24 10:17:54 -0700239 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800240 component_spec, variant_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700241 if options.comps or options.missing:
242 map(comp_db.CompExists, options.comps)
243 map(comp_db.CompClassExists, options.missing)
244 extra_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800245 components=options.comps,
246 missing=options.missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700247 print 'cmdline asserted components:\n%s' % extra_comp_spec.Encode()
248 if hwid_tool.ComponentSpecsConflict(component_spec, extra_comp_spec):
249 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700250 % YamlWrite(sorted(
251 hwid_tool.ComponentSpecClasses(component_spec) &
252 hwid_tool.ComponentSpecClasses(extra_comp_spec))))
Tammo Spalink95c43732012-07-25 15:57:14 -0700253 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800254 component_spec, extra_comp_spec)
Tammo Spalink01e11722012-07-24 10:17:54 -0700255 spec_classes = hwid_tool.ComponentSpecClasses(component_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700256 missing_classes = set(comp_db.all_comp_classes) - spec_classes
Tammo Spalink5c699832012-07-03 17:50:39 +0800257 if missing_classes and not options.optimistic:
Andy Cheng8ece7382012-08-22 16:25:42 +0800258 non_probeable_missing = missing_classes - PROBEABLE_COMPONENT_CLASSES
259 if non_probeable_missing:
Tammo Spalink95c43732012-07-25 15:57:14 -0700260 sys.exit('FAILURE: these classes are necessary, were not specified '
Tammo Spalink70b48a52012-08-08 16:54:51 -0700261 'as inputs, and cannot be probed for:\n%s'
262 'This problem can often be addressed by specifying all of '
263 'the missing components on the command line (see the command '
Andy Cheng8ece7382012-08-22 16:25:42 +0800264 'help).' % YamlWrite(list(non_probeable_missing)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700265 print 'probing for missing classes:'
266 print YamlWrite(list(missing_classes))
267 probe_results = Probe(target_comp_classes=list(missing_classes),
268 probe_volatile=False, probe_initial_config=False)
269 cooked_components = comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800270 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700271 if cooked_components.unmatched:
272 sys.exit('ERROR: some probed components are unrecognized:\n%s'
273 % YamlWrite(cooked_components.unmatched))
274 probed_comp_spec = comp_db.CreateComponentSpec(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800275 components=cooked_components.matched,
276 missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700277 component_spec = hwid_tool.CombineComponentSpecs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800278 component_spec, probed_comp_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700279 print YamlWrite({'component data used for matching': {
Hung-Te Lin56b18402015-01-16 14:52:30 +0800280 'missing component classes': component_spec.classes_missing,
281 'found components': component_spec.components}})
Tammo Spalink95c43732012-07-25 15:57:14 -0700282 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800283 extant_components=hwid_tool.ComponentSpecCompClassMap(
284 component_spec).keys(),
285 classes_missing=component_spec.classes_missing)
Tammo Spalink95c43732012-07-25 15:57:14 -0700286 match_tree = device.BuildMatchTree(component_data)
287 if not match_tree:
288 sys.exit('FAILURE: NO matching BOMs found')
289 print 'potential BOMs/VARIANTs:'
290 potential_variants = set()
291 potential_volatiles = set()
292 for bom_name, variant_tree in match_tree.items():
293 print ' BOM: %-8s VARIANTS: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800294 bom_name, ', '.join(sorted(variant_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700295 for variant_code in variant_tree:
296 potential_variants.add(variant_code)
297 for volatile_code in device.volatiles:
298 status = device.GetHwidStatus(bom_name, variant_code, volatile_code)
299 if status in options.status:
300 potential_volatiles.add(volatile_code)
301 print ''
302 if len(potential_variants) == 0:
303 sys.exit('FAILURE: no matching VARIANTs found')
304 if len(potential_volatiles) == 0:
305 sys.exit('FAILURE: no VOLATILEs found for potential matching BOMs/VARIANTS '
306 '(with specified status)')
Tammo Spalink394e4492012-08-01 10:20:30 -0700307 if (options.optimistic and
308 len(match_tree) == 1 and
309 len(potential_variants) == 1 and
310 len(potential_volatiles) == 1):
311 print ('MATCHING HWID: %s' % device.FmtHwid(match_tree.keys().pop(),
312 potential_variants.pop(),
313 potential_volatiles.pop()))
Tammo Spalink5c699832012-07-03 17:50:39 +0800314 return
Tammo Spalink95c43732012-07-25 15:57:14 -0700315 print ('probing VOLATILEs to resolve potential matches: %s\n' %
316 ', '.join(sorted(potential_volatiles)))
317 vol_probe_results = Probe(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800318 target_comp_classes=[],
319 probe_volatile=True,
320 probe_initial_config=False)
Tammo Spalink95c43732012-07-25 15:57:14 -0700321 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800322 vol_probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700323 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800324 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700325 matched_hwids = device.GetMatchTreeHwids(match_tree)
326 if matched_hwids:
327 for hwid in matched_hwids:
Ricky Liang02f3bd72012-09-21 14:33:01 +0800328 if matched_hwids[hwid] in options.status:
329 print 'MATCHING HWID: %s' % hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700330 return
331 print 'exact HWID matching failed, but the following BOMs match: %s' % (
Hung-Te Lin56b18402015-01-16 14:52:30 +0800332 ', '.join(sorted(match_tree)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700333 if options.optimistic and len(match_tree) == 1:
334 bom_name = set(match_tree).pop()
Tammo Spalink5c699832012-07-03 17:50:39 +0800335 bom = device.boms[bom_name]
Tammo Spalink95c43732012-07-25 15:57:14 -0700336 variant_matches = match_tree[bom_name]
Tammo Spalink5c699832012-07-03 17:50:39 +0800337 if len(variant_matches) == 1:
338 var_code = set(variant_matches).pop()
339 elif len(bom.variants) == 1:
340 var_code = set(bom.variants).pop()
341 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700342 sys.exit('FAILURE: NO matching HWIDs found; optimistic matching failed '
343 'because there were too many variants to choose from for BOM %r'
344 % bom_name)
345 hwids = [device.FmtHwid(bom_name, var_code, vol_code)
346 for vol_code in device.volatiles
347 if device.GetHwidStatus(bom_name, var_code, vol_code)
348 in options.status]
349 for hwid in hwids:
350 print 'MATCHING HWID: %s' % hwid
Tammo Spalink5c699832012-07-03 17:50:39 +0800351 return
352 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700353 print ('optimistic matching not attempted because either it was '
354 'not requested, or because the number of BOMs was <> 1\n')
355 sys.exit('FAILURE: NO matching HWIDs found')
Tammo Spalink8fab5312012-05-28 18:33:30 +0800356
357
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800358@Command('probe',
359 CmdArg('--comps', nargs='*',
360 help='List of keys from the component_db registry.'),
Ricky Liangb30da672013-06-14 12:36:34 +0800361 CmdArg('--fast_fw_probe', action='store_true',
362 help='Do a fast probe for EC and main firmware versions only. '
363 'This implies --no_vol and --no_ic.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800364 CmdArg('--no_vol', action='store_true',
365 help='Do not probe volatile data.'),
366 CmdArg('--no_ic', action='store_true',
Jon Salz0f8a6842012-09-25 11:28:22 +0800367 help='Do not probe initial_config data.'),
368 CmdArg('--include_vpd', action='store_true',
369 help='Include VPD data in volatiles.'))
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800370def RunProbe(options):
371 """Print yaml-formatted breakdown of probed device properties."""
Ricky Lianga70a1202013-03-15 15:03:17 +0800372 print GetGooftool(options).Probe(
373 target_comp_classes=options.comps,
Ricky Liangb30da672013-06-14 12:36:34 +0800374 fast_fw_probe=options.fast_fw_probe,
Ricky Lianga70a1202013-03-15 15:03:17 +0800375 probe_volatile=not options.no_vol,
376 probe_initial_config=not options.no_ic,
377 probe_vpd=options.include_vpd).Encode()
Ricky Liang53390232013-03-08 15:37:57 +0800378
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800379
Tammo Spalink214caf42012-05-28 10:45:00 +0800380@Command('verify_components',
381 _hwdb_path_cmd_arg,
Tammo Spalink5c699832012-07-03 17:50:39 +0800382 CmdArg('target_comps', nargs='*'))
Tammo Spalink214caf42012-05-28 10:45:00 +0800383def VerifyComponents(options):
Andy Cheng8ece7382012-08-22 16:25:42 +0800384 """Verify that probeable components all match entries in the component_db.
Tammo Spalink214caf42012-05-28 10:45:00 +0800385
Tammo Spalink5c699832012-07-03 17:50:39 +0800386 Probe for each component class in the target_comps and verify
Tammo Spalink214caf42012-05-28 10:45:00 +0800387 that a corresponding match exists in the component_db -- make sure
388 that these components are present, that they have been approved, but
389 do not check against any specific BOM/HWID configurations.
390 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800391
Andy Chengc531e2f2012-10-15 19:09:17 +0800392 try:
Ricky Lianga70a1202013-03-15 15:03:17 +0800393 result = GetGooftool(options).VerifyComponents(
Andy Chengc531e2f2012-10-15 19:09:17 +0800394 options.target_comps)
395 except ValueError, e:
396 sys.exit(e)
397
Ricky Liang53390232013-03-08 15:37:57 +0800398 PrintVerifyComponentsResults(result)
399
400
401def PrintVerifyComponentsResults(result):
402 """Prints out the results of VerifyComponents method call.
403
404 Groups the results into two groups: 'matches' and 'errors', and prints out
405 their values.
406 """
Andy Chengc531e2f2012-10-15 19:09:17 +0800407 # group by matches and errors
Tammo Spalink214caf42012-05-28 10:45:00 +0800408 matches = []
Andy Chengc531e2f2012-10-15 19:09:17 +0800409 errors = []
410 for result_list in result.values():
411 for component_name, _, error in result_list:
412 if component_name:
413 matches.append(component_name)
Tammo Spalink214caf42012-05-28 10:45:00 +0800414 else:
Andy Chengc531e2f2012-10-15 19:09:17 +0800415 errors.append(error)
416
Andy Cheng228a8c92012-08-27 10:53:57 +0800417 if matches:
418 print 'found probeable components:\n %s' % '\n '.join(matches)
Tammo Spalink214caf42012-05-28 10:45:00 +0800419 if errors:
Andy Cheng228a8c92012-08-27 10:53:57 +0800420 print '\nerrors:\n %s' % '\n '.join(errors)
421 sys.exit('\ncomponent verification FAILURE')
Tammo Spalink214caf42012-05-28 10:45:00 +0800422 else:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800423 print '\ncomponent verification SUCCESS'
Tammo Spalink214caf42012-05-28 10:45:00 +0800424
425
Ricky Liang43b879b2014-02-24 11:36:55 +0800426@Command('verify_hwid_v2',
Tammo Spalink95c43732012-07-25 15:57:14 -0700427 _hwid_status_list_cmd_arg,
Jon Salz0f8a6842012-09-25 11:28:22 +0800428 _hwdb_path_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800429 _probe_results_cmd_arg,
430 _hwid_cmd_arg)
Ricky Liang43b879b2014-02-24 11:36:55 +0800431def VerifyHWIDv2(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800432 """Verify system HWID properties match probed device properties.
433
434 First probe components, volatile and initial_config parameters for
435 the DUT. Then use the available device data to produce a list of
436 candidate HWIDs. Then verify the HWID from the DUT is present in
437 that list. Then verify that the DUT initial config values match
438 those specified for its HWID. Finally, verify that VPD contains all
439 the necessary fields as specified by the board data, and when
440 possible verify that values are legitimate.
441 """
Ricky Liangf7857c12012-09-17 13:34:41 +0800442 def VerifyVpd(ro_vpd_keys, rw_vpd_keys):
Tammo Spalink5c699832012-07-03 17:50:39 +0800443 for key in ro_vpd_keys:
444 if key not in ro_vpd:
Ricky Liangf7857c12012-09-17 13:34:41 +0800445 sys.exit('Missing required RO VPD field: %s' % key)
Tammo Spalink01e11722012-07-24 10:17:54 -0700446 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800447 value = ro_vpd[key]
Ricky Liangf7857c12012-09-17 13:34:41 +0800448 if (known_valid_values is not None) and (value not in known_valid_values):
449 sys.exit('Invalid RO VPD entry : key %r, value %r' % (key, value))
Ricky Liangf7857c12012-09-17 13:34:41 +0800450 for key in rw_vpd_keys:
451 if key not in rw_vpd:
452 sys.exit('Missing required RW VPD field: %s' % key)
453 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
454 value = rw_vpd[key]
455 if (known_valid_values is not None) and (value not in known_valid_values):
456 sys.exit('Invalid RW VPD entry : key %r, value %r' % (key, value))
Andy Cheng0465d132013-03-20 12:12:06 +0800457 event_log.Log('vpd', ro_vpd=FilterDict(ro_vpd), rw_vpd=FilterDict(rw_vpd))
Tammo Spalink5c699832012-07-03 17:50:39 +0800458 map(hwid_tool.Validate.Status, options.status)
Jon Salz0f8a6842012-09-25 11:28:22 +0800459
Jon Salz0f8a6842012-09-25 11:28:22 +0800460 if options.hwid:
461 hwid_str = options.hwid
462 else:
Hung-Te Lin74346d72016-01-07 22:16:57 +0800463 main_fw_file = crosfw.LoadMainFirmware().GetFileName()
Jon Salz0f8a6842012-09-25 11:28:22 +0800464 gbb_result = Shell('gbb_utility -g --hwid %s' % main_fw_file).stdout
465 hwid_str = re.findall(r'hardware_id:(.*)', gbb_result)[0].strip()
Tammo Spalink95c43732012-07-25 15:57:14 -0700466 hwid = hwid_tool.ParseHwid(hwid_str)
Tammo Spalink5c699832012-07-03 17:50:39 +0800467 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Jon Salz0f8a6842012-09-25 11:28:22 +0800468 print 'Verifying HWID: %r\n' % hwid.hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700469 device = hw_db.GetDevice(hwid.board)
470 hwid_status = device.GetHwidStatus(hwid.bom, hwid.variant, hwid.volatile)
471 if hwid_status not in options.status:
Tammo Spalink5c699832012-07-03 17:50:39 +0800472 sys.exit('HWID status must be one of [%s], found %r' %
Hung-Te Lin4f5beb12012-08-20 14:48:06 +0800473 (', '.join(options.status), hwid_status))
Jon Salz0f8a6842012-09-25 11:28:22 +0800474 if options.probe_results:
475 # Pull in probe results (including VPD data) from the given file
476 # rather than probing the current system.
477 probe_results = hwid_tool.ProbeResults.Decode(
478 open(options.probe_results).read())
479 ro_vpd = {}
480 rw_vpd = {}
481 for k, v in probe_results.found_volatile_values.items():
Hung-Te Lin56b18402015-01-16 14:52:30 +0800482 match = re.match(r'^vpd\.(ro|rw)\.(\w+)$', k)
Jon Salz0f8a6842012-09-25 11:28:22 +0800483 if match:
484 del probe_results.found_volatile_values[k]
485 (ro_vpd if match.group(1) == 'ro' else rw_vpd)[match.group(2)] = v
486 else:
487 probe_results = Probe()
Hung-Te Lin74346d72016-01-07 22:16:57 +0800488 ro_vpd = ReadRoVpd()
489 rw_vpd = ReadRwVpd()
Tammo Spalink95c43732012-07-25 15:57:14 -0700490 cooked_components = hw_db.comp_db.MatchComponentProbeValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800491 probe_results.found_probe_value_map)
Tammo Spalink95c43732012-07-25 15:57:14 -0700492 cooked_volatiles = device.MatchVolatileValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800493 probe_results.found_volatile_values)
Tammo Spalink95c43732012-07-25 15:57:14 -0700494 cooked_initial_configs = device.MatchInitialConfigValues(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800495 probe_results.initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700496 component_data = hwid_tool.ComponentData(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800497 extant_components=cooked_components.matched,
498 classes_missing=probe_results.missing_component_classes)
Tammo Spalink95c43732012-07-25 15:57:14 -0700499 match_tree = device.BuildMatchTree(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800500 component_data, cooked_volatiles.matched_tags)
Tammo Spalink95c43732012-07-25 15:57:14 -0700501 matched_hwids = device.GetMatchTreeHwids(match_tree)
502 print 'HWID status: %s\n' % hwid_status
503 print 'probed system components:'
504 print YamlWrite(cooked_components.__dict__)
505 print 'missing component classes:'
506 print YamlWrite(probe_results.missing_component_classes)
507 print 'probed volatiles:'
508 print YamlWrite(cooked_volatiles.__dict__)
509 print 'probed initial_configs:'
510 print YamlWrite(cooked_initial_configs)
511 print 'hwid match tree:'
512 print YamlWrite(match_tree)
Andy Cheng0465d132013-03-20 12:12:06 +0800513 event_log.Log(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800514 'probe',
515 found_components=cooked_components.__dict__,
516 missing_component_classes=probe_results.missing_component_classes,
517 volatiles=cooked_volatiles.__dict__,
518 initial_configs=cooked_initial_configs)
Tammo Spalink95c43732012-07-25 15:57:14 -0700519 if hwid.hwid not in matched_hwids:
Tammo Spalink5c699832012-07-03 17:50:39 +0800520 err_msg = 'HWID verification FAILED.\n'
Tammo Spalink95c43732012-07-25 15:57:14 -0700521 if cooked_components.unmatched:
Tammo Spalink5c699832012-07-03 17:50:39 +0800522 sys.exit(err_msg + 'some components could not be indentified:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700523 YamlWrite(cooked_components.unmatched))
524 if not match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800525 sys.exit(err_msg + 'no matching boms were found for components:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700526 component_data.Encode())
527 if hwid.bom not in match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800528 sys.exit(err_msg + 'matching boms [%s] do not include target bom %r' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700529 (', '.join(sorted(match_tree)), hwid.bom))
530 err_msg += 'target bom %r matches components' % hwid.bom
531 if hwid.bom not in device.IntersectBomsAndInitialConfigs(
Hung-Te Lin56b18402015-01-16 14:52:30 +0800532 cooked_initial_configs):
Tammo Spalink5c699832012-07-03 17:50:39 +0800533 sys.exit(err_msg + ', but failed initial config verification')
Tammo Spalink95c43732012-07-25 15:57:14 -0700534 matched_variants = match_tree.get(hwid.bom, {})
535 if hwid.variant not in matched_variants:
Tammo Spalink5c699832012-07-03 17:50:39 +0800536 sys.exit(err_msg + ', but target variant_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700537 hwid.variant)
538 matched_volatiles = matched_variants.get(hwid.variant, {})
539 if hwid.volatile not in matched_volatiles:
Tammo Spalink5c699832012-07-03 17:50:39 +0800540 sys.exit(err_msg + ', but target volatile_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700541 hwid.volatile)
542 found_status = matched_volatiles.get(hwid.volatile, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800543 sys.exit(err_msg + ', but hwid status %r was unacceptable' % found_status)
Ricky Liangf7857c12012-09-17 13:34:41 +0800544 VerifyVpd(device.vpd_ro_fields, device.vpd_rw_fields)
Andy Cheng0465d132013-03-20 12:12:06 +0800545 event_log.Log('verified_hwid', hwid=hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -0700546 print 'Verification SUCCESS!'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800547
548
Hung-Te Line1d80f62016-03-31 14:58:13 +0800549@Command('verify_keys',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800550 _release_rootfs_cmd_arg,
551 _firmware_path_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700552def VerifyKeys(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800553 """Verify keys in firmware and SSD match."""
Hung-Te Line1d80f62016-03-31 14:58:13 +0800554 return GetGooftool(options).VerifyKeys(
Hung-Te Lincdb96522016-04-15 16:51:10 +0800555 options.release_rootfs, options.firmware_path)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800556
557
558@Command('set_fw_bitmap_locale')
Tammo Spalink01e11722012-07-24 10:17:54 -0700559def SetFirmwareBitmapLocale(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800560 """Use VPD locale value to set firmware bitmap default language."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800561
Ricky Lianga70a1202013-03-15 15:03:17 +0800562 (index, locale) = GetGooftool(options).SetFirmwareBitmapLocale()
Andy Cheng2582d292012-12-04 17:38:28 +0800563 logging.info('Firmware bitmap initial locale set to %d (%s).',
564 index, locale)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800565
566
Hung-Te Line1d80f62016-03-31 14:58:13 +0800567@Command('verify_system_time',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800568 _release_rootfs_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700569def VerifySystemTime(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800570 """Verify system time is later than release filesystem creation time."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800571
Hung-Te Lincdb96522016-04-15 16:51:10 +0800572 return GetGooftool(options).VerifySystemTime(options.release_rootfs)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800573
574
Hung-Te Line1d80f62016-03-31 14:58:13 +0800575@Command('verify_rootfs',
Hung-Te Lincdb96522016-04-15 16:51:10 +0800576 _release_rootfs_cmd_arg)
Tammo Spalink01e11722012-07-24 10:17:54 -0700577def VerifyRootFs(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800578 """Verify rootfs on SSD is valid by checking hash."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800579
Hung-Te Line1d80f62016-03-31 14:58:13 +0800580 return GetGooftool(options).VerifyRootFs(options.release_rootfs)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800581
Hung-Te Lin56b18402015-01-16 14:52:30 +0800582
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800583@Command('verify_tpm')
584def VerifyTPM(options): # pylint: disable=W0613
585 """Verify TPM is cleared."""
586
587 return GetGooftool(options).VerifyTPM()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800588
Hung-Te Lin56b18402015-01-16 14:52:30 +0800589
Hung-Te Lindd708d42014-07-11 17:05:01 +0800590@Command('verify_me_locked')
591def VerifyManagementEngineLocked(options): # pylint: disable=W0613
592 """Verify Managment Engine is locked."""
593
594 return GetGooftool(options).VerifyManagementEngineLocked()
595
Hung-Te Lin56b18402015-01-16 14:52:30 +0800596
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800597@Command('verify_switch_wp')
Andy Chengc92e6f92012-11-20 16:55:53 +0800598def VerifyWPSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800599 """Verify hardware write protection switch is enabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800600
Ricky Lianga70a1202013-03-15 15:03:17 +0800601 GetGooftool(options).VerifyWPSwitch()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800602
603
604@Command('verify_switch_dev')
Tammo Spalink01e11722012-07-24 10:17:54 -0700605def VerifyDevSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800606 """Verify developer switch is disabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800607
Ricky Lianga70a1202013-03-15 15:03:17 +0800608 if GetGooftool(options).CheckDevSwitchForDisabling():
Hung-Te Lind7d34722012-07-26 16:48:35 +0800609 logging.warn('VerifyDevSwitch: No physical switch.')
Andy Cheng0465d132013-03-20 12:12:06 +0800610 event_log.Log('switch_dev', type='virtual switch')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800611
612
Jon Salzadd90d32014-04-29 16:16:27 +0800613@Command('verify_branding')
614def VerifyBranding(options): # pylint: disable=W0613
615 """Verify that branding fields are properly set.
616
617 customization_id, if set in the RO VPD, must be of the correct format.
618
619 rlz_brand_code must be set either in the RO VPD or OEM partition, and must
620 be of the correct format.
621 """
622 return GetGooftool(options).VerifyBranding()
623
624
bowgotsai13820f42015-09-10 23:18:04 +0800625@Command('verify_release_channel',
626 _enforced_release_channels_cmd_arg)
bowgotsai529139c2015-05-30 01:39:49 +0800627def VerifyReleaseChannel(options): # pylint: disable=W0613
628 """Verify that release image channel is correct.
629
630 ChromeOS has four channels: canary, dev, beta and stable.
631 The last three channels support image auto-updates, checks
632 that release image channel is one of them.
633 """
bowgotsai13820f42015-09-10 23:18:04 +0800634 return GetGooftool(options).VerifyReleaseChannel(
635 options.enforced_release_channels)
bowgotsai529139c2015-05-30 01:39:49 +0800636
637
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800638@Command('write_protect')
Tammo Spalink01e11722012-07-24 10:17:54 -0700639def EnableFwWp(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800640 """Enable then verify firmware write protection."""
641
Hung-Te Linb21c6682012-08-01 13:53:57 +0800642 def CalculateLegacyRange(fw_type, length, section_data,
643 section_name):
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800644 ro_size = length / 2
645 ro_a = int(section_data[0] / ro_size)
646 ro_b = int((section_data[0] + section_data[1] - 1) / ro_size)
647 if ro_a != ro_b:
Hung-Te Lin56b18402015-01-16 14:52:30 +0800648 raise Error('%s firmware section %s has illegal size' %
Hung-Te Linb21c6682012-08-01 13:53:57 +0800649 (fw_type, section_name))
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800650 ro_offset = ro_a * ro_size
651 return (ro_offset, ro_size)
652
653 def WriteProtect(fw_file_path, fw_type, legacy_section):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800654 """Calculate protection size, then invoke flashrom.
655
656 Our supported chips only allow write protecting half their total
657 size, so we parition the flash chipset space accordingly.
658 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800659
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800660 raw_image = open(fw_file_path, 'rb').read()
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800661 wp_section = 'WP_RO'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800662 image = crosfw.FirmwareImage(raw_image)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800663 if image.has_section(wp_section):
664 section_data = image.get_section_area(wp_section)
665 ro_offset = section_data[0]
666 ro_size = section_data[1]
667 elif image.has_section(legacy_section):
668 section_data = image.get_section_area(legacy_section)
669 (ro_offset, ro_size) = CalculateLegacyRange(
Hung-Te Linb21c6682012-08-01 13:53:57 +0800670 fw_type, len(raw_image), section_data, legacy_section)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800671 else:
672 raise Error('could not find %s firmware section %s or %s' %
673 (fw_type, wp_section, legacy_section))
674
675 logging.debug('write protecting %s [off=%x size=%x]', fw_type,
676 ro_offset, ro_size)
677 crosfw.Flashrom(fw_type).EnableWriteProtection(ro_offset, ro_size)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800678
679 WriteProtect(crosfw.LoadMainFirmware().GetFileName(), 'main', 'RO_SECTION')
Andy Cheng0465d132013-03-20 12:12:06 +0800680 event_log.Log('wp', fw='main')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800681 ec_fw_file = crosfw.LoadEcFirmware().GetFileName()
682 if ec_fw_file is not None:
683 WriteProtect(ec_fw_file, 'ec', 'EC_RO')
Andy Cheng0465d132013-03-20 12:12:06 +0800684 event_log.Log('wp', fw='ec')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800685 else:
686 logging.warning('EC not write protected (seems there is no EC flash).')
687
688
689@Command('clear_gbb_flags')
Andy Chengc92e6f92012-11-20 16:55:53 +0800690def ClearGBBFlags(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800691 """Zero out the GBB flags, in preparation for transition to release state.
692
693 No GBB flags are set in release/shipping state, but they are useful
694 for factory/development. See "gbb_utility --flags" for details.
695 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800696
Ricky Lianga70a1202013-03-15 15:03:17 +0800697 GetGooftool(options).ClearGBBFlags()
Andy Cheng0465d132013-03-20 12:12:06 +0800698 event_log.Log('clear_gbb_flags')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800699
700
Jon Salzaa3a30e2013-05-15 15:56:28 +0800701@Command('clear_factory_vpd_entries')
702def ClearFactoryVPDEntries(options): # pylint: disable=W0613
703 """Clears factory.* items in the RW VPD."""
704 entries = GetGooftool(options).ClearFactoryVPDEntries()
705 event_log.Log('clear_factory_vpd_entries', entries=FilterDict(entries))
706
707
Mattias Nisslercca761b2015-04-15 21:53:04 +0200708@Command('generate_stable_device_secret')
709def GenerateStableDeviceSecret(options): # pylint: disable=W0613
710 """Generates a a fresh stable device secret and stores it in the RO VPD."""
711 GetGooftool(options).GenerateStableDeviceSecret()
712 event_log.Log('generate_stable_device_secret')
713
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800714
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800715@Command('wipe_in_place',
716 CmdArg('--fast', action='store_true',
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800717 help='use non-secure but faster wipe method.'),
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800718 _cutoff_args_cmd_arg,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800719 _shopfloor_url_args_cmd_arg,
720 _station_ip_cmd_arg,
721 _station_port_cmd_arg,
722 _wipe_finish_token_cmd_arg)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800723def WipeInPlace(options):
724 """Start factory wipe directly without reboot."""
725
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800726 GetGooftool(options).WipeInPlace(options.fast,
727 options.cutoff_args,
728 options.shopfloor_url,
729 options.station_ip,
730 options.station_port,
731 options.wipe_finish_token)
Mattias Nisslercca761b2015-04-15 21:53:04 +0200732
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800733@Command('wipe_init',
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800734 CmdArg('--wipe_args', help='arguments for clobber-state'),
735 CmdArg('--state_dev', help='path to stateful partition device'),
736 CmdArg('--root_disk', help='path to primary device'),
737 CmdArg('--old_root', help='path to old root'),
738 _cutoff_args_cmd_arg,
739 _shopfloor_url_args_cmd_arg,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800740 _release_rootfs_cmd_arg,
741 _station_ip_cmd_arg,
742 _station_port_cmd_arg,
743 _wipe_finish_token_cmd_arg)
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800744def WipeInit(options):
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800745 GetGooftool(options).WipeInit(options.wipe_args,
746 options.cutoff_args,
747 options.shopfloor_url,
748 options.state_dev,
749 options.release_rootfs,
750 options.root_disk,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800751 options.old_root,
752 options.station_ip,
753 options.station_port,
754 options.wipe_finish_token)
Wei-Han Chen7dc6d132016-04-06 11:11:53 +0800755
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800756@Command('prepare_wipe',
757 CmdArg('--fast', action='store_true',
758 help='use non-secure but faster wipe method.'))
759def PrepareWipe(options):
760 """Prepare system for transition to release state in next reboot."""
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800761
Ricky Lianga70a1202013-03-15 15:03:17 +0800762 GetGooftool(options).PrepareWipe(options.fast)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800763
Hung-Te Lin56b18402015-01-16 14:52:30 +0800764
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800765@Command('verify',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800766 CmdArg('--no_write_protect', action='store_true',
767 help='Do not check write protection switch state.'),
Ricky Liang43b879b2014-02-24 11:36:55 +0800768 _hwid_version_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700769 _hwid_status_list_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800770 _hwdb_path_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800771 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800772 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800773 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800774 _rma_mode_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800775 _cros_core_cmd_arg,
Hung-Te Lincdb96522016-04-15 16:51:10 +0800776 _release_rootfs_cmd_arg,
777 _firmware_path_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800778 _enforced_release_channels_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800779def Verify(options):
780 """Verifies if whole factory process is ready for finalization.
781
782 This routine performs all the necessary checks to make sure the
783 device is ready to be finalized, but does not modify state. These
784 checks include dev switch, firmware write protection switch, hwid,
785 system time, keys, and root file system.
786 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800787
Hung-Te Lin6d827542012-07-19 11:50:41 +0800788 if not options.no_write_protect:
Ricky Lianga70a1202013-03-15 15:03:17 +0800789 VerifyWPSwitch(options)
Hung-Te Lindd708d42014-07-11 17:05:01 +0800790 VerifyManagementEngineLocked(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800791 VerifyDevSwitch(options)
792 if options.hwid_version == 2:
Ricky Liang43b879b2014-02-24 11:36:55 +0800793 VerifyHWIDv2(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800794 elif options.hwid_version == 3:
Ricky Liangc662be32013-12-24 11:50:23 +0800795 VerifyHWIDv3(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800796 else:
797 raise Error, 'Invalid HWID version: %r' % options.hwid_version
798 VerifySystemTime(options)
799 VerifyKeys(options)
800 VerifyRootFs(options)
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800801 VerifyTPM(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800802 if options.cros_core:
803 logging.info('VerifyBranding is skipped for ChromeOS Core device.')
804 else:
805 VerifyBranding(options)
bowgotsai529139c2015-05-30 01:39:49 +0800806 VerifyReleaseChannel(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800807
Hung-Te Lin56b18402015-01-16 14:52:30 +0800808
Jon Salzfe9036f2014-01-16 14:11:23 +0800809@Command('untar_stateful_files')
Hung-Te Lin388bce22014-06-03 19:56:40 +0800810def UntarStatefulFiles(unused_options):
Jon Salzfe9036f2014-01-16 14:11:23 +0800811 """Untars stateful files from stateful_files.tar.xz on stateful partition.
812
813 If that file does not exist (which should only be R30 and earlier),
814 this is a no-op.
815 """
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +0800816 tar_file = os.path.join(paths.DEVICE_STATEFUL_PATH, 'stateful_files.tar.xz')
Jon Salzfe9036f2014-01-16 14:11:23 +0800817 if os.path.exists(tar_file):
Wei-Han Chen2ebb92d2016-01-12 14:51:41 +0800818 Spawn(['tar', 'xf', tar_file], cwd=paths.DEVICE_STATEFUL_PATH,
Jon Salzfe9036f2014-01-16 14:11:23 +0800819 log=True, check_call=True)
820 else:
821 logging.warning('No stateful files at %s', tar_file)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800822
Jon Salz40b9f822014-07-25 16:39:55 +0800823
824@Command('log_source_hashes')
825def LogSourceHashes(options): # pylint: disable=W0613
826 """Logs hashes of source files in the factory toolkit."""
Jon Salze60307f2014-08-05 16:20:00 +0800827 # WARNING: The following line is necessary to validate the integrity
828 # of the factory software. Do not remove or modify it.
829 #
830 # 警告:此行会验证工厂软件的完整性,禁止删除或修改。
Wei-Han Chena5c01a02016-04-23 19:27:19 +0800831 factory_par = sys_utils.GetRunningFactoryPythonArchivePath()
832 if factory_par:
833 event_log.Log(
834 'source_hashes',
835 **file_utils.HashPythonArchive(factory_par))
836 else:
837 event_log.Log(
838 'source_hashes',
839 **file_utils.HashSourceTree(os.path.join(paths.FACTORY_PATH, 'py')))
Jon Salz40b9f822014-07-25 16:39:55 +0800840
841
Tammo Spalink86a61c62012-05-25 15:10:35 +0800842@Command('log_system_details')
Tammo Spalink01e11722012-07-24 10:17:54 -0700843def LogSystemDetails(options): # pylint: disable=W0613
Tammo Spalink86a61c62012-05-25 15:10:35 +0800844 """Write miscellaneous system details to the event log."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800845
Ricky Liang43b879b2014-02-24 11:36:55 +0800846 event_log.Log('system_details', **GetGooftool(options).GetSystemDetails())
Tammo Spalink86a61c62012-05-25 15:10:35 +0800847
848
Jon Salza88b83b2013-05-27 20:00:35 +0800849def CreateReportArchiveBlob(*args, **kwargs):
850 """Creates a report archive and returns it as a blob.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800851
Jon Salza88b83b2013-05-27 20:00:35 +0800852 Args:
853 See CreateReportArchive.
Andy Cheng7a76cb82012-11-19 18:08:19 +0800854
Jon Salza88b83b2013-05-27 20:00:35 +0800855 Returns:
856 An xmlrpclib.Binary object containing a .tar.xz file.
857 """
858 with open(CreateReportArchive(*args, **kwargs)) as f:
859 return xmlrpclib.Binary(f.read())
860
861
862def CreateReportArchive(device_sn=None, add_file=None):
863 """Creates a report archive in a temporary directory.
864
865 Args:
866 device_sn: The device serial number (optional).
867 add_file: A list of files to add (optional).
868
869 Returns:
870 Path to the archive.
871 """
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800872 def NormalizeAsFileName(token):
873 return re.sub(r'\W+', '', token).strip()
Jon Salza88b83b2013-05-27 20:00:35 +0800874
875 target_name = '%s%s.tar.xz' % (
876 time.strftime('%Y%m%dT%H%M%SZ',
877 time.gmtime()),
Hung-Te Lin56b18402015-01-16 14:52:30 +0800878 ('' if device_sn is None else
879 '_' + NormalizeAsFileName(device_sn)))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800880 target_path = os.path.join(gettempdir(), target_name)
Jon Salza88b83b2013-05-27 20:00:35 +0800881
Tammo Spalink86a61c62012-05-25 15:10:35 +0800882 # Intentionally ignoring dotfiles in EVENT_LOG_DIR.
Andy Cheng0465d132013-03-20 12:12:06 +0800883 tar_cmd = 'cd %s ; tar cJf %s *' % (event_log.EVENT_LOG_DIR, target_path)
Joel Kitching4b1b6c02016-05-10 14:34:30 +0800884 tar_cmd += ' --add-file %s' % paths.GetFactoryLogPath()
Jon Salza88b83b2013-05-27 20:00:35 +0800885 if add_file:
886 for f in add_file:
Jon Salz65266432012-07-30 19:02:49 +0800887 # Require absolute paths since the tar command may change the
888 # directory.
889 if not f.startswith('/'):
890 raise Error('Not an absolute path: %s' % f)
891 if not os.path.exists(f):
892 raise Error('File does not exist: %s' % f)
893 tar_cmd += ' --add-file %s' % pipes.quote(f)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800894 cmd_result = Shell(tar_cmd)
Jon Salzff88c022012-11-03 12:19:58 +0800895
896 if ((cmd_result.status == 1) and
897 all((x == '' or
898 'file changed as we read it' in x or
899 "Removing leading `/' from member names" in x)
900 for x in cmd_result.stderr.split('\n'))):
901 # That's OK. Make sure it's valid though.
Vic Yang85199e72013-01-28 14:33:11 +0800902 Spawn(['tar', 'tfJ', target_path], check_call=True, log=True,
Jon Salzff88c022012-11-03 12:19:58 +0800903 ignore_stdout=True)
904 elif not cmd_result.success:
Tammo Spalink86a61c62012-05-25 15:10:35 +0800905 raise Error('unable to tar event logs, cmd %r failed, stderr: %r' %
906 (tar_cmd, cmd_result.stderr))
Jon Salzff88c022012-11-03 12:19:58 +0800907
Jon Salza88b83b2013-05-27 20:00:35 +0800908 return target_path
909
910_upload_method_cmd_arg = CmdArg(
911 '--upload_method', metavar='METHOD:PARAM',
912 help=('How to perform the upload. METHOD should be one of '
913 '{ftp, shopfloor, ftps, cpfe}.'))
914_add_file_cmd_arg = CmdArg(
915 '--add_file', metavar='FILE', action='append',
916 help='Extra file to include in report (must be an absolute path)')
917
Hung-Te Lin56b18402015-01-16 14:52:30 +0800918
Jon Salza88b83b2013-05-27 20:00:35 +0800919@Command('upload_report',
920 _upload_method_cmd_arg,
921 _add_file_cmd_arg)
922def UploadReport(options):
923 """Create a report containing key device details."""
Hung-Te Lin74346d72016-01-07 22:16:57 +0800924 ro_vpd = ReadRoVpd()
Jon Salza88b83b2013-05-27 20:00:35 +0800925 device_sn = ro_vpd.get('serial_number', None)
926 if device_sn is None:
927 logging.warning('RO_VPD missing device serial number')
928 device_sn = 'MISSING_SN_' + event_log.TimedUuid()
929 target_path = CreateReportArchive(device_sn)
930
Tammo Spalink86a61c62012-05-25 15:10:35 +0800931 if options.upload_method is None or options.upload_method == 'none':
932 logging.warning('REPORT UPLOAD SKIPPED (report left at %s)', target_path)
933 return
934 method, param = options.upload_method.split(':', 1)
935 if method == 'shopfloor':
936 report_upload.ShopFloorUpload(target_path, param)
937 elif method == 'ftp':
Jay Kim360c1dd2012-06-25 10:58:11 -0700938 report_upload.FtpUpload(target_path, 'ftp:' + param)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800939 elif method == 'ftps':
940 report_upload.CurlUrlUpload(target_path, '--ftp-ssl-reqd ftp:%s' % param)
941 elif method == 'cpfe':
Shawn Nematbakhsh3404a092013-01-28 16:49:09 -0800942 report_upload.CpfeUpload(target_path, pipes.quote(param))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800943 else:
944 raise Error('unknown report upload method %r', method)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800945
946
947@Command('finalize',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800948 CmdArg('--no_write_protect', action='store_true',
949 help='Do not enable firmware write protection.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800950 CmdArg('--fast', action='store_true',
951 help='use non-secure but faster wipe method.'),
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +0800952 CmdArg('--wipe_in_place', action='store_true',
953 help='Start factory wiping in place without reboot.'),
Shun-Hsing Ou8d3c40a2015-10-08 18:16:08 +0800954 _cutoff_args_cmd_arg,
Shun-Hsing Oudb407d62015-11-11 11:03:59 +0800955 _shopfloor_url_args_cmd_arg,
Ricky Liang43b879b2014-02-24 11:36:55 +0800956 _hwid_version_cmd_arg,
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800957 _hwdb_path_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700958 _hwid_status_list_cmd_arg,
Jon Salz65266432012-07-30 19:02:49 +0800959 _upload_method_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800960 _add_file_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800961 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800962 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800963 _hwid_cmd_arg,
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800964 _rma_mode_cmd_arg,
bowgotsai13820f42015-09-10 23:18:04 +0800965 _cros_core_cmd_arg,
Hung-Te Lincdb96522016-04-15 16:51:10 +0800966 _release_rootfs_cmd_arg,
967 _firmware_path_cmd_arg,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800968 _enforced_release_channels_cmd_arg,
969 _station_ip_cmd_arg,
970 _station_port_cmd_arg,
971 _wipe_finish_token_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800972def Finalize(options):
973 """Verify system readiness and trigger transition into release state.
974
Jon Salzaa3a30e2013-05-15 15:56:28 +0800975 This routine does the following:
976 - Verifies system state (see verify command)
Jon Salzfe9036f2014-01-16 14:11:23 +0800977 - Untars stateful_files.tar.xz, if it exists, in the stateful partition, to
978 initialize files such as the CRX cache
Jon Salzaa3a30e2013-05-15 15:56:28 +0800979 - Modifies firmware bitmaps to match locale
980 - Clears all factory-friendly flags from the GBB
981 - Removes factory-specific entries from RW_VPD (factory.*)
982 - Enables firmware write protection (cannot rollback after this)
983 - Uploads system logs & reports
984 - Sets the necessary boot flags to cause wipe of the factory image on the
985 next boot.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800986 """
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800987 Verify(options)
Jon Salz40b9f822014-07-25 16:39:55 +0800988 LogSourceHashes(options)
Jon Salzfe9036f2014-01-16 14:11:23 +0800989 UntarStatefulFiles(options)
Chih-Yu Huang714dbc42015-07-21 16:42:16 +0800990 if options.cros_core:
991 logging.info('SetFirmwareBitmapLocale is skipped for ChromeOS Core device.')
992 else:
993 SetFirmwareBitmapLocale(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800994 ClearGBBFlags(options)
Jon Salzaa3a30e2013-05-15 15:56:28 +0800995 ClearFactoryVPDEntries(options)
Mattias Nisslercca761b2015-04-15 21:53:04 +0200996 GenerateStableDeviceSecret(options)
Hung-Te Lin6d827542012-07-19 11:50:41 +0800997 if options.no_write_protect:
998 logging.warn('WARNING: Firmware Write Protection is SKIPPED.')
Andy Cheng0465d132013-03-20 12:12:06 +0800999 event_log.Log('wp', fw='both', status='skipped')
Hung-Te Lin6d827542012-07-19 11:50:41 +08001000 else:
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001001 EnableFwWp({})
Jon Salza0f58e02012-05-29 19:33:39 +08001002 LogSystemDetails(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001003 UploadReport(options)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +08001004 if options.wipe_in_place:
1005 event_log.Log('wipe_in_place')
Wei-Han Chen0a3320e2016-04-23 01:32:07 +08001006 # WipeInPlace(options)
1007 wipe_args = []
Wei-Han Chen1f02f8f2016-05-31 11:05:24 +08001008 if options.cutoff_args:
1009 wipe_args += ['--cutoff_args', options.cutoff_args]
1010 if options.shopfloor_url:
1011 wipe_args += ['--shopfloor_url', options.shopfloor_url]
Wei-Han Chen0a3320e2016-04-23 01:32:07 +08001012 if options.fast:
1013 wipe_args += ['--fast']
Wei-Han Chenbe1355a2016-04-24 19:31:03 +08001014 if options.station_ip:
1015 wipe_args += ['--station_ip', options.station_ip]
1016 if options.station_port:
1017 wipe_args += ['--station_port', options.station_port]
1018 if options.wipe_finish_token:
1019 wipe_args += ['--wipe_finish_token', options.wipe_finish_token]
Wei-Han Chen0a3320e2016-04-23 01:32:07 +08001020 ExecFactoryPar('gooftool', 'wipe_in_place', *wipe_args)
Shun-Hsing Oucdc64e12015-01-14 22:07:33 +08001021 else:
1022 PrepareWipe(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001023
1024
Ricky Liangc662be32013-12-24 11:50:23 +08001025def VerifyHWIDv3(options):
1026 """A simple wrapper that calls out to HWID utils to verify version 3 HWID.
Ricky Liang53390232013-03-08 15:37:57 +08001027
Ricky Liangc662be32013-12-24 11:50:23 +08001028 This is mainly for Gooftool to verify v3 HWID during finalize. For testing
1029 and development purposes, please use `hwid` command.
Ricky Liang53390232013-03-08 15:37:57 +08001030 """
Ricky Liangc662be32013-12-24 11:50:23 +08001031 db = GetGooftool(options).db
1032 encoded_string = options.hwid or hwid_utils.GetHWIDString()
Ricky Liang7905f272013-03-16 01:57:10 +08001033 if options.probe_results:
Ricky Liangc662be32013-12-24 11:50:23 +08001034 probed_results = yaml.load(open(options.probe_results).read())
Ricky Liang7905f272013-03-16 01:57:10 +08001035 else:
Ricky Liangc662be32013-12-24 11:50:23 +08001036 probed_results = yaml.load(Probe(probe_vpd=True).Encode())
1037 vpd = hwid_utils.GetVPD(probed_results)
Ricky Liang53390232013-03-08 15:37:57 +08001038
Hung-Te Lin11052952015-03-18 13:48:59 +08001039 event_log.Log('probed_results', probed_results=FilterDict(probed_results))
1040 event_log.Log('vpd', vpd=FilterDict(vpd))
Ricky Liang53390232013-03-08 15:37:57 +08001041
Ricky Liangc662be32013-12-24 11:50:23 +08001042 hwid_utils.VerifyHWID(db, encoded_string, probed_results, vpd,
Hung-Te Lin56b18402015-01-16 14:52:30 +08001043 rma_mode=options.rma_mode)
Ricky Liang53390232013-03-08 15:37:57 +08001044
Ricky Liangc662be32013-12-24 11:50:23 +08001045 event_log.Log('verified_hwid', hwid=encoded_string)
Ricky Liang53390232013-03-08 15:37:57 +08001046
1047
Ricky Liang59611a62013-06-11 13:47:33 +08001048def ParseDecodedHWID(hwid):
1049 """Parse the HWID object into a more compact dict.
1050
1051 Args:
1052 hwid: A decoded HWID object.
1053
1054 Returns:
1055 A dict containing the board name, the binary string, and the list of
1056 components.
1057 """
1058 results = {}
1059 results['board'] = hwid.database.board
1060 results['binary_string'] = hwid.binary_string
1061 results['components'] = collections.defaultdict(list)
1062 components = hwid.bom.components
1063 for comp_cls in sorted(components):
1064 for (comp_name, probed_values, _) in sorted(components[comp_cls]):
1065 if not probed_values:
1066 db_components = hwid.database.components
1067 probed_values = db_components.GetComponentAttributes(
1068 comp_cls, comp_name).get('values')
1069 results['components'][comp_cls].append(
1070 {comp_name: probed_values if probed_values else None})
1071 # Convert defaultdict to dict.
1072 results['components'] = dict(results['components'])
1073 return results
1074
1075
henryhsu44d793a2013-07-20 00:07:38 +08001076@Command('get_firmware_hash',
1077 CmdArg('--file', metavar='FILE', help='Firmware File.'))
1078def GetFirmwareHash(options):
henryhsuf6f835c2013-07-20 20:49:25 +08001079 """Get firmware hash from a file"""
henryhsu44d793a2013-07-20 00:07:38 +08001080 if os.path.exists(options.file):
1081 hashes = CalculateFirmwareHashes(options.file)
1082 for section, value_dict in hashes.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +08001083 print '%s:' % section
henryhsu44d793a2013-07-20 00:07:38 +08001084 for key, value in value_dict.iteritems():
Hung-Te Lin56b18402015-01-16 14:52:30 +08001085 print ' %s: %s' % (key, value)
henryhsu44d793a2013-07-20 00:07:38 +08001086 else:
1087 raise Error('File does not exist: %s' % options.file)
1088
henryhsuf6f835c2013-07-20 20:49:25 +08001089
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001090def Main():
1091 """Run sub-command specified by the command line args."""
Andy Cheng7a76cb82012-11-19 18:08:19 +08001092
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001093 options = ParseCmdline(
Ricky Liangc662be32013-12-24 11:50:23 +08001094 ('Perform Google required factory tests. All the HWID-related functions '
1095 'provided here are mainly for the deprecated HWID v2. To access HWID '
1096 'v3-related utilities, please use `hwid` command.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001097 CmdArg('-l', '--log', metavar='PATH',
1098 help='Write logs to this file.'),
Jon Salza4bea382012-10-29 13:00:34 +08001099 CmdArg('--suppress-event-logs', action='store_true',
1100 help='Suppress event logging.'),
Wei-Han Chenaff56232016-04-16 09:17:59 +08001101 CmdArg('--phase', default=None,
1102 help=('override phase for phase checking (defaults to the current '
1103 'as returned by the "factory phase" command)')),
Tammo Spalink8fab5312012-05-28 18:33:30 +08001104 verbosity_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001105 SetupLogging(options.verbosity, options.log)
Andy Cheng0465d132013-03-20 12:12:06 +08001106 event_log.SetGlobalLoggerDefaultPrefix('gooftool')
1107 event_log.GetGlobalLogger().suppress = options.suppress_event_logs
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001108 logging.debug('gooftool options: %s', repr(options))
Wei-Han Chenaff56232016-04-16 09:17:59 +08001109
1110 phase.OverridePhase(options.phase)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +08001111 try:
1112 logging.debug('GOOFTOOL command %r', options.command_name)
1113 options.command(options)
1114 logging.info('GOOFTOOL command %r SUCCESS', options.command_name)
1115 except Error, e:
1116 logging.exception(e)
1117 sys.exit('GOOFTOOL command %r ERROR: %s' % (options.command_name, e))
1118 except Exception, e:
1119 logging.exception(e)
1120 sys.exit('UNCAUGHT RUNTIME EXCEPTION %s' % e)
1121
1122
1123if __name__ == '__main__':
1124 Main()