• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 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
5
6"""The autotest performing FW update, both EC and AP in CCD mode."""
7import logging
8
9from autotest_lib.client.common_lib import error
10from autotest_lib.server.cros.faft.cr50_test import Cr50Test
11from autotest_lib.server.cros.servo import servo
12
13MAX_TRIES=2
14
15
16class firmware_Cr50CCDFirmwareUpdate(Cr50Test):
17    """A test that can provision a machine to the correct firmware version."""
18
19    version = 1
20    should_restore_fw = False
21
22    def initialize(self, host, cmdline_args, full_args):
23        """Initialize the test and check if cr50 exists.
24
25        Raises:
26            TestNAError: If the dut is not proper for this test for its RDD
27                         recognition problem.
28        """
29        super(firmware_Cr50CCDFirmwareUpdate,
30              self).initialize(host, cmdline_args, full_args)
31
32        # Don't bother if there is no Chrome EC.
33        if not self.check_ec_capability():
34            raise error.TestNAError('Nothing needs to be tested on this device')
35
36        servo_type = self.servo.get_servo_version()
37        if 'ccd_cr50' not in servo_type:
38            raise error.TestNAError('unsupported servo type: %s' % servo_type)
39
40        if eval(full_args.get('backup_fw', 'False')):
41            self.backup_firmware()
42
43    def cleanup(self):
44        try:
45            if not self.should_restore_fw:
46                return
47
48            self.cr50.reboot()
49            self.switcher.mode_aware_reboot(reboot_type='cold')
50
51            # Verify the EC is responsive before raising an error and going to
52            # cleanup. Repair and cleanup don't recover corrupted EC firmware
53            # very well.
54            try:
55                self.verify_ec_response()
56            except Exception as e:
57                logging.error('Caught exception: %s', str(e))
58
59            if self.is_firmware_saved():
60                logging.info('Restoring firmware')
61                self.restore_firmware()
62            else:
63                logging.info('chromeos-firmwareupdate --mode=recovery')
64                result = self._client.run('chromeos-firmwareupdate'
65                                          ' --mode=recovery',
66                                          ignore_status=True)
67                if result.exit_status != 0:
68                    logging.error('chromeos-firmwareupdate failed: %s',
69                                  result.stdout.strip())
70                self._client.reboot()
71        except Exception as e:
72            logging.error('Caught exception: %s', str(e))
73        finally:
74            super(firmware_Cr50CCDFirmwareUpdate, self).cleanup()
75
76    def verify_ec_response(self):
77        """ Verify the EC is responsive."""
78        # Try to reflash EC a couple of times to see if it's possible to recover
79        # the device now.
80        count = MAX_TRIES
81        while True:
82            try:
83                if self.servo.get_ec_board():
84                    return
85            except servo.ConsoleError as e:
86                logging.error('EC console is unresponsive: %s', str(e))
87
88            if count == 0:
89                break
90
91            count -= 1
92            # In the last iteration, try with main servo device.
93            if count == 0:
94                self.servo.enable_main_servo_device()
95
96            try:
97                self.cros_host.firmware_install(build=self.b_ver,
98                                                install_bios=False)
99            except Exception as e:
100                logging.error('firmware_install failed: %s', str(e))
101
102        logging.error('DUT likely needs a manual recovery.')
103
104    def run_once(self, host, rw_only=False):
105        """The method called by the control file to start the test.
106
107        Args:
108          host: a CrosHost object of the machine to update.
109          rw_only: True to only update the RW firmware.
110
111        Raises:
112          TestFail: if the firmware version remains unchanged.
113          TestError: if the latest firmware release cannot be located.
114          TestNAError: if the test environment is not properly set.
115                       e.g. the servo type doesn't support this test.
116        """
117        self.cros_host = host
118        # Get the parent (a.k.a. reference board or baseboard), and hand it
119        # to get_latest_release_version so that it
120        # can use it in search as secondary candidate. For example, bob doesn't
121        # have its own release directory, but its parent, gru does.
122        parent = getattr(self.faft_config, 'parent', None)
123
124        self.b_ver = host.get_latest_release_version(self.faft_config.platform,
125                                                     parent)
126        if not self.b_ver:
127            raise error.TestError('Cannot locate the latest release for %s' %
128                                  self.faft_config.platform)
129
130        # Fast open cr50 and check if testlab is enabled.
131        self.fast_ccd_open(enable_testlab=True)
132        if self.servo.has_control('active_v4_device'):
133            try:
134                self.servo.set('active_v4_device', 'ccd_cr50')
135            except error.TestFail as e:
136                raise error.TestNAError('cannot change active_v4_device: %s' %
137                                        str(e))
138
139        # If it is ITE EC, then ccd reset factory.
140        if self.servo.get('ec_chip') == 'it83xx':
141            self.cr50.set_cap('I2C', 'Always')
142
143        self.should_restore_fw = True
144        try:
145            self.cros_host.firmware_install(build=self.b_ver, rw_only=rw_only,
146                                            dest=self.resultsdir,
147                                            verify_version=True)
148        except Exception as e:
149            # The test failed to flash the firmware.
150            raise error.TestFail('firmware_install failed with CCD: %s' %
151                                 str(e))
152