blob: e6bcbc92715e6cb1782bbdc0e4345e763e236920 [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
Andy Cheng0465d132013-03-20 12:12:06 +080031from cros.factory import event_log
Jon Salz0f8a6842012-09-25 11:28:22 +080032from cros.factory.common import Error, SetupLogging, Shell
Andy Chengc531e2f2012-10-15 19:09:17 +080033from cros.factory.gooftool import Gooftool
Ricky Liang53390232013-03-08 15:37:57 +080034from cros.factory.gooftool import crosfw
Tammo Spalink01e11722012-07-24 10:17:54 -070035from cros.factory.gooftool import report_upload
Andy Cheng8ece7382012-08-22 16:25:42 +080036from cros.factory.gooftool.probe import Probe, PROBEABLE_COMPONENT_CLASSES
Jon Salz0f8a6842012-09-25 11:28:22 +080037from cros.factory.gooftool.probe import ReadRoVpd, ReadRwVpd
henryhsu44d793a2013-07-20 00:07:38 +080038from cros.factory.gooftool.probe import CalculateFirmwareHashes
Jon Salz193d7c62013-03-07 13:40:19 +080039from cros.factory.gooftool.vpd_data import KNOWN_VPD_FIELD_DATA
Tammo Spalinka40293e2012-07-04 14:58:56 +080040from cros.factory.hacked_argparse import CmdArg, Command, ParseCmdline
41from cros.factory.hacked_argparse import verbosity_cmd_arg
Tammo Spalink01e11722012-07-24 10:17:54 -070042from cros.factory.hwdb import hwid_tool
Hung-Te Linca61e732014-08-27 10:27:25 +080043from cros.factory.hwdb.yaml_datastore import YamlWrite
Ricky Liangeede7922013-06-19 10:18:41 +080044from cros.factory.hwid import common
Ricky Liangc662be32013-12-24 11:50:23 +080045from cros.factory.hwid import hwid_utils
Jon Salz40b9f822014-07-25 16:39:55 +080046from cros.factory.test import factory
Jon Salzfe9036f2014-01-16 14:11:23 +080047from cros.factory.test.factory import FACTORY_LOG_PATH, DEVICE_STATEFUL_PATH
Jon Salz40b9f822014-07-25 16:39:55 +080048from cros.factory.utils import file_utils
Jon Salzff88c022012-11-03 12:19:58 +080049from cros.factory.utils.process_utils import Spawn
Jon Salz8baad8b2013-03-11 20:01:45 +080050from cros.factory.privacy import FilterDict
Tammo Spalink86a61c62012-05-25 15:10:35 +080051
Tammo Spalink5c699832012-07-03 17:50:39 +080052
Tammo Spalink5c699832012-07-03 17:50:39 +080053# TODO(tammo): Replace calls to sys.exit with raise Exit, and maybe
54# treat that specially (as a smoot exit, as opposed to the more
55# verbose output for generic Error).
56
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080057_global_gooftool = None
58_gooftool_lock = threading.Lock()
Tammo Spalink5c699832012-07-03 17:50:39 +080059
Ricky Lianga70a1202013-03-15 15:03:17 +080060def GetGooftool(options):
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080061 global _global_gooftool # pylint: disable=W0603
Ricky Lianga70a1202013-03-15 15:03:17 +080062
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080063 if _global_gooftool is None:
64 with _gooftool_lock:
Ricky Liang43b879b2014-02-24 11:36:55 +080065 hwid_version = getattr(options, 'hwid_version', 3)
66 if hwid_version == 2:
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080067 hwdb_path = getattr(options, 'hwdb_path', None)
68 component_db = (
69 hwid_tool.HardwareDb(options.hwdb_path).comp_db if hwdb_path
70 else None)
71 _global_gooftool = Gooftool(hwid_version=2, component_db=component_db)
Ricky Liang43b879b2014-02-24 11:36:55 +080072 elif hwid_version == 3:
Cheng-Yi Chiang9fc121c2014-01-27 11:23:22 +080073 board = getattr(options, 'board', None)
74 hwdb_path = getattr(options, 'hwdb_path', None)
75 _global_gooftool = Gooftool(hwid_version=3, board=board,
76 hwdb_path=hwdb_path)
77 else:
78 raise Error, 'Invalid HWID version: %r' % options.hwid_version
79
80 return _global_gooftool
Ricky Lianga70a1202013-03-15 15:03:17 +080081
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080082@Command('write_hwid',
83 CmdArg('hwid', metavar='HWID', help='HWID string'))
Andy Chengc92e6f92012-11-20 16:55:53 +080084def WriteHWID(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080085 """Write specified HWID value into the system BB."""
Andy Cheng7a76cb82012-11-19 18:08:19 +080086
Tammo Spalink95c43732012-07-25 15:57:14 -070087 logging.info('writing hwid string %r', options.hwid)
Ricky Lianga70a1202013-03-15 15:03:17 +080088 GetGooftool(options).WriteHWID(options.hwid)
Andy Cheng0465d132013-03-20 12:12:06 +080089 event_log.Log('write_hwid', hwid=options.hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -070090 print 'Wrote HWID: %r' % options.hwid
Tammo Spalink9a96b8a2012-04-03 11:10:41 +080091
92
Ricky Liang53390232013-03-08 15:37:57 +080093_board_cmd_arg = CmdArg(
94 '--board', metavar='BOARD',
95 default=None, help='Board name to test.')
96
Tammo Spalink8fab5312012-05-28 18:33:30 +080097_hwdb_path_cmd_arg = CmdArg(
98 '--hwdb_path', metavar='PATH',
Ricky Liangeede7922013-06-19 10:18:41 +080099 default=common.DEFAULT_HWID_DATA_PATH,
Tammo Spalink8fab5312012-05-28 18:33:30 +0800100 help='Path to the HWID database.')
101
Tammo Spalink95c43732012-07-25 15:57:14 -0700102_hwid_status_list_cmd_arg = CmdArg(
103 '--status', nargs='*', default=['supported'],
104 help='allow only HWIDs with these status values')
105
Jon Salzce124fb2012-10-02 17:42:03 +0800106_probe_results_cmd_arg = CmdArg(
107 '--probe_results', metavar='RESULTS.yaml',
Ricky Liangc662be32013-12-24 11:50:23 +0800108 help=('Output from "gooftool probe --include_vpd" (used instead of '
Jon Salzce124fb2012-10-02 17:42:03 +0800109 'probing this system).'))
110
Ricky Liang53390232013-03-08 15:37:57 +0800111_device_info_cmd_arg = CmdArg(
Ricky Liangf89f73a2013-03-19 05:00:24 +0800112 '--device_info', metavar='DEVICE_INFO.yaml', default=None,
Ricky Liang53390232013-03-08 15:37:57 +0800113 help='A dict of device info to use instead of fetching from shopfllor '
114 'server.')
115
Jon Salzce124fb2012-10-02 17:42:03 +0800116_hwid_cmd_arg = CmdArg(
117 '--hwid', metavar='HWID',
Ricky Lianga70a1202013-03-15 15:03:17 +0800118 help='HWID to verify (instead of the currently set HWID of this system).')
Jon Salzce124fb2012-10-02 17:42:03 +0800119
Bernie Thompson3c11c872013-07-22 18:22:45 -0700120_rma_mode_cmd_arg = CmdArg(
121 '--rma_mode', action='store_true',
122 help='Enable RMA mode, do not check for deprecated components.')
Tammo Spalink95c43732012-07-25 15:57:14 -0700123
Ricky Liang43b879b2014-02-24 11:36:55 +0800124_hwid_version_cmd_arg = CmdArg(
125 '-i', '--hwid-version', default=3, choices=(2, 3), type=int,
126 help='Version of HWID to operate on. (default: %(default)s)')
127
128
Tammo Spalink95c43732012-07-25 15:57:14 -0700129@Command('best_match_hwids',
Tammo Spalink8fab5312012-05-28 18:33:30 +0800130 _hwdb_path_cmd_arg,
131 CmdArg('-b', '--board', metavar='BOARD',
Tammo Spalink95c43732012-07-25 15:57:14 -0700132 help='optional BOARD name, needed only if data is present '
133 'for more than one'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800134 CmdArg('--bom', metavar='BOM', help='BOM name'),
135 CmdArg('--variant', metavar='VARIANT', help='VARIANT code'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800136 CmdArg('--optimistic', action='store_true',
137 help='do not probe; assume singletons match'),
Tammo Spalink95c43732012-07-25 15:57:14 -0700138 CmdArg('--comps', nargs='*', default=[],
139 help='list of canonical component names'),
140 CmdArg('--missing', nargs='*', default=[],
141 help='list component classes to be assumed missing'),
Tammo Spalink5c699832012-07-03 17:50:39 +0800142 CmdArg('--status', nargs='*', default=['supported'],
Tammo Spalink95c43732012-07-25 15:57:14 -0700143 help='consider only HWIDs within this list of status values'))
144def BestMatchHwids(options):
Ricky Liangc662be32013-12-24 11:50:23 +0800145 """Determine a list of possible HWIDs using provided args and probing.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800146
147 VOLATILE can always be determined by probing. To get a unique
148 result, VARIANT must be specified for all cases where the matching
149 BOM has more than one associated variant code, otherwise all HWID
150 variants will be returned. Both VARIANT and BOM information can
Tammo Spalink95c43732012-07-25 15:57:14 -0700151 alternatively be specified using the --stdin_comps argument, which
152 allows specifying a list of canonical names (one per line) on stdin,
153 one per line. Based on what is known from BOM and stdin_comps,
154 determine a list of components to probe for, and use those probe
155 results to resolve a list of matching HWIDs. If no boms,
156 components, or variant codes are specified, then a list of all HWIDs
Andy Cheng8ece7382012-08-22 16:25:42 +0800157 that match probeable components will be returned.
Tammo Spalink8fab5312012-05-28 18:33:30 +0800158
159 Returns (on stdout): A list of HWIDs that match the available probe
160 results and argument contraints, one per line.
Tammo Spalink70b48a52012-08-08 16:54:51 -0700161
162 Example:
163
164 // Three ways to specify a keyboard (assuming it is a variant component)
165 gooftool best_match_hwids --missing keyboard
166 gooftool best_match_hwids --variant A or
167 gooftool best_match_hwids --comps us_kbd
Tammo Spalink8fab5312012-05-28 18:33:30 +0800168 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800169
Tammo Spalink5c699832012-07-03 17:50:39 +0800170 map(hwid_tool.Validate.Status, options.status)
Tammo Spalink95c43732012-07-25 15:57:14 -0700171 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Tammo Spalink5c699832012-07-03 17:50:39 +0800172 comp_db = hw_db.comp_db
Tammo Spalink3a7e9022012-06-27 14:08:40 +0800173 device = hw_db.GetDevice(options.board)
Tammo Spalink5c699832012-07-03 17:50:39 +0800174 component_spec = hwid_tool.ComponentSpec.New()
Tammo Spalink8fab5312012-05-28 18:33:30 +0800175 if options.bom:
Tammo Spalink5c699832012-07-03 17:50:39 +0800176 device.BomExists(options.bom)
Tammo Spalink01e11722012-07-24 10:17:54 -0700177 component_spec = hwid_tool.CombineComponentSpecs(
Tammo Spalink5c699832012-07-03 17:50:39 +0800178 component_spec, device.boms[options.bom].primary)
Tammo Spalink8fab5312012-05-28 18:33:30 +0800179 if options.variant:
Tammo Spalink5c699832012-07-03 17:50:39 +0800180 device.VariantExists(options.variant)
181 variant_spec = device.variants[options.variant]
Tammo Spalink01e11722012-07-24 10:17:54 -0700182 if hwid_tool.ComponentSpecsConflict(component_spec, variant_spec):
Tammo Spalink95c43732012-07-25 15:57:14 -0700183 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700184 % YamlWrite(sorted(
185 hwid_tool.ComponentSpecClasses(component_spec) &
186 hwid_tool.ComponentSpecClasses(variant_spec))))
Tammo Spalink01e11722012-07-24 10:17:54 -0700187 component_spec = hwid_tool.CombineComponentSpecs(
188 component_spec, variant_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700189 if options.comps or options.missing:
190 map(comp_db.CompExists, options.comps)
191 map(comp_db.CompClassExists, options.missing)
192 extra_comp_spec = comp_db.CreateComponentSpec(
193 components=options.comps,
194 missing=options.missing)
195 print 'cmdline asserted components:\n%s' % extra_comp_spec.Encode()
196 if hwid_tool.ComponentSpecsConflict(component_spec, extra_comp_spec):
197 sys.exit('ERROR: multiple specifications for these components:\n%s'
Tammo Spalink394e4492012-08-01 10:20:30 -0700198 % YamlWrite(sorted(
199 hwid_tool.ComponentSpecClasses(component_spec) &
200 hwid_tool.ComponentSpecClasses(extra_comp_spec))))
Tammo Spalink95c43732012-07-25 15:57:14 -0700201 component_spec = hwid_tool.CombineComponentSpecs(
202 component_spec, extra_comp_spec)
Tammo Spalink01e11722012-07-24 10:17:54 -0700203 spec_classes = hwid_tool.ComponentSpecClasses(component_spec)
Tammo Spalink95c43732012-07-25 15:57:14 -0700204 missing_classes = set(comp_db.all_comp_classes) - spec_classes
Tammo Spalink5c699832012-07-03 17:50:39 +0800205 if missing_classes and not options.optimistic:
Andy Cheng8ece7382012-08-22 16:25:42 +0800206 non_probeable_missing = missing_classes - PROBEABLE_COMPONENT_CLASSES
207 if non_probeable_missing:
Tammo Spalink95c43732012-07-25 15:57:14 -0700208 sys.exit('FAILURE: these classes are necessary, were not specified '
Tammo Spalink70b48a52012-08-08 16:54:51 -0700209 'as inputs, and cannot be probed for:\n%s'
210 'This problem can often be addressed by specifying all of '
211 'the missing components on the command line (see the command '
Andy Cheng8ece7382012-08-22 16:25:42 +0800212 'help).' % YamlWrite(list(non_probeable_missing)))
Tammo Spalink95c43732012-07-25 15:57:14 -0700213 print 'probing for missing classes:'
214 print YamlWrite(list(missing_classes))
215 probe_results = Probe(target_comp_classes=list(missing_classes),
216 probe_volatile=False, probe_initial_config=False)
217 cooked_components = comp_db.MatchComponentProbeValues(
218 probe_results.found_probe_value_map)
219 if cooked_components.unmatched:
220 sys.exit('ERROR: some probed components are unrecognized:\n%s'
221 % YamlWrite(cooked_components.unmatched))
222 probed_comp_spec = comp_db.CreateComponentSpec(
223 components=cooked_components.matched,
224 missing=probe_results.missing_component_classes)
225 component_spec = hwid_tool.CombineComponentSpecs(
226 component_spec, probed_comp_spec)
227 print YamlWrite({'component data used for matching': {
228 'missing component classes': component_spec.classes_missing,
229 'found components': component_spec.components}})
230 component_data = hwid_tool.ComponentData(
231 extant_components=hwid_tool.ComponentSpecCompClassMap(
232 component_spec).keys(),
233 classes_missing=component_spec.classes_missing)
234 match_tree = device.BuildMatchTree(component_data)
235 if not match_tree:
236 sys.exit('FAILURE: NO matching BOMs found')
237 print 'potential BOMs/VARIANTs:'
238 potential_variants = set()
239 potential_volatiles = set()
240 for bom_name, variant_tree in match_tree.items():
241 print ' BOM: %-8s VARIANTS: %s' % (
242 bom_name, ', '.join(sorted(variant_tree)))
243 for variant_code in variant_tree:
244 potential_variants.add(variant_code)
245 for volatile_code in device.volatiles:
246 status = device.GetHwidStatus(bom_name, variant_code, volatile_code)
247 if status in options.status:
248 potential_volatiles.add(volatile_code)
249 print ''
250 if len(potential_variants) == 0:
251 sys.exit('FAILURE: no matching VARIANTs found')
252 if len(potential_volatiles) == 0:
253 sys.exit('FAILURE: no VOLATILEs found for potential matching BOMs/VARIANTS '
254 '(with specified status)')
Tammo Spalink394e4492012-08-01 10:20:30 -0700255 if (options.optimistic and
256 len(match_tree) == 1 and
257 len(potential_variants) == 1 and
258 len(potential_volatiles) == 1):
259 print ('MATCHING HWID: %s' % device.FmtHwid(match_tree.keys().pop(),
260 potential_variants.pop(),
261 potential_volatiles.pop()))
Tammo Spalink5c699832012-07-03 17:50:39 +0800262 return
Tammo Spalink95c43732012-07-25 15:57:14 -0700263 print ('probing VOLATILEs to resolve potential matches: %s\n' %
264 ', '.join(sorted(potential_volatiles)))
265 vol_probe_results = Probe(
266 target_comp_classes=[],
267 probe_volatile=True,
268 probe_initial_config=False)
269 cooked_volatiles = device.MatchVolatileValues(
270 vol_probe_results.found_volatile_values)
271 match_tree = device.BuildMatchTree(
272 component_data, cooked_volatiles.matched_tags)
273 matched_hwids = device.GetMatchTreeHwids(match_tree)
274 if matched_hwids:
275 for hwid in matched_hwids:
Ricky Liang02f3bd72012-09-21 14:33:01 +0800276 if matched_hwids[hwid] in options.status:
277 print 'MATCHING HWID: %s' % hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700278 return
279 print 'exact HWID matching failed, but the following BOMs match: %s' % (
280 ', '.join(sorted(match_tree)))
281 if options.optimistic and len(match_tree) == 1:
282 bom_name = set(match_tree).pop()
Tammo Spalink5c699832012-07-03 17:50:39 +0800283 bom = device.boms[bom_name]
Tammo Spalink95c43732012-07-25 15:57:14 -0700284 variant_matches = match_tree[bom_name]
Tammo Spalink5c699832012-07-03 17:50:39 +0800285 if len(variant_matches) == 1:
286 var_code = set(variant_matches).pop()
287 elif len(bom.variants) == 1:
288 var_code = set(bom.variants).pop()
289 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700290 sys.exit('FAILURE: NO matching HWIDs found; optimistic matching failed '
291 'because there were too many variants to choose from for BOM %r'
292 % bom_name)
293 hwids = [device.FmtHwid(bom_name, var_code, vol_code)
294 for vol_code in device.volatiles
295 if device.GetHwidStatus(bom_name, var_code, vol_code)
296 in options.status]
297 for hwid in hwids:
298 print 'MATCHING HWID: %s' % hwid
Tammo Spalink5c699832012-07-03 17:50:39 +0800299 return
300 else:
Tammo Spalink95c43732012-07-25 15:57:14 -0700301 print ('optimistic matching not attempted because either it was '
302 'not requested, or because the number of BOMs was <> 1\n')
303 sys.exit('FAILURE: NO matching HWIDs found')
Tammo Spalink8fab5312012-05-28 18:33:30 +0800304
305
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800306@Command('probe',
307 CmdArg('--comps', nargs='*',
308 help='List of keys from the component_db registry.'),
Ricky Liangb30da672013-06-14 12:36:34 +0800309 CmdArg('--fast_fw_probe', action='store_true',
310 help='Do a fast probe for EC and main firmware versions only. '
311 'This implies --no_vol and --no_ic.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800312 CmdArg('--no_vol', action='store_true',
313 help='Do not probe volatile data.'),
314 CmdArg('--no_ic', action='store_true',
Jon Salz0f8a6842012-09-25 11:28:22 +0800315 help='Do not probe initial_config data.'),
316 CmdArg('--include_vpd', action='store_true',
317 help='Include VPD data in volatiles.'))
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800318def RunProbe(options):
319 """Print yaml-formatted breakdown of probed device properties."""
Ricky Lianga70a1202013-03-15 15:03:17 +0800320 print GetGooftool(options).Probe(
321 target_comp_classes=options.comps,
Ricky Liangb30da672013-06-14 12:36:34 +0800322 fast_fw_probe=options.fast_fw_probe,
Ricky Lianga70a1202013-03-15 15:03:17 +0800323 probe_volatile=not options.no_vol,
324 probe_initial_config=not options.no_ic,
325 probe_vpd=options.include_vpd).Encode()
Ricky Liang53390232013-03-08 15:37:57 +0800326
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800327
Tammo Spalink214caf42012-05-28 10:45:00 +0800328@Command('verify_components',
329 _hwdb_path_cmd_arg,
Tammo Spalink5c699832012-07-03 17:50:39 +0800330 CmdArg('target_comps', nargs='*'))
Tammo Spalink214caf42012-05-28 10:45:00 +0800331def VerifyComponents(options):
Andy Cheng8ece7382012-08-22 16:25:42 +0800332 """Verify that probeable components all match entries in the component_db.
Tammo Spalink214caf42012-05-28 10:45:00 +0800333
Tammo Spalink5c699832012-07-03 17:50:39 +0800334 Probe for each component class in the target_comps and verify
Tammo Spalink214caf42012-05-28 10:45:00 +0800335 that a corresponding match exists in the component_db -- make sure
336 that these components are present, that they have been approved, but
337 do not check against any specific BOM/HWID configurations.
338 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800339
Andy Chengc531e2f2012-10-15 19:09:17 +0800340 try:
Ricky Lianga70a1202013-03-15 15:03:17 +0800341 result = GetGooftool(options).VerifyComponents(
Andy Chengc531e2f2012-10-15 19:09:17 +0800342 options.target_comps)
343 except ValueError, e:
344 sys.exit(e)
345
Ricky Liang53390232013-03-08 15:37:57 +0800346 PrintVerifyComponentsResults(result)
347
348
349def PrintVerifyComponentsResults(result):
350 """Prints out the results of VerifyComponents method call.
351
352 Groups the results into two groups: 'matches' and 'errors', and prints out
353 their values.
354 """
Andy Chengc531e2f2012-10-15 19:09:17 +0800355 # group by matches and errors
Tammo Spalink214caf42012-05-28 10:45:00 +0800356 matches = []
Andy Chengc531e2f2012-10-15 19:09:17 +0800357 errors = []
358 for result_list in result.values():
359 for component_name, _, error in result_list:
360 if component_name:
361 matches.append(component_name)
Tammo Spalink214caf42012-05-28 10:45:00 +0800362 else:
Andy Chengc531e2f2012-10-15 19:09:17 +0800363 errors.append(error)
364
Andy Cheng228a8c92012-08-27 10:53:57 +0800365 if matches:
366 print 'found probeable components:\n %s' % '\n '.join(matches)
Tammo Spalink214caf42012-05-28 10:45:00 +0800367 if errors:
Andy Cheng228a8c92012-08-27 10:53:57 +0800368 print '\nerrors:\n %s' % '\n '.join(errors)
369 sys.exit('\ncomponent verification FAILURE')
Tammo Spalink214caf42012-05-28 10:45:00 +0800370 else:
Andy Cheng228a8c92012-08-27 10:53:57 +0800371 print "\ncomponent verification SUCCESS"
Tammo Spalink214caf42012-05-28 10:45:00 +0800372
373
Ricky Liang43b879b2014-02-24 11:36:55 +0800374@Command('verify_hwid_v2',
Tammo Spalink95c43732012-07-25 15:57:14 -0700375 _hwid_status_list_cmd_arg,
Jon Salz0f8a6842012-09-25 11:28:22 +0800376 _hwdb_path_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800377 _probe_results_cmd_arg,
378 _hwid_cmd_arg)
Ricky Liang43b879b2014-02-24 11:36:55 +0800379def VerifyHWIDv2(options):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800380 """Verify system HWID properties match probed device properties.
381
382 First probe components, volatile and initial_config parameters for
383 the DUT. Then use the available device data to produce a list of
384 candidate HWIDs. Then verify the HWID from the DUT is present in
385 that list. Then verify that the DUT initial config values match
386 those specified for its HWID. Finally, verify that VPD contains all
387 the necessary fields as specified by the board data, and when
388 possible verify that values are legitimate.
389 """
Ricky Liangf7857c12012-09-17 13:34:41 +0800390 def VerifyVpd(ro_vpd_keys, rw_vpd_keys):
Tammo Spalink5c699832012-07-03 17:50:39 +0800391 for key in ro_vpd_keys:
392 if key not in ro_vpd:
Ricky Liangf7857c12012-09-17 13:34:41 +0800393 sys.exit('Missing required RO VPD field: %s' % key)
Tammo Spalink01e11722012-07-24 10:17:54 -0700394 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800395 value = ro_vpd[key]
Ricky Liangf7857c12012-09-17 13:34:41 +0800396 if (known_valid_values is not None) and (value not in known_valid_values):
397 sys.exit('Invalid RO VPD entry : key %r, value %r' % (key, value))
Ricky Liangf7857c12012-09-17 13:34:41 +0800398 for key in rw_vpd_keys:
399 if key not in rw_vpd:
400 sys.exit('Missing required RW VPD field: %s' % key)
401 known_valid_values = KNOWN_VPD_FIELD_DATA.get(key, None)
402 value = rw_vpd[key]
403 if (known_valid_values is not None) and (value not in known_valid_values):
404 sys.exit('Invalid RW VPD entry : key %r, value %r' % (key, value))
Andy Cheng0465d132013-03-20 12:12:06 +0800405 event_log.Log('vpd', ro_vpd=FilterDict(ro_vpd), rw_vpd=FilterDict(rw_vpd))
Tammo Spalink5c699832012-07-03 17:50:39 +0800406 map(hwid_tool.Validate.Status, options.status)
Jon Salz0f8a6842012-09-25 11:28:22 +0800407
Jon Salz81350812012-10-11 16:13:22 +0800408 if not options.hwid or not options.probe_results:
409 main_fw_file = crosfw.LoadMainFirmware().GetFileName()
Jon Salz0f8a6842012-09-25 11:28:22 +0800410
411 if options.hwid:
412 hwid_str = options.hwid
413 else:
414 gbb_result = Shell('gbb_utility -g --hwid %s' % main_fw_file).stdout
415 hwid_str = re.findall(r'hardware_id:(.*)', gbb_result)[0].strip()
Tammo Spalink95c43732012-07-25 15:57:14 -0700416 hwid = hwid_tool.ParseHwid(hwid_str)
Tammo Spalink5c699832012-07-03 17:50:39 +0800417 hw_db = hwid_tool.HardwareDb(options.hwdb_path)
Jon Salz0f8a6842012-09-25 11:28:22 +0800418 print 'Verifying HWID: %r\n' % hwid.hwid
Tammo Spalink95c43732012-07-25 15:57:14 -0700419 device = hw_db.GetDevice(hwid.board)
420 hwid_status = device.GetHwidStatus(hwid.bom, hwid.variant, hwid.volatile)
421 if hwid_status not in options.status:
Tammo Spalink5c699832012-07-03 17:50:39 +0800422 sys.exit('HWID status must be one of [%s], found %r' %
Hung-Te Lin4f5beb12012-08-20 14:48:06 +0800423 (', '.join(options.status), hwid_status))
Jon Salz0f8a6842012-09-25 11:28:22 +0800424 if options.probe_results:
425 # Pull in probe results (including VPD data) from the given file
426 # rather than probing the current system.
427 probe_results = hwid_tool.ProbeResults.Decode(
428 open(options.probe_results).read())
429 ro_vpd = {}
430 rw_vpd = {}
431 for k, v in probe_results.found_volatile_values.items():
432 match = re.match('^vpd\.(ro|rw)\.(\w+)$', k)
433 if match:
434 del probe_results.found_volatile_values[k]
435 (ro_vpd if match.group(1) == 'ro' else rw_vpd)[match.group(2)] = v
436 else:
437 probe_results = Probe()
438 ro_vpd = ReadRoVpd(main_fw_file)
439 rw_vpd = ReadRwVpd(main_fw_file)
Tammo Spalink95c43732012-07-25 15:57:14 -0700440 cooked_components = hw_db.comp_db.MatchComponentProbeValues(
441 probe_results.found_probe_value_map)
442 cooked_volatiles = device.MatchVolatileValues(
443 probe_results.found_volatile_values)
444 cooked_initial_configs = device.MatchInitialConfigValues(
445 probe_results.initial_configs)
446 component_data = hwid_tool.ComponentData(
447 extant_components=cooked_components.matched,
448 classes_missing=probe_results.missing_component_classes)
449 match_tree = device.BuildMatchTree(
450 component_data, cooked_volatiles.matched_tags)
451 matched_hwids = device.GetMatchTreeHwids(match_tree)
452 print 'HWID status: %s\n' % hwid_status
453 print 'probed system components:'
454 print YamlWrite(cooked_components.__dict__)
455 print 'missing component classes:'
456 print YamlWrite(probe_results.missing_component_classes)
457 print 'probed volatiles:'
458 print YamlWrite(cooked_volatiles.__dict__)
459 print 'probed initial_configs:'
460 print YamlWrite(cooked_initial_configs)
461 print 'hwid match tree:'
462 print YamlWrite(match_tree)
Andy Cheng0465d132013-03-20 12:12:06 +0800463 event_log.Log(
Tammo Spalink5c699832012-07-03 17:50:39 +0800464 'probe',
Tammo Spalink95c43732012-07-25 15:57:14 -0700465 found_components=cooked_components.__dict__,
466 missing_component_classes=probe_results.missing_component_classes,
467 volatiles=cooked_volatiles.__dict__,
468 initial_configs=cooked_initial_configs)
469 if hwid.hwid not in matched_hwids:
Tammo Spalink5c699832012-07-03 17:50:39 +0800470 err_msg = 'HWID verification FAILED.\n'
Tammo Spalink95c43732012-07-25 15:57:14 -0700471 if cooked_components.unmatched:
Tammo Spalink5c699832012-07-03 17:50:39 +0800472 sys.exit(err_msg + 'some components could not be indentified:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700473 YamlWrite(cooked_components.unmatched))
474 if not match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800475 sys.exit(err_msg + 'no matching boms were found for components:\n%s' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700476 component_data.Encode())
477 if hwid.bom not in match_tree:
Tammo Spalink5c699832012-07-03 17:50:39 +0800478 sys.exit(err_msg + 'matching boms [%s] do not include target bom %r' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700479 (', '.join(sorted(match_tree)), hwid.bom))
480 err_msg += 'target bom %r matches components' % hwid.bom
481 if hwid.bom not in device.IntersectBomsAndInitialConfigs(
482 cooked_initial_configs):
Tammo Spalink5c699832012-07-03 17:50:39 +0800483 sys.exit(err_msg + ', but failed initial config verification')
Tammo Spalink95c43732012-07-25 15:57:14 -0700484 matched_variants = match_tree.get(hwid.bom, {})
485 if hwid.variant not in matched_variants:
Tammo Spalink5c699832012-07-03 17:50:39 +0800486 sys.exit(err_msg + ', but target variant_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700487 hwid.variant)
488 matched_volatiles = matched_variants.get(hwid.variant, {})
489 if hwid.volatile not in matched_volatiles:
Tammo Spalink5c699832012-07-03 17:50:39 +0800490 sys.exit(err_msg + ', but target volatile_code %r did not match' %
Tammo Spalink95c43732012-07-25 15:57:14 -0700491 hwid.volatile)
492 found_status = matched_volatiles.get(hwid.volatile, None)
Tammo Spalink5c699832012-07-03 17:50:39 +0800493 sys.exit(err_msg + ', but hwid status %r was unacceptable' % found_status)
Ricky Liangf7857c12012-09-17 13:34:41 +0800494 VerifyVpd(device.vpd_ro_fields, device.vpd_rw_fields)
Andy Cheng0465d132013-03-20 12:12:06 +0800495 event_log.Log('verified_hwid', hwid=hwid)
Tammo Spalink95c43732012-07-25 15:57:14 -0700496 print 'Verification SUCCESS!'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800497
498
499@Command('verify_keys')
Tammo Spalink01e11722012-07-24 10:17:54 -0700500def VerifyKeys(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800501 """Verify keys in firmware and SSD match."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800502
Ricky Lianga70a1202013-03-15 15:03:17 +0800503 return GetGooftool(options).VerifyKeys()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800504
505
506@Command('set_fw_bitmap_locale')
Tammo Spalink01e11722012-07-24 10:17:54 -0700507def SetFirmwareBitmapLocale(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800508 """Use VPD locale value to set firmware bitmap default language."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800509
Ricky Lianga70a1202013-03-15 15:03:17 +0800510 (index, locale) = GetGooftool(options).SetFirmwareBitmapLocale()
Andy Cheng2582d292012-12-04 17:38:28 +0800511 logging.info('Firmware bitmap initial locale set to %d (%s).',
512 index, locale)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800513
514
515@Command('verify_system_time')
Tammo Spalink01e11722012-07-24 10:17:54 -0700516def VerifySystemTime(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800517 """Verify system time is later than release filesystem creation time."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800518
Ricky Lianga70a1202013-03-15 15:03:17 +0800519 return GetGooftool(options).VerifySystemTime()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800520
521
522@Command('verify_rootfs')
Tammo Spalink01e11722012-07-24 10:17:54 -0700523def VerifyRootFs(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800524 """Verify rootfs on SSD is valid by checking hash."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800525
Ricky Lianga70a1202013-03-15 15:03:17 +0800526 return GetGooftool(options).VerifyRootFs()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800527
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800528@Command('verify_tpm')
529def VerifyTPM(options): # pylint: disable=W0613
530 """Verify TPM is cleared."""
531
532 return GetGooftool(options).VerifyTPM()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800533
Hung-Te Lindd708d42014-07-11 17:05:01 +0800534@Command('verify_me_locked')
535def VerifyManagementEngineLocked(options): # pylint: disable=W0613
536 """Verify Managment Engine is locked."""
537
538 return GetGooftool(options).VerifyManagementEngineLocked()
539
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800540@Command('verify_switch_wp')
Andy Chengc92e6f92012-11-20 16:55:53 +0800541def VerifyWPSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800542 """Verify hardware write protection switch is enabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800543
Ricky Lianga70a1202013-03-15 15:03:17 +0800544 GetGooftool(options).VerifyWPSwitch()
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800545
546
547@Command('verify_switch_dev')
Tammo Spalink01e11722012-07-24 10:17:54 -0700548def VerifyDevSwitch(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800549 """Verify developer switch is disabled."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800550
Ricky Lianga70a1202013-03-15 15:03:17 +0800551 if GetGooftool(options).CheckDevSwitchForDisabling():
Hung-Te Lind7d34722012-07-26 16:48:35 +0800552 logging.warn('VerifyDevSwitch: No physical switch.')
Andy Cheng0465d132013-03-20 12:12:06 +0800553 event_log.Log('switch_dev', type='virtual switch')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800554
555
Jon Salzadd90d32014-04-29 16:16:27 +0800556@Command('verify_branding')
557def VerifyBranding(options): # pylint: disable=W0613
558 """Verify that branding fields are properly set.
559
560 customization_id, if set in the RO VPD, must be of the correct format.
561
562 rlz_brand_code must be set either in the RO VPD or OEM partition, and must
563 be of the correct format.
564 """
565 return GetGooftool(options).VerifyBranding()
566
567
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800568@Command('write_protect')
Tammo Spalink01e11722012-07-24 10:17:54 -0700569def EnableFwWp(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800570 """Enable then verify firmware write protection."""
571
Hung-Te Linb21c6682012-08-01 13:53:57 +0800572 def CalculateLegacyRange(fw_type, length, section_data,
573 section_name):
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800574 ro_size = length / 2
575 ro_a = int(section_data[0] / ro_size)
576 ro_b = int((section_data[0] + section_data[1] - 1) / ro_size)
577 if ro_a != ro_b:
578 raise Error("%s firmware section %s has illegal size" %
Hung-Te Linb21c6682012-08-01 13:53:57 +0800579 (fw_type, section_name))
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800580 ro_offset = ro_a * ro_size
581 return (ro_offset, ro_size)
582
583 def WriteProtect(fw_file_path, fw_type, legacy_section):
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800584 """Calculate protection size, then invoke flashrom.
585
586 Our supported chips only allow write protecting half their total
587 size, so we parition the flash chipset space accordingly.
588 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800589
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800590 raw_image = open(fw_file_path, 'rb').read()
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800591 wp_section = 'WP_RO'
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800592 image = crosfw.FirmwareImage(raw_image)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800593 if image.has_section(wp_section):
594 section_data = image.get_section_area(wp_section)
595 ro_offset = section_data[0]
596 ro_size = section_data[1]
597 elif image.has_section(legacy_section):
598 section_data = image.get_section_area(legacy_section)
599 (ro_offset, ro_size) = CalculateLegacyRange(
Hung-Te Linb21c6682012-08-01 13:53:57 +0800600 fw_type, len(raw_image), section_data, legacy_section)
Hung-Te Lin7ea39e82012-07-31 18:39:33 +0800601 else:
602 raise Error('could not find %s firmware section %s or %s' %
603 (fw_type, wp_section, legacy_section))
604
605 logging.debug('write protecting %s [off=%x size=%x]', fw_type,
606 ro_offset, ro_size)
607 crosfw.Flashrom(fw_type).EnableWriteProtection(ro_offset, ro_size)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800608
609 WriteProtect(crosfw.LoadMainFirmware().GetFileName(), 'main', 'RO_SECTION')
Andy Cheng0465d132013-03-20 12:12:06 +0800610 event_log.Log('wp', fw='main')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800611 ec_fw_file = crosfw.LoadEcFirmware().GetFileName()
612 if ec_fw_file is not None:
613 WriteProtect(ec_fw_file, 'ec', 'EC_RO')
Andy Cheng0465d132013-03-20 12:12:06 +0800614 event_log.Log('wp', fw='ec')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800615 else:
616 logging.warning('EC not write protected (seems there is no EC flash).')
617
618
619@Command('clear_gbb_flags')
Andy Chengc92e6f92012-11-20 16:55:53 +0800620def ClearGBBFlags(options): # pylint: disable=W0613
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800621 """Zero out the GBB flags, in preparation for transition to release state.
622
623 No GBB flags are set in release/shipping state, but they are useful
624 for factory/development. See "gbb_utility --flags" for details.
625 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800626
Ricky Lianga70a1202013-03-15 15:03:17 +0800627 GetGooftool(options).ClearGBBFlags()
Andy Cheng0465d132013-03-20 12:12:06 +0800628 event_log.Log('clear_gbb_flags')
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800629
630
Jon Salzaa3a30e2013-05-15 15:56:28 +0800631@Command('clear_factory_vpd_entries')
632def ClearFactoryVPDEntries(options): # pylint: disable=W0613
633 """Clears factory.* items in the RW VPD."""
634 entries = GetGooftool(options).ClearFactoryVPDEntries()
635 event_log.Log('clear_factory_vpd_entries', entries=FilterDict(entries))
636
637
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800638@Command('prepare_wipe',
639 CmdArg('--fast', action='store_true',
640 help='use non-secure but faster wipe method.'))
641def PrepareWipe(options):
642 """Prepare system for transition to release state in next reboot."""
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800643
Ricky Lianga70a1202013-03-15 15:03:17 +0800644 GetGooftool(options).PrepareWipe(options.fast)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800645
646@Command('verify',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800647 CmdArg('--no_write_protect', action='store_true',
648 help='Do not check write protection switch state.'),
Ricky Liang43b879b2014-02-24 11:36:55 +0800649 _hwid_version_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700650 _hwid_status_list_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800651 _hwdb_path_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800652 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800653 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800654 _hwid_cmd_arg,
655 _rma_mode_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800656def Verify(options):
657 """Verifies if whole factory process is ready for finalization.
658
659 This routine performs all the necessary checks to make sure the
660 device is ready to be finalized, but does not modify state. These
661 checks include dev switch, firmware write protection switch, hwid,
662 system time, keys, and root file system.
663 """
Andy Cheng7a76cb82012-11-19 18:08:19 +0800664
Hung-Te Lin6d827542012-07-19 11:50:41 +0800665 if not options.no_write_protect:
Ricky Lianga70a1202013-03-15 15:03:17 +0800666 VerifyWPSwitch(options)
Hung-Te Lindd708d42014-07-11 17:05:01 +0800667 VerifyManagementEngineLocked(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800668 VerifyDevSwitch(options)
669 if options.hwid_version == 2:
Ricky Liang43b879b2014-02-24 11:36:55 +0800670 VerifyHWIDv2(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800671 elif options.hwid_version == 3:
Ricky Liangc662be32013-12-24 11:50:23 +0800672 VerifyHWIDv3(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800673 else:
674 raise Error, 'Invalid HWID version: %r' % options.hwid_version
675 VerifySystemTime(options)
676 VerifyKeys(options)
677 VerifyRootFs(options)
Cheng-Yi Chiang676b5292013-06-18 12:05:33 +0800678 VerifyTPM(options)
Jon Salzadd90d32014-04-29 16:16:27 +0800679 VerifyBranding(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800680
Jon Salzfe9036f2014-01-16 14:11:23 +0800681@Command('untar_stateful_files')
Hung-Te Lin388bce22014-06-03 19:56:40 +0800682def UntarStatefulFiles(unused_options):
Jon Salzfe9036f2014-01-16 14:11:23 +0800683 """Untars stateful files from stateful_files.tar.xz on stateful partition.
684
685 If that file does not exist (which should only be R30 and earlier),
686 this is a no-op.
687 """
688 tar_file = os.path.join(DEVICE_STATEFUL_PATH, 'stateful_files.tar.xz')
689 if os.path.exists(tar_file):
690 Spawn(['tar', 'xf', tar_file], cwd=DEVICE_STATEFUL_PATH,
691 log=True, check_call=True)
692 else:
693 logging.warning('No stateful files at %s', tar_file)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800694
Jon Salz40b9f822014-07-25 16:39:55 +0800695
696@Command('log_source_hashes')
697def LogSourceHashes(options): # pylint: disable=W0613
698 """Logs hashes of source files in the factory toolkit."""
Jon Salze60307f2014-08-05 16:20:00 +0800699 # WARNING: The following line is necessary to validate the integrity
700 # of the factory software. Do not remove or modify it.
701 #
702 # 警告:此行会验证工厂软件的完整性,禁止删除或修改。
Jon Salz40b9f822014-07-25 16:39:55 +0800703 event_log.Log(
704 'source_hashes',
Jon Salz9596ae02014-07-29 14:25:49 +0800705 **file_utils.HashSourceTree(os.path.join(factory.FACTORY_PATH, 'py')))
Jon Salz40b9f822014-07-25 16:39:55 +0800706
707
Tammo Spalink86a61c62012-05-25 15:10:35 +0800708@Command('log_system_details')
Tammo Spalink01e11722012-07-24 10:17:54 -0700709def LogSystemDetails(options): # pylint: disable=W0613
Tammo Spalink86a61c62012-05-25 15:10:35 +0800710 """Write miscellaneous system details to the event log."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800711
Ricky Liang43b879b2014-02-24 11:36:55 +0800712 event_log.Log('system_details', **GetGooftool(options).GetSystemDetails())
Tammo Spalink86a61c62012-05-25 15:10:35 +0800713
714
Jon Salza88b83b2013-05-27 20:00:35 +0800715def CreateReportArchiveBlob(*args, **kwargs):
716 """Creates a report archive and returns it as a blob.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800717
Jon Salza88b83b2013-05-27 20:00:35 +0800718 Args:
719 See CreateReportArchive.
Andy Cheng7a76cb82012-11-19 18:08:19 +0800720
Jon Salza88b83b2013-05-27 20:00:35 +0800721 Returns:
722 An xmlrpclib.Binary object containing a .tar.xz file.
723 """
724 with open(CreateReportArchive(*args, **kwargs)) as f:
725 return xmlrpclib.Binary(f.read())
726
727
728def CreateReportArchive(device_sn=None, add_file=None):
729 """Creates a report archive in a temporary directory.
730
731 Args:
732 device_sn: The device serial number (optional).
733 add_file: A list of files to add (optional).
734
735 Returns:
736 Path to the archive.
737 """
Hung-Te Lin6bd16472012-06-20 16:26:47 +0800738 def NormalizeAsFileName(token):
739 return re.sub(r'\W+', '', token).strip()
Jon Salza88b83b2013-05-27 20:00:35 +0800740
741 target_name = '%s%s.tar.xz' % (
742 time.strftime('%Y%m%dT%H%M%SZ',
743 time.gmtime()),
744 ("" if device_sn is None else
745 "_" + NormalizeAsFileName(device_sn)))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800746 target_path = os.path.join(gettempdir(), target_name)
Jon Salza88b83b2013-05-27 20:00:35 +0800747
Tammo Spalink86a61c62012-05-25 15:10:35 +0800748 # Intentionally ignoring dotfiles in EVENT_LOG_DIR.
Andy Cheng0465d132013-03-20 12:12:06 +0800749 tar_cmd = 'cd %s ; tar cJf %s *' % (event_log.EVENT_LOG_DIR, target_path)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800750 tar_cmd += ' --add-file %s' % FACTORY_LOG_PATH
Jon Salza88b83b2013-05-27 20:00:35 +0800751 if add_file:
752 for f in add_file:
Jon Salz65266432012-07-30 19:02:49 +0800753 # Require absolute paths since the tar command may change the
754 # directory.
755 if not f.startswith('/'):
756 raise Error('Not an absolute path: %s' % f)
757 if not os.path.exists(f):
758 raise Error('File does not exist: %s' % f)
759 tar_cmd += ' --add-file %s' % pipes.quote(f)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800760 cmd_result = Shell(tar_cmd)
Jon Salzff88c022012-11-03 12:19:58 +0800761
762 if ((cmd_result.status == 1) and
763 all((x == '' or
764 'file changed as we read it' in x or
765 "Removing leading `/' from member names" in x)
766 for x in cmd_result.stderr.split('\n'))):
767 # That's OK. Make sure it's valid though.
Vic Yang85199e72013-01-28 14:33:11 +0800768 Spawn(['tar', 'tfJ', target_path], check_call=True, log=True,
Jon Salzff88c022012-11-03 12:19:58 +0800769 ignore_stdout=True)
770 elif not cmd_result.success:
Tammo Spalink86a61c62012-05-25 15:10:35 +0800771 raise Error('unable to tar event logs, cmd %r failed, stderr: %r' %
772 (tar_cmd, cmd_result.stderr))
Jon Salzff88c022012-11-03 12:19:58 +0800773
Jon Salza88b83b2013-05-27 20:00:35 +0800774 return target_path
775
776_upload_method_cmd_arg = CmdArg(
777 '--upload_method', metavar='METHOD:PARAM',
778 help=('How to perform the upload. METHOD should be one of '
779 '{ftp, shopfloor, ftps, cpfe}.'))
780_add_file_cmd_arg = CmdArg(
781 '--add_file', metavar='FILE', action='append',
782 help='Extra file to include in report (must be an absolute path)')
783
784@Command('upload_report',
785 _upload_method_cmd_arg,
786 _add_file_cmd_arg)
787def UploadReport(options):
788 """Create a report containing key device details."""
789 ro_vpd = ReadRoVpd(crosfw.LoadMainFirmware().GetFileName())
790 device_sn = ro_vpd.get('serial_number', None)
791 if device_sn is None:
792 logging.warning('RO_VPD missing device serial number')
793 device_sn = 'MISSING_SN_' + event_log.TimedUuid()
794 target_path = CreateReportArchive(device_sn)
795
Tammo Spalink86a61c62012-05-25 15:10:35 +0800796 if options.upload_method is None or options.upload_method == 'none':
797 logging.warning('REPORT UPLOAD SKIPPED (report left at %s)', target_path)
798 return
799 method, param = options.upload_method.split(':', 1)
800 if method == 'shopfloor':
801 report_upload.ShopFloorUpload(target_path, param)
802 elif method == 'ftp':
Jay Kim360c1dd2012-06-25 10:58:11 -0700803 report_upload.FtpUpload(target_path, 'ftp:' + param)
Tammo Spalink86a61c62012-05-25 15:10:35 +0800804 elif method == 'ftps':
805 report_upload.CurlUrlUpload(target_path, '--ftp-ssl-reqd ftp:%s' % param)
806 elif method == 'cpfe':
Shawn Nematbakhsh3404a092013-01-28 16:49:09 -0800807 report_upload.CpfeUpload(target_path, pipes.quote(param))
Tammo Spalink86a61c62012-05-25 15:10:35 +0800808 else:
809 raise Error('unknown report upload method %r', method)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800810
811
812@Command('finalize',
Hung-Te Lin6d827542012-07-19 11:50:41 +0800813 CmdArg('--no_write_protect', action='store_true',
814 help='Do not enable firmware write protection.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800815 CmdArg('--fast', action='store_true',
816 help='use non-secure but faster wipe method.'),
Ricky Liang43b879b2014-02-24 11:36:55 +0800817 _hwid_version_cmd_arg,
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800818 _hwdb_path_cmd_arg,
Tammo Spalink95c43732012-07-25 15:57:14 -0700819 _hwid_status_list_cmd_arg,
Jon Salz65266432012-07-30 19:02:49 +0800820 _upload_method_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800821 _add_file_cmd_arg,
Ricky Lianga70a1202013-03-15 15:03:17 +0800822 _board_cmd_arg,
Jon Salzce124fb2012-10-02 17:42:03 +0800823 _probe_results_cmd_arg,
Cheng-Yi Chiang406ad912013-11-14 16:51:33 +0800824 _hwid_cmd_arg,
825 _rma_mode_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800826def Finalize(options):
827 """Verify system readiness and trigger transition into release state.
828
Jon Salzaa3a30e2013-05-15 15:56:28 +0800829 This routine does the following:
830 - Verifies system state (see verify command)
Jon Salzfe9036f2014-01-16 14:11:23 +0800831 - Untars stateful_files.tar.xz, if it exists, in the stateful partition, to
832 initialize files such as the CRX cache
Jon Salzaa3a30e2013-05-15 15:56:28 +0800833 - Modifies firmware bitmaps to match locale
834 - Clears all factory-friendly flags from the GBB
835 - Removes factory-specific entries from RW_VPD (factory.*)
836 - Enables firmware write protection (cannot rollback after this)
837 - Uploads system logs & reports
838 - Sets the necessary boot flags to cause wipe of the factory image on the
839 next boot.
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800840 """
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800841 Verify(options)
Jon Salz40b9f822014-07-25 16:39:55 +0800842 LogSourceHashes(options)
Jon Salzfe9036f2014-01-16 14:11:23 +0800843 UntarStatefulFiles(options)
Ricky Lianga70a1202013-03-15 15:03:17 +0800844 SetFirmwareBitmapLocale(options)
845 ClearGBBFlags(options)
Jon Salzaa3a30e2013-05-15 15:56:28 +0800846 ClearFactoryVPDEntries(options)
Hung-Te Lin6d827542012-07-19 11:50:41 +0800847 if options.no_write_protect:
848 logging.warn('WARNING: Firmware Write Protection is SKIPPED.')
Andy Cheng0465d132013-03-20 12:12:06 +0800849 event_log.Log('wp', fw='both', status='skipped')
Hung-Te Lin6d827542012-07-19 11:50:41 +0800850 else:
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800851 EnableFwWp({})
Jon Salza0f58e02012-05-29 19:33:39 +0800852 LogSystemDetails(options)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800853 UploadReport(options)
854 PrepareWipe(options)
855
856
Ricky Liangc662be32013-12-24 11:50:23 +0800857def VerifyHWIDv3(options):
858 """A simple wrapper that calls out to HWID utils to verify version 3 HWID.
Ricky Liang53390232013-03-08 15:37:57 +0800859
Ricky Liangc662be32013-12-24 11:50:23 +0800860 This is mainly for Gooftool to verify v3 HWID during finalize. For testing
861 and development purposes, please use `hwid` command.
Ricky Liang53390232013-03-08 15:37:57 +0800862 """
Ricky Liangc662be32013-12-24 11:50:23 +0800863 db = GetGooftool(options).db
864 encoded_string = options.hwid or hwid_utils.GetHWIDString()
Ricky Liang7905f272013-03-16 01:57:10 +0800865 if options.probe_results:
Ricky Liangc662be32013-12-24 11:50:23 +0800866 probed_results = yaml.load(open(options.probe_results).read())
Ricky Liang7905f272013-03-16 01:57:10 +0800867 else:
Ricky Liangc662be32013-12-24 11:50:23 +0800868 probed_results = yaml.load(Probe(probe_vpd=True).Encode())
869 vpd = hwid_utils.GetVPD(probed_results)
Ricky Liang53390232013-03-08 15:37:57 +0800870
Ricky Liangc662be32013-12-24 11:50:23 +0800871 event_log.Log('probed_results', probed_results=probed_results)
872 event_log.Log('vpd', vpd=vpd)
Ricky Liang53390232013-03-08 15:37:57 +0800873
Ricky Liangc662be32013-12-24 11:50:23 +0800874 hwid_utils.VerifyHWID(db, encoded_string, probed_results, vpd,
875 rma_mode=options.rma_mode)
Ricky Liang53390232013-03-08 15:37:57 +0800876
Ricky Liangc662be32013-12-24 11:50:23 +0800877 event_log.Log('verified_hwid', hwid=encoded_string)
Ricky Liang53390232013-03-08 15:37:57 +0800878
879
Ricky Liang59611a62013-06-11 13:47:33 +0800880def ParseDecodedHWID(hwid):
881 """Parse the HWID object into a more compact dict.
882
883 Args:
884 hwid: A decoded HWID object.
885
886 Returns:
887 A dict containing the board name, the binary string, and the list of
888 components.
889 """
890 results = {}
891 results['board'] = hwid.database.board
892 results['binary_string'] = hwid.binary_string
893 results['components'] = collections.defaultdict(list)
894 components = hwid.bom.components
895 for comp_cls in sorted(components):
896 for (comp_name, probed_values, _) in sorted(components[comp_cls]):
897 if not probed_values:
898 db_components = hwid.database.components
899 probed_values = db_components.GetComponentAttributes(
900 comp_cls, comp_name).get('values')
901 results['components'][comp_cls].append(
902 {comp_name: probed_values if probed_values else None})
903 # Convert defaultdict to dict.
904 results['components'] = dict(results['components'])
905 return results
906
907
henryhsu44d793a2013-07-20 00:07:38 +0800908@Command('get_firmware_hash',
909 CmdArg('--file', metavar='FILE', help='Firmware File.'))
910def GetFirmwareHash(options):
henryhsuf6f835c2013-07-20 20:49:25 +0800911 """Get firmware hash from a file"""
henryhsu44d793a2013-07-20 00:07:38 +0800912 if os.path.exists(options.file):
913 hashes = CalculateFirmwareHashes(options.file)
914 for section, value_dict in hashes.iteritems():
915 print "%s:" % section
916 for key, value in value_dict.iteritems():
917 print " %s: %s" % (key, value)
918 else:
919 raise Error('File does not exist: %s' % options.file)
920
henryhsuf6f835c2013-07-20 20:49:25 +0800921
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800922def Main():
923 """Run sub-command specified by the command line args."""
Andy Cheng7a76cb82012-11-19 18:08:19 +0800924
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800925 options = ParseCmdline(
Ricky Liangc662be32013-12-24 11:50:23 +0800926 ('Perform Google required factory tests. All the HWID-related functions '
927 'provided here are mainly for the deprecated HWID v2. To access HWID '
928 'v3-related utilities, please use `hwid` command.'),
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800929 CmdArg('-l', '--log', metavar='PATH',
930 help='Write logs to this file.'),
Jon Salza4bea382012-10-29 13:00:34 +0800931 CmdArg('--suppress-event-logs', action='store_true',
932 help='Suppress event logging.'),
Tammo Spalink8fab5312012-05-28 18:33:30 +0800933 verbosity_cmd_arg)
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800934 SetupLogging(options.verbosity, options.log)
Andy Cheng0465d132013-03-20 12:12:06 +0800935 event_log.SetGlobalLoggerDefaultPrefix('gooftool')
936 event_log.GetGlobalLogger().suppress = options.suppress_event_logs
Tammo Spalink9a96b8a2012-04-03 11:10:41 +0800937 logging.debug('gooftool options: %s', repr(options))
938 try:
939 logging.debug('GOOFTOOL command %r', options.command_name)
940 options.command(options)
941 logging.info('GOOFTOOL command %r SUCCESS', options.command_name)
942 except Error, e:
943 logging.exception(e)
944 sys.exit('GOOFTOOL command %r ERROR: %s' % (options.command_name, e))
945 except Exception, e:
946 logging.exception(e)
947 sys.exit('UNCAUGHT RUNTIME EXCEPTION %s' % e)
948
949
950if __name__ == '__main__':
951 Main()