• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2017 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
6import time
7
8from autotest_lib.client.common_lib import error
9from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
10from autotest_lib.server.cros import vboot_constants as vboot
11
12
13class firmware_ECUpdateId(FirmwareTest):
14    """
15    Servo based EC test for updating EC ID for verifying EC EFS.
16    """
17    version = 1
18
19    def initialize(self, host, cmdline_args, dev_mode=False):
20        super(firmware_ECUpdateId, self).initialize(host, cmdline_args)
21        # Don't bother if there is no Chrome EC or if the EC is non-EFS.
22        if not self.check_ec_capability():
23            raise error.TestNAError("Nothing needs to be tested on this device")
24        if not self.faft_client.ec.is_efs():
25            raise error.TestNAError("Nothing needs to be tested for non-EFS")
26        if self._no_ec_sync:
27            raise error.TestNAError(
28                    "User selected to disable EC software sync")
29        # If EC isn't write-protected, it won't do EFS. Should enable WP.
30        self._setup_ec_write_protect(True)
31        # In order to test software sync, it must be enabled.
32        self.clear_set_gbb_flags(vboot.GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC, 0)
33        self.backup_firmware()
34        self.switcher.setup_mode('dev' if dev_mode else 'normal',
35                                 allow_gbb_force=True)
36        # It makes updater-related RPCs to use the active AP/EC firmware,
37        # instead of the firmware in the shellball.
38        self.setup_firmwareupdate_shellball()
39        self.setup_usbkey(usbkey=False)
40        self.setup_rw_boot()
41        self.setup_ec_rw_to_a()
42        self.dev_mode = dev_mode
43
44    def cleanup(self):
45        # The superclass's cleanup() restores the original WP state.
46        # Do it before restore the firmware.
47        super(firmware_ECUpdateId, self).cleanup()
48        try:
49            if self.is_firmware_saved():
50                self.restore_firmware()
51        except Exception as e:
52            logging.error("Caught exception: %s", str(e))
53
54    def setup_ec_rw_to_a(self):
55        """For EC EFS, make EC boot into RW A."""
56        if self.faft_client.ec.is_efs():
57            active_copy = self.servo.get_ec_active_copy()
58            if active_copy == 'RW_B':
59                from_section = 'rw_b'
60                to_section = 'rw'
61                logging.info("Copy EC RW from '%s' to '%s'",
62                             from_section, to_section)
63                self.faft_client.ec.copy_rw(from_section, to_section)
64
65                logging.info("EC reboot to switch slot. Wait DUT up...")
66                reboot = lambda: self.faft_client.ec.reboot_to_switch_slot()
67                self.switcher.mode_aware_reboot('custom', reboot)
68
69    def get_active_hash(self):
70        """Return the current EC hash."""
71        ec_hash = self.faft_client.ec.get_active_hash()
72        logging.info("Current EC hash: %s", ec_hash)
73        return ec_hash
74
75    def active_hash_checker(self, expected_hash):
76        """Check if the current EC hash equals to the given one."""
77        ec_hash = self.get_active_hash()
78        result = ec_hash == expected_hash
79        if not result:
80            logging.info("Expected EC hash %s but now %s",
81                         expected_hash, ec_hash)
82        return result
83
84    def active_copy_checker(self, expected_copy):
85        """Check if the EC active copy is matched."""
86        # Get the active copy via servod (EC console).
87        # The result of crossystem doesn't reflect RW_B.
88        active_copy = self.servo.get_ec_active_copy()
89        result = active_copy == expected_copy
90        if not result:
91            logging.info("Expected EC in %s but now in %s",
92                         expected_copy, active_copy)
93        return result
94
95    def corrupt_active_rw(self):
96        """Corrupt the active RW portion."""
97        section = 'rw'
98        if self.servo.get_ec_active_copy() == 'RW_B':
99            section = 'rw_b'
100        logging.info("Corrupt the EC section: %s", section)
101        self.faft_client.ec.corrupt_body(section)
102
103    def run_once(self):
104        """Execute the main body of the test.
105        """
106        logging.info("Check the current state and record hash.")
107        self.check_state((self.active_copy_checker, 'RW'))
108        original_hash = self.get_active_hash()
109
110        logging.info("Modify EC ID and flash it back to BIOS...")
111        self.faft_client.updater.modify_ecid_and_flash_to_bios()
112        modified_hash = self.faft_client.updater.get_ec_hash()
113
114        logging.info("Reboot EC. Verify if EFS works as intended.")
115        self.sync_and_ec_reboot('hard')
116        time.sleep(self.faft_config.software_sync_update)
117        self.switcher.wait_for_client()
118
119        logging.info("Expect EC in another RW slot (the modified hash).")
120        self.check_state((self.active_copy_checker, 'RW_B'))
121        self.check_state((self.active_hash_checker, modified_hash))
122
123        logging.info("Disable EC WP (also reboot)")
124        self.switcher.mode_aware_reboot(
125                'custom',
126                lambda:self.set_ec_write_protect_and_reboot(False))
127
128        logging.info("Corrupt the active EC RW.")
129        self.corrupt_active_rw()
130
131        logging.info("Re-enable EC WP (also reboot)")
132        self.switcher.mode_aware_reboot(
133                'custom',
134                lambda:self.set_ec_write_protect_and_reboot(True))
135
136        logging.info("Expect EC recovered.")
137        # * EC performs EC-EFS, jumps to A, and boots AP.
138        # * AP software-sync's to EC B. Reboots.
139        # * EC performs EC-EFS and jumps to B.
140        self.check_state((self.active_copy_checker, 'RW_B'))
141        self.check_state((self.active_hash_checker, modified_hash))
142
143        logging.info("Restore the original AP firmware and reboot.")
144        self.restore_firmware(restore_ec=False)
145
146        logging.info("Expect EC restored back (the original hash).")
147        # * EC performs EC-EFS, jumps to B, and boots AP.
148        # * AP software-sync's to EC A. Reboots.
149        # * EC performs EC-EFS and jumps to A.
150        self.check_state((self.active_copy_checker, 'RW'))
151        self.check_state((self.active_hash_checker, original_hash))
152