• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2018 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import pprint
6import logging
7
8from autotest_lib.client.common_lib import error
9from autotest_lib.server.cros.faft.cr50_test import Cr50Test
10
11
12class firmware_Cr50CheckCap(Cr50Test):
13    """Verify cr50 capabilities"""
14    version = 1
15
16    # The default requirements for these capabilities change between prod and
17    # prepvt images. Make sure they match the expected values.
18    SPECIAL_CAPS = ['OpenNoDevMode', 'OpenFromUSB']
19    EXPECTED_REQ_PREPVT = 'Always'
20    EXPECTED_REQ_PROD = 'IfOpened'
21
22    def check_cap_command(self, command, enable_factory, reset_caps):
23        """Verify the cr50 cap response after running the given command"""
24        self.cr50.send_command(command)
25        caps = self.cr50.get_cap_dict()
26        logging.info(caps)
27        in_factory_mode, is_reset = self.cr50.get_cap_overview(caps)
28        if reset_caps and not is_reset:
29            raise error.TestFail('%r did not reset capabilities' % command)
30        if enable_factory and not in_factory_mode:
31            raise error.TestFail('%r did not enable factory mode' % command)
32
33
34    def check_cap_req(self, cap_dict, cap, expected_req):
35        """Check the current cap requirement against the expected requirement"""
36        req = cap_dict[cap]
37        if req != expected_req:
38            raise error.TestFail('%r should be %r not %r' % (cap, expected_req,
39                                                             req))
40
41
42    def ccd_ec_uart_works(self):
43        """Returns True if the CCD ec uart works."""
44        logging.info('checking ec console')
45        try:
46            self.servo.get('ec_board', self._ec_prefix)
47            logging.info('ccd ec console is responsive')
48            return True
49        except:
50            logging.info('ccd ec console is unresponsive')
51            return False
52
53
54    def check_cap_accessiblity(self, ccd_level, cap_setting, expect_accessible):
55        """Check setting cap requirements restricts the capabilities correctly.
56
57        Set each ccd capability to cap_setting. Set the ccd state to ccd_level.
58        Then verify the capability accessiblity matches expect_accessible.
59
60        Args:
61            ccd_level: a ccd state level: 'lock', 'unlock', or 'open'.
62            cap_setting: A ccd cap setting: 'IfOpened', 'Always', or
63                         'UnlessLocked'.
64            expect_accessible: True if capabilities should be accessible
65
66        Raises:
67            TestFail if expect_accessible doesn't match the accessibility state.
68        """
69        # Run testlab open, so we won't have to do physical presence stuff.
70        self.cr50.send_command('ccd testlab open')
71
72        # Set all capabilities to cap_setting
73        caps = self.cr50.get_cap_dict().keys()
74        cap_settings = {}
75        for cap in caps:
76            cap_settings[cap] = cap_setting
77        self.cr50.set_caps(cap_settings)
78
79        # Set the ccd state to ccd_level
80        self.cr50.set_ccd_level(ccd_level, self.CCD_PASSWORD)
81        cap_dict = self.cr50.get_cap_dict()
82        logging.info('Cap state with console %r req %r:\n%s', ccd_level,
83                     cap_setting, pprint.pformat(cap_dict))
84
85        # Check the accessiblity
86        for cap, cap_info in cap_dict.iteritems():
87            if cap_info[self.cr50.CAP_IS_ACCESSIBLE] != expect_accessible:
88                raise error.TestFail('%r is %raccessible' % (cap,
89                                     'not ' if expect_accessible else ''))
90
91        if (self.check_ec_uart and
92            expect_accessible != self.ccd_ec_uart_works()):
93            raise error.TestFail('EC UART is %saccessible when it should%s be' %
94                                 ('not ' if expect_accessible else '',
95                                  '' if expect_accessible else "n't"))
96
97
98    def run_once(self, ccd_open_restricted=False):
99        """Check cr50 capabilities work correctly."""
100        self.fast_ccd_open(enable_testlab=True)
101
102        self._ec_prefix = '' if self.servo.main_device_is_ccd() else 'ccd_cr50'
103        # Only check EC uart if the board has a working EC and cr50 can detect
104        # servo connect/disconnect.
105        self.check_ec_uart = (
106                self.check_ec_capability(suppress_warning=True) and
107                self.cr50.check_servo_monitor() and
108                self.servo.has_control('ec_board', self._ec_prefix))
109        if self.check_ec_uart and self._ec_prefix:
110            try:
111                self.servo.set('active_v4_device', self._ec_prefix)
112            except:
113                self.check_ec_uart = False
114
115        # Make sure factory reset sets all capabilities to Always
116        self.check_cap_command('ccd reset factory', True, False)
117
118        # Make sure ccd reset sets all capabilites to Default
119        self.check_cap_command('ccd reset', False, True)
120
121        expected_req = (self.EXPECTED_REQ_PROD if ccd_open_restricted else
122                        self.EXPECTED_REQ_PREPVT)
123        cap_dict = self.cr50.get_cap_dict(info=self.cr50.CAP_REQ)
124        # Make sure the special ccd capabilities match ccd_open_restricted
125        for cap in self.SPECIAL_CAPS:
126            self.check_cap_req(cap_dict, cap, expected_req)
127
128        # Set the password so we can change the ccd level from the console
129        self.cr50.send_command('ccd testlab open')
130        self.cr50.send_command('ccd reset')
131        self.set_ccd_password(self.CCD_PASSWORD)
132
133        # Make sure ccd accessiblity behaves as expected based on the cap
134        # settings and the ccd state.
135        self.check_cap_accessiblity('open', 'IfOpened', True)
136        self.check_cap_accessiblity('open', 'UnlessLocked', True)
137        self.check_cap_accessiblity('open', 'Always', True)
138
139        self.check_cap_accessiblity('unlock', 'IfOpened', False)
140        self.check_cap_accessiblity('unlock', 'UnlessLocked', True)
141        self.check_cap_accessiblity('unlock', 'Always', True)
142
143        self.check_cap_accessiblity('lock', 'IfOpened', False)
144        self.check_cap_accessiblity('lock', 'UnlessLocked', False)
145        self.check_cap_accessiblity('lock', 'Always', True)
146