1# Copyright (c) 2012 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
6from threading import Timer
7
8from autotest_lib.client.common_lib import error
9from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
10
11
12class firmware_FAFTSetup(FirmwareTest):
13    """This test checks the following FAFT hardware requirement:
14      - Warm reset
15      - Cold reset
16      - Recovery boot with USB stick
17      - USB stick is plugged into Servo board, not DUT
18      - Keyboard simulation
19      - No terminal opened on EC console
20    """
21    version = 1
22
23    # Delay to ensure client is ready to read the key press.
24    KEY_PRESS_DELAY = 2
25
26
27    def console_checker(self):
28        """Verify EC console is available if using Chrome EC."""
29        if not self.check_ec_capability(suppress_warning=True):
30            # Not Chrome EC. Nothing to check.
31            return True
32        try:
33            self.ec.send_command("chan 0")
34            expected_output = ["Chip:\s+[^\r\n]*\r\n",
35                               "RO:\s+[^\r\n]*\r\n",
36                               "RW:\s+[^\r\n]*\r\n",
37                               "Build:\s+[^\r\n]*\r\n"]
38            self.ec.send_command_get_output("version",
39                                            expected_output)
40            self.ec.send_command("chan 0xffffffff")
41            return True
42        except: # pylint: disable=W0702
43            logging.error("Cannot talk to EC console.")
44            logging.error(
45                    "Please check there is no terminal opened on EC console.")
46            raise error.TestFail("Failed EC console check.")
47
48    def base_keyboard_checker(self, press_action):
49        """Press key and check from DUT.
50
51        Args:
52            press_action: A callable that would press the keys when called.
53        """
54        result = True
55        # Stop UI so that key presses don't go to Chrome.
56        self.faft_client.system.run_shell_command("stop ui")
57
58        # Press the keys
59        Timer(self.KEY_PRESS_DELAY, press_action).start()
60
61        # Invoke client side script to monitor keystrokes
62        if not self.faft_client.system.check_keys([28, 29, 32]):
63            result = False
64
65        # Turn UI back on
66        self.faft_client.system.run_shell_command("start ui")
67        return result
68
69    def keyboard_checker(self):
70        """Press 'd', Ctrl, ENTER by servo and check from DUT."""
71
72        def keypress():
73            self.servo.ctrl_d()
74            self.servo.enter_key()
75
76        return self.base_keyboard_checker(keypress)
77
78    def run_once(self):
79        logging.info("Check EC console is available and test warm reboot")
80        self.console_checker()
81        self.switcher.mode_aware_reboot()
82
83        logging.info("Check test image is on USB stick and run recovery boot")
84        self.assert_test_image_in_usb_disk()
85        self.switcher.reboot_to_mode(to_mode='rec')
86
87        self.check_state((self.checkers.crossystem_checker,
88                          {'mainfw_type': 'recovery'}))
89
90        logging.info("Check cold boot")
91        self.switcher.mode_aware_reboot(reboot_type='cold')
92
93        if self.faft_config.fw_bypasser_type != 'ctrl_d_bypasser':
94            logging.info("Check keyboard simulation")
95            self.check_state(self.keyboard_checker)
96        else:
97            logging.info("Skip keyboard simulation on an embedded device")
98