1# Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import logging 6import time 7 8from autotest_lib.client.common_lib import error 9from autotest_lib.server.cros.faft.firmware_test import FirmwareTest 10 11 12class firmware_FwScreenPressPower(FirmwareTest): 13 """ 14 Servo based power button triggered shutdown test during firmware screens. 15 16 This test requires a USB disk plugged-in, which contains a Chrome OS test 17 image (built by "build_image --test"). On runtime, this test triggers 18 firmware screens (developer, remove, insert, yuck, and to_norm screens), 19 and then presses the power button in order to power the machine down. 20 """ 21 version = 1 22 NEEDS_SERVO_USB = True 23 24 SHORT_SHUTDOWN_CONFIRMATION_PERIOD = 0.1 25 26 def wait_fw_screen_and_press_power(self): 27 """Wait for firmware warning screen and press power button.""" 28 time.sleep(self.faft_config.firmware_screen) 29 # While the firmware screen, the power button probing loop sleeps 30 # 0.25 second on every scan. Use the normal delay (1.2 second) for 31 # power press. 32 self.servo.power_normal_press() 33 34 def wait_longer_fw_screen_and_press_power(self): 35 """Wait for firmware screen without timeout and press power button.""" 36 time.sleep(self.faft_config.dev_screen_timeout) 37 self.wait_fw_screen_and_press_power() 38 39 def wait_second_screen_and_press_power(self): 40 """Wait and trigger a second screen and press power button.""" 41 self.switcher.trigger_dev_to_rec() 42 self.wait_fw_screen_and_press_power() 43 44 def wait_yuck_screen_and_press_power(self): 45 """Insert corrupted USB for yuck screen and press power button.""" 46 # This USB stick will be removed in cleanup phase. 47 self.servo.switch_usbkey('dut') 48 time.sleep(self.faft_config.usb_plug) 49 self.wait_longer_fw_screen_and_press_power() 50 51 def initialize(self, host, cmdline_args): 52 """Initialize the test""" 53 super(firmware_FwScreenPressPower, self).initialize(host, cmdline_args) 54 self.switcher.setup_mode('dev') 55 self.setup_usbkey(True, host=True) 56 usb_dev = self.servo.probe_host_usb_dev() 57 # Corrupt the kernel of USB stick. It is needed for triggering a 58 # yuck screen later. 59 self.corrupt_usb_kernel(usb_dev) 60 61 def cleanup(self): 62 """Cleanup the test""" 63 try: 64 self.servo.switch_usbkey('host') 65 usb_dev = self.servo.probe_host_usb_dev() 66 # Restore the kernel of USB stick which is corrupted on setup phase. 67 self.restore_usb_kernel(usb_dev) 68 except Exception as e: 69 logging.error("Caught exception: %s", str(e)) 70 super(firmware_FwScreenPressPower, self).cleanup() 71 72 def run_once(self): 73 """Main test logic""" 74 if self.faft_config.mode_switcher_type not in ( 75 'keyboard_dev_switcher', 'tablet_detachable_switcher', 76 'menu_switcher'): 77 raise error.TestNAError("This test is only valid on devices with " 78 "screens.") 79 if not self.faft_config.has_powerbutton: 80 raise error.TestNAError("This test is only valid on devices with " 81 "power button.") 82 83 logging.info( 84 "Expected dev mode and reboot. " 85 "When the next DEVELOPER SCREEN shown, press power button " 86 "to make DUT shutdown.") 87 self.check_state((self.checkers.crossystem_checker, { 88 'devsw_boot': '1', 89 'mainfw_type': 'developer', 90 })) 91 self.switcher.simple_reboot() 92 self.run_shutdown_process( 93 self.wait_fw_screen_and_press_power, 94 post_power_action=self.switcher.bypass_dev_mode) 95 self.switcher.wait_for_client() 96 97 if self.faft_config.power_button_dev_switch: 98 logging.info( 99 "Skipping TO_NORM screen test. The power button is " 100 "used to confirm DEV mode to NORM mode.") 101 else: 102 logging.info( 103 "Reboot. When the developer screen shown, press " 104 "enter key to trigger either TO_NORM screen (new) or " 105 "RECOVERY INSERT screen (old). Then press power button " 106 "to make DUT shutdown.") 107 self.check_state((self.checkers.crossystem_checker, { 108 'devsw_boot': '1', 109 'mainfw_type': 'developer', 110 })) 111 self.switcher.simple_reboot() 112 self.run_shutdown_process( 113 self.wait_second_screen_and_press_power, 114 post_power_action=self.switcher.bypass_dev_mode, 115 shutdown_timeout=self.SHORT_SHUTDOWN_CONFIRMATION_PERIOD 116 ) 117 self.switcher.wait_for_client() 118 119 logging.info("Request recovery boot. When the RECOVERY INSERT " 120 "screen shows, press power button to make DUT shutdown.") 121 self.check_state((self.checkers.crossystem_checker, { 122 'devsw_boot': '1', 123 'mainfw_type': 'developer', 124 })) 125 self.faft_client.system.request_recovery_boot() 126 self.switcher.simple_reboot('cold') 127 self.run_shutdown_process( 128 self.wait_longer_fw_screen_and_press_power, 129 post_power_action=self.switcher.bypass_dev_mode, 130 shutdown_timeout=self.SHORT_SHUTDOWN_CONFIRMATION_PERIOD) 131 self.switcher.wait_for_client() 132 133 logging.info("Request recovery boot again. When the recovery " 134 "insert screen shows, insert a corrupted USB and trigger " 135 "a YUCK SCREEN. Then press power button to " 136 "make DUT shutdown.") 137 self.check_state((self.checkers.crossystem_checker, { 138 'devsw_boot': '1', 139 'mainfw_type': 'developer', 140 })) 141 self.faft_client.system.request_recovery_boot() 142 self.switcher.simple_reboot('cold') 143 self.run_shutdown_process( 144 self.wait_yuck_screen_and_press_power, 145 post_power_action=self.switcher.bypass_dev_mode, 146 shutdown_timeout=self.SHORT_SHUTDOWN_CONFIRMATION_PERIOD) 147 self.switcher.wait_for_client() 148 149 logging.info("Switch back to normal mode.") 150 self.check_state((self.checkers.crossystem_checker, { 151 'devsw_boot': '1', 152 'mainfw_type': 'developer', 153 })) 154 self.switcher.reboot_to_mode(to_mode='normal') 155 156 logging.info("Expected normal mode and request recovery boot. " 157 "Because an USB stick is inserted, a RECOVERY REMOVE " 158 "screen shows. Press power button to make DUT shutdown.") 159 self.check_state((self.checkers.crossystem_checker, { 160 'devsw_boot': '0', 161 'mainfw_type': 'normal', 162 })) 163 self.faft_client.system.request_recovery_boot() 164 self.switcher.simple_reboot('cold') 165 self.run_shutdown_process( 166 self.wait_longer_fw_screen_and_press_power, 167 shutdown_timeout=self.SHORT_SHUTDOWN_CONFIRMATION_PERIOD) 168 self.switcher.wait_for_client() 169 170 logging.info("Check and done.") 171 self.check_state((self.checkers.crossystem_checker, { 172 'devsw_boot': '0', 173 'mainfw_type': 'normal', 174 })) 175