1# Copyright (c) 2015 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import logging 6import time 7 8from autotest_lib.client.common_lib import error 9from autotest_lib.server.cros import vboot_constants as vboot 10from autotest_lib.server.cros.faft.firmware_test import FirmwareTest 11 12 13class firmware_ECLidShutdown(FirmwareTest): 14 """ 15 Exercises the GBB_FLAG_DISABLE_LID_SHUTDOWN flag: confirms that when the 16 flag is enabled, a closed lid will not prevent booting. 17 """ 18 version = 1 19 20 # Delay to allow for a power state change after closing or opening the lid. 21 # This value is determined experimentally. 22 LID_POWER_STATE_DELAY = 5 23 POWER_STATE_CHECK_TRIES = 3 24 POWER_STATE_CHECK_DELAY = 10 25 IGNORE_LID_IN_USERSPACE_CMD = 'echo 0 > /var/lib/power_manager/use_lid' 26 CHECK_POWER_MANAGER_CFG_DEFAULT = '[ ! -f /var/lib/power_manager/use_lid ]' 27 28 def initialize(self, host, cmdline_args): 29 super(firmware_ECLidShutdown, self).initialize(host, cmdline_args) 30 self.setup_usbkey(usbkey=False) 31 32 def cleanup(self): 33 """Reopens the lid, boots the DUT to normal mode, and clears the GBB 34 flag manipulated in this test. 35 """ 36 try: 37 self._reset_ec_regexp() 38 logging.info('The screen should turn back on now, during cleanup.') 39 self.servo.set_nocheck('lid_open', 'yes') 40 time.sleep(self.LID_POWER_STATE_DELAY) 41 if self.servo.get('lid_open') != 'yes': 42 raise error.TestFail('The device did not stay in a mechanical' 43 'on state after a lid open.') 44 self.switcher.simple_reboot(sync_before_boot=False) 45 self.switcher.wait_for_client() 46 self.clear_set_gbb_flags(vboot.GBB_FLAG_DISABLE_LID_SHUTDOWN, 0) 47 self.faft_client.system.run_shell_command( 48 self.CHECK_POWER_MANAGER_CFG_DEFAULT) 49 except Exception as exc: 50 logging.debug( 51 'Exception during cleanup considered non-fatal. ' 52 'Traceback:', exc_info=True) 53 super(firmware_ECLidShutdown, self).cleanup() 54 55 def _reset_ec_regexp(self): 56 """Resets ec_uart_regexp field. 57 58 Needs to be done for the ec_uart_regexp otherwise 59 dut-control command will time out due to no match. 60 """ 61 self.servo.set('ec_uart_regexp', 'None') 62 63 def _check_lid_shutdown(self): 64 """ 65 Checks behavior with GBB_FLAG_DISABLE_LID_SHUTDOWN disabled. 66 67 Clears the flag that disables listening to the lid for shutdown (when 68 the lid is closed at boot), boots into recovery mode and confirms that 69 the device stays in a mechanical off state. Reopens the lid and 70 restores the device. 71 """ 72 self.clear_set_gbb_flags(vboot.GBB_FLAG_DISABLE_LID_SHUTDOWN, 0) 73 # TODO(kmshelton): Simplify to not use recovery mode. 74 self.faft_client.system.request_recovery_boot() 75 self.servo.set('lid_open', 'no') 76 time.sleep(self.LID_POWER_STATE_DELAY) 77 self.switcher.simple_reboot(sync_before_boot=False) 78 # Some boards may reset the lid_open state when AP reboot, 79 # check b/137612865 80 time.sleep(self.faft_config.ec_boot_to_console) 81 if self.servo.get('lid_open') != 'no': 82 self.servo.set('lid_open', 'no') 83 time.sleep(self.LID_POWER_STATE_DELAY) 84 time.sleep(self.faft_config.firmware_screen) 85 if not self.wait_power_state('G3', 86 self.POWER_STATE_CHECK_TRIES, 87 self.POWER_STATE_CHECK_DELAY): 88 raise error.TestFail('The device did not stay in a mechanical off ' 89 'state after a lid close and a warm reboot.') 90 # kukui resets EC on opening the lid in some cases, so 91 # using servo.set('lid_open', 'yes') would verify the set result 92 # immediately by getting the control back, and this results a failure of 93 # console-no-response due to EC reset. We should use set_nocheck 94 # instead. 95 self.servo.set_nocheck('lid_open', 'yes') 96 time.sleep(self.LID_POWER_STATE_DELAY) 97 if self.servo.get('lid_open') != 'yes': 98 raise error.TestFail('The device did not stay in a mechanical on ' 99 'state after a lid open.') 100 101 time.sleep(self.faft_config.firmware_screen) 102 self.switcher.simple_reboot(sync_before_boot=False) 103 self._reset_ec_regexp() 104 self.switcher.wait_for_client() 105 106 return True 107 108 def _check_lid_shutdown_disabled(self): 109 """ 110 Checks behavior with GBB_FLAG_DISABLE_LID_SHUTDOWN enabled. 111 112 Sets the flag that disables listening to the lid for shutdown (when 113 the lid is closed at boot), disables the power daemon, closes the lid, 114 boots to a firmware screen. 115 """ 116 self.clear_set_gbb_flags(0, vboot.GBB_FLAG_DISABLE_LID_SHUTDOWN) 117 self.faft_client.system.request_recovery_boot() 118 self.faft_client.system.run_shell_command( 119 self.IGNORE_LID_IN_USERSPACE_CMD) 120 self.servo.set('lid_open', 'no') 121 if not self.wait_power_state('S0', self.POWER_STATE_CHECK_TRIES): 122 raise error.TestError( 123 'The device did not stay in S0 when the lid was closed ' 124 'with powerd ignoring lid state. Maybe userspace power ' 125 'management behaviors have changed.') 126 self.switcher.simple_reboot(sync_before_boot=False) 127 time.sleep(self.faft_config.ec_boot_to_console) 128 if self.servo.get('lid_open') != 'no': 129 self.servo.set('lid_open', 'no') 130 time.sleep(self.LID_POWER_STATE_DELAY) 131 logging.info('The screen will remain black, even though we are at a ' 132 'recovery screen.') 133 time.sleep(self.faft_config.firmware_screen) 134 if not self.wait_power_state('S0', self.POWER_STATE_CHECK_TRIES): 135 raise error.TestFail( 136 'The device did get to an active state when warm reset ' 137 'with the lid off and GBB_FLAG_DISABLE_LID_SHUTDOWN ' 138 'enabled.') 139 140 return True 141 142 def run_once(self): 143 """Runs a single iteration of the test.""" 144 if not self.check_ec_capability(['lid']): 145 raise error.TestNAError('This device needs a lid to run this test') 146 147 logging.info('Verify the device does shutdown when verified boot ' 148 'starts while the lid is closed and ' 149 'GBB_FLAG_DISABLE_LID_SHUTDOWN disabled.') 150 self.check_state(self._check_lid_shutdown) 151 152 logging.info('Verify the device does not shutdown when verified boot ' 153 'starts while the lid is closed with ' 154 'GBB_FLAG_DISABLE_LID_SHUTDOWN enabled.') 155 self.check_state(self._check_lid_shutdown_disabled) 156