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