• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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