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