1# Copyright (c) 2011 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 import vboot_constants as vboot
9from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
10
11
12class firmware_DevTriggerRecovery(FirmwareTest):
13    """
14    Servo based recovery boot test triggered by pressing enter at dev screen.
15
16    This test requires a USB disk plugged-in, which contains a Chrome OS test
17    image (built by "build_image --test"). On runtime, this test changes dev
18    switch and reboot. It then presses the enter key at dev warning screen to
19    trigger recovery boot and checks the success of it.
20    """
21    version = 1
22
23    # The devsw off->on transition states are different based on platforms.
24    # For Alex/ZGB, it is dev switch on but normal firmware boot.
25    # For other platforms, it is dev switch on and developer firmware boot.
26    def check_devsw_on_transition(self):
27        if self.faft_client.need_dev_transition:
28            return self.checkers.crossystem_checker({
29                    'devsw_boot': '1',
30                    'mainfw_act': 'A',
31                    'mainfw_type': 'normal',
32                    })
33        else:
34            return self.checkers.crossystem_checker({
35                    'devsw_boot': '1',
36                    'mainfw_act': 'A',
37                    'mainfw_type': 'developer',
38                    })
39
40    # The devsw on->off transition states are different based on platforms.
41    # For Alex/ZGB, it is firmware B normal boot. Firmware A is still developer.
42    # For other platforms, it is directly firmware A normal boot.
43    def check_devsw_off_transition(self):
44        if self.faft_client.need_dev_transition:
45            return self.checkers.crossystem_checker({
46                    'devsw_boot': '0',
47                    'mainfw_act': 'B',
48                    'mainfw_type': 'normal',
49                    })
50        else:
51            return self.checkers.crossystem_checker({
52                    'devsw_boot': '0',
53                    'mainfw_act': 'A',
54                    'mainfw_type': 'normal',
55                    })
56
57    def initialize(self, host, cmdline_args):
58        super(firmware_DevTriggerRecovery, self).initialize(host, cmdline_args)
59        self.switcher.setup_mode('normal')
60        self.setup_usbkey(usbkey=True, host=False)
61
62    def run_once(self):
63        if self.faft_config.mode_switcher_type != 'physical_button_switcher':
64            raise error.TestNAError('This test is only valid in physical button'
65                                    'controlled dev mode firmware.')
66
67        logging.info("Enable dev mode.")
68        self.check_state((self.checkers.crossystem_checker, {
69                              'devsw_boot': '0',
70                              'mainfw_act': 'A',
71                              'mainfw_type': 'normal',
72                              }))
73        self.servo.enable_development_mode()
74        self.switcher.mode_aware_reboot(wait_for_dut_up=False)
75        self.switcher.bypass_dev_mode()
76        self.switcher.wait_for_client()
77
78        logging.info("Expected values based on platforms (see above), "
79                     "run 'chromeos-firmwareupdate --mode todev && reboot', "
80                     "and trigger recovery boot at dev screen. ")
81        self.check_state(self.check_devsw_on_transition)
82        self.faft_client.system.run_shell_command(
83                 'chromeos-firmwareupdate --mode todev && reboot')
84        # Ignore the default reboot_action here because the
85        # userspace_action (firmware updater) will reboot the system.
86        self.switcher.trigger_dev_to_rec()
87        self.switcher.wait_for_client()
88
89        logging.info("Expected recovery boot and disable dev switch.")
90        self.check_state((self.checkers.crossystem_checker, {
91                     'devsw_boot': '1',
92                     'mainfw_type': 'recovery',
93                     'recovery_reason' : vboot.RECOVERY_REASON['RW_DEV_SCREEN'],
94                     }))
95        self.servo.disable_development_mode()
96        self.switcher.mode_aware_reboot()
97
98        logging.info("Expected values based on platforms (see above), "
99                     "and run 'chromeos-firmwareupdate --mode tonormal && "
100                     "reboot'")
101        self.check_state(self.check_devsw_off_transition)
102        self.faft_client.system.run_shell_command(
103                            'chromeos-firmwareupdate --mode tonormal && reboot')
104        self.switcher.wait_for_client()
105
106        logging.info("Expected normal mode boot, done.")
107        self.check_state((self.checkers.crossystem_checker, {
108                              'devsw_boot': '0',
109                              'mainfw_act': 'A',
110                              'mainfw_type': 'normal',
111                              }))
112