blob: d6ada860ef3b7ef6aada897da06c9f082db380c2 [file] [log] [blame]
#!/usr/bin/python
#
# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import argparse
import logging
import os
import re
import sys
import yaml
from collections import defaultdict
import factory_common # pylint: disable=W0611
from cros.factory import common
import cros.factory.hwid.common
from cros.factory.hwid import database
from cros.factory.utils.process_utils import Spawn
DESCRIPTION = """Scans existing HWID databases files for matching components.
All boards in chromeos-hwid/boards.yaml are scanned, on the corresponding branch
listed in that file.
"""
def main():
parser = argparse.ArgumentParser(
description=DESCRIPTION,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('probe_results', metavar='FILE.yaml',
help=('A file containing YAML-formatted probe results '
'output by "gooftool probe".'))
parser.add_argument('--board', '-b', metavar='B',
action='append', dest='boards',
help=('Board to scan (may be provided multiple times, '
'e.g., "--board A --board B"). If no --board '
'argument is provided, all known boards are '
'scanned.'))
args = parser.parse_args()
common.SetupLogging(level=logging.INFO)
hwid_dir = os.path.dirname(cros.factory.hwid.common.DEFAULT_HWID_DATA_PATH)
boards_yaml_path = os.path.join(hwid_dir, 'boards.yaml')
with open(boards_yaml_path) as f:
boards_yaml = yaml.load(f)
board_dbs = {}
if args.boards:
args.boards = [x.upper() for x in args.boards]
missing_boards = set(args.boards) - set(boards_yaml.keys())
if missing_boards:
print sys.stderr, 'Unknown board(s) %r; valid choices are %r' % (
missing_boards, sorted(boards_yaml.keys()))
for board, board_info in sorted(boards_yaml.items()):
if board_info['version'] != 3:
continue
if args.boards and board not in args.boards:
continue
logging.info('Reading %(path)s on branch %(branch)s', board_info)
board_db_yaml = Spawn(
['git', 'show', 'cros-internal/%(branch)s:%(path)s' % board_info],
check_output=True, log_stderr_on_error=True, cwd=hwid_dir).stdout_data
board_dbs[board] = database.Database.LoadData(yaml.load(board_db_yaml),
strict=False)
with open(args.probe_results) as f:
probe_result = f.read()
# Map from (board, component_class) to the matching probe result.
matches = defaultdict(list)
# Map from board -> list of matching results.
board_matches = defaultdict(list)
# Map from component -> list of matching results.
component_matches = defaultdict(list)
# Loop through each board and see what the probe result matches, if anything.
boms = {}
for board, board_db in sorted(board_dbs.items()):
bom = board_db.ProbeResultToBOM(probe_result)
boms[board] = bom
for component_class, results in sorted(bom.components.items()):
if component_class in ['hash_gbb', 'key_recovery', 'key_root',
'ro_main_firmware', 'rw_main_firmware',
'ro_ec_firmware', 'rw_ec_firmware']:
# We don't really care for these pseudo-components
continue
for result in results:
if result.error:
# Not a match at all
continue
if result.component_name == 'opaque':
# Not a true match
continue
matches[board, component_class].append(result)
board_matches[board].append((component_class, result))
component_matches[component_class].append((board, result))
separator = '\n' + ('-' * 40)
# Summarize to board and component view.
print separator
print 'Matches by board:'
for board, results in sorted(board_matches.items()):
print ' %s matches:' % board
for component_class, r in results:
print ' %s: %s' % (component_class, r.component_name)
print separator
print 'Matches by component class:'
for component_class, results in sorted(component_matches.items()):
print ' %s matches:' % component_class
for board, r in results:
print ' %s: %s' % (board, r.component_name)
# Detailed view.
print separator
print 'Detailed information about matches:'
yaml_out = {}
for k, results in sorted(matches.items()):
board, component_class = k
items = {}
yaml_out['%s %s' % (board, component_class)] = items
for r in results:
items[r.component_name] = r.probed_values
out = yaml.dump(yaml_out)
# Indent by 2 spaces
out = re.sub('(?m)^', ' ', out)
print out
if __name__ == '__main__':
main()