• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
6
7from autotest_lib.client.common_lib import error
8from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
9
10
11class firmware_ECBootTime(FirmwareTest):
12    """
13    Servo based EC boot time test.
14    """
15    version = 1
16
17    def initialize(self, host, cmdline_args):
18        super(firmware_ECBootTime, self).initialize(host, cmdline_args)
19        # Only run in normal mode
20        self.switcher.setup_mode('normal')
21        self.host = host
22
23    def check_boot_time(self):
24        """Check EC and AP boot times"""
25        # Initialize a list of two strings, one printed by the EC when the AP
26        # is taken out of reset, and another one printed when the EC observes
27        # the AP running. These strings are used as for console output anchors
28        # when calculating the AP boot time.
29        #
30        # This is very approximate, a better long term solution would be to
31        # have the EC print the same fixed strings for these two events on all
32        # platforms. http://crosbug.com/p/21628 has been opened to track this
33        # issue.
34        if self._x86:
35            boot_anchors = ["\[([0-9\.]+) PB", "\[([0-9\.]+) Port 80"]
36        elif self._arm_legacy:
37            boot_anchors = ["\[([0-9\.]+) AP running ...",
38                            "\[([0-9\.]+) XPSHOLD seen"]
39        else:
40            boot_anchors = ["\[([0-9\.]+) power state 1 = S5",
41                            "\[([0-9\.]+) power state 3 = S0"]
42
43        # regular expression to say that EC is ready. For systems that
44        # run out of ram there is a second boot where the PMIC is
45        # asked to power cycle the EC to be 100% sure (I wish) that
46        # the code is clean. Looking for the "Inits done" generates a
47        # match after the first boot, and introduces a race between
48        # the EC booting the second time and the test sending the
49        # power_cmd.
50        if self._doubleboot:
51            ec_ready = ["(?ms)UART.*UART.*?\[([0-9.]+) "]
52        else:
53            ec_ready = ["([0-9.]+) Inits done"]
54
55        # Really before sending the power on console command, we should wait
56        # until the console task is ready to receive input.  The console task
57        # prints a string when it's ready to do so, so let's search for that
58        # too.
59        ec_ready.append("Console is enabled")
60
61        power_cmd = "powerbtn" if self.faft_config.ec_has_powerbtn_cmd else \
62                    "power on"
63        # Try the EC reboot command several times in case the console
64        # output is not clean enough for the full string to be found.
65        retry = 10
66        while retry > 0:
67            retry = retry - 1
68            try:
69                reboot = self.ec.send_command_get_output(
70                    "reboot ap-off", ec_ready)
71                break
72            except error.TestFail:
73                logging.info("Unable to parse EC console output, "
74                             "%d more attempts", retry)
75        if retry == 0:
76            # If the magic string was not found reboot the EC and wait
77            # for the host to come up so it is ready for the next test.
78            self.ec.reboot()
79            self.host.wait_up(timeout=30)
80            raise error.TestFail("Unable to reboot EC cleanly, " +
81                                 "Please try removing AC power")
82        logging.debug("reboot: %r", reboot)
83
84        power_press = self.ec.send_command_get_output(
85            power_cmd, boot_anchors)
86        reboot_time = float(reboot[0][1])
87        power_press_time = float(power_press[0][1])
88        firmware_resp_time = float(power_press[1][1])
89        boot_time = firmware_resp_time - power_press_time
90        logging.info("EC cold boot time: %f s", reboot_time)
91        if reboot_time > 1.0:
92            raise error.TestFail("EC cold boot time longer than 1 second.")
93        logging.info("EC boot time: %f s", boot_time)
94        if boot_time > 1.0:
95            raise error.TestFail("Boot time longer than 1 second.")
96
97    def is_arm_legacy_board(self):
98        arm_legacy = ('Snow', 'Spring', 'Pit', 'Pi', 'Big', 'Blaze', 'Kitty')
99        output = self.faft_client.system.get_platform_name()
100        return output in arm_legacy
101
102    def run_once(self):
103        if not self.check_ec_capability():
104            raise error.TestNAError("Nothing needs to be tested on this device")
105        self._x86 = ('x86' in self.faft_config.ec_capability)
106        self._doubleboot = ('doubleboot' in self.faft_config.ec_capability)
107        self._arm_legacy = self.is_arm_legacy_board()
108        dev_mode = self.checkers.crossystem_checker({'devsw_boot': '1'})
109        logging.info("Reboot and check EC cold boot time and host boot time.")
110        self.switcher.mode_aware_reboot('custom', self.check_boot_time)
111
112    def cleanup(self):
113        # Restore the ec_uart_regexp to None
114        self.ec.set_uart_regexp('None')
115