| # Copyright 2018 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 pprint |
| import logging |
| |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.server.cros.faft.cr50_test import Cr50Test |
| |
| |
| class firmware_Cr50CheckCap(Cr50Test): |
| """Verify cr50 capabilities""" |
| version = 1 |
| |
| # The default requirements for these capabilities change between prod and |
| # prepvt images. Make sure they match the expected values. |
| SPECIAL_CAPS = ['OpenNoDevMode', 'OpenFromUSB'] |
| EXPECTED_REQ_PREPVT = 'Always' |
| EXPECTED_REQ_PROD = 'IfOpened' |
| |
| def check_cap_command(self, command, enable_factory, reset_caps): |
| """Verify the cr50 cap response after running the given command""" |
| self.cr50.send_command(command) |
| caps = self.cr50.get_cap_dict() |
| logging.info(caps) |
| in_factory_mode, is_reset = self.cr50.get_cap_overview(caps) |
| if reset_caps and not is_reset: |
| raise error.TestFail('%r did not reset capabilities' % command) |
| if enable_factory and not in_factory_mode: |
| raise error.TestFail('%r did not enable factory mode' % command) |
| |
| |
| def check_cap_req(self, cap_dict, cap, expected_req): |
| """Check the current cap requirement against the expected requirement""" |
| req = cap_dict[cap] |
| if req != expected_req: |
| raise error.TestFail('%r should be %r not %r' % (cap, expected_req, |
| req)) |
| |
| |
| def ccd_ec_uart_works(self): |
| """Returns True if the CCD ec uart works.""" |
| logging.info('checking ec console') |
| try: |
| self.servo.get('ec_board', self._ec_prefix) |
| logging.info('ccd ec console is responsive') |
| return True |
| except: |
| logging.info('ccd ec console is unresponsive') |
| return False |
| |
| |
| def check_cap_accessiblity(self, ccd_level, cap_setting, expect_accessible): |
| """Check setting cap requirements restricts the capabilities correctly. |
| |
| Set each ccd capability to cap_setting. Set the ccd state to ccd_level. |
| Then verify the capability accessiblity matches expect_accessible. |
| |
| Args: |
| ccd_level: a ccd state level: 'lock', 'unlock', or 'open'. |
| cap_setting: A ccd cap setting: 'IfOpened', 'Always', or |
| 'UnlessLocked'. |
| expect_accessible: True if capabilities should be accessible |
| |
| Raises: |
| TestFail if expect_accessible doesn't match the accessibility state. |
| """ |
| # Run testlab open, so we won't have to do physical presence stuff. |
| self.cr50.send_command('ccd testlab open') |
| |
| # Set all capabilities to cap_setting |
| caps = self.cr50.get_cap_dict().keys() |
| cap_settings = {} |
| for cap in caps: |
| cap_settings[cap] = cap_setting |
| self.cr50.set_caps(cap_settings) |
| |
| # Set the ccd state to ccd_level |
| self.cr50.set_ccd_level(ccd_level, self.CCD_PASSWORD) |
| cap_dict = self.cr50.get_cap_dict() |
| logging.info('Cap state with console %r req %r:\n%s', ccd_level, |
| cap_setting, pprint.pformat(cap_dict)) |
| |
| # Check the accessiblity |
| for cap, cap_info in cap_dict.iteritems(): |
| if cap_info[self.cr50.CAP_IS_ACCESSIBLE] != expect_accessible: |
| raise error.TestFail('%r is %raccessible' % (cap, |
| 'not ' if expect_accessible else '')) |
| |
| if (self.check_ec_uart and |
| expect_accessible != self.ccd_ec_uart_works()): |
| raise error.TestFail('EC UART is %saccessible when it should%s be' % |
| ('not ' if expect_accessible else '', |
| '' if expect_accessible else "n't")) |
| |
| |
| def run_once(self, ccd_open_restricted=False): |
| """Check cr50 capabilities work correctly.""" |
| self.fast_ccd_open(enable_testlab=True) |
| |
| self._ec_prefix = '' if self.servo.main_device_is_ccd() else 'ccd_cr50' |
| # Only check EC uart if the board has a working EC and cr50 can detect |
| # servo connect/disconnect. |
| self.check_ec_uart = ( |
| self.check_ec_capability(suppress_warning=True) and |
| self.cr50.check_servo_monitor() and |
| self.servo.has_control('ec_board', self._ec_prefix)) |
| if self.check_ec_uart and self._ec_prefix: |
| try: |
| self.servo.set('active_v4_device', self._ec_prefix) |
| except: |
| self.check_ec_uart = False |
| |
| # Make sure factory reset sets all capabilities to Always |
| self.check_cap_command('ccd reset factory', True, False) |
| |
| # Make sure ccd reset sets all capabilites to Default |
| self.check_cap_command('ccd reset', False, True) |
| |
| expected_req = (self.EXPECTED_REQ_PROD if ccd_open_restricted else |
| self.EXPECTED_REQ_PREPVT) |
| cap_dict = self.cr50.get_cap_dict(info=self.cr50.CAP_REQ) |
| # Make sure the special ccd capabilities match ccd_open_restricted |
| for cap in self.SPECIAL_CAPS: |
| self.check_cap_req(cap_dict, cap, expected_req) |
| |
| # Set the password so we can change the ccd level from the console |
| self.cr50.send_command('ccd testlab open') |
| self.cr50.send_command('ccd reset') |
| self.set_ccd_password(self.CCD_PASSWORD) |
| |
| # Make sure ccd accessiblity behaves as expected based on the cap |
| # settings and the ccd state. |
| self.check_cap_accessiblity('open', 'IfOpened', True) |
| self.check_cap_accessiblity('open', 'UnlessLocked', True) |
| self.check_cap_accessiblity('open', 'Always', True) |
| |
| self.check_cap_accessiblity('unlock', 'IfOpened', False) |
| self.check_cap_accessiblity('unlock', 'UnlessLocked', True) |
| self.check_cap_accessiblity('unlock', 'Always', True) |
| |
| self.check_cap_accessiblity('lock', 'IfOpened', False) |
| self.check_cap_accessiblity('lock', 'UnlessLocked', False) |
| self.check_cap_accessiblity('lock', 'Always', True) |