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
11from autotest_lib.server.cros.faft.utils import mode_switcher
12
13class firmware_ECLidShutdown(FirmwareTest):
14    """
15    Testing GBB_FLAG_DISABLE_LID_SHUTDOWN flag
16    """
17    version = 1
18
19    # Delay between closing and opening the lid
20    LID_DELAY = 2
21    # time to wait before checking if DUT booted into OS mode
22    BOOTUP_TIME = 30
23    # time to wait to let DUT transition into recovery mode
24    RECOVERY_DELAY = 1
25    # # times to check if DUT in expected power state
26    # This accomodates if DUT needs to transition into certain states.
27    PWR_RETRIES = 13
28
29    def initialize(self, host, cmdline_args):
30        super(firmware_ECLidShutdown, self).initialize(host, cmdline_args)
31        self.setup_usbkey(usbkey=False)
32
33    def cleanup(self):
34        """If DUT not pingable, may be still stuck in recovery mode.
35        Reboot it.  Also, reset GBB_FLAGS and make sure that lid set
36        to open (in case of error).
37        """
38        # reset ec_uart_regexp to prevent timeouts in case there was
39        # an error before we could reset it
40        self._reset_ec_regexp()
41        if self.servo.get('lid_open') == 'no':
42            self.servo.set('lid_open', 'yes')
43        self.clear_set_gbb_flags(vboot.GBB_FLAG_DISABLE_LID_SHUTDOWN,
44                                 0)
45        try:
46            self.switcher.wait_for_client()
47        except ConnectionError:
48            logging.error("ERROR: client not in OS mode.  Rebooting ...")
49            # reboot back to OS mode
50            self.switcher.mode_aware_reboot(reboot_type='cold',
51                                            sync_before_boot=False)
52        super(firmware_ECLidShutdown, self).cleanup()
53
54    def _reset_ec_regexp(self):
55        """Reset ec_uart_regexp field
56
57        Needs to be done for the ec_uart_regexp otherwise
58        dut-control command will time out due to no match.
59        """
60        self.servo.set('ec_uart_regexp', 'None')
61
62    def verify_lid_shutdown(self):
63        """
64        Make sure that firmware boots into OS with lid closed
65        """
66        self.clear_set_gbb_flags(vboot.GBB_FLAG_DISABLE_LID_SHUTDOWN,
67                                 0)
68        # reboot into recovery mode and wait a bit for it to actually get there
69        self.faft_client.system.request_recovery_boot()
70        self.switcher.mode_aware_reboot(wait_for_dut_up=False)
71        time.sleep(self.RECOVERY_DELAY)
72
73        # close/open lid
74        self.servo.set('lid_open', 'no')
75        time.sleep(self.LID_DELAY)
76        if not self.wait_power_state("G3", self.PWR_RETRIES):
77            logging.error("ERROR: EC does not shut down")
78            return False
79        self.servo.set('lid_open', 'yes')
80
81        # ping DUT - should boot into OS now
82        self._reset_ec_regexp()
83        self.switcher.wait_for_client()
84
85        return True
86
87    def check_disable_lid_shutdown(self):
88        """
89        Set flag to disable shutdown of DUT when lid closed.  Then check
90        if DUT shuts down during recovery mode screen.
91        """
92        # enable shutdown flag
93        self.clear_set_gbb_flags(0,
94                                 vboot.GBB_FLAG_DISABLE_LID_SHUTDOWN)
95        # reboot into recovery mode and wait a bit for it to get there
96        self.faft_client.system.request_recovery_boot()
97        self.switcher.mode_aware_reboot(wait_for_dut_up=False)
98        time.sleep(self.RECOVERY_DELAY)
99
100        # close/open the lid
101        self.servo.set('lid_open', 'no')
102        time.sleep(self.LID_DELAY)
103        if not self.wait_power_state("S0", self.PWR_RETRIES):
104            logging.error("ERROR: EC shuts down")
105            return False
106        self.servo.set('lid_open', 'yes')
107
108        # this should be more than enough time for system to boot up
109        # if it was going to.
110        time.sleep(self.BOOTUP_TIME)
111
112        # should still be offline
113        self.switcher.wait_for_client_offline()
114
115        # reboot back to OS mode
116        self.switcher.mode_aware_reboot(reboot_type='cold',
117                                        sync_before_boot=False)
118
119        # disable flag
120        self._reset_ec_regexp()
121        return True
122
123
124    def run_once(self):
125        if not self.check_ec_capability(['lid']):
126            raise error.TestNAError("This device needs a lid to run this test")
127
128        logging.info("Verify DUT with DISABLE_LID_SHUTDOWN disabled")
129        self.check_state(self.verify_lid_shutdown)
130
131        logging.info("Verify DUT with DISABLE_LID_SHUTDOWN enabled")
132        self.check_state(self.check_disable_lid_shutdown)
133
134