• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 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 re
7
8from autotest_lib.client.common_lib import error
9from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
10from autotest_lib.server.cros.faft.firmware_test import ConnectionError
11
12class firmware_RecoveryCacheBootKeys(FirmwareTest):
13    """
14    This test ensures that when booting to recovery mode the device will use the
15    cache instead training memory every boot.
16    """
17    version = 1
18
19    USED_CACHE_MSG = ('MRC: Hash comparison successful. '
20                      'Using data from RECOVERY_MRC_CACHE')
21    REBUILD_CACHE_MSG = "MRC: cache data 'RECOVERY_MRC_CACHE' needs update."
22    RECOVERY_CACHE_SECTION = 'RECOVERY_MRC_CACHE'
23    FIRMWARE_LOG_CMD = 'cbmem -c'
24    FMAP_CMD = 'mosys eeprom map'
25    RECOVERY_REASON_REBUILD_CMD = 'crossystem recovery_request=0xC4'
26
27    def initialize(self, host, cmdline_args, dev_mode=False):
28        super(firmware_RecoveryCacheBootKeys, self).initialize(host,
29                                                              cmdline_args)
30        self.client = host
31        self.dev_mode = dev_mode
32        self.backup_firmware()
33        self.switcher.setup_mode('dev' if dev_mode else 'normal')
34        self.setup_usbkey(usbkey=True, host=False)
35
36    def cleanup(self):
37        try:
38            self.restore_firmware()
39        except ConnectionError:
40            logging.error("ERROR: DUT did not come up.  Need to cleanup!")
41        super(firmware_RecoveryCacheBootKeys, self).cleanup()
42
43    def boot_to_recovery(self):
44        """Boot device into recovery mode."""
45        self.switcher.reboot_to_mode(to_mode='rec')
46
47        self.check_state((self.checkers.crossystem_checker,
48                          {'mainfw_type': 'recovery'}))
49
50    def run_command(self, command):
51        """Runs the specified command and returns the output
52        as a list of strings.
53
54        @param command: The command to run on the DUT
55        @return A list of strings of the command output
56        """
57        logging.info('Command to run: %s', command)
58
59        output = self.faft_client.system.run_shell_command_get_output(command)
60
61        logging.info('Command output: %s', output)
62
63        return output
64
65    def check_command_output(self, cmd, pattern):
66        """Checks the output of the given command for the given pattern
67
68        @param cmd: The command to run
69        @param pattern: The pattern to search for
70        @return True if pattern found
71        """
72
73        logging.info('Checking %s output for %s', cmd, pattern)
74
75        checker = re.compile(pattern)
76
77        cmd_output = self.run_command(cmd)
78
79        for line in cmd_output:
80            if re.search(checker, line):
81                return True
82
83        return False
84
85    def cache_exist(self):
86        """Checks the firmware log to ensure that the recovery cache exists.
87
88        @return True if cache exists
89        """
90        logging.info("Checking if device has RECOVERY_MRC_CACHE")
91
92        return self.check_command_output(self.FMAP_CMD,
93                                         self.RECOVERY_CACHE_SECTION)
94
95    def check_cache_used(self):
96        """Checks the firmware log to ensure that the recovery cache was used
97        during recovery boot.
98
99        @return True if cache used
100        """
101        logging.info('Checking if cache was used.')
102
103        return self.check_command_output(self.FIRMWARE_LOG_CMD,
104                                         self.USED_CACHE_MSG)
105
106    def check_cache_rebuilt(self):
107        """Checks the firmware log to ensure that the recovery cache was rebuilt
108        during recovery boot.
109
110        @return True if cache rebuilt
111        """
112        logging.info('Checking if cache was rebuilt.')
113
114        return self.check_command_output(self.FIRMWARE_LOG_CMD,
115                                         self.REBUILD_CACHE_MSG)
116
117
118
119    def run_once(self):
120        if not self.cache_exist():
121            raise error.TestNAError('No RECOVERY_MRC_CACHE was found on DUT.')
122
123        logging.info('Checking 3-Key recovery boot.')
124        self.boot_to_recovery()
125
126        if not self.check_cache_used():
127            raise error.TestFail('[3-Key] - Recovery Cache was not used.')
128
129        logging.info('Checking 4-key recovery rebuilt cache boot.')
130
131        self.ec.send_command('apshutdown')
132        self.ec.send_command('hostevent set 0x20004000')
133        self.ec.send_command('powerbtn')
134        self.switcher.wait_for_client()
135
136        if not self.check_cache_rebuilt():
137            raise error.TestFail('[4-key] - Recovery Cache was not rebuilt.')