firmware_test.py revision 18c4e1643b3ac6f6a201e2008020cdae8c590a7d
1086aeeaae12517475c22695a200be45495516549Ben Murdoch# Copyright (c) 2014 The Chromium OS Authors. All rights reserved. 2b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch# Use of this source code is governed by a BSD-style license that can be 3b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch# found in the LICENSE file. 4b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochimport ast 6b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochimport ctypes 7b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochimport logging 8b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochimport os 9b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochimport re 10b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochimport time 11b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochimport uuid 12b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 13b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochfrom autotest_lib.client.bin import utils 14b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochfrom autotest_lib.client.common_lib import error 15b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochfrom autotest_lib.server import test 16b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochfrom autotest_lib.server.cros import vboot_constants as vboot 17b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochfrom autotest_lib.server.cros.faft.config.config import Config as FAFTConfig 18b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochfrom autotest_lib.server.cros.faft.rpc_proxy import RPCProxy 19b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochfrom autotest_lib.server.cros.faft.utils import mode_switcher 20b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochfrom autotest_lib.server.cros.faft.utils.faft_checkers import FAFTCheckers 21b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochfrom autotest_lib.server.cros.servo import chrome_ec 22b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 23b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 24b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass ConnectionError(Exception): 25b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Raised on an error of connecting DUT.""" 26b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pass 27b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 28b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 29b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass FAFTBase(test.test): 30b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """The base class of FAFT classes. 31b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch It launches the FAFTClient on DUT, such that the test can access its 33086aeeaae12517475c22695a200be45495516549Ben Murdoch firmware functions and interfaces. It also provides some methods to 34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch handle the reboot mechanism, in order to ensure FAFTClient is still 35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch connected after reboot. 36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def initialize(self, host): 38b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Create a FAFTClient object and install the dependency.""" 39b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo = host.servo 40b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo.initialize_dut() 41b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._client = host 42b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client = RPCProxy(host) 43b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.lockfile = '/var/tmp/faft/lock' 44b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 45b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def wait_for_client(self, timeout=100): 46b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Wait for the client to come back online. 47b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 48b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch New remote processes will be launched if their used flags are enabled. 49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 50b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param timeout: Time in seconds to wait for the client SSH daemon to 51b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch come up. 52b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @raise ConnectionError: Failed to connect DUT. 53b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 54b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if not self._client.wait_up(timeout): 55b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch raise ConnectionError() 56b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # Check the FAFT client is avaiable. 57b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.system.is_available() 58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 59b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def wait_for_client_offline(self, timeout=60, orig_boot_id=None): 60b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Wait for the client to come offline. 61b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 62b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param timeout: Time in seconds to wait the client to come offline. 63b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param orig_boot_id: A string containing the original boot id. 64b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @raise ConnectionError: Failed to connect DUT. 65b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 66b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # When running against panther, we see that sometimes 67b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # ping_wait_down() does not work correctly. There needs to 68b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # be some investigation to the root cause. 69b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # If we sleep for 120s before running get_boot_id(), it 70b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # does succeed. But if we change this to ping_wait_down() 71b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # there are implications on the wait time when running 72b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # commands at the fw screens. 7344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if not self._client.ping_wait_down(timeout): 74b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if orig_boot_id and self._client.get_boot_id() != orig_boot_id: 75b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.warn('Reboot done very quickly.') 761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return 771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block raise ConnectionError() 78b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 79b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass FirmwareTest(FAFTBase): 81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Base class that sets up helper objects/functions for firmware tests. 83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TODO: add documentaion as the FAFT rework progresses. 85b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch version = 1 87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # Mapping of partition number of kernel and rootfs. 89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch KERNEL_MAP = {'a':'2', 'b':'4', '2':'2', '4':'4', '3':'2', '5':'4'} 90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ROOTFS_MAP = {'a':'3', 'b':'5', '2':'3', '4':'5', '3':'3', '5':'5'} 91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch OTHER_KERNEL_MAP = {'a':'4', 'b':'2', '2':'4', '4':'2', '3':'4', '5':'2'} 92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch OTHER_ROOTFS_MAP = {'a':'5', 'b':'3', '2':'5', '4':'3', '3':'5', '5':'3'} 9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CHROMEOS_MAGIC = "CHROMEOS" 95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CORRUPTED_MAGIC = "CORRUPTD" 96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 97e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch _SERVOD_LOG = '/var/log/servod.log' 98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch _ROOTFS_PARTITION_NUMBER = 3 100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block _backup_firmware_sha = () 1021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block _backup_kernel_sha = dict() 1031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block _backup_cgpt_attr = dict() 1041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block _backup_gbb_flags = None 105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch _backup_dev_mode = None 106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 107086aeeaae12517475c22695a200be45495516549Ben Murdoch # Class level variable, keep track the states of one time setup. 108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # This variable is preserved across tests which inherit this class. 109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch _global_setup_done = { 110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'gbb_flags': False, 111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'reimage': False, 112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'usb_check': False, 113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block @classmethod 1161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block def check_setup_done(cls, label): 1179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block """Check if the given setup is done. 118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param label: The label of the setup. 120b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return cls._global_setup_done[label] 12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block @classmethod 124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def mark_setup_done(cls, label): 125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Mark the given setup done. 126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block @param label: The label of the setup. 128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block cls._global_setup_done[label] = True 130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @classmethod 132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def unmark_setup_done(cls, label): 133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Mark the given setup not done. 134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param label: The label of the setup. 136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cls._global_setup_done[label] = False 1381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def initialize(self, host, cmdline_args, ec_wp=None): 140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch super(FirmwareTest, self).initialize(host) 141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.run_id = str(uuid.uuid4()) 142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('FirmwareTest initialize begin (id=%s)', self.run_id) 143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # Parse arguments from command line 144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch args = {} 145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.power_control = host.POWER_CONTROL_RPM 146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for arg in cmdline_args: 147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch match = re.search("^(\w+)=(.+)", arg) 1481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if match: 149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch args[match.group(1)] = match.group(2) 150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if 'power_control' in args: 151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.power_control = args['power_control'] 15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if self.power_control not in host.POWER_CONTROL_VALID_ARGS: 153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch raise error.TestError('Valid values for --args=power_control ' 154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'are %s. But you entered wrong argument ' 1551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 'as "%s".' 15644f0eee88ff00398ff7f715fab053374d808c90dSteve Block % (host.POWER_CONTROL_VALID_ARGS, 1571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.power_control)) 158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_config = FAFTConfig( 160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.system.get_platform_name()) 16144f0eee88ff00398ff7f715fab053374d808c90dSteve Block self.checkers = FAFTCheckers(self) 162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.switcher = mode_switcher.create_mode_switcher(self) 163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if self.faft_config.chrome_ec: 165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.ec = chrome_ec.ChromeEC(self.servo) 166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._setup_uart_capture() 168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._setup_servo_log() 169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._record_system_info() 170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.fw_vboot2 = self.faft_client.system.get_fw_vboot2() 171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('vboot version: %d', 2 if self.fw_vboot2 else 1) 172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if self.fw_vboot2: 173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.system.set_fw_try_next('A') 174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if self.faft_client.system.get_crossystem_value('mainfw_act') == 'B': 175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('mainfw_act is B. rebooting to set it A') 176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.switcher.mode_aware_reboot() 177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._setup_gbb_flags() 178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._stop_service('update-engine') 179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._create_faft_lockfile() 180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._setup_ec_write_protect(ec_wp) 181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # See chromium:239034 regarding needing this sync. 182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.blocking_sync() 183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('FirmwareTest initialize done (id=%s)', self.run_id) 184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def cleanup(self): 186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Autotest cleanup function.""" 187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # Unset state checker in case it's set by subclass 188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('FirmwareTest cleaning up (id=%s)', self.run_id) 189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch try: 190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.system.is_available() 191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch except: 192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # Remote is not responding. Revive DUT so that subsequent tests 1931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # don't fail. 1941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self._restore_routine_from_timeout() 1951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.switcher.restore_mode() 1961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self._restore_ec_write_protect() 197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._restore_gbb_flags() 198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._start_service('update-engine') 199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._remove_faft_lockfile() 200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._record_servo_log() 201b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._record_faft_client_log() 202b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._cleanup_uart_capture() 203b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch super(FirmwareTest, self).cleanup() 204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('FirmwareTest cleanup done (id=%s)', self.run_id) 205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def _record_system_info(self): 207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Record some critical system info to the attr keyval. 208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 209b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch This info is used by generate_test_report later. 210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 211b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.write_attr_keyval({ 212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'fw_version': self.faft_client.ec.get_version(), 2131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 'hwid': self.faft_client.system.get_crossystem_value('hwid'), 2141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 'fwid': self.faft_client.system.get_crossystem_value('fwid'), 2151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block }) 216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def invalidate_firmware_setup(self): 218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Invalidate all firmware related setup state. 219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch This method is called when the firmware is re-flashed. It resets all 221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch firmware related setup states so that the next test setup properly 222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch again. 223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.unmark_setup_done('gbb_flags') 225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def _retrieve_recovery_reason_from_trap(self): 227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Try to retrieve the recovery reason from a trapped recovery screen. 228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @return: The recovery_reason, 0 if any error. 230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch recovery_reason = 0 232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('Try to retrieve recovery reason...') 233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if self.servo.get_usbkey_direction() == 'dut': 234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.switcher.bypass_rec_mode() 2351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block else: 2361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.servo.switch_usbkey('dut') 2371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block try: 2391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.wait_for_client() 2401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block lines = self.faft_client.system.run_shell_command_get_output( 2411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 'crossystem recovery_reason') 2421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block recovery_reason = int(lines[0]) 2431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block logging.info('Got the recovery reason %d.', recovery_reason) 2441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block except ConnectionError: 2451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block logging.error('Failed to get the recovery reason due to connection ' 2461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 'error.') 2471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return recovery_reason 2481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block def _reset_client(self): 2501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block """Reset client to a workable state. 2511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block This method is called when the client is not responsive. It may be 2531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block caused by the following cases: 2541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block - halt on a firmware screen without timeout, e.g. REC_INSERT screen; 2551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block - corrupted firmware; 2561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block - corrutped OS image. 257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 2581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # DUT may halt on a firmware screen. Try cold reboot. 259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('Try cold reboot...') 260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.switcher.mode_aware_reboot(reboot_type='cold', 261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch sync_before_boot=False, 2621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block wait_for_dut_up=False) 2631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.wait_for_client_offline() 264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.switcher.bypass_dev_mode() 265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch try: 266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.wait_for_client() 2671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return 268b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch except ConnectionError: 269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.warn('Cold reboot doesn\'t help, still connection error.') 270b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # DUT may be broken by a corrupted firmware. Restore firmware. 272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # We assume the recovery boot still works fine. Since the recovery 2731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # code is in RO region and all FAFT tests don't change the RO region 2741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # except GBB. 275b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if self.is_firmware_saved(): 276b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._ensure_client_in_recovery() 277b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.info('Try restore the original firmware...') 278b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if self.is_firmware_changed(): 279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch try: 280b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.restore_firmware() 2811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return 282b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch except ConnectionError: 283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.warn('Restoring firmware doesn\'t help, still ' 284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'connection error.') 2851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # Perhaps it's kernel that's broken. Let's try restoring it. 287b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if self.is_kernel_saved(): 288b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._ensure_client_in_recovery() 289b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.info('Try restore the original kernel...') 2901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if self.is_kernel_changed(): 2911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block try: 2921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.restore_kernel() 2931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return 2941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block except ConnectionError: 295b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.warn('Restoring kernel doesn\'t help, still ' 296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'connection error.') 297b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # DUT may be broken by a corrupted OS image. Restore OS image. 2991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self._ensure_client_in_recovery() 3001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block logging.info('Try restore the OS image...') 3011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.faft_client.system.run_shell_command('chromeos-install --yes') 302b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.switcher.mode_aware_reboot(wait_for_dut_up=False) 303b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.wait_for_client_offline() 304b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.switcher.bypass_dev_mode() 305b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch try: 306b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.wait_for_client() 307b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.info('Successfully restore OS image.') 308b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return 309b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch except ConnectionError: 310b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.warn('Restoring OS image doesn\'t help, still connection ' 311b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 'error.') 312b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 313b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch def _ensure_client_in_recovery(self): 314b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Ensure client in recovery boot; reboot into it if necessary. 315b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 316b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @raise TestError: if failed to boot the USB image. 317b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 318b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.info('Try boot into USB image...') 319b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.switcher.reboot_to_mode(to_mode='rec', sync_before_boot=False, 320b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch wait_for_dut_up=False) 321b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.servo.switch_usbkey('host') 322b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.switcher.bypass_rec_mode() 323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch try: 324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.wait_for_client() 325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch except ConnectionError: 326b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch raise error.TestError('Failed to boot the USB image.') 327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def _restore_routine_from_timeout(self): 329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """A routine to try to restore the system from a timeout error. 330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch This method is called when FAFT failed to connect DUT after reboot. 332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @raise TestFail: This exception is already raised, with a decription 334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch why it failed. 335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # DUT is disconnected. Capture the UART output for debug. 337b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._record_uart_capture() 338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # TODO(waihong@chromium.org): Implement replugging the Ethernet to 340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # identify if it is a network flaky. 341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch recovery_reason = self._retrieve_recovery_reason_from_trap() 343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # Reset client to a workable state. 345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._reset_client() 346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # Raise the proper TestFail exception. 348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if recovery_reason: 349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch raise error.TestFail('Trapped in the recovery screen (reason: %d) ' 350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'and timed out' % recovery_reason) 351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch else: 352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch raise error.TestFail('Timed out waiting for DUT reboot') 353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def assert_test_image_in_usb_disk(self, usb_dev=None): 355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Assert an USB disk plugged-in on servo and a test image inside. 356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param usb_dev: A string of USB stick path on the host, like '/dev/sdc'. 358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch If None, it is detected automatically. 359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @raise TestError: if USB disk not detected or not a test image. 360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if self.check_setup_done('usb_check'): 362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return 363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if usb_dev: 364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch assert self.servo.get_usbkey_direction() == 'host' 365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch else: 366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo.switch_usbkey('host') 367b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch usb_dev = self.servo.probe_host_usb_dev() 368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if not usb_dev: 369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch raise error.TestError( 370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'An USB disk should be plugged in the servo board.') 371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch rootfs = '%s%s' % (usb_dev, self._ROOTFS_PARTITION_NUMBER) 373b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.info('usb dev is %s', usb_dev) 374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch tmpd = self.servo.system_output('mktemp -d -t usbcheck.XXXX') 375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo.system('mount -o ro %s %s' % (rootfs, tmpd)) 376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch try: 378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch usb_lsb = self.servo.system_output('cat %s' % 379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch os.path.join(tmpd, 'etc/lsb-release')) 380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.debug('Dumping lsb-release on USB stick:\n%s', usb_lsb) 381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dut_lsb = '\n'.join(self.faft_client.system. 382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch run_shell_command_get_output('cat /etc/lsb-release')) 383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.debug('Dumping lsb-release on DUT:\n%s', dut_lsb) 384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if not re.search(r'RELEASE_DESCRIPTION=.*(T|t)est', usb_lsb): 385b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch raise error.TestError('USB stick in servo is no test image') 386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch usb_board = re.search(r'BOARD=(.*)', usb_lsb).group(1) 387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dut_board = re.search(r'BOARD=(.*)', dut_lsb).group(1) 388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if usb_board != dut_board: 389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch raise error.TestError('USB stick in servo contains a %s ' 390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'image, but DUT is a %s' % (usb_board, dut_board)) 391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch finally: 392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for cmd in ('umount %s' % rootfs, 'sync', 'rm -rf %s' % tmpd): 393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo.system(cmd) 394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.mark_setup_done('usb_check') 396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def setup_usbkey(self, usbkey, host=None): 398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Setup the USB disk for the test. 399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch It checks the setup of USB disk and a valid ChromeOS test image inside. 401b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch It also muxes the USB disk to either the host or DUT by request. 402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param usbkey: True if the USB disk is required for the test, False if 404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch not required. 405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param host: Optional, True to mux the USB disk to host, False to mux it 406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch to DUT, default to do nothing. 407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if usbkey: 409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.assert_test_image_in_usb_disk() 410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch elif host is None: 411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # USB disk is not required for the test. Better to mux it to host. 412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch host = True 413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 414b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if host is True: 415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo.switch_usbkey('host') 416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch elif host is False: 417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo.switch_usbkey('dut') 418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def get_usbdisk_path_on_dut(self): 420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Get the path of the USB disk device plugged-in the servo on DUT. 421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Returns: 423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch A string representing USB disk path, like '/dev/sdb', or None if 424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch no USB disk is found. 425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cmd = 'ls -d /dev/s*[a-z]' 427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch original_value = self.servo.get_usbkey_direction() 428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 429b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch # Make the dut unable to see the USB disk. 430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo.switch_usbkey('off') 431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch no_usb_set = set( 432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.system.run_shell_command_get_output(cmd)) 433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # Make the dut able to see the USB disk. 4351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.servo.switch_usbkey('dut') 436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch time.sleep(self.faft_config.usb_plug) 4371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block has_usb_set = set( 4381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.faft_client.system.run_shell_command_get_output(cmd)) 4391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # Back to its original value. 441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if original_value != self.servo.get_usbkey_direction(): 442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo.switch_usbkey(original_value) 443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block diff_set = has_usb_set - no_usb_set 4451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if len(diff_set) == 1: 446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return diff_set.pop() 447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch else: 448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return None 449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def _create_faft_lockfile(self): 451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Creates the FAFT lockfile.""" 452b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.info('Creating FAFT lockfile...') 453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch command = 'touch %s' % (self.lockfile) 454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.system.run_shell_command(command) 455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def _remove_faft_lockfile(self): 457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Removes the FAFT lockfile.""" 4581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block logging.info('Removing FAFT lockfile...') 459b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch command = 'rm -f %s' % (self.lockfile) 460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.system.run_shell_command(command) 461b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 462b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch def _stop_service(self, service): 463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Stops a upstart service on the client. 464b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 465b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @param service: The name of the upstart service. 466b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 467b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.info('Stopping %s...', service) 468b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch command = 'status %s | grep stop || stop %s' % (service, service) 469b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.faft_client.system.run_shell_command(command) 470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def _start_service(self, service): 472b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Starts a upstart service on the client. 473b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param service: The name of the upstart service. 475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('Starting %s...', service) 4771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block command = 'status %s | grep start || start %s' % (service, service) 478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.system.run_shell_command(command) 479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def _write_gbb_flags(self, new_flags): 481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Write the GBB flags to the current firmware. 4821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block @param new_flags: The flags to write. 484b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 485b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch gbb_flags = self.faft_client.bios.get_gbb_flags() 486b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if gbb_flags == new_flags: 487b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return 4881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block logging.info('Changing GBB flags from 0x%x to 0x%x.', 489b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch gbb_flags, new_flags) 490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.system.run_shell_command( 491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch '/usr/share/vboot/bin/set_gbb_flags.sh 0x%x' % new_flags) 492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.bios.reload() 493b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch # If changing FORCE_DEV_SWITCH_ON flag, reboot to get a clear state 494b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if ((gbb_flags ^ new_flags) & vboot.GBB_FLAG_FORCE_DEV_SWITCH_ON): 495b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.switcher.mode_aware_reboot() 496b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def clear_set_gbb_flags(self, clear_mask, set_mask): 498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Clear and set the GBB flags in the current flashrom. 499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 500b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @param clear_mask: A mask of flags to be cleared. 501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param set_mask: A mask of flags to be set. 502b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 503b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch gbb_flags = self.faft_client.bios.get_gbb_flags() 504b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch new_flags = gbb_flags & ctypes.c_uint32(~clear_mask).value | set_mask 505b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._write_gbb_flags(new_flags) 506b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def check_ec_capability(self, required_cap=None, suppress_warning=False): 508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Check if current platform has required EC capabilities. 509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 510b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @param required_cap: A list containing required EC capabilities. Pass in 511b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch None to only check for presence of Chrome EC. 512b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @param suppress_warning: True to suppress any warning messages. 513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @return: True if requirements are met. Otherwise, False. 514b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if not self.faft_config.chrome_ec: 516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if not suppress_warning: 517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.warn('Requires Chrome EC to run this test.') 5181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return False 519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 520b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if not required_cap: 521b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return True 522b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for cap in required_cap: 524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if cap not in self.faft_config.ec_capability: 525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if not suppress_warning: 526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.warn('Requires EC capability "%s" to run this ' 527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'test.', cap) 528b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return False 529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return True 531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def check_root_part_on_non_recovery(self, part): 533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Check the partition number of root device and on normal/dev boot. 534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param part: A string of partition number, e.g.'3'. 536b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @return: True if the root device matched and on normal/dev boot; 537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch otherwise, False. 538b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 539b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return self.checkers.root_part_checker(part) and \ 540b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.checkers.crossystem_checker({ 541b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 'mainfw_type': ('normal', 'developer'), 542b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch }) 543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def _join_part(self, dev, part): 545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Return a concatenated string of device and partition number. 546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param dev: A string of device, e.g.'/dev/sda'. 548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param part: A string of partition number, e.g.'3'. 549b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @return: A concatenated string of device and partition number, 550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch e.g.'/dev/sda3'. 551b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 552b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch >>> seq = FirmwareTest() 553b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch >>> seq._join_part('/dev/sda', '3') 554b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch '/dev/sda3' 555b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch >>> seq._join_part('/dev/mmcblk0', '2') 556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch '/dev/mmcblk0p2' 557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if 'mmcblk' in dev: 559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return dev + 'p' + part 560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch else: 561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return dev + part 562b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def copy_kernel_and_rootfs(self, from_part, to_part): 564b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Copy kernel and rootfs from from_part to to_part. 565b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 566b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @param from_part: A string of partition number to be copied from. 567b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @param to_part: A string of partition number to be copied to. 568b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch root_dev = self.faft_client.system.get_root_dev() 570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('Copying kernel from %s to %s. Please wait...', 571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch from_part, to_part) 572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.system.run_shell_command('dd if=%s of=%s bs=4M' % 573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (self._join_part(root_dev, self.KERNEL_MAP[from_part]), 574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._join_part(root_dev, self.KERNEL_MAP[to_part]))) 5751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block logging.info('Copying rootfs from %s to %s. Please wait...', 576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch from_part, to_part) 577b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.faft_client.system.run_shell_command('dd if=%s of=%s bs=4M' % 578b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch (self._join_part(root_dev, self.ROOTFS_MAP[from_part]), 579b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._join_part(root_dev, self.ROOTFS_MAP[to_part]))) 580b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def ensure_kernel_boot(self, part): 582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Ensure the request kernel boot. 583b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch If not, it duplicates the current kernel to the requested kernel 585b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch and sets the requested higher priority to ensure it boot. 586b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 587b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @param part: A string of kernel partition number or 'a'/'b'. 588b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if not self.checkers.root_part_checker(part): 590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if self.faft_client.kernel.diff_a_b(): 591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.copy_kernel_and_rootfs( 5921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block from_part=self.OTHER_KERNEL_MAP[part], 593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch to_part=part) 594b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.reset_and_prioritize_kernel(part) 595b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 596b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch def set_hardware_write_protect(self, enable): 597b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Set hardware write protect pin. 598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param enable: True if asserting write protect pin. Otherwise, False. 600b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo.set('fw_wp_vref', self.faft_config.wp_voltage) 602b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.servo.set('fw_wp_en', 'on') 603b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.servo.set('fw_wp', 'on' if enable else 'off') 604b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 605b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch def set_ec_write_protect_and_reboot(self, enable): 606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Set EC write protect status and reboot to take effect. 607b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch The write protect state is only activated if both hardware write 609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch protect pin is asserted and software write protect flag is set. 610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch This method asserts/deasserts hardware write protect pin first, and 6111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block set corresponding EC software write protect flag. 612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 613b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch If the device uses non-Chrome EC, set the software write protect via 614b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch flashrom. 615b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch If the device uses Chrome EC, a reboot is required for write protect 617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch to take effect. Since the software write protect flag cannot be unset 618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if hardware write protect pin is asserted, we need to deasserted the 619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pin first if we are deactivating write protect. Similarly, a reboot 620b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch is required before we can modify the software flag. 621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param enable: True if activating EC write protect. Otherwise, False. 623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.set_hardware_write_protect(enable) 6251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if self.faft_config.chrome_ec: 626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.set_chrome_ec_write_protect_and_reboot(enable) 627b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch else: 628b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.faft_client.ec.set_write_protect(enable) 629b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.switcher.mode_aware_reboot() 630b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def set_chrome_ec_write_protect_and_reboot(self, enable): 632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Set Chrome EC write protect status and reboot to take effect. 633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param enable: True if activating EC write protect. Otherwise, False. 635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 6361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if enable: 637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # Set write protect flag and reboot to take effect. 638b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.ec.set_flash_write_protect(enable) 639b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.sync_and_ec_reboot() 640b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch else: 641b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch # Reboot after deasserting hardware write protect pin to deactivate 642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # write protect. And then remove software write protect flag. 643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.sync_and_ec_reboot() 644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.ec.set_flash_write_protect(enable) 645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def _setup_ec_write_protect(self, ec_wp): 647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Setup for EC write-protection. 6481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch It makes sure the EC in the requested write-protection state. If not, it 650b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch flips the state. Flipping the write-protection requires DUT reboot. 651b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 652b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @param ec_wp: True to request EC write-protected; False to request EC 653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch not write-protected; None to do nothing. 654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 655b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if ec_wp is None: 656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._old_ec_wp = None 657b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return 658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._old_ec_wp = self.checkers.crossystem_checker({'wpsw_boot': '1'}) 659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if ec_wp != self._old_ec_wp: 660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('The test required EC is %swrite-protected. Reboot ' 661b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 'and flip the state.', '' if ec_wp else 'not ') 662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.switcher.mode_aware_reboot( 663b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 'custom', 664b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch lambda:self.set_ec_write_protect_and_reboot(ec_wp)) 665b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 666b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch def _restore_ec_write_protect(self): 667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Restore the original EC write-protection.""" 668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (not hasattr(self, '_old_ec_wp')) or (self._old_ec_wp is None): 669b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return 670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if not self.checkers.crossystem_checker( 671b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch {'wpsw_boot': '1' if self._old_ec_wp else '0'}): 672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('Restore original EC write protection and reboot.') 673b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.switcher.mode_aware_reboot( 674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'custom', 675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lambda:self.set_ec_write_protect_and_reboot( 676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._old_ec_wp)) 677b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def _setup_uart_capture(self): 679b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Setup the CPU/EC/PD UART capture.""" 680b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.cpu_uart_file = os.path.join(self.resultsdir, 'cpu_uart.txt') 681b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.servo.set('cpu_uart_capture', 'on') 682b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.ec_uart_file = None 683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.usbpd_uart_file = None 684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if self.faft_config.chrome_ec: 685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch try: 686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo.set('ec_uart_capture', 'on') 687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.ec_uart_file = os.path.join(self.resultsdir, 'ec_uart.txt') 688b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch except error.TestFail as e: 689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if 'No control named' in str(e): 690b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.warn('The servod is too old that ec_uart_capture ' 691b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 'not supported.') 692b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch # Log separate PD console if supported 693b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if self.check_ec_capability(['usbpd_uart'], suppress_warning=True): 694b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch try: 695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo.set('usbpd_uart_capture', 'on') 696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.usbpd_uart_file = os.path.join(self.resultsdir, 697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'usbpd_uart.txt') 698b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch except error.TestFail as e: 699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if 'No control named' in str(e): 700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.warn('The servod is too old that ' 701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'usbpd_uart_capture is not supported.') 7021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block else: 703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('Not a Google EC, cannot capture ec console output.') 704b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 705b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch def _record_uart_capture(self): 706b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Record the CPU/EC/PD UART output stream to files.""" 707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if self.cpu_uart_file: 708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch with open(self.cpu_uart_file, 'a') as f: 709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch f.write(ast.literal_eval(self.servo.get('cpu_uart_stream'))) 710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if self.ec_uart_file and self.faft_config.chrome_ec: 711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch with open(self.ec_uart_file, 'a') as f: 712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch f.write(ast.literal_eval(self.servo.get('ec_uart_stream'))) 7131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (self.usbpd_uart_file and self.faft_config.chrome_ec and 714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.check_ec_capability(['usbpd_uart'], suppress_warning=True)): 715b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch with open(self.usbpd_uart_file, 'a') as f: 716b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch f.write(ast.literal_eval(self.servo.get('usbpd_uart_stream'))) 717b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def _cleanup_uart_capture(self): 719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Cleanup the CPU/EC/PD UART capture.""" 720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # Flush the remaining UART output. 721b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._record_uart_capture() 722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo.set('cpu_uart_capture', 'off') 723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if self.ec_uart_file and self.faft_config.chrome_ec: 724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo.set('ec_uart_capture', 'off') 7251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (self.usbpd_uart_file and self.faft_config.chrome_ec and 726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.check_ec_capability(['usbpd_uart'], suppress_warning=True)): 727b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.servo.set('usbpd_uart_capture', 'off') 728b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 729b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch def _fetch_servo_log(self): 730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Fetch the servo log.""" 731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cmd = '[ -e %s ] && cat %s || echo NOTFOUND' % ((self._SERVOD_LOG,) * 2) 732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch servo_log = self.servo.system_output(cmd) 733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return None if servo_log == 'NOTFOUND' else servo_log 734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def _setup_servo_log(self): 736b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Setup the servo log capturing.""" 737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo_log_original_len = -1 738b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if self.servo.is_localhost(): 739b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch # No servo log recorded when servod runs locally. 740b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return 741b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch servo_log = self._fetch_servo_log() 743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if servo_log: 744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo_log_original_len = len(servo_log) 745b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch else: 746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.warn('Servo log file not found.') 747b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def _record_servo_log(self): 749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Record the servo log to the results directory.""" 750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if self.servo_log_original_len != -1: 751e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch servo_log = self._fetch_servo_log() 752e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch servo_log_file = os.path.join(self.resultsdir, 'servod.log') 753e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch with open(servo_log_file, 'a') as f: 754e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch f.write(servo_log[self.servo_log_original_len:]) 755e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 756e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch def _record_faft_client_log(self): 757e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch """Record the faft client log to the results directory.""" 758e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch client_log = self.faft_client.system.dump_log(True) 759e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch client_log_file = os.path.join(self.resultsdir, 'faft_client.log') 760e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch with open(client_log_file, 'w') as f: 761e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch f.write(client_log) 7621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def _setup_gbb_flags(self): 764b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Setup the GBB flags for FAFT test.""" 765b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if self.faft_config.gbb_version < 1.1: 766b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.info('Skip modifying GBB on versions older than 1.1.') 767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return 768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if self.check_setup_done('gbb_flags'): 770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return 771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._backup_gbb_flags = self.faft_client.bios.get_gbb_flags() 7731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('Set proper GBB flags for test.') 775b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.clear_set_gbb_flags(vboot.GBB_FLAG_DEV_SCREEN_SHORT_DELAY | 776b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch vboot.GBB_FLAG_FORCE_DEV_SWITCH_ON | 777b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch vboot.GBB_FLAG_FORCE_DEV_BOOT_USB | 778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch vboot.GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK, 779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch vboot.GBB_FLAG_ENTER_TRIGGERS_TONORM | 780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch vboot.GBB_FLAG_FAFT_KEY_OVERIDE) 781b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.mark_setup_done('gbb_flags') 782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def drop_backup_gbb_flags(self): 784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Drops the backup GBB flags. 7851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block This can be used when a test intends to permanently change GBB flags. 7871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block """ 7881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self._backup_gbb_flags = None 7891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block def _restore_gbb_flags(self): 7911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block """Restore GBB flags to their original state.""" 7921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if not self._backup_gbb_flags: 7931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return 7941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self._write_gbb_flags(self._backup_gbb_flags) 7951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.unmark_setup_done('gbb_flags') 7961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block def setup_tried_fwb(self, tried_fwb): 7981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block """Setup for fw B tried state. 7991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block It makes sure the system in the requested fw B tried state. If not, it 8011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block tries to do so. 8021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 803b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @param tried_fwb: True if requested in tried_fwb=1; 804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch False if tried_fwb=0. 805b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 806b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if tried_fwb: 807b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if not self.checkers.crossystem_checker({'tried_fwb': '1'}): 808b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.info( 809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'Firmware is not booted with tried_fwb. Reboot into it.') 810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.system.set_try_fw_b() 811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch else: 812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if not self.checkers.crossystem_checker({'tried_fwb': '0'}): 813b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.info( 814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'Firmware is booted with tried_fwb. Reboot to clear.') 815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def power_on(self): 817b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Switch DUT AC power on.""" 818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._client.power_on(self.power_control) 819b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 820b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch def power_off(self): 821b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Switch DUT AC power off.""" 822b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._client.power_off(self.power_control) 823b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def power_cycle(self): 825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Power cycle DUT AC power.""" 826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._client.power_cycle(self.power_control) 827b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def setup_rw_boot(self, section='a'): 829b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Make sure firmware is in RW-boot mode. 830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch If the given firmware section is in RO-boot mode, turn off the RO-boot 832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch flag and reboot DUT into RW-boot mode. 8331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param section: A firmware section, either 'a' or 'b'. 835b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 836b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch flags = self.faft_client.bios.get_preamble_flags(section) 837b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if flags & vboot.PREAMBLE_USE_RO_NORMAL: 838b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch flags = flags ^ vboot.PREAMBLE_USE_RO_NORMAL 839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.bios.set_preamble_flags(section, flags) 840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.switcher.mode_aware_reboot() 841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def setup_kernel(self, part): 843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Setup for kernel test. 844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch It makes sure both kernel A and B bootable and the current boot is 846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch the requested kernel part. 8471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param part: A string of kernel partition number or 'a'/'b'. 849b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 850b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.ensure_kernel_boot(part) 851b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.info('Checking the integrity of kernel B and rootfs B...') 852b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (self.faft_client.kernel.diff_a_b() or 853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch not self.faft_client.rootfs.verify_rootfs('B')): 854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('Copying kernel and rootfs from A to B...') 855b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.copy_kernel_and_rootfs(from_part=part, 856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch to_part=self.OTHER_KERNEL_MAP[part]) 857b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.reset_and_prioritize_kernel(part) 858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def reset_and_prioritize_kernel(self, part): 860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Make the requested partition highest priority. 8611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch This function also reset kerenl A and B to bootable. 8631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block @param part: A string of partition number to be prioritized. 8651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block """ 8661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block root_dev = self.faft_client.system.get_root_dev() 867b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch # Reset kernel A and B to bootable. 868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.system.run_shell_command( 869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'cgpt add -i%s -P1 -S1 -T0 %s' % (self.KERNEL_MAP['a'], root_dev)) 8701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.faft_client.system.run_shell_command( 8711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 'cgpt add -i%s -P1 -S1 -T0 %s' % (self.KERNEL_MAP['b'], root_dev)) 872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # Set kernel part highest priority. 873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.system.run_shell_command('cgpt prioritize -i%s %s' % 874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (self.KERNEL_MAP[part], root_dev)) 8751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def blocking_sync(self): 8771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block """Run a blocking sync command.""" 8781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # The double calls to sync fakes a blocking call 8791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # since the first call returns before the flush 8801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # is complete, but the second will wait for the 881b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch # first to finish. 882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.system.run_shell_command('sync') 883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.system.run_shell_command('sync') 8841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # sync only sends SYNCHRONIZE_CACHE but doesn't 886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # check the status. For mmc devices, use `mmc 887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # status get` command to send an empty command to 888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # wait for the disk to be available again. For 889b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch # other devices, hdparm sends TUR to check if 890086aeeaae12517475c22695a200be45495516549Ben Murdoch # a device is ready for transfer operation. 891b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch root_dev = self.faft_client.system.get_root_dev() 892b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if 'mmcblk' in root_dev: 893b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.faft_client.system.run_shell_command('mmc status get %s' % 894b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch root_dev) 895086aeeaae12517475c22695a200be45495516549Ben Murdoch else: 896086aeeaae12517475c22695a200be45495516549Ben Murdoch self.faft_client.system.run_shell_command('hdparm -f %s' % root_dev) 897086aeeaae12517475c22695a200be45495516549Ben Murdoch 898086aeeaae12517475c22695a200be45495516549Ben Murdoch def wait_for_kernel_up(self): 899086aeeaae12517475c22695a200be45495516549Ben Murdoch """ 900086aeeaae12517475c22695a200be45495516549Ben Murdoch Helper function that waits for the device to boot up to kernel. 901086aeeaae12517475c22695a200be45495516549Ben Murdoch """ 902086aeeaae12517475c22695a200be45495516549Ben Murdoch logging.info("-[FAFT]-[ start wait_for_kernel_up ]---") 903086aeeaae12517475c22695a200be45495516549Ben Murdoch # Wait for the system to respond to ping before attempting ssh 904b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if not self._client.ping_wait_up(90): 905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.warning("-[FAFT]-[ system did not respond to ping ]") 906b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch try: 907b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.wait_for_client() 908b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch # Stop update-engine as it may change firmware/kernel. 909b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._stop_service('update-engine') 910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch except ConnectionError: 911b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.error('wait_for_client() timed out.') 912b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._restore_routine_from_timeout() 913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info("-[FAFT]-[ end wait_for_kernel_up ]-----") 914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def sync_and_ec_reboot(self, flags=''): 916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Request the client sync and do a EC triggered reboot. 917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 9181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block @param flags: Optional, a space-separated string of flags passed to EC 919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch reboot command, including: 920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: EC soft reboot; 921b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 'hard': EC cold/hard reboot. 922b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 923b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.blocking_sync() 924b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.ec.reboot(flags) 925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch time.sleep(self.faft_config.ec_boot_to_console) 926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.check_lid_and_power_on() 927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def reboot_and_reset_tpm(self): 929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Reboot into recovery mode, reset TPM, then reboot back to disk.""" 930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.switcher.reboot_to_mode(to_mode='rec') 931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.system.run_shell_command('chromeos-tpm-recovery') 932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.switcher.mode_aware_reboot() 933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def full_power_off_and_on(self): 9351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block """Shutdown the device by pressing power button and power on again.""" 936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch boot_id = self.get_bootid() 937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # Press power button to trigger Chrome OS normal shutdown process. 938b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch # We use a customized delay since the normal-press 1.2s is not enough. 939b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.servo.power_key(self.faft_config.hold_pwr_button) 940b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch # device can take 44-51 seconds to restart, 941b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch # add buffer from the default timeout of 60 seconds. 942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.wait_for_client_offline(timeout=100, orig_boot_id=boot_id) 943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch time.sleep(self.faft_config.shutdown) 944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # Short press power button to boot DUT again. 945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo.power_short_press() 946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def check_lid_and_power_on(self): 948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch On devices with EC software sync, system powers on after EC reboots if 950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lid is open. Otherwise, the EC shuts down CPU after about 3 seconds. 951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch This method checks lid switch state and presses power button if 952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch necessary. 953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if self.servo.get("lid_open") == "no": 9551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block time.sleep(self.faft_config.software_sync) 956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.servo.power_short_press() 957b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 958b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch def _modify_usb_kernel(self, usb_dev, from_magic, to_magic): 959b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Modify the kernel header magic in USB stick. 960b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch The kernel header magic is the first 8-byte of kernel partition. 962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch We modify it to make it fail on kernel verification check. 963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param usb_dev: A string of USB stick path on the host, like '/dev/sdc'. 965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param from_magic: A string of magic which we change it from. 966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param to_magic: A string of magic which we change it to. 9671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block @raise TestError: if failed to change magic. 968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch assert len(from_magic) == 8 9701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block assert len(to_magic) == 8 971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # USB image only contains one kernel. 9721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block kernel_part = self._join_part(usb_dev, self.KERNEL_MAP['a']) 973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch read_cmd = "sudo dd if=%s bs=8 count=1 2>/dev/null" % kernel_part 974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_magic = self.servo.system_output(read_cmd) 975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if current_magic == to_magic: 9761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block logging.info("The kernel magic is already %s.", current_magic) 977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return 9781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if current_magic != from_magic: 9791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block raise error.TestError("Invalid kernel image on USB: wrong magic.") 9801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('Modify the kernel magic in USB, from %s to %s.', 982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch from_magic, to_magic) 9831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block write_cmd = ("echo -n '%s' | sudo dd of=%s oflag=sync conv=notrunc " 984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch " 2>/dev/null" % (to_magic, kernel_part)) 9851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.servo.system(write_cmd) 986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if self.servo.system_output(read_cmd) != to_magic: 988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch raise error.TestError("Failed to write new magic.") 9891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def corrupt_usb_kernel(self, usb_dev): 991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Corrupt USB kernel by modifying its magic from CHROMEOS to CORRUPTD. 9921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param usb_dev: A string of USB stick path on the host, like '/dev/sdc'. 9941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block """ 995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._modify_usb_kernel(usb_dev, self.CHROMEOS_MAGIC, 996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.CORRUPTED_MAGIC) 997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 9981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block def restore_usb_kernel(self, usb_dev): 999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Restore USB kernel by modifying its magic from CORRUPTD to CHROMEOS. 1000b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1001b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @param usb_dev: A string of USB stick path on the host, like '/dev/sdc'. 1002b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 1003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._modify_usb_kernel(usb_dev, self.CORRUPTED_MAGIC, 1004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.CHROMEOS_MAGIC) 1005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def _call_action(self, action_tuple, check_status=False): 1007b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Call the action function with/without arguments. 1008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param action_tuple: A function, or a tuple (function, args, error_msg), 1010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch in which, args and error_msg are optional. args is 10111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block either a value or a tuple if multiple arguments. 1012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch This can also be a list containing multiple 1013b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch function or tuple. In this case, these actions are 1014b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch called in sequence. 1015b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @param check_status: Check the return value of action function. If not 1016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch succeed, raises a TestFail exception. 1017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @return: The result value of the action function. 10181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block @raise TestError: An error when the action function is not callable. 1019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @raise TestFail: When check_status=True, action function not succeed. 1020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 1021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if isinstance(action_tuple, list): 1022086aeeaae12517475c22695a200be45495516549Ben Murdoch return all([self._call_action(action, check_status=check_status) 1023086aeeaae12517475c22695a200be45495516549Ben Murdoch for action in action_tuple]) 10241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1025086aeeaae12517475c22695a200be45495516549Ben Murdoch action = action_tuple 1026086aeeaae12517475c22695a200be45495516549Ben Murdoch args = () 10271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block error_msg = 'Not succeed' 1028086aeeaae12517475c22695a200be45495516549Ben Murdoch if isinstance(action_tuple, tuple): 1029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch action = action_tuple[0] 1030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if len(action_tuple) >= 2: 1031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch args = action_tuple[1] 10321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if not isinstance(args, tuple): 1033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch args = (args,) 1034b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if len(action_tuple) >= 3: 1035b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch error_msg = action_tuple[2] 1036b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if action is None: 10389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return 10399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 10409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if not callable(action): 1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch raise error.TestError('action is not callable!') 1042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 104344f0eee88ff00398ff7f715fab053374d808c90dSteve Block info_msg = 'calling %s' % str(action) 10441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if args: 104544f0eee88ff00398ff7f715fab053374d808c90dSteve Block info_msg += ' with args %s' % str(args) 10461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block logging.info(info_msg) 10471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ret = action(*args) 10481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 104944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if check_status and not ret: 105044f0eee88ff00398ff7f715fab053374d808c90dSteve Block raise error.TestFail('%s: %s returning %s' % 10511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (error_msg, info_msg, str(ret))) 10521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return ret 10531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 10541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block def run_shutdown_process(self, shutdown_action, pre_power_action=None, 10559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block post_power_action=None, shutdown_timeout=None): 1056b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Run shutdown_action(), which makes DUT shutdown, and power it on. 1057b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1058b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @param shutdown_action: function which makes DUT shutdown, like 10599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block pressing power key. 10609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block @param pre_power_action: function which is called before next power on. 10619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block @param post_power_action: function which is called after next power on. 1062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param shutdown_timeout: a timeout to confirm DUT shutdown. 1063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @raise TestFail: if the shutdown_action() failed to turn DUT off. 1064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 1065b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._call_action(shutdown_action) 1066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('Wait to ensure DUT shut down...') 1067b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch try: 1068b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if shutdown_timeout is None: 1069b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch shutdown_timeout = self.faft_config.shutdown_timeout 1070b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.wait_for_client(timeout=shutdown_timeout) 1071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch raise error.TestFail( 1072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'Should shut the device down after calling %s.' % 1073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch str(shutdown_action)) 1074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch except ConnectionError: 1075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info( 1076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'DUT is surely shutdown. We are going to power it on again...') 10771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if pre_power_action: 1079b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._call_action(pre_power_action) 1080b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.servo.power_short_press() 1081b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if post_power_action: 1082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._call_action(post_power_action) 1083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def get_bootid(self, retry=3): 1085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 1086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Return the bootid. 10871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block """ 1088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch boot_id = None 1089b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch while retry: 1090b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch try: 1091b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch boot_id = self._client.get_boot_id() 1092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break 1093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch except error.AutoservRunError: 1094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch retry -= 1 1095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if retry: 1096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('Retry to get boot_id...') 10971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block else: 1098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.warning('Failed to get boot_id.') 1099b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.info('boot_id: %s', boot_id) 1100b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return boot_id 1101b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1102b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch def check_state(self, func): 1103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 1104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Wrapper around _call_action with check_status set to True. This is a 1105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch helper function to be used by tests and is currently implemented by 1106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch calling _call_action with check_status=True. 1107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TODO: This function's arguments need to be made more stringent. And 11091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block its functionality should be moved over to check functions directly in 1110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch the future. 1111b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1112b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @param func: A function, or a tuple (function, args, error_msg), 1113b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch in which, args and error_msg are optional. args is 1114b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch either a value or a tuple if multiple arguments. 1115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch This can also be a list containing multiple 1116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function or tuple. In this case, these actions are 1117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch called in sequence. 1118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @return: The result value of the action function. 1119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @raise TestFail: If the function does notsucceed. 1120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 11211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block logging.info("-[FAFT]-[ start stepstate_checker ]----------") 1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._call_action(func, check_status=True) 1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info("-[FAFT]-[ end state_checker ]----------------") 1124b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1125b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch def get_current_firmware_sha(self): 1126b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Get current firmware sha of body and vblock. 1127b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @return: Current firmware sha follows the order ( 1129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch vblock_a_sha, body_a_sha, vblock_b_sha, body_b_sha) 1130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_firmware_sha = (self.faft_client.bios.get_sig_sha('a'), 1132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.bios.get_body_sha('a'), 1133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.bios.get_sig_sha('b'), 1134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.bios.get_body_sha('b')) 1135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if not all(current_firmware_sha): 1136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch raise error.TestError('Failed to get firmware sha.') 1137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return current_firmware_sha 1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 11391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block def is_firmware_changed(self): 1140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Check if the current firmware changed, by comparing its SHA. 1141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1142b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @return: True if it is changed, otherwise Flase. 1143b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 1144b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch # Device may not be rebooted after test. 1145b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.faft_client.bios.reload() 1146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_sha = self.get_current_firmware_sha() 1148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if current_sha == self._backup_firmware_sha: 1150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return False 1151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch else: 1152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch corrupt_VBOOTA = (current_sha[0] != self._backup_firmware_sha[0]) 1153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch corrupt_FVMAIN = (current_sha[1] != self._backup_firmware_sha[1]) 1154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch corrupt_VBOOTB = (current_sha[2] != self._backup_firmware_sha[2]) 1155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch corrupt_FVMAINB = (current_sha[3] != self._backup_firmware_sha[3]) 1156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info("Firmware changed:") 11571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block logging.info('VBOOTA is changed: %s', corrupt_VBOOTA) 1158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('VBOOTB is changed: %s', corrupt_VBOOTB) 1159b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.info('FVMAIN is changed: %s', corrupt_FVMAIN) 1160b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.info('FVMAINB is changed: %s', corrupt_FVMAINB) 1161b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return True 1162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def backup_firmware(self, suffix='.original'): 1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Backup firmware to file, and then send it to host. 1165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param suffix: a string appended to backup file name 11671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block """ 1168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch remote_temp_dir = self.faft_client.system.create_temp_dir() 1169b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self.faft_client.bios.dump_whole(os.path.join(remote_temp_dir, 'bios')) 1170b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._client.get_file(os.path.join(remote_temp_dir, 'bios'), 1171b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch os.path.join(self.resultsdir, 'bios' + suffix)) 1172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._backup_firmware_sha = self.get_current_firmware_sha() 1174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('Backup firmware stored in %s with suffix %s', 117544f0eee88ff00398ff7f715fab053374d808c90dSteve Block self.resultsdir, suffix) 117644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 117744f0eee88ff00398ff7f715fab053374d808c90dSteve Block def is_firmware_saved(self): 117844f0eee88ff00398ff7f715fab053374d808c90dSteve Block """Check if a firmware saved (called backup_firmware before). 117944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 118044f0eee88ff00398ff7f715fab053374d808c90dSteve Block @return: True if the firmware is backuped; otherwise False. 118144f0eee88ff00398ff7f715fab053374d808c90dSteve Block """ 118244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return self._backup_firmware_sha != () 118344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 118444f0eee88ff00398ff7f715fab053374d808c90dSteve Block def clear_saved_firmware(self): 118544f0eee88ff00398ff7f715fab053374d808c90dSteve Block """Clear the firmware saved by the method backup_firmware.""" 118644f0eee88ff00398ff7f715fab053374d808c90dSteve Block self._backup_firmware_sha = () 118744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 118844f0eee88ff00398ff7f715fab053374d808c90dSteve Block def restore_firmware(self, suffix='.original'): 118944f0eee88ff00398ff7f715fab053374d808c90dSteve Block """Restore firmware from host in resultsdir. 1190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param suffix: a string appended to backup file name 1192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 11931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if not self.is_firmware_changed(): 1194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return 11951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 11961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # Backup current corrupted firmware. 11971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.backup_firmware(suffix='.corrupt') 1198b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch # Restore firmware. 1200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch remote_temp_dir = self.faft_client.system.create_temp_dir() 1201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._client.send_file(os.path.join(self.resultsdir, 'bios' + suffix), 1202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch os.path.join(remote_temp_dir, 'bios')) 12031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.faft_client.bios.write_whole( 1205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch os.path.join(remote_temp_dir, 'bios')) 1206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.switcher.mode_aware_reboot() 1207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('Successfully restore firmware.') 1208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1209b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch def setup_firmwareupdate_shellball(self, shellball=None): 12109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block """Deside a shellball to use in firmware update test. 1211b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1212b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Check if there is a given shellball, and it is a shell script. Then, 1213b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch send it to the remote host. Otherwise, use 1214b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch /usr/sbin/chromeos-firmwareupdate. 12159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 12169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block @param shellball: path of a shellball or default to None. 12179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 12189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block @return: Path of shellball in remote host. If use default shellball, 1219b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch reutrn None. 12209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block """ 12219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block updater_path = None 12229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if shellball: 12231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # Determine the firmware file is a shellball or a raw binary. 1224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch is_shellball = (utils.system_output("file %s" % shellball).find( 1225b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch "shell script") != -1) 1226b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if is_shellball: 1227b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch logging.info('Device will update firmware with shellball %s', 1228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch shellball) 1229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch temp_dir = self.faft_client.system.create_temp_dir( 1230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 'shellball_') 1231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch temp_shellball = os.path.join(temp_dir, 'updater.sh') 1232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._client.send_file(shellball, temp_shellball) 123344f0eee88ff00398ff7f715fab053374d808c90dSteve Block updater_path = temp_shellball 12341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block else: 123544f0eee88ff00398ff7f715fab053374d808c90dSteve Block raise error.TestFail( 12361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 'The given shellball is not a shell script.') 12371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return updater_path 12381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 123944f0eee88ff00398ff7f715fab053374d808c90dSteve Block def is_kernel_changed(self): 124044f0eee88ff00398ff7f715fab053374d808c90dSteve Block """Check if the current kernel is changed, by comparing its SHA1 hash. 12411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block @return: True if it is changed; otherwise, False. 12431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block """ 12441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block changed = False 1245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for p in ('A', 'B'): 1246b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch backup_sha = self._backup_kernel_sha.get(p, None) 1247b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch current_sha = self.faft_client.kernel.get_sha(p) 1248b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if backup_sha != current_sha: 1249b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch changed = True 1250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('Kernel %s is changed', p) 1251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return changed 1252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def backup_kernel(self, suffix='.original'): 1254b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Backup kernel to files, and the send them to host. 1255b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch @param suffix: a string appended to backup file name. 1257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """ 1258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch remote_temp_dir = self.faft_client.system.create_temp_dir() 125944f0eee88ff00398ff7f715fab053374d808c90dSteve Block for p in ('A', 'B'): 1260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch remote_path = os.path.join(remote_temp_dir, 'kernel_%s' % p) 126144f0eee88ff00398ff7f715fab053374d808c90dSteve Block self.faft_client.kernel.dump(p, remote_path) 126244f0eee88ff00398ff7f715fab053374d808c90dSteve Block self._client.get_file( 12631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block remote_path, 1264b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch os.path.join(self.resultsdir, 'kernel_%s%s' % (p, suffix))) 1265b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._backup_kernel_sha[p] = self.faft_client.kernel.get_sha(p) 1266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('Backup kernel stored in %s with suffix %s', 126744f0eee88ff00398ff7f715fab053374d808c90dSteve Block self.resultsdir, suffix) 126844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 126944f0eee88ff00398ff7f715fab053374d808c90dSteve Block def is_kernel_saved(self): 1270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Check if kernel images are saved (backup_kernel called before). 12711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1272b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @return: True if the kernel is saved; otherwise, False. 127344f0eee88ff00398ff7f715fab053374d808c90dSteve Block """ 127444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return len(self._backup_kernel_sha) != 0 127544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def clear_saved_kernel(self): 1277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Clear the kernel saved by backup_kernel().""" 1278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self._backup_kernel_sha = dict() 12791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block def restore_kernel(self, suffix='.original'): 12811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block """Restore kernel from host in resultsdir. 12821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block @param suffix: a string appended to backup file name. 12841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block """ 12851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if not self.is_kernel_changed(): 12861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return 12871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # Backup current corrupted kernel. 12891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.backup_kernel(suffix='.corrupt') 12901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # Restore kernel. 12921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block remote_temp_dir = self.faft_client.system.create_temp_dir() 12931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for p in ('A', 'B'): 12941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block remote_path = os.path.join(remote_temp_dir, 'kernel_%s' % p) 1295b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._client.send_file( 1296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch os.path.join(self.resultsdir, 'kernel_%s%s' % (p, suffix)), 1297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch remote_path) 1298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.faft_client.kernel.write(p, remote_path) 1299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch self.switcher.mode_aware_reboot() 1301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('Successfully restored kernel.') 13021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def backup_cgpt_attributes(self): 1304b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """Backup CGPT partition table attributes.""" 1305b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch self._backup_cgpt_attr = self.faft_client.cgpt.get_attributes() 1306b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch def restore_cgpt_attributes(self): 1308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch """Restore CGPT partition table attributes.""" 1309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_table = self.faft_client.cgpt.get_attributes() 1310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if current_table == self._backup_cgpt_attr: 1311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return 1312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch logging.info('CGPT table is changed. Original: %r. Current: %r.', 13131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self._backup_cgpt_attr, 1314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_table) 13151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.faft_client.cgpt.set_attributes(self._backup_cgpt_attr) 13161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 13171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.switcher.mode_aware_reboot() 13181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block logging.info('Successfully restored CGPT table.') 1319b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1320b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch def try_fwb(self, count=0): 1321b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """set to try booting FWB count # times 13221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1323b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Wrapper to set fwb_tries for vboot1 and fw_try_count,fw_try_next for 1324b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch vboot2 1325b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1326b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch @param count: an integer specifying value to program into 1327b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch fwb_tries(vb1)/fw_try_next(vb2) 1328b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch """ 13291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if self.fw_vboot2: 13301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.faft_client.system.set_fw_try_next('B', count) 13311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block else: 13321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block # vboot1: we need to boot into fwb at least once 13331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if not count: 13341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block count = count + 1 13351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block self.faft_client.system.set_try_fw_b(count) 13361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 13371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block