1# Copyright (c) 2020 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_DevDefaultBoot(FirmwareTest):
12    """
13    This test requires a USB disk plugged in, containing a Chrome OS test image.
14    On runtime, this test first switches DUT to developer mode, and modifies
15    the dev_default_boot crossystem value.
16    After waiting at the dev warning, or pressing enter in the detachable UI
17    dev options, the device should boot whatever's selected by default.
18    """
19    version = 1
20    NEEDS_SERVO_USB = True
21
22    def initialize(self, host, cmdline_args, ec_wp=None):
23        """Initialize the test"""
24        super(firmware_DevDefaultBoot, self).initialize(host, cmdline_args,
25                                                        ec_wp=ec_wp)
26        self.switcher.setup_mode('dev')
27        # Use the USB key for Ctrl-U dev boot, not recovery.
28        self.setup_usbkey(usbkey=True, host=False, used_for_recovery=False)
29
30        self.orig_boot_usb = self.faft_client.system.get_dev_boot_usb()
31        logging.info('Original dev_boot_usb: %s', self.orig_boot_usb)
32
33    def cleanup(self):
34        """Cleanup the test"""
35        if hasattr(self, 'orig_boot_usb'):
36            try:
37                self.ensure_dev_internal_boot(self.orig_boot_usb)
38            except Exception as e:
39                logging.error("Error while restoring dev_boot_usb: %s", str(e))
40        super(firmware_DevDefaultBoot, self).cleanup()
41
42    def try_timeout_default_internal(self):
43        """With dev_default_boot=disk, wait for default: should boot internal"""
44        logging.info('%s', self.try_timeout_default_internal.__doc__.strip())
45
46        self.faft_client.system.set_dev_default_boot('disk')
47        self.switcher.simple_reboot()
48        # No ctrl-d or tablet bypass, so it uses the default
49        self.switcher.wait_for_client()
50        self.check_state((
51                self.checkers.dev_boot_usb_checker, False,
52                "dev_default_boot=disk, but didn't boot internal after timer"))
53
54    def try_menu_default_internal(self):
55        """With dev_default_boot=disk, use menu default: should boot internal"""
56        logging.info('%s', self.try_menu_default_internal.__doc__.strip())
57
58        self.faft_client.system.set_dev_default_boot('disk')
59        self.switcher.simple_reboot()
60        self.switcher.bypass_dev_default_boot()
61        self.check_state((
62                self.checkers.dev_boot_usb_checker, False,
63                "dev_default_boot=disk, but didn't boot"
64                " internal disk as default menu option"
65        ))
66
67    def try_timeout_default_usb(self):
68        """With dev_default_boot=usb, wait for default: should boot USB"""
69        logging.info('%s', self.try_timeout_default_usb.__doc__.strip())
70
71        self.faft_client.system.set_dev_default_boot('usb')
72        self.switcher.simple_reboot()
73        # No ctrl-d or tablet bypass, so it uses the default
74        self.switcher.wait_for_client()
75        self.check_state((
76                self.checkers.dev_boot_usb_checker, (True, True),
77                "dev_default_boot=usb, but didn't boot USB after timer"))
78
79    def try_menu_default_usb(self):
80        """With dev_default_boot=usb, use menu default: should boot USB"""
81        logging.info('%s', self.try_menu_default_usb.__doc__.strip())
82
83        self.faft_client.system.set_dev_default_boot('usb')
84        self.switcher.simple_reboot()
85        self.switcher.bypass_dev_default_boot()
86        self.check_state((
87                self.checkers.dev_boot_usb_checker, (True, True),
88                "dev_default_boot=usb, but didn't boot"
89                " USB as default menu option"))
90
91    def run_once(self):
92        """Main test logic"""
93        if (self.faft_config.has_keyboard and
94                not self.check_ec_capability(['keyboard'])):
95            raise error.TestNAError("TEST IT MANUALLY! This test can't be "
96                                    "automated on non-Chrome-EC devices.")
97
98        self.faft_client.system.set_dev_boot_usb(1)
99        has_menu = self.faft_config.mode_switcher_type in (
100                'menu_switcher',
101                'tablet_detachable_switcher',
102        )
103
104        self.try_timeout_default_internal()
105        if has_menu:
106            self.try_menu_default_internal()
107
108        self.try_timeout_default_usb()
109        if has_menu:
110            self.try_menu_default_usb()
111
112        # try again to make sure it can be changed back
113        self.try_timeout_default_internal()
114