1# Copyright (c) 2011 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 logging 6import time 7 8from autotest_lib.client.bin import test 9from autotest_lib.client.common_lib import error, smogcheck_tpm, \ 10 smogcheck_ttci, smogcheck_util 11from autotest_lib.client.cros import service_stopper 12 13 14class hardware_TPMTakeOwnership(test.test): 15 """ 16 Autotest test case to measure TPM_TakeOwnership timing data. 17 """ 18 version = 1 19 20 21 def initialize(self): 22 smogcheck_util.enableI2C() 23 self.ttci_obj = None 24 self.tpm_obj = None 25 self.attr_dict = dict() # Attributes to output 26 self.perf_dict = dict() # Performance measures to output 27 self._services = service_stopper.ServiceStopper(['cryptohomed', 28 'chapsd', 'tcsd']) 29 self._services.stop_services() 30 31 32 def _prepareTpmController(self): 33 """Prepare a TpmController instance for use. 34 35 Returns: 36 an operational TpmControler instance, ready to use. 37 38 Raises: 39 TestFail: if error creating a new TpmController instance. 40 """ 41 try: 42 self.tpm_obj = smogcheck_tpm.TpmController() 43 except smogcheck_tpm.SmogcheckError as e: 44 raise error.TestFail('Error creating a TpmController: %s', e) 45 46 47 def _prepareTtciController(self): 48 """Prepare TtciController instances for use. 49 50 Returns: 51 an operational TtciController instance, ready to use. 52 53 Raises: 54 TestFail: if error creating a new TtciController instance. 55 """ 56 try: 57 self.ttci_obj = smogcheck_ttci.TtciController() 58 except smogcheck_ttci.TtciError as e: 59 raise error.TestFail('Error creating a TtciController: %s' % e) 60 61 62 def _sleep(self, amount): 63 """Sleeps for 'amount' of time and logs a message. 64 65 Args: 66 amount: an integer or float in seconds. 67 """ 68 time.sleep(amount) 69 if amount >= 1: 70 logging.debug('Slept for %0.2f second', amount) 71 elif amount >= 0.001: 72 logging.debug('Slept for %0.2f millisecond', (amount * 1000)) 73 else: 74 logging.debug('Slept for %0.2f microsecond', (amount * 1000000)) 75 76 77 def run_once(self, loop=-1, max_acceptable_delay=-1): 78 self._prepareTtciController() 79 self._prepareTpmController() 80 81 timestamps = dict() 82 time_list = [] 83 try: 84 # Verify TPM is operational before triggering hardware Reset 85 self.tpm_obj.runTpmSelfTest() 86 87 # Activate hardware Reset signal 88 if self.ttci_obj.TTCI_Set_Reset_Control(turn_on=True): 89 raise error.TestFail('TTCI_Set_Reset_Control() error: %s' % 90 self.ttci_obj.err) 91 logging.info('TPM hardware Reset signal activated') 92 93 # Wait for 100 milisec 94 self._sleep(0.1) 95 96 # Deactivate hardware Reset signal 97 if self.ttci_obj.TTCI_Set_Reset_Control(turn_on=False): 98 raise error.TestFail('TTCI_Set_Reset_Control() error: %s' % 99 self.ttci_obj.err) 100 logging.info('TPM hardware Reset signal DEactivated') 101 102 # Run TPM_Starup 103 smogcheck_util.runInSubprocess(['tpmc', 'startup']) 104 105 # Run TPM_SelfTestFull 106 smogcheck_util.runInSubprocess(['tpmc', 'test']) 107 108 # Run TPM_AssertPhysicalPresence 109 smogcheck_util.runInSubprocess(['tpmc', 'ppon']) 110 111 # Run TPM_OwnerClear 112 smogcheck_util.runInSubprocess(['tpmc', 'clear']) 113 114 for i in range(loop): 115 smogcheck_util.runInSubprocess(['start', 'tcsd']) 116 # Wait 3 sec for tcsd to start 117 self._sleep(3) 118 119 # Run TPM_TakeOwnership and record elapsed time 120 timestamps[i] = self.tpm_obj.takeTpmOwnership() 121 122 smogcheck_util.runInSubprocess(['stop', 'tcsd']) 123 # Wait for 1 sec for tcsd to stop 124 self._sleep(1) 125 126 # Run TPM_OwnerClear 127 smogcheck_util.runInSubprocess(['tpmc', 'clear']) 128 129 # Output timing measurements 130 for k, v in timestamps.items(): 131 sec, ms = divmod(v/1000, 1000) 132 key = 'iteration_%d_delay_in_sec' % k 133 delay_float = float(v)/1000000 134 self.perf_dict[key] = delay_float 135 time_list.append(delay_float) 136 self.perf_dict['num_total_iterations'] = len(timestamps) 137 # TODO(tgao): modify generate_test_report to support attr_dict 138 #self.attr_dict['timing_measurement_for'] = 'TPM_TakeOwnership' 139 time_list.sort() 140 time_list.reverse() 141 count = 0 142 for i in time_list: 143 if i <= max_acceptable_delay: 144 break 145 logging.debug('Actual value (%0.2f) exceeds max (%0.2f)', 146 i, max_acceptable_delay) 147 count += 1 148 self.perf_dict['num_iterations_exceeding_max_delay'] = count 149 self.perf_dict['max_acceptable_delay_in_sec'] = max_acceptable_delay 150 self.perf_dict['min_delay_in_sec_actual'] = time_list[-1] 151 # Set this attribute last. If it exceeds user-specified limit in 152 # test suite control file, output report would still be complete 153 self.perf_dict['max_delay_in_sec_actual'] = time_list[0] 154 155 except smogcheck_tpm.SmogcheckError as e: 156 raise error.TestFail('Error: %r' % e) 157 finally: 158 # Output attibutes and performance keyval pairs 159 self.write_iteration_keyval(self.attr_dict, self.perf_dict) 160 161 # Close TPM context 162 if self.tpm_obj.closeContext(): 163 raise error.TestFail('Error closing tspi context') 164 165 166 def cleanup(self): 167 self._services.restore_services() 168