105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally# Copyright (c) 2014 The Chromium OS Authors. All rights reserved. 205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally# Use of this source code is governed by a BSD-style license that can be 305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally# found in the LICENSE file. 405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinallyimport ast 605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinallyimport ctypes 705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinallyimport logging 805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinallyimport os 99a10b9bfa8a160ca306e8f4ad9666c555ab3f94bTom Wai-Hong Tamimport pprint 1005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinallyimport re 1105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinallyimport time 1205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinallyimport uuid 1305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 14530490a25d656468ade45a4e165e683846ccd403Shelley Chenfrom threading import Timer 1505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinallyfrom autotest_lib.client.bin import utils 1605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinallyfrom autotest_lib.client.common_lib import error 17cab6be36a26c73dd4e6fa2f85ba48f50cfd92acaJ. Richard Barnettefrom autotest_lib.server import test 1805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinallyfrom autotest_lib.server.cros import vboot_constants as vboot 1905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinallyfrom autotest_lib.server.cros.faft.config.config import Config as FAFTConfig 2005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinallyfrom autotest_lib.server.cros.faft.rpc_proxy import RPCProxy 21ed4d67be4d0faa1a267d33e86905df1153d78333Tom Wai-Hong Tamfrom autotest_lib.server.cros.faft.utils import mode_switcher 22a57ff841026d6878e4ecbf993efd994638fde879J. Richard Barnettefrom autotest_lib.server.cros.faft.utils.faft_checkers import FAFTCheckers 2305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinallyfrom autotest_lib.server.cros.servo import chrome_ec 24fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scottfrom autotest_lib.server.cros.servo import chrome_usbpd 2505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 2619bfb6ea468c34e1b44842033eb784c2ef3eed42Tom Wai-Hong TamConnectionError = mode_switcher.ConnectionError 2705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 2805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 29cab6be36a26c73dd4e6fa2f85ba48f50cfd92acaJ. Richard Barnetteclass FAFTBase(test.test): 3005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """The base class of FAFT classes. 3105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 3205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally It launches the FAFTClient on DUT, such that the test can access its 3305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally firmware functions and interfaces. It also provides some methods to 3405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally handle the reboot mechanism, in order to ensure FAFTClient is still 3505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally connected after reboot. 3605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 3705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def initialize(self, host): 3805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Create a FAFTClient object and install the dependency.""" 39cab6be36a26c73dd4e6fa2f85ba48f50cfd92acaJ. Richard Barnette self.servo = host.servo 40cab6be36a26c73dd4e6fa2f85ba48f50cfd92acaJ. Richard Barnette self.servo.initialize_dut() 4105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._client = host 4205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client = RPCProxy(host) 4310eb618d5336f1bd6f4cd4c135ea93d1e3a880bfDuncan Laurie self.lockfile = '/var/tmp/faft/lock' 4405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 4505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 4605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinallyclass FirmwareTest(FAFTBase): 4705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 48ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally Base class that sets up helper objects/functions for firmware tests. 49ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally 50ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally TODO: add documentaion as the FAFT rework progresses. 5105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 5205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally version = 1 5305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 5405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Mapping of partition number of kernel and rootfs. 5505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally KERNEL_MAP = {'a':'2', 'b':'4', '2':'2', '4':'4', '3':'2', '5':'4'} 5605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally ROOTFS_MAP = {'a':'3', 'b':'5', '2':'3', '4':'5', '3':'3', '5':'5'} 5705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally OTHER_KERNEL_MAP = {'a':'4', 'b':'2', '2':'4', '4':'2', '3':'4', '5':'2'} 5805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally OTHER_ROOTFS_MAP = {'a':'5', 'b':'3', '2':'5', '4':'3', '3':'5', '5':'3'} 5905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 6005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally CHROMEOS_MAGIC = "CHROMEOS" 6105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally CORRUPTED_MAGIC = "CORRUPTD" 6205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 63530490a25d656468ade45a4e165e683846ccd403Shelley Chen # Delay for waiting client to return before EC suspend 64530490a25d656468ade45a4e165e683846ccd403Shelley Chen EC_SUSPEND_DELAY = 5 65530490a25d656468ade45a4e165e683846ccd403Shelley Chen 66530490a25d656468ade45a4e165e683846ccd403Shelley Chen # Delay between EC suspend and wake 67530490a25d656468ade45a4e165e683846ccd403Shelley Chen WAKE_DELAY = 10 68530490a25d656468ade45a4e165e683846ccd403Shelley Chen 69530490a25d656468ade45a4e165e683846ccd403Shelley Chen # Delay between closing and opening lid 70530490a25d656468ade45a4e165e683846ccd403Shelley Chen LID_DELAY = 1 71530490a25d656468ade45a4e165e683846ccd403Shelley Chen 7205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally _SERVOD_LOG = '/var/log/servod.log' 7305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 7405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally _ROOTFS_PARTITION_NUMBER = 3 7505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 7605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally _backup_firmware_sha = () 7705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally _backup_kernel_sha = dict() 7805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally _backup_cgpt_attr = dict() 7905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally _backup_gbb_flags = None 8005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally _backup_dev_mode = None 8105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 8205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Class level variable, keep track the states of one time setup. 8305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # This variable is preserved across tests which inherit this class. 8405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally _global_setup_done = { 8505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'gbb_flags': False, 8605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'reimage': False, 8705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'usb_check': False, 8805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally } 8905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 9005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @classmethod 9105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def check_setup_done(cls, label): 9205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Check if the given setup is done. 9305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 9405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param label: The label of the setup. 9505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 9605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return cls._global_setup_done[label] 9705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 9805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @classmethod 9905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def mark_setup_done(cls, label): 10005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Mark the given setup done. 10105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 10205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param label: The label of the setup. 10305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 10405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally cls._global_setup_done[label] = True 10505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 10605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @classmethod 10705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def unmark_setup_done(cls, label): 10805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Mark the given setup not done. 10905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 11005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param label: The label of the setup. 11105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 11205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally cls._global_setup_done[label] = False 11305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 11405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def initialize(self, host, cmdline_args, ec_wp=None): 11505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally super(FirmwareTest, self).initialize(host) 11605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.run_id = str(uuid.uuid4()) 11705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('FirmwareTest initialize begin (id=%s)', self.run_id) 11805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Parse arguments from command line 11905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally args = {} 12005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.power_control = host.POWER_CONTROL_RPM 12105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally for arg in cmdline_args: 12205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally match = re.search("^(\w+)=(.+)", arg) 12305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if match: 12405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally args[match.group(1)] = match.group(2) 12505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if 'power_control' in args: 12605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.power_control = args['power_control'] 12705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.power_control not in host.POWER_CONTROL_VALID_ARGS: 12805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally raise error.TestError('Valid values for --args=power_control ' 12905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'are %s. But you entered wrong argument ' 13005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'as "%s".' 13105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally % (host.POWER_CONTROL_VALID_ARGS, 13205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.power_control)) 13305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 13405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_config = FAFTConfig( 13505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.system.get_platform_name()) 1360cc9a4fe28f221cfc73bb35c30fa79338c4b43f1Tom Wai-Hong Tam self.checkers = FAFTCheckers(self) 137ed4d67be4d0faa1a267d33e86905df1153d78333Tom Wai-Hong Tam self.switcher = mode_switcher.create_mode_switcher(self) 13805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 13905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.faft_config.chrome_ec: 14005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.ec = chrome_ec.ChromeEC(self.servo) 141fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott # Check for presence of a USBPD console 142fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott if self.faft_config.chrome_usbpd: 143fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott self.usbpd = chrome_usbpd.ChromeUSBPD(self.servo) 144fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott elif self.faft_config.chrome_ec: 145fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott # If no separate USBPD console, then PD exists on EC console 146fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott self.usbpd = self.ec 147fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott # Get plankton console 14807a848f9faddc3302cf46e7d3238adcbabfaca6cScott self.plankton = host.plankton 14907a848f9faddc3302cf46e7d3238adcbabfaca6cScott self.plankton_host = host._plankton_host 15005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 1518b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally self._setup_uart_capture() 1528b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally self._setup_servo_log() 1538b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally self._record_system_info() 154682a6d6a8f607fb70a7812194202826e1e6e85ccDaisuke Nojiri self.fw_vboot2 = self.faft_client.system.get_fw_vboot2() 155682a6d6a8f607fb70a7812194202826e1e6e85ccDaisuke Nojiri logging.info('vboot version: %d', 2 if self.fw_vboot2 else 1) 156682a6d6a8f607fb70a7812194202826e1e6e85ccDaisuke Nojiri if self.fw_vboot2: 157682a6d6a8f607fb70a7812194202826e1e6e85ccDaisuke Nojiri self.faft_client.system.set_fw_try_next('A') 158682a6d6a8f607fb70a7812194202826e1e6e85ccDaisuke Nojiri if self.faft_client.system.get_crossystem_value('mainfw_act') == 'B': 159682a6d6a8f607fb70a7812194202826e1e6e85ccDaisuke Nojiri logging.info('mainfw_act is B. rebooting to set it A') 1604777624b69b3b223a5d3c3abe86000783f6c0e96Tom Wai-Hong Tam self.switcher.mode_aware_reboot() 1618b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally self._setup_gbb_flags() 1628b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally self._stop_service('update-engine') 16310eb618d5336f1bd6f4cd4c135ea93d1e3a880bfDuncan Laurie self._create_faft_lockfile() 1648b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally self._setup_ec_write_protect(ec_wp) 1651b7a48b6c4e7cd007039a22d47667ea126240aadYusuf Mohsinally # See chromium:239034 regarding needing this sync. 1661bacc9661de528d838294d0c517905f4ded7f632Yusuf Mohsinally self.blocking_sync() 16705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('FirmwareTest initialize done (id=%s)', self.run_id) 16805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 16905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def cleanup(self): 17005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Autotest cleanup function.""" 17105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Unset state checker in case it's set by subclass 17205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('FirmwareTest cleaning up (id=%s)', self.run_id) 17305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally try: 17405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.system.is_available() 17505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally except: 17605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Remote is not responding. Revive DUT so that subsequent tests 17705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # don't fail. 17805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._restore_routine_from_timeout() 1790cc9a4fe28f221cfc73bb35c30fa79338c4b43f1Tom Wai-Hong Tam self.switcher.restore_mode() 1808b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally self._restore_ec_write_protect() 1818b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally self._restore_gbb_flags() 1828b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally self._start_service('update-engine') 18310eb618d5336f1bd6f4cd4c135ea93d1e3a880bfDuncan Laurie self._remove_faft_lockfile() 1848b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally self._record_servo_log() 1858b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally self._record_faft_client_log() 1868b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally self._cleanup_uart_capture() 18705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally super(FirmwareTest, self).cleanup() 18805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('FirmwareTest cleanup done (id=%s)', self.run_id) 18905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 1908b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally def _record_system_info(self): 19105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Record some critical system info to the attr keyval. 19205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 193004a8cd96f2c9bc228ca9d58428e88d36fc36307Christopher Wiley This info is used by generate_test_report later. 19405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 1959a10b9bfa8a160ca306e8f4ad9666c555ab3f94bTom Wai-Hong Tam system_info = { 19605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'hwid': self.faft_client.system.get_crossystem_value('hwid'), 19732075c167a2d4252802645c46378b5d5bea91ae6Tom Wai-Hong Tam 'ec_version': self.faft_client.ec.get_version(), 19832075c167a2d4252802645c46378b5d5bea91ae6Tom Wai-Hong Tam 'ro_fwid': self.faft_client.system.get_crossystem_value('ro_fwid'), 19932075c167a2d4252802645c46378b5d5bea91ae6Tom Wai-Hong Tam 'rw_fwid': self.faft_client.system.get_crossystem_value('fwid'), 2009a10b9bfa8a160ca306e8f4ad9666c555ab3f94bTom Wai-Hong Tam 'servod_version': self._client._servo_host.run( 2019a10b9bfa8a160ca306e8f4ad9666c555ab3f94bTom Wai-Hong Tam 'servod --version').stdout.strip(), 2029a10b9bfa8a160ca306e8f4ad9666c555ab3f94bTom Wai-Hong Tam } 2039a10b9bfa8a160ca306e8f4ad9666c555ab3f94bTom Wai-Hong Tam logging.info('System info:\n' + pprint.pformat(system_info)) 2049a10b9bfa8a160ca306e8f4ad9666c555ab3f94bTom Wai-Hong Tam self.write_attr_keyval(system_info) 20505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 20605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def invalidate_firmware_setup(self): 20705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Invalidate all firmware related setup state. 20805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 20905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally This method is called when the firmware is re-flashed. It resets all 21005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally firmware related setup states so that the next test setup properly 21105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally again. 21205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 21305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.unmark_setup_done('gbb_flags') 21405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 21505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def _retrieve_recovery_reason_from_trap(self): 21605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Try to retrieve the recovery reason from a trapped recovery screen. 21705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 21805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @return: The recovery_reason, 0 if any error. 21905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 22005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally recovery_reason = 0 22105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Try to retrieve recovery reason...') 22205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.servo.get_usbkey_direction() == 'dut': 2230430288e1ea7c2976db8612c595223dc2a220563Tom Wai-Hong Tam self.switcher.bypass_rec_mode() 22405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally else: 22505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.switch_usbkey('dut') 22605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 22705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally try: 22819bfb6ea468c34e1b44842033eb784c2ef3eed42Tom Wai-Hong Tam self.switcher.wait_for_client() 22905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally lines = self.faft_client.system.run_shell_command_get_output( 23005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'crossystem recovery_reason') 23105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally recovery_reason = int(lines[0]) 23205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Got the recovery reason %d.', recovery_reason) 23305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally except ConnectionError: 23405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.error('Failed to get the recovery reason due to connection ' 23505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'error.') 23605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return recovery_reason 23705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 23805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def _reset_client(self): 23905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Reset client to a workable state. 24005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 24105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally This method is called when the client is not responsive. It may be 24205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally caused by the following cases: 24305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally - halt on a firmware screen without timeout, e.g. REC_INSERT screen; 24405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally - corrupted firmware; 24505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally - corrutped OS image. 24605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 24705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # DUT may halt on a firmware screen. Try cold reboot. 24805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Try cold reboot...') 249a704f184b788093ddbde169f7120607af84271f7Tom Wai-Hong Tam self.switcher.mode_aware_reboot(reboot_type='cold', 250a704f184b788093ddbde169f7120607af84271f7Tom Wai-Hong Tam sync_before_boot=False, 251a704f184b788093ddbde169f7120607af84271f7Tom Wai-Hong Tam wait_for_dut_up=False) 25219bfb6ea468c34e1b44842033eb784c2ef3eed42Tom Wai-Hong Tam self.switcher.wait_for_client_offline() 2530430288e1ea7c2976db8612c595223dc2a220563Tom Wai-Hong Tam self.switcher.bypass_dev_mode() 25405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally try: 25519bfb6ea468c34e1b44842033eb784c2ef3eed42Tom Wai-Hong Tam self.switcher.wait_for_client() 25605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return 25705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally except ConnectionError: 25805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.warn('Cold reboot doesn\'t help, still connection error.') 25905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 26005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # DUT may be broken by a corrupted firmware. Restore firmware. 26105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # We assume the recovery boot still works fine. Since the recovery 26205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # code is in RO region and all FAFT tests don't change the RO region 26305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # except GBB. 26405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.is_firmware_saved(): 26505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._ensure_client_in_recovery() 26605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Try restore the original firmware...') 26705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.is_firmware_changed(): 26805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally try: 26905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.restore_firmware() 27005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return 27105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally except ConnectionError: 27205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.warn('Restoring firmware doesn\'t help, still ' 27305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'connection error.') 27405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 27505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Perhaps it's kernel that's broken. Let's try restoring it. 27605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.is_kernel_saved(): 27705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._ensure_client_in_recovery() 27805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Try restore the original kernel...') 27905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.is_kernel_changed(): 28005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally try: 28105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.restore_kernel() 28205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return 28305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally except ConnectionError: 28405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.warn('Restoring kernel doesn\'t help, still ' 28505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'connection error.') 28605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 28705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # DUT may be broken by a corrupted OS image. Restore OS image. 28805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._ensure_client_in_recovery() 28905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Try restore the OS image...') 29005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.system.run_shell_command('chromeos-install --yes') 291a704f184b788093ddbde169f7120607af84271f7Tom Wai-Hong Tam self.switcher.mode_aware_reboot(wait_for_dut_up=False) 29219bfb6ea468c34e1b44842033eb784c2ef3eed42Tom Wai-Hong Tam self.switcher.wait_for_client_offline() 2930430288e1ea7c2976db8612c595223dc2a220563Tom Wai-Hong Tam self.switcher.bypass_dev_mode() 29405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally try: 29519bfb6ea468c34e1b44842033eb784c2ef3eed42Tom Wai-Hong Tam self.switcher.wait_for_client() 29605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Successfully restore OS image.') 29705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return 29805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally except ConnectionError: 29905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.warn('Restoring OS image doesn\'t help, still connection ' 30005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'error.') 30105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 30205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def _ensure_client_in_recovery(self): 30305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Ensure client in recovery boot; reboot into it if necessary. 30405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 30505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @raise TestError: if failed to boot the USB image. 30605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 30705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Try boot into USB image...') 308d7a0d05665faa4ee5621b906efeb6e718b9ed1a8Tom Wai-Hong Tam self.switcher.reboot_to_mode(to_mode='rec', sync_before_boot=False, 309d7a0d05665faa4ee5621b906efeb6e718b9ed1a8Tom Wai-Hong Tam wait_for_dut_up=False) 310f2de4debd08a4825542fd4fd848ccd6b4fb000f8Tom Wai-Hong Tam self.servo.switch_usbkey('host') 3110430288e1ea7c2976db8612c595223dc2a220563Tom Wai-Hong Tam self.switcher.bypass_rec_mode() 31205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally try: 31319bfb6ea468c34e1b44842033eb784c2ef3eed42Tom Wai-Hong Tam self.switcher.wait_for_client() 31405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally except ConnectionError: 31505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally raise error.TestError('Failed to boot the USB image.') 31605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 31764ee3a7f9105e8819abf9e14f5a767a23d836823Yusuf Mohsinally def _restore_routine_from_timeout(self): 31805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """A routine to try to restore the system from a timeout error. 31905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 32005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally This method is called when FAFT failed to connect DUT after reboot. 32105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 32205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @raise TestFail: This exception is already raised, with a decription 32305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally why it failed. 32405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 32505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # DUT is disconnected. Capture the UART output for debug. 3268b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally self._record_uart_capture() 32705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 32805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # TODO(waihong@chromium.org): Implement replugging the Ethernet to 32905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # identify if it is a network flaky. 33005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 33105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally recovery_reason = self._retrieve_recovery_reason_from_trap() 33205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 33305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Reset client to a workable state. 33405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._reset_client() 33505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 33605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Raise the proper TestFail exception. 33764ee3a7f9105e8819abf9e14f5a767a23d836823Yusuf Mohsinally if recovery_reason: 33805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally raise error.TestFail('Trapped in the recovery screen (reason: %d) ' 33905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'and timed out' % recovery_reason) 34005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally else: 34105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally raise error.TestFail('Timed out waiting for DUT reboot') 34205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 34318c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner def assert_test_image_in_usb_disk(self, usb_dev=None): 34405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Assert an USB disk plugged-in on servo and a test image inside. 34505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 34605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param usb_dev: A string of USB stick path on the host, like '/dev/sdc'. 34705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally If None, it is detected automatically. 34818c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner @raise TestError: if USB disk not detected or not a test image. 34905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 35005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.check_setup_done('usb_check'): 35105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return 35205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if usb_dev: 35305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally assert self.servo.get_usbkey_direction() == 'host' 35405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally else: 35505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.switch_usbkey('host') 35605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally usb_dev = self.servo.probe_host_usb_dev() 35705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if not usb_dev: 35805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally raise error.TestError( 35905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'An USB disk should be plugged in the servo board.') 36005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 36105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally rootfs = '%s%s' % (usb_dev, self._ROOTFS_PARTITION_NUMBER) 36205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('usb dev is %s', usb_dev) 36305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally tmpd = self.servo.system_output('mktemp -d -t usbcheck.XXXX') 36405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.system('mount -o ro %s %s' % (rootfs, tmpd)) 36505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 366dc535dfe1f95fe8ec4b95b02ffc12ed0fb40f83cJulius Werner try: 36718c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner usb_lsb = self.servo.system_output('cat %s' % 36818c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner os.path.join(tmpd, 'etc/lsb-release')) 36918c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner logging.debug('Dumping lsb-release on USB stick:\n%s', usb_lsb) 37018c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner dut_lsb = '\n'.join(self.faft_client.system. 37118c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner run_shell_command_get_output('cat /etc/lsb-release')) 37218c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner logging.debug('Dumping lsb-release on DUT:\n%s', dut_lsb) 373e6adca4984389bc6fd46f7e5d7a45aec43f884fdJulius Werner if not re.search(r'RELEASE_TRACK=.*test', usb_lsb): 37418c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner raise error.TestError('USB stick in servo is no test image') 37518c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner usb_board = re.search(r'BOARD=(.*)', usb_lsb).group(1) 37618c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner dut_board = re.search(r'BOARD=(.*)', dut_lsb).group(1) 37718c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner if usb_board != dut_board: 37818c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner raise error.TestError('USB stick in servo contains a %s ' 37918c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner 'image, but DUT is a %s' % (usb_board, dut_board)) 380dc535dfe1f95fe8ec4b95b02ffc12ed0fb40f83cJulius Werner finally: 381dc535dfe1f95fe8ec4b95b02ffc12ed0fb40f83cJulius Werner for cmd in ('umount %s' % rootfs, 'sync', 'rm -rf %s' % tmpd): 382dc535dfe1f95fe8ec4b95b02ffc12ed0fb40f83cJulius Werner self.servo.system(cmd) 38305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 38405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.mark_setup_done('usb_check') 38505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 38618c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner def setup_usbkey(self, usbkey, host=None): 38705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Setup the USB disk for the test. 38805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 38905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally It checks the setup of USB disk and a valid ChromeOS test image inside. 39005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally It also muxes the USB disk to either the host or DUT by request. 39105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 39205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param usbkey: True if the USB disk is required for the test, False if 39305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally not required. 39405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param host: Optional, True to mux the USB disk to host, False to mux it 39505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally to DUT, default to do nothing. 39605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 39705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if usbkey: 39818c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner self.assert_test_image_in_usb_disk() 39905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally elif host is None: 40005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # USB disk is not required for the test. Better to mux it to host. 40105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally host = True 40205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 40305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if host is True: 40405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.switch_usbkey('host') 40505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally elif host is False: 40605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.switch_usbkey('dut') 40705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 40805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def get_usbdisk_path_on_dut(self): 40905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Get the path of the USB disk device plugged-in the servo on DUT. 41005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 41105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally Returns: 41205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally A string representing USB disk path, like '/dev/sdb', or None if 41305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally no USB disk is found. 41405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 41505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally cmd = 'ls -d /dev/s*[a-z]' 41605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally original_value = self.servo.get_usbkey_direction() 41705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 41805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Make the dut unable to see the USB disk. 41905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.switch_usbkey('off') 42005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally no_usb_set = set( 42105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.system.run_shell_command_get_output(cmd)) 42205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 42305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Make the dut able to see the USB disk. 42405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.switch_usbkey('dut') 425b0314a0ab7b590cb0b25b80513673eb157f7b5e9Tom Wai-Hong Tam time.sleep(self.faft_config.usb_plug) 42605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally has_usb_set = set( 42705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.system.run_shell_command_get_output(cmd)) 42805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 42905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Back to its original value. 43005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if original_value != self.servo.get_usbkey_direction(): 43105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.switch_usbkey(original_value) 43205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 43305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally diff_set = has_usb_set - no_usb_set 43405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if len(diff_set) == 1: 43505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return diff_set.pop() 43605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally else: 43705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return None 43805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 43910eb618d5336f1bd6f4cd4c135ea93d1e3a880bfDuncan Laurie def _create_faft_lockfile(self): 44010eb618d5336f1bd6f4cd4c135ea93d1e3a880bfDuncan Laurie """Creates the FAFT lockfile.""" 44110eb618d5336f1bd6f4cd4c135ea93d1e3a880bfDuncan Laurie logging.info('Creating FAFT lockfile...') 44210eb618d5336f1bd6f4cd4c135ea93d1e3a880bfDuncan Laurie command = 'touch %s' % (self.lockfile) 44310eb618d5336f1bd6f4cd4c135ea93d1e3a880bfDuncan Laurie self.faft_client.system.run_shell_command(command) 44410eb618d5336f1bd6f4cd4c135ea93d1e3a880bfDuncan Laurie 44510eb618d5336f1bd6f4cd4c135ea93d1e3a880bfDuncan Laurie def _remove_faft_lockfile(self): 44610eb618d5336f1bd6f4cd4c135ea93d1e3a880bfDuncan Laurie """Removes the FAFT lockfile.""" 44710eb618d5336f1bd6f4cd4c135ea93d1e3a880bfDuncan Laurie logging.info('Removing FAFT lockfile...') 44810eb618d5336f1bd6f4cd4c135ea93d1e3a880bfDuncan Laurie command = 'rm -f %s' % (self.lockfile) 44910eb618d5336f1bd6f4cd4c135ea93d1e3a880bfDuncan Laurie self.faft_client.system.run_shell_command(command) 45010eb618d5336f1bd6f4cd4c135ea93d1e3a880bfDuncan Laurie 4518b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally def _stop_service(self, service): 45205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Stops a upstart service on the client. 45305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 45405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param service: The name of the upstart service. 45505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 45605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Stopping %s...', service) 45705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally command = 'status %s | grep stop || stop %s' % (service, service) 45805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.system.run_shell_command(command) 45905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 4608b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally def _start_service(self, service): 46105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Starts a upstart service on the client. 46205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 46305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param service: The name of the upstart service. 46405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 46505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Starting %s...', service) 46605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally command = 'status %s | grep start || start %s' % (service, service) 46705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.system.run_shell_command(command) 46805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 46905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def clear_set_gbb_flags(self, clear_mask, set_mask): 47005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Clear and set the GBB flags in the current flashrom. 47105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 47205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param clear_mask: A mask of flags to be cleared. 47305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param set_mask: A mask of flags to be set. 47405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 47505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally gbb_flags = self.faft_client.bios.get_gbb_flags() 47605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally new_flags = gbb_flags & ctypes.c_uint32(~clear_mask).value | set_mask 477fc0c77097ba960aa1e2a6388770fea905ab0d4a7Tom Wai-Hong Tam if new_flags != gbb_flags: 478fc0c77097ba960aa1e2a6388770fea905ab0d4a7Tom Wai-Hong Tam self._backup_gbb_flags = gbb_flags 479fc0c77097ba960aa1e2a6388770fea905ab0d4a7Tom Wai-Hong Tam logging.info('Changing GBB flags from 0x%x to 0x%x.', 480fc0c77097ba960aa1e2a6388770fea905ab0d4a7Tom Wai-Hong Tam gbb_flags, new_flags) 481fc0c77097ba960aa1e2a6388770fea905ab0d4a7Tom Wai-Hong Tam self.faft_client.bios.set_gbb_flags(new_flags) 482fc0c77097ba960aa1e2a6388770fea905ab0d4a7Tom Wai-Hong Tam # If changing FORCE_DEV_SWITCH_ON flag, reboot to get a clear state 483fc0c77097ba960aa1e2a6388770fea905ab0d4a7Tom Wai-Hong Tam if ((gbb_flags ^ new_flags) & vboot.GBB_FLAG_FORCE_DEV_SWITCH_ON): 484fc0c77097ba960aa1e2a6388770fea905ab0d4a7Tom Wai-Hong Tam self.switcher.mode_aware_reboot() 485fc0c77097ba960aa1e2a6388770fea905ab0d4a7Tom Wai-Hong Tam else: 486fc0c77097ba960aa1e2a6388770fea905ab0d4a7Tom Wai-Hong Tam logging.info('Current GBB flags look good for test: 0x%x.', 487fc0c77097ba960aa1e2a6388770fea905ab0d4a7Tom Wai-Hong Tam gbb_flags) 48805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 48905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def check_ec_capability(self, required_cap=None, suppress_warning=False): 49005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Check if current platform has required EC capabilities. 49105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 49205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param required_cap: A list containing required EC capabilities. Pass in 49305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally None to only check for presence of Chrome EC. 49405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param suppress_warning: True to suppress any warning messages. 49505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @return: True if requirements are met. Otherwise, False. 49605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 49705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if not self.faft_config.chrome_ec: 49805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if not suppress_warning: 49905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.warn('Requires Chrome EC to run this test.') 50005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return False 50105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 50205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if not required_cap: 50305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return True 50405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 50505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally for cap in required_cap: 50605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if cap not in self.faft_config.ec_capability: 50705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if not suppress_warning: 50805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.warn('Requires EC capability "%s" to run this ' 50905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'test.', cap) 51005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return False 51105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 51205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return True 51305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 51405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def check_root_part_on_non_recovery(self, part): 51505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Check the partition number of root device and on normal/dev boot. 51605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 51705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param part: A string of partition number, e.g.'3'. 51805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @return: True if the root device matched and on normal/dev boot; 51905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally otherwise, False. 52005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 52105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return self.checkers.root_part_checker(part) and \ 52205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.checkers.crossystem_checker({ 52305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'mainfw_type': ('normal', 'developer'), 52405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally }) 52505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 52605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def _join_part(self, dev, part): 52705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Return a concatenated string of device and partition number. 52805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 52905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param dev: A string of device, e.g.'/dev/sda'. 53005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param part: A string of partition number, e.g.'3'. 53105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @return: A concatenated string of device and partition number, 53205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally e.g.'/dev/sda3'. 53305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 53405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally >>> seq = FirmwareTest() 53505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally >>> seq._join_part('/dev/sda', '3') 53605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally '/dev/sda3' 53705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally >>> seq._join_part('/dev/mmcblk0', '2') 53805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally '/dev/mmcblk0p2' 53905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 54005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if 'mmcblk' in dev: 54105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return dev + 'p' + part 54205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally else: 54305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return dev + part 54405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 54505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def copy_kernel_and_rootfs(self, from_part, to_part): 54605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Copy kernel and rootfs from from_part to to_part. 54705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 54805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param from_part: A string of partition number to be copied from. 54905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param to_part: A string of partition number to be copied to. 55005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 55105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally root_dev = self.faft_client.system.get_root_dev() 55205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Copying kernel from %s to %s. Please wait...', 55305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally from_part, to_part) 55405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.system.run_shell_command('dd if=%s of=%s bs=4M' % 55505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally (self._join_part(root_dev, self.KERNEL_MAP[from_part]), 55605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._join_part(root_dev, self.KERNEL_MAP[to_part]))) 55705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Copying rootfs from %s to %s. Please wait...', 55805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally from_part, to_part) 55905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.system.run_shell_command('dd if=%s of=%s bs=4M' % 56005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally (self._join_part(root_dev, self.ROOTFS_MAP[from_part]), 56105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._join_part(root_dev, self.ROOTFS_MAP[to_part]))) 56205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 56305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def ensure_kernel_boot(self, part): 56405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Ensure the request kernel boot. 56505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 56605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally If not, it duplicates the current kernel to the requested kernel 56705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally and sets the requested higher priority to ensure it boot. 56805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 56905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param part: A string of kernel partition number or 'a'/'b'. 57005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 57105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if not self.checkers.root_part_checker(part): 57205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.faft_client.kernel.diff_a_b(): 57305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.copy_kernel_and_rootfs( 57405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally from_part=self.OTHER_KERNEL_MAP[part], 57505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally to_part=part) 576ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally self.reset_and_prioritize_kernel(part) 577b1a8601683815deaa44a912647534dbe1a37f643Tom Wai-Hong Tam self.switcher.mode_aware_reboot() 57805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 57905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def set_hardware_write_protect(self, enable): 58005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Set hardware write protect pin. 58105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 58205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param enable: True if asserting write protect pin. Otherwise, False. 58305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 58405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.set('fw_wp_vref', self.faft_config.wp_voltage) 58505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.set('fw_wp_en', 'on') 58605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.set('fw_wp', 'on' if enable else 'off') 58705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 58805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def set_ec_write_protect_and_reboot(self, enable): 58905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Set EC write protect status and reboot to take effect. 59005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 59105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally The write protect state is only activated if both hardware write 59205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally protect pin is asserted and software write protect flag is set. 59305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally This method asserts/deasserts hardware write protect pin first, and 59405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally set corresponding EC software write protect flag. 59505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 59605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally If the device uses non-Chrome EC, set the software write protect via 59705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally flashrom. 59805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 59905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally If the device uses Chrome EC, a reboot is required for write protect 60005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally to take effect. Since the software write protect flag cannot be unset 60105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if hardware write protect pin is asserted, we need to deasserted the 60205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally pin first if we are deactivating write protect. Similarly, a reboot 60305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally is required before we can modify the software flag. 60405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 60505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param enable: True if activating EC write protect. Otherwise, False. 60605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 60705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.set_hardware_write_protect(enable) 60805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.faft_config.chrome_ec: 60905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.set_chrome_ec_write_protect_and_reboot(enable) 61005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally else: 61105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.ec.set_write_protect(enable) 612a704f184b788093ddbde169f7120607af84271f7Tom Wai-Hong Tam self.switcher.mode_aware_reboot() 61305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 61405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def set_chrome_ec_write_protect_and_reboot(self, enable): 61505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Set Chrome EC write protect status and reboot to take effect. 61605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 61705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param enable: True if activating EC write protect. Otherwise, False. 61805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 61905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if enable: 62005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Set write protect flag and reboot to take effect. 62105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.ec.set_flash_write_protect(enable) 62205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.sync_and_ec_reboot() 62305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally else: 62405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Reboot after deasserting hardware write protect pin to deactivate 62505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # write protect. And then remove software write protect flag. 62605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.sync_and_ec_reboot() 62705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.ec.set_flash_write_protect(enable) 62805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 6298b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally def _setup_ec_write_protect(self, ec_wp): 63005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Setup for EC write-protection. 63105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 63205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally It makes sure the EC in the requested write-protection state. If not, it 63305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally flips the state. Flipping the write-protection requires DUT reboot. 63405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 63505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param ec_wp: True to request EC write-protected; False to request EC 63605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally not write-protected; None to do nothing. 63705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 63805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if ec_wp is None: 63905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._old_ec_wp = None 64005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return 64105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._old_ec_wp = self.checkers.crossystem_checker({'wpsw_boot': '1'}) 64205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if ec_wp != self._old_ec_wp: 64305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('The test required EC is %swrite-protected. Reboot ' 64405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'and flip the state.', '' if ec_wp else 'not ') 6453e92b8e9041fa7bb44dc9285e2c415eb611697a9Tom Wai-Hong Tam self.switcher.mode_aware_reboot( 6463e92b8e9041fa7bb44dc9285e2c415eb611697a9Tom Wai-Hong Tam 'custom', 6473e92b8e9041fa7bb44dc9285e2c415eb611697a9Tom Wai-Hong Tam lambda:self.set_ec_write_protect_and_reboot(ec_wp)) 64805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 6498b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally def _restore_ec_write_protect(self): 65005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Restore the original EC write-protection.""" 65105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if (not hasattr(self, '_old_ec_wp')) or (self._old_ec_wp is None): 65205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return 65305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if not self.checkers.crossystem_checker( 65405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally {'wpsw_boot': '1' if self._old_ec_wp else '0'}): 655ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally logging.info('Restore original EC write protection and reboot.') 6563e92b8e9041fa7bb44dc9285e2c415eb611697a9Tom Wai-Hong Tam self.switcher.mode_aware_reboot( 6573e92b8e9041fa7bb44dc9285e2c415eb611697a9Tom Wai-Hong Tam 'custom', 6583e92b8e9041fa7bb44dc9285e2c415eb611697a9Tom Wai-Hong Tam lambda:self.set_ec_write_protect_and_reboot( 6593e92b8e9041fa7bb44dc9285e2c415eb611697a9Tom Wai-Hong Tam self._old_ec_wp)) 66005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 6618b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally def _setup_uart_capture(self): 662af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie """Setup the CPU/EC/PD UART capture.""" 66305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.cpu_uart_file = os.path.join(self.resultsdir, 'cpu_uart.txt') 66405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.set('cpu_uart_capture', 'on') 66505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.ec_uart_file = None 666af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie self.usbpd_uart_file = None 66705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.faft_config.chrome_ec: 66805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally try: 66905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.set('ec_uart_capture', 'on') 67005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.ec_uart_file = os.path.join(self.resultsdir, 'ec_uart.txt') 67105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally except error.TestFail as e: 67205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if 'No control named' in str(e): 67305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.warn('The servod is too old that ec_uart_capture ' 67405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'not supported.') 675af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie # Log separate PD console if supported 676af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie if self.check_ec_capability(['usbpd_uart'], suppress_warning=True): 677af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie try: 678af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie self.servo.set('usbpd_uart_capture', 'on') 679af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie self.usbpd_uart_file = os.path.join(self.resultsdir, 680af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie 'usbpd_uart.txt') 681af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie except error.TestFail as e: 682af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie if 'No control named' in str(e): 683af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie logging.warn('The servod is too old that ' 684af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie 'usbpd_uart_capture is not supported.') 68505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally else: 68605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Not a Google EC, cannot capture ec console output.') 68705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 6888b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally def _record_uart_capture(self): 689af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie """Record the CPU/EC/PD UART output stream to files.""" 69005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.cpu_uart_file: 69105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally with open(self.cpu_uart_file, 'a') as f: 69205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally f.write(ast.literal_eval(self.servo.get('cpu_uart_stream'))) 69305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.ec_uart_file and self.faft_config.chrome_ec: 69405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally with open(self.ec_uart_file, 'a') as f: 69505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally f.write(ast.literal_eval(self.servo.get('ec_uart_stream'))) 696af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie if (self.usbpd_uart_file and self.faft_config.chrome_ec and 697af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie self.check_ec_capability(['usbpd_uart'], suppress_warning=True)): 698af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie with open(self.usbpd_uart_file, 'a') as f: 699af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie f.write(ast.literal_eval(self.servo.get('usbpd_uart_stream'))) 70005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 7018b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally def _cleanup_uart_capture(self): 702af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie """Cleanup the CPU/EC/PD UART capture.""" 70305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Flush the remaining UART output. 7048b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally self._record_uart_capture() 70505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.set('cpu_uart_capture', 'off') 70605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.ec_uart_file and self.faft_config.chrome_ec: 70705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.set('ec_uart_capture', 'off') 708af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie if (self.usbpd_uart_file and self.faft_config.chrome_ec and 709af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie self.check_ec_capability(['usbpd_uart'], suppress_warning=True)): 710af61c1fb249fe2e0702eba0385cb07f368d6eb68Duncan Laurie self.servo.set('usbpd_uart_capture', 'off') 71105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 712c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen def _get_power_state(self, power_state): 713c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen """ 714c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen Return the current power state of the AP 715c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen """ 716c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen return self.ec.send_command_get_output("powerinfo", [power_state]) 717c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen 718c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen def wait_power_state(self, power_state, retries): 719c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen """ 720c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen Wait for certain power state. 721c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen 722c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen @param power_state: power state you are expecting 723c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen @param retries: retries. This is necessary if AP is powering down 724c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen and transitioning through different states. 725c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen """ 726c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen logging.info('Checking power state "%s" maximum %d times.', 727c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen power_state, retries) 728c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen while retries > 0: 729c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen logging.info("try count: %d" % retries) 730c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen try: 731c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen retries = retries - 1 732c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen ret = self._get_power_state(power_state) 733c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen return True 734c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen except error.TestFail: 735c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen pass 736c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen return False 737c0781c4988c2ad6bd3b56be567f966ae3124661cShelley Chen 738530490a25d656468ade45a4e165e683846ccd403Shelley Chen def delayed(seconds): 739530490a25d656468ade45a4e165e683846ccd403Shelley Chen def decorator(f): 740530490a25d656468ade45a4e165e683846ccd403Shelley Chen def wrapper(*args, **kargs): 741530490a25d656468ade45a4e165e683846ccd403Shelley Chen t = Timer(seconds, f, args, kargs) 742530490a25d656468ade45a4e165e683846ccd403Shelley Chen t.start() 743530490a25d656468ade45a4e165e683846ccd403Shelley Chen return wrapper 744530490a25d656468ade45a4e165e683846ccd403Shelley Chen return decorator 745530490a25d656468ade45a4e165e683846ccd403Shelley Chen 746530490a25d656468ade45a4e165e683846ccd403Shelley Chen @delayed(WAKE_DELAY) 747530490a25d656468ade45a4e165e683846ccd403Shelley Chen def wake_by_power_button(self): 748530490a25d656468ade45a4e165e683846ccd403Shelley Chen """Delay by WAKE_DELAY seconds and then wake DUT with power button.""" 749530490a25d656468ade45a4e165e683846ccd403Shelley Chen self.servo.power_normal_press() 750530490a25d656468ade45a4e165e683846ccd403Shelley Chen 751530490a25d656468ade45a4e165e683846ccd403Shelley Chen @delayed(WAKE_DELAY) 752530490a25d656468ade45a4e165e683846ccd403Shelley Chen def wake_by_lid_switch(self): 753530490a25d656468ade45a4e165e683846ccd403Shelley Chen """Delay by WAKE_DELAY seconds and then wake DUT with lid switch.""" 754530490a25d656468ade45a4e165e683846ccd403Shelley Chen self.servo.set('lid_open', 'no') 755530490a25d656468ade45a4e165e683846ccd403Shelley Chen time.sleep(self.LID_DELAY) 756530490a25d656468ade45a4e165e683846ccd403Shelley Chen self.servo.set('lid_open', 'yes') 757530490a25d656468ade45a4e165e683846ccd403Shelley Chen 758530490a25d656468ade45a4e165e683846ccd403Shelley Chen def suspend_as_reboot(self, wake_func): 759530490a25d656468ade45a4e165e683846ccd403Shelley Chen """ 760530490a25d656468ade45a4e165e683846ccd403Shelley Chen Suspend DUT and also kill FAFT client so that this acts like a reboot. 761530490a25d656468ade45a4e165e683846ccd403Shelley Chen 762530490a25d656468ade45a4e165e683846ccd403Shelley Chen Args: 763530490a25d656468ade45a4e165e683846ccd403Shelley Chen wake_func: A function that is called to wake DUT. Note that this 764530490a25d656468ade45a4e165e683846ccd403Shelley Chen function must delay itself so that we don't wake DUT before 765530490a25d656468ade45a4e165e683846ccd403Shelley Chen suspend_as_reboot returns. 766530490a25d656468ade45a4e165e683846ccd403Shelley Chen """ 767530490a25d656468ade45a4e165e683846ccd403Shelley Chen cmd = '(sleep %d; powerd_dbus_suspend) &' % self.EC_SUSPEND_DELAY 768530490a25d656468ade45a4e165e683846ccd403Shelley Chen self.faft_client.system.run_shell_command(cmd) 769530490a25d656468ade45a4e165e683846ccd403Shelley Chen self.faft_client.disconnect() 770530490a25d656468ade45a4e165e683846ccd403Shelley Chen time.sleep(self.EC_SUSPEND_DELAY) 771530490a25d656468ade45a4e165e683846ccd403Shelley Chen logging.info("wake function disabled") 772530490a25d656468ade45a4e165e683846ccd403Shelley Chen wake_func() 773530490a25d656468ade45a4e165e683846ccd403Shelley Chen 7748b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally def _fetch_servo_log(self): 77505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Fetch the servo log.""" 77605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally cmd = '[ -e %s ] && cat %s || echo NOTFOUND' % ((self._SERVOD_LOG,) * 2) 77705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally servo_log = self.servo.system_output(cmd) 77805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return None if servo_log == 'NOTFOUND' else servo_log 77905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 7808b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally def _setup_servo_log(self): 78105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Setup the servo log capturing.""" 78205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo_log_original_len = -1 78305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.servo.is_localhost(): 78405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # No servo log recorded when servod runs locally. 78505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return 78605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 7878b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally servo_log = self._fetch_servo_log() 78805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if servo_log: 78905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo_log_original_len = len(servo_log) 79005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally else: 79105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.warn('Servo log file not found.') 79205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 7938b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally def _record_servo_log(self): 79405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Record the servo log to the results directory.""" 79505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.servo_log_original_len != -1: 7968b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally servo_log = self._fetch_servo_log() 79705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally servo_log_file = os.path.join(self.resultsdir, 'servod.log') 79805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally with open(servo_log_file, 'a') as f: 79905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally f.write(servo_log[self.servo_log_original_len:]) 80005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 8018b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally def _record_faft_client_log(self): 80205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Record the faft client log to the results directory.""" 80305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally client_log = self.faft_client.system.dump_log(True) 80405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally client_log_file = os.path.join(self.resultsdir, 'faft_client.log') 80505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally with open(client_log_file, 'w') as f: 80605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally f.write(client_log) 80705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 8088b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally def _setup_gbb_flags(self): 80905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Setup the GBB flags for FAFT test.""" 81005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.faft_config.gbb_version < 1.1: 81105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Skip modifying GBB on versions older than 1.1.') 81205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return 81305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 81405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.check_setup_done('gbb_flags'): 81505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return 81605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 81705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Set proper GBB flags for test.') 81805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.clear_set_gbb_flags(vboot.GBB_FLAG_DEV_SCREEN_SHORT_DELAY | 81905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally vboot.GBB_FLAG_FORCE_DEV_SWITCH_ON | 82005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally vboot.GBB_FLAG_FORCE_DEV_BOOT_USB | 82146ebbb1ee25320a2fe6330edb13a062eec7ef7bbTom Wai-Hong Tam vboot.GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK | 82246ebbb1ee25320a2fe6330edb13a062eec7ef7bbTom Wai-Hong Tam vboot.GBB_FLAG_FORCE_DEV_BOOT_FASTBOOT_FULL_CAP, 82305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally vboot.GBB_FLAG_ENTER_TRIGGERS_TONORM | 82405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally vboot.GBB_FLAG_FAFT_KEY_OVERIDE) 82505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.mark_setup_done('gbb_flags') 82605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 82705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def drop_backup_gbb_flags(self): 82805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Drops the backup GBB flags. 82905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 83005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally This can be used when a test intends to permanently change GBB flags. 83105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 83205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._backup_gbb_flags = None 83305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 8348b377eb0528c632e4cb2d888f7388faf764f9987Yusuf Mohsinally def _restore_gbb_flags(self): 83505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Restore GBB flags to their original state.""" 836fc0c77097ba960aa1e2a6388770fea905ab0d4a7Tom Wai-Hong Tam if self._backup_gbb_flags is None: 83705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return 8382e3db4a5e9179d2a4f8f01b885884bf64b664646Tom Wai-Hong Tam # Setting up and restoring the GBB flags take a lot of time. For 8392e3db4a5e9179d2a4f8f01b885884bf64b664646Tom Wai-Hong Tam # speed-up purpose, don't restore it. 8402e3db4a5e9179d2a4f8f01b885884bf64b664646Tom Wai-Hong Tam logging.info('***') 8412e3db4a5e9179d2a4f8f01b885884bf64b664646Tom Wai-Hong Tam logging.info('*** Please manually restore the original GBB flags to: ' 8422e3db4a5e9179d2a4f8f01b885884bf64b664646Tom Wai-Hong Tam '0x%x ***', self._backup_gbb_flags) 8432e3db4a5e9179d2a4f8f01b885884bf64b664646Tom Wai-Hong Tam logging.info('***') 84405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.unmark_setup_done('gbb_flags') 84505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 84605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def setup_tried_fwb(self, tried_fwb): 84705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Setup for fw B tried state. 84805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 84905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally It makes sure the system in the requested fw B tried state. If not, it 85005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally tries to do so. 85105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 85205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param tried_fwb: True if requested in tried_fwb=1; 85305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally False if tried_fwb=0. 85405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 85505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if tried_fwb: 85605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if not self.checkers.crossystem_checker({'tried_fwb': '1'}): 85705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info( 85805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'Firmware is not booted with tried_fwb. Reboot into it.') 859ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally self.faft_client.system.set_try_fw_b() 86005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally else: 86105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if not self.checkers.crossystem_checker({'tried_fwb': '0'}): 86205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info( 86305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'Firmware is booted with tried_fwb. Reboot to clear.') 86405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 86505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def power_on(self): 86605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Switch DUT AC power on.""" 86705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._client.power_on(self.power_control) 86805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 86905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def power_off(self): 87005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Switch DUT AC power off.""" 87105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._client.power_off(self.power_control) 87205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 87305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def power_cycle(self): 87405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Power cycle DUT AC power.""" 87505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._client.power_cycle(self.power_control) 87605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 87705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def setup_rw_boot(self, section='a'): 87805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Make sure firmware is in RW-boot mode. 87905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 88005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally If the given firmware section is in RO-boot mode, turn off the RO-boot 88105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally flag and reboot DUT into RW-boot mode. 88205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 88305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param section: A firmware section, either 'a' or 'b'. 88405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 88505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally flags = self.faft_client.bios.get_preamble_flags(section) 88605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if flags & vboot.PREAMBLE_USE_RO_NORMAL: 88705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally flags = flags ^ vboot.PREAMBLE_USE_RO_NORMAL 888ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally self.faft_client.bios.set_preamble_flags(section, flags) 8894777624b69b3b223a5d3c3abe86000783f6c0e96Tom Wai-Hong Tam self.switcher.mode_aware_reboot() 89005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 89105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def setup_kernel(self, part): 89205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Setup for kernel test. 89305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 89405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally It makes sure both kernel A and B bootable and the current boot is 89505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally the requested kernel part. 89605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 89705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param part: A string of kernel partition number or 'a'/'b'. 89805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 89905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.ensure_kernel_boot(part) 90005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Checking the integrity of kernel B and rootfs B...') 90105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if (self.faft_client.kernel.diff_a_b() or 90205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally not self.faft_client.rootfs.verify_rootfs('B')): 90305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Copying kernel and rootfs from A to B...') 90405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.copy_kernel_and_rootfs(from_part=part, 90505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally to_part=self.OTHER_KERNEL_MAP[part]) 90605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.reset_and_prioritize_kernel(part) 90705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 90805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def reset_and_prioritize_kernel(self, part): 90905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Make the requested partition highest priority. 91005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 91105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally This function also reset kerenl A and B to bootable. 91205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 91305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param part: A string of partition number to be prioritized. 91405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 91505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally root_dev = self.faft_client.system.get_root_dev() 91605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Reset kernel A and B to bootable. 91705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.system.run_shell_command( 91805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'cgpt add -i%s -P1 -S1 -T0 %s' % (self.KERNEL_MAP['a'], root_dev)) 91905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.system.run_shell_command( 92005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'cgpt add -i%s -P1 -S1 -T0 %s' % (self.KERNEL_MAP['b'], root_dev)) 92105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Set kernel part highest priority. 92205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.system.run_shell_command('cgpt prioritize -i%s %s' % 92305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally (self.KERNEL_MAP[part], root_dev)) 92405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 9251bacc9661de528d838294d0c517905f4ded7f632Yusuf Mohsinally def blocking_sync(self): 9261bacc9661de528d838294d0c517905f4ded7f632Yusuf Mohsinally """Run a blocking sync command.""" 9271bacc9661de528d838294d0c517905f4ded7f632Yusuf Mohsinally # The double calls to sync fakes a blocking call 9281bacc9661de528d838294d0c517905f4ded7f632Yusuf Mohsinally # since the first call returns before the flush 9291bacc9661de528d838294d0c517905f4ded7f632Yusuf Mohsinally # is complete, but the second will wait for the 9301bacc9661de528d838294d0c517905f4ded7f632Yusuf Mohsinally # first to finish. 9311bacc9661de528d838294d0c517905f4ded7f632Yusuf Mohsinally self.faft_client.system.run_shell_command('sync') 9321bacc9661de528d838294d0c517905f4ded7f632Yusuf Mohsinally self.faft_client.system.run_shell_command('sync') 9331bacc9661de528d838294d0c517905f4ded7f632Yusuf Mohsinally 9345bee610032835a130b14892b29c70d867639ea43Ryan Lin # sync only sends SYNCHRONIZE_CACHE but doesn't 935b575242a8f8d8e5f67350f20701f3a9b73a33504Steve Fung # check the status. For mmc devices, use `mmc 936b575242a8f8d8e5f67350f20701f3a9b73a33504Steve Fung # status get` command to send an empty command to 937b575242a8f8d8e5f67350f20701f3a9b73a33504Steve Fung # wait for the disk to be available again. For 938b575242a8f8d8e5f67350f20701f3a9b73a33504Steve Fung # other devices, hdparm sends TUR to check if 9395bee610032835a130b14892b29c70d867639ea43Ryan Lin # a device is ready for transfer operation. 9405bee610032835a130b14892b29c70d867639ea43Ryan Lin root_dev = self.faft_client.system.get_root_dev() 941b575242a8f8d8e5f67350f20701f3a9b73a33504Steve Fung if 'mmcblk' in root_dev: 942b575242a8f8d8e5f67350f20701f3a9b73a33504Steve Fung self.faft_client.system.run_shell_command('mmc status get %s' % 943b575242a8f8d8e5f67350f20701f3a9b73a33504Steve Fung root_dev) 944b575242a8f8d8e5f67350f20701f3a9b73a33504Steve Fung else: 945b575242a8f8d8e5f67350f20701f3a9b73a33504Steve Fung self.faft_client.system.run_shell_command('hdparm -f %s' % root_dev) 946ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally 94705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def sync_and_ec_reboot(self, flags=''): 94805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Request the client sync and do a EC triggered reboot. 94905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 95005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param flags: Optional, a space-separated string of flags passed to EC 95105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally reboot command, including: 95205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally default: EC soft reboot; 95305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'hard': EC cold/hard reboot. 95405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 9551bacc9661de528d838294d0c517905f4ded7f632Yusuf Mohsinally self.blocking_sync() 95605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.ec.reboot(flags) 95705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally time.sleep(self.faft_config.ec_boot_to_console) 95805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.check_lid_and_power_on() 95905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 96018c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner def reboot_and_reset_tpm(self): 96118c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner """Reboot into recovery mode, reset TPM, then reboot back to disk.""" 96218c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner self.switcher.reboot_to_mode(to_mode='rec') 96318c4e1643b3ac6f6a201e2008020cdae8c590a7dJulius Werner self.faft_client.system.run_shell_command('chromeos-tpm-recovery') 964a704f184b788093ddbde169f7120607af84271f7Tom Wai-Hong Tam self.switcher.mode_aware_reboot() 96505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 96605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def full_power_off_and_on(self): 96705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Shutdown the device by pressing power button and power on again.""" 968101b0b26778060c13e6fbceddc92f21734f2878fDanny Chan boot_id = self.get_bootid() 96905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Press power button to trigger Chrome OS normal shutdown process. 97005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # We use a customized delay since the normal-press 1.2s is not enough. 97125d703a846f3a717dd8a65997aee0ddfd6afe440David Hendricks self.servo.power_key(self.faft_config.hold_pwr_button_poweroff) 972101b0b26778060c13e6fbceddc92f21734f2878fDanny Chan # device can take 44-51 seconds to restart, 973101b0b26778060c13e6fbceddc92f21734f2878fDanny Chan # add buffer from the default timeout of 60 seconds. 97419bfb6ea468c34e1b44842033eb784c2ef3eed42Tom Wai-Hong Tam self.switcher.wait_for_client_offline(timeout=100, orig_boot_id=boot_id) 97505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally time.sleep(self.faft_config.shutdown) 97605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Short press power button to boot DUT again. 97725d703a846f3a717dd8a65997aee0ddfd6afe440David Hendricks self.servo.power_key(self.faft_config.hold_pwr_button_poweron) 97805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 97905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def check_lid_and_power_on(self): 98005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 98105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally On devices with EC software sync, system powers on after EC reboots if 98205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally lid is open. Otherwise, the EC shuts down CPU after about 3 seconds. 98305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally This method checks lid switch state and presses power button if 98405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally necessary. 98505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 98605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.servo.get("lid_open") == "no": 98705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally time.sleep(self.faft_config.software_sync) 98805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.power_short_press() 98905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 99005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def _modify_usb_kernel(self, usb_dev, from_magic, to_magic): 99105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Modify the kernel header magic in USB stick. 99205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 99305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally The kernel header magic is the first 8-byte of kernel partition. 99405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally We modify it to make it fail on kernel verification check. 99505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 99605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param usb_dev: A string of USB stick path on the host, like '/dev/sdc'. 99705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param from_magic: A string of magic which we change it from. 99805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param to_magic: A string of magic which we change it to. 99905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @raise TestError: if failed to change magic. 100005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 100105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally assert len(from_magic) == 8 100205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally assert len(to_magic) == 8 100305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # USB image only contains one kernel. 100405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally kernel_part = self._join_part(usb_dev, self.KERNEL_MAP['a']) 100505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally read_cmd = "sudo dd if=%s bs=8 count=1 2>/dev/null" % kernel_part 100605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally current_magic = self.servo.system_output(read_cmd) 100705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if current_magic == to_magic: 100805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info("The kernel magic is already %s.", current_magic) 100905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return 101005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if current_magic != from_magic: 101105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally raise error.TestError("Invalid kernel image on USB: wrong magic.") 101205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 101305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Modify the kernel magic in USB, from %s to %s.', 101405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally from_magic, to_magic) 101505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally write_cmd = ("echo -n '%s' | sudo dd of=%s oflag=sync conv=notrunc " 101605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally " 2>/dev/null" % (to_magic, kernel_part)) 101705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.servo.system(write_cmd) 101805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 101905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if self.servo.system_output(read_cmd) != to_magic: 102005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally raise error.TestError("Failed to write new magic.") 102105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 102205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def corrupt_usb_kernel(self, usb_dev): 102305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Corrupt USB kernel by modifying its magic from CHROMEOS to CORRUPTD. 102405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 102505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param usb_dev: A string of USB stick path on the host, like '/dev/sdc'. 102605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 102705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._modify_usb_kernel(usb_dev, self.CHROMEOS_MAGIC, 102805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.CORRUPTED_MAGIC) 102905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 103005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def restore_usb_kernel(self, usb_dev): 103105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Restore USB kernel by modifying its magic from CORRUPTD to CHROMEOS. 103205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 103305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param usb_dev: A string of USB stick path on the host, like '/dev/sdc'. 103405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 103505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._modify_usb_kernel(usb_dev, self.CORRUPTED_MAGIC, 103605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.CHROMEOS_MAGIC) 103705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 103805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def _call_action(self, action_tuple, check_status=False): 103905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Call the action function with/without arguments. 104005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 104105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param action_tuple: A function, or a tuple (function, args, error_msg), 104205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally in which, args and error_msg are optional. args is 104305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally either a value or a tuple if multiple arguments. 104405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally This can also be a list containing multiple 104505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally function or tuple. In this case, these actions are 104605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally called in sequence. 104705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param check_status: Check the return value of action function. If not 104805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally succeed, raises a TestFail exception. 104905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @return: The result value of the action function. 105005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @raise TestError: An error when the action function is not callable. 105105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @raise TestFail: When check_status=True, action function not succeed. 105205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 105305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if isinstance(action_tuple, list): 105405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return all([self._call_action(action, check_status=check_status) 105505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally for action in action_tuple]) 105605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 105705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally action = action_tuple 105805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally args = () 105905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally error_msg = 'Not succeed' 106005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if isinstance(action_tuple, tuple): 106105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally action = action_tuple[0] 106205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if len(action_tuple) >= 2: 106305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally args = action_tuple[1] 106405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if not isinstance(args, tuple): 106505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally args = (args,) 106605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if len(action_tuple) >= 3: 106705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally error_msg = action_tuple[2] 106805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 106905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if action is None: 107005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return 107105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 107205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if not callable(action): 107305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally raise error.TestError('action is not callable!') 107405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 107505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally info_msg = 'calling %s' % str(action) 107605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if args: 107705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally info_msg += ' with args %s' % str(args) 107805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info(info_msg) 107905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally ret = action(*args) 108005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 108105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if check_status and not ret: 108205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally raise error.TestFail('%s: %s returning %s' % 108305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally (error_msg, info_msg, str(ret))) 108405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return ret 108505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 108605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def run_shutdown_process(self, shutdown_action, pre_power_action=None, 1087a7db9b5519c73ad922c8926ecb0c4d30a376dbfcDanny Chan run_power_action=True, post_power_action=None, shutdown_timeout=None): 108805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Run shutdown_action(), which makes DUT shutdown, and power it on. 108905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 109005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param shutdown_action: function which makes DUT shutdown, like 109105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally pressing power key. 109205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param pre_power_action: function which is called before next power on. 1093a7db9b5519c73ad922c8926ecb0c4d30a376dbfcDanny Chan @param power_action: power_key press by default, set to None to skip. 109405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param post_power_action: function which is called after next power on. 109505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param shutdown_timeout: a timeout to confirm DUT shutdown. 109605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @raise TestFail: if the shutdown_action() failed to turn DUT off. 109705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 109805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._call_action(shutdown_action) 109905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Wait to ensure DUT shut down...') 110005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally try: 110105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if shutdown_timeout is None: 110205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally shutdown_timeout = self.faft_config.shutdown_timeout 110319bfb6ea468c34e1b44842033eb784c2ef3eed42Tom Wai-Hong Tam self.switcher.wait_for_client(timeout=shutdown_timeout) 110405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally raise error.TestFail( 110505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'Should shut the device down after calling %s.' % 110605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally str(shutdown_action)) 110705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally except ConnectionError: 110805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info( 110905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'DUT is surely shutdown. We are going to power it on again...') 111005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 111105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if pre_power_action: 111205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._call_action(pre_power_action) 1113a7db9b5519c73ad922c8926ecb0c4d30a376dbfcDanny Chan if run_power_action: 1114a7db9b5519c73ad922c8926ecb0c4d30a376dbfcDanny Chan self.servo.power_key(self.faft_config.hold_pwr_button_poweron) 111505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if post_power_action: 111605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._call_action(post_power_action) 111705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 1118ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally def get_bootid(self, retry=3): 111905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 1120ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally Return the bootid. 112105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 112205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally boot_id = None 112305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally while retry: 112405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally try: 112505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally boot_id = self._client.get_boot_id() 112605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally break 112705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally except error.AutoservRunError: 112805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally retry -= 1 112905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if retry: 113005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Retry to get boot_id...') 113105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally else: 113205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.warning('Failed to get boot_id.') 113305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('boot_id: %s', boot_id) 1134ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally return boot_id 113505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 1136ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally def check_state(self, func): 1137ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally """ 1138ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally Wrapper around _call_action with check_status set to True. This is a 1139ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally helper function to be used by tests and is currently implemented by 1140ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally calling _call_action with check_status=True. 114105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 1142ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally TODO: This function's arguments need to be made more stringent. And 1143ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally its functionality should be moved over to check functions directly in 1144ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally the future. 114505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 1146ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally @param func: A function, or a tuple (function, args, error_msg), 1147ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally in which, args and error_msg are optional. args is 1148ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally either a value or a tuple if multiple arguments. 1149ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally This can also be a list containing multiple 1150ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally function or tuple. In this case, these actions are 1151ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally called in sequence. 1152ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally @return: The result value of the action function. 1153ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally @raise TestFail: If the function does notsucceed. 1154ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally """ 1155ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally logging.info("-[FAFT]-[ start stepstate_checker ]----------") 1156ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally self._call_action(func, check_status=True) 1157ab1b5fc3918ca226dda7d39487dedc24b5efe20bYusuf Mohsinally logging.info("-[FAFT]-[ end state_checker ]----------------") 115805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 115905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def get_current_firmware_sha(self): 116005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Get current firmware sha of body and vblock. 116105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 116205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @return: Current firmware sha follows the order ( 116305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally vblock_a_sha, body_a_sha, vblock_b_sha, body_b_sha) 116405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 116505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally current_firmware_sha = (self.faft_client.bios.get_sig_sha('a'), 116605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.bios.get_body_sha('a'), 116705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.bios.get_sig_sha('b'), 116805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.bios.get_body_sha('b')) 116905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if not all(current_firmware_sha): 117005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally raise error.TestError('Failed to get firmware sha.') 117105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return current_firmware_sha 117205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 117305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def is_firmware_changed(self): 117405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Check if the current firmware changed, by comparing its SHA. 117505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 117605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @return: True if it is changed, otherwise Flase. 117705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 117805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Device may not be rebooted after test. 117905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.bios.reload() 118005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 118105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally current_sha = self.get_current_firmware_sha() 118205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 118305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if current_sha == self._backup_firmware_sha: 118405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return False 118505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally else: 118605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally corrupt_VBOOTA = (current_sha[0] != self._backup_firmware_sha[0]) 118705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally corrupt_FVMAIN = (current_sha[1] != self._backup_firmware_sha[1]) 118805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally corrupt_VBOOTB = (current_sha[2] != self._backup_firmware_sha[2]) 118905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally corrupt_FVMAINB = (current_sha[3] != self._backup_firmware_sha[3]) 119005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info("Firmware changed:") 119105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('VBOOTA is changed: %s', corrupt_VBOOTA) 119205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('VBOOTB is changed: %s', corrupt_VBOOTB) 119305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('FVMAIN is changed: %s', corrupt_FVMAIN) 119405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('FVMAINB is changed: %s', corrupt_FVMAINB) 119505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return True 119605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 119705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def backup_firmware(self, suffix='.original'): 119805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Backup firmware to file, and then send it to host. 119905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 120005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param suffix: a string appended to backup file name 120105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 120205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally remote_temp_dir = self.faft_client.system.create_temp_dir() 1203e1d5e66392a398106a5a384a2fa31b177c07b9ccTom Wai-Hong Tam remote_bios_path = os.path.join(remote_temp_dir, 'bios') 1204e1d5e66392a398106a5a384a2fa31b177c07b9ccTom Wai-Hong Tam self.faft_client.bios.dump_whole(remote_bios_path) 1205e1d5e66392a398106a5a384a2fa31b177c07b9ccTom Wai-Hong Tam self._client.get_file(remote_bios_path, 120605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally os.path.join(self.resultsdir, 'bios' + suffix)) 1207e1d5e66392a398106a5a384a2fa31b177c07b9ccTom Wai-Hong Tam self._client.run('rm -rf %s' % remote_temp_dir) 120805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Backup firmware stored in %s with suffix %s', 120905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.resultsdir, suffix) 121005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 1211e1d5e66392a398106a5a384a2fa31b177c07b9ccTom Wai-Hong Tam self._backup_firmware_sha = self.get_current_firmware_sha() 1212e1d5e66392a398106a5a384a2fa31b177c07b9ccTom Wai-Hong Tam 121305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def is_firmware_saved(self): 121405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Check if a firmware saved (called backup_firmware before). 121505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 121605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @return: True if the firmware is backuped; otherwise False. 121705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 121805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return self._backup_firmware_sha != () 121905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 122005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def clear_saved_firmware(self): 122105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Clear the firmware saved by the method backup_firmware.""" 122205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._backup_firmware_sha = () 122305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 122405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def restore_firmware(self, suffix='.original'): 122505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Restore firmware from host in resultsdir. 122605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 122705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param suffix: a string appended to backup file name 122805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 122905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if not self.is_firmware_changed(): 123005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return 123105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 123205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Backup current corrupted firmware. 123305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.backup_firmware(suffix='.corrupt') 123405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 123505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Restore firmware. 123605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally remote_temp_dir = self.faft_client.system.create_temp_dir() 123705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._client.send_file(os.path.join(self.resultsdir, 'bios' + suffix), 123805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally os.path.join(remote_temp_dir, 'bios')) 123905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 124005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.bios.write_whole( 124105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally os.path.join(remote_temp_dir, 'bios')) 1242a704f184b788093ddbde169f7120607af84271f7Tom Wai-Hong Tam self.switcher.mode_aware_reboot() 124305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Successfully restore firmware.') 124405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 124505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def setup_firmwareupdate_shellball(self, shellball=None): 124605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Deside a shellball to use in firmware update test. 124705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 124805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally Check if there is a given shellball, and it is a shell script. Then, 124905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally send it to the remote host. Otherwise, use 125005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally /usr/sbin/chromeos-firmwareupdate. 125105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 125205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param shellball: path of a shellball or default to None. 125305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 125405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @return: Path of shellball in remote host. If use default shellball, 125505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally reutrn None. 125605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 125705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally updater_path = None 125805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if shellball: 125905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Determine the firmware file is a shellball or a raw binary. 126005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally is_shellball = (utils.system_output("file %s" % shellball).find( 126105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally "shell script") != -1) 126205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if is_shellball: 126305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Device will update firmware with shellball %s', 126405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally shellball) 126505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally temp_dir = self.faft_client.system.create_temp_dir( 126605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'shellball_') 126705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally temp_shellball = os.path.join(temp_dir, 'updater.sh') 126805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._client.send_file(shellball, temp_shellball) 126905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally updater_path = temp_shellball 127005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally else: 127105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally raise error.TestFail( 127205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 'The given shellball is not a shell script.') 127305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return updater_path 127405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 127505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def is_kernel_changed(self): 127605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Check if the current kernel is changed, by comparing its SHA1 hash. 127705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 127805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @return: True if it is changed; otherwise, False. 127905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 128005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally changed = False 128105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally for p in ('A', 'B'): 128205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally backup_sha = self._backup_kernel_sha.get(p, None) 128305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally current_sha = self.faft_client.kernel.get_sha(p) 128405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if backup_sha != current_sha: 128505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally changed = True 128605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Kernel %s is changed', p) 128705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return changed 128805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 128905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def backup_kernel(self, suffix='.original'): 129005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Backup kernel to files, and the send them to host. 129105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 129205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param suffix: a string appended to backup file name. 129305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 129405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally remote_temp_dir = self.faft_client.system.create_temp_dir() 129505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally for p in ('A', 'B'): 129605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally remote_path = os.path.join(remote_temp_dir, 'kernel_%s' % p) 129705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.kernel.dump(p, remote_path) 129805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._client.get_file( 129905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally remote_path, 130005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally os.path.join(self.resultsdir, 'kernel_%s%s' % (p, suffix))) 130105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._backup_kernel_sha[p] = self.faft_client.kernel.get_sha(p) 130205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Backup kernel stored in %s with suffix %s', 130305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.resultsdir, suffix) 130405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 130505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def is_kernel_saved(self): 130605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Check if kernel images are saved (backup_kernel called before). 130705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 130805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @return: True if the kernel is saved; otherwise, False. 130905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 131005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return len(self._backup_kernel_sha) != 0 131105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 131205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def clear_saved_kernel(self): 131305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Clear the kernel saved by backup_kernel().""" 131405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._backup_kernel_sha = dict() 131505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 131605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def restore_kernel(self, suffix='.original'): 131705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Restore kernel from host in resultsdir. 131805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 131905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally @param suffix: a string appended to backup file name. 132005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """ 132105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if not self.is_kernel_changed(): 132205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return 132305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 132405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Backup current corrupted kernel. 132505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.backup_kernel(suffix='.corrupt') 132605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 132705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally # Restore kernel. 132805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally remote_temp_dir = self.faft_client.system.create_temp_dir() 132905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally for p in ('A', 'B'): 133005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally remote_path = os.path.join(remote_temp_dir, 'kernel_%s' % p) 133105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._client.send_file( 133205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally os.path.join(self.resultsdir, 'kernel_%s%s' % (p, suffix)), 133305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally remote_path) 133405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.kernel.write(p, remote_path) 133505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 1336a704f184b788093ddbde169f7120607af84271f7Tom Wai-Hong Tam self.switcher.mode_aware_reboot() 133705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Successfully restored kernel.') 133805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 133905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def backup_cgpt_attributes(self): 134005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Backup CGPT partition table attributes.""" 134105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._backup_cgpt_attr = self.faft_client.cgpt.get_attributes() 134205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 134305c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally def restore_cgpt_attributes(self): 134405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally """Restore CGPT partition table attributes.""" 134505c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally current_table = self.faft_client.cgpt.get_attributes() 134605c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally if current_table == self._backup_cgpt_attr: 134705c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally return 134805c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('CGPT table is changed. Original: %r. Current: %r.', 134905c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self._backup_cgpt_attr, 135005c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally current_table) 135105c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally self.faft_client.cgpt.set_attributes(self._backup_cgpt_attr) 135205c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally 1353a704f184b788093ddbde169f7120607af84271f7Tom Wai-Hong Tam self.switcher.mode_aware_reboot() 135405c3c558c1dadb05195c84c10bf8e2c21048096fYusuf Mohsinally logging.info('Successfully restored CGPT table.') 13553edea989126b84d38135371e780184694892a55aShelley Chen 13563edea989126b84d38135371e780184694892a55aShelley Chen def try_fwb(self, count=0): 13573edea989126b84d38135371e780184694892a55aShelley Chen """set to try booting FWB count # times 13583edea989126b84d38135371e780184694892a55aShelley Chen 13593edea989126b84d38135371e780184694892a55aShelley Chen Wrapper to set fwb_tries for vboot1 and fw_try_count,fw_try_next for 13603edea989126b84d38135371e780184694892a55aShelley Chen vboot2 13613edea989126b84d38135371e780184694892a55aShelley Chen 13623edea989126b84d38135371e780184694892a55aShelley Chen @param count: an integer specifying value to program into 13633edea989126b84d38135371e780184694892a55aShelley Chen fwb_tries(vb1)/fw_try_next(vb2) 13643edea989126b84d38135371e780184694892a55aShelley Chen """ 13653edea989126b84d38135371e780184694892a55aShelley Chen if self.fw_vboot2: 13663edea989126b84d38135371e780184694892a55aShelley Chen self.faft_client.system.set_fw_try_next('B', count) 13673edea989126b84d38135371e780184694892a55aShelley Chen else: 13683edea989126b84d38135371e780184694892a55aShelley Chen # vboot1: we need to boot into fwb at least once 13693edea989126b84d38135371e780184694892a55aShelley Chen if not count: 13703edea989126b84d38135371e780184694892a55aShelley Chen count = count + 1 13713edea989126b84d38135371e780184694892a55aShelley Chen self.faft_client.system.set_try_fw_b(count) 13723edea989126b84d38135371e780184694892a55aShelley Chen 1373