| # Copyright (c) 2011 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 logging |
| import time |
| |
| from autotest_lib.client.bin import test |
| from autotest_lib.client.common_lib import error, smogcheck_tpm, \ |
| smogcheck_ttci, smogcheck_util |
| from autotest_lib.client.cros import service_stopper |
| |
| |
| class hardware_TPMTakeOwnership(test.test): |
| version = 1 |
| |
| |
| def initialize(self): |
| smogcheck_util.enableI2C() |
| self.ttci_obj = None |
| self.tpm_obj = None |
| self.attr_dict = dict() # Attributes to output |
| self.perf_dict = dict() # Performance measures to output |
| self._services = service_stopper.ServiceStopper(['cryptohomed', |
| 'chapsd', 'tcsd']) |
| self._services.stop_services() |
| |
| |
| def _prepareTpmController(self): |
| """Prepare a TpmController instance for use. |
| |
| Returns: |
| an operational TpmControler instance, ready to use. |
| |
| Raises: |
| TestFail: if error creating a new TpmController instance. |
| """ |
| try: |
| self.tpm_obj = smogcheck_tpm.TpmController() |
| except smogcheck_tpm.SmogcheckError as e: |
| raise error.TestFail('Error creating a TpmController: %s', e) |
| |
| |
| def _prepareTtciController(self): |
| """Prepare TtciController instances for use. |
| |
| Returns: |
| an operational TtciController instance, ready to use. |
| |
| Raises: |
| TestFail: if error creating a new TtciController instance. |
| """ |
| try: |
| self.ttci_obj = smogcheck_ttci.TtciController() |
| except smogcheck_ttci.TtciError as e: |
| raise error.TestFail('Error creating a TtciController: %s' % e) |
| |
| |
| def _sleep(self, amount): |
| """Sleeps for 'amount' of time and logs a message. |
| |
| Args: |
| amount: an integer or float in seconds. |
| """ |
| time.sleep(amount) |
| if amount >= 1: |
| logging.debug('Slept for %0.2f second', amount) |
| elif amount >= 0.001: |
| logging.debug('Slept for %0.2f millisecond', (amount * 1000)) |
| else: |
| logging.debug('Slept for %0.2f microsecond', (amount * 1000000)) |
| |
| |
| def run_once(self, loop=-1, max_acceptable_delay=-1): |
| self._prepareTtciController() |
| self._prepareTpmController() |
| |
| timestamps = dict() |
| time_list = [] |
| try: |
| # Verify TPM is operational before triggering hardware Reset |
| self.tpm_obj.runTpmSelfTest() |
| |
| # Activate hardware Reset signal |
| if self.ttci_obj.TTCI_Set_Reset_Control(turn_on=True): |
| raise error.TestFail('TTCI_Set_Reset_Control() error: %s' % |
| self.ttci_obj.err) |
| logging.info('TPM hardware Reset signal activated') |
| |
| # Wait for 100 milisec |
| self._sleep(0.1) |
| |
| # Deactivate hardware Reset signal |
| if self.ttci_obj.TTCI_Set_Reset_Control(turn_on=False): |
| raise error.TestFail('TTCI_Set_Reset_Control() error: %s' % |
| self.ttci_obj.err) |
| logging.info('TPM hardware Reset signal DEactivated') |
| |
| # Run TPM_Starup |
| smogcheck_util.runInSubprocess(['tpmc', 'startup']) |
| |
| # Run TPM_SelfTestFull |
| smogcheck_util.runInSubprocess(['tpmc', 'test']) |
| |
| # Run TPM_AssertPhysicalPresence |
| smogcheck_util.runInSubprocess(['tpmc', 'ppon']) |
| |
| # Run TPM_OwnerClear |
| smogcheck_util.runInSubprocess(['tpmc', 'clear']) |
| |
| for i in range(loop): |
| smogcheck_util.runInSubprocess(['start', 'tcsd']) |
| # Wait 3 sec for tcsd to start |
| self._sleep(3) |
| |
| # Run TPM_TakeOwnership and record elapsed time |
| timestamps[i] = self.tpm_obj.takeTpmOwnership() |
| |
| smogcheck_util.runInSubprocess(['stop', 'tcsd']) |
| # Wait for 1 sec for tcsd to stop |
| self._sleep(1) |
| |
| # Run TPM_OwnerClear |
| smogcheck_util.runInSubprocess(['tpmc', 'clear']) |
| |
| # Output timing measurements |
| for k, v in timestamps.iteritems(): |
| sec, ms = divmod(v/1000, 1000) |
| key = 'iteration_%d_delay_in_sec' % k |
| delay_float = float(v)/1000000 |
| self.perf_dict[key] = delay_float |
| time_list.append(delay_float) |
| self.perf_dict['num_total_iterations'] = len(timestamps) |
| # TODO(tgao): modify generate_test_report to support attr_dict |
| #self.attr_dict['timing_measurement_for'] = 'TPM_TakeOwnership' |
| time_list.sort() |
| time_list.reverse() |
| count = 0 |
| for i in time_list: |
| if i <= max_acceptable_delay: |
| break |
| logging.debug('Actual value (%0.2f) exceeds max (%0.2f)', |
| i, max_acceptable_delay) |
| count += 1 |
| self.perf_dict['num_iterations_exceeding_max_delay'] = count |
| self.perf_dict['max_acceptable_delay_in_sec'] = max_acceptable_delay |
| self.perf_dict['min_delay_in_sec_actual'] = time_list[-1] |
| # Set this attribute last. If it exceeds user-specified limit in |
| # test suite control file, output report would still be complete |
| self.perf_dict['max_delay_in_sec_actual'] = time_list[0] |
| |
| except smogcheck_tpm.SmogcheckError as e: |
| raise error.TestFail('Error: %r' % e) |
| finally: |
| # Output attibutes and performance keyval pairs |
| self.write_iteration_keyval(self.attr_dict, self.perf_dict) |
| |
| # Close TPM context |
| if self.tpm_obj.closeContext(): |
| raise error.TestFail('Error closing tspi context') |
| |
| |
| def cleanup(self): |
| self._services.restore_services() |