• 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
6
7from autotest_lib.client.common_lib import error
8from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
9
10
11class firmware_RecoveryCacheBootKeys(FirmwareTest):
12    """
13    This test ensures that when booting to recovery mode the device will use the
14    cache instead training memory every boot.
15    """
16    version = 1
17
18    USED_CACHE_MSG = ('MRC: Hash comparison successful. '
19                      'Using data from RECOVERY_MRC_CACHE')
20    REBUILD_CACHE_MSG = "MRC: cache data 'RECOVERY_MRC_CACHE' needs update."
21    RECOVERY_CACHE_SECTION = 'RECOVERY_MRC_CACHE'
22    FIRMWARE_LOG_CMD = 'cbmem -1' + ' | grep ' + REBUILD_CACHE_MSG[:3]
23    FMAP_CMD = 'mosys eeprom map'
24    RECOVERY_REASON_REBUILD_CMD = 'crossystem recovery_request=0xC4'
25
26    def initialize(self, host, cmdline_args, dev_mode=False):
27        super(firmware_RecoveryCacheBootKeys, self).initialize(
28                host, cmdline_args)
29
30        if not self.faft_config.rec_force_mrc:
31            raise error.TestNAError('DUT cannot force memory training.')
32
33        self.client = host
34        self.dev_mode = dev_mode
35        self.switcher.setup_mode('dev' if dev_mode else 'normal')
36        self.setup_usbkey(usbkey=True, host=False)
37
38    def cleanup(self):
39        super(firmware_RecoveryCacheBootKeys, self).cleanup()
40        self.switcher.simple_reboot()
41
42    def boot_to_recovery(self, rebuild_mrc_cache=False):
43        """Boots the device into recovery mode."""
44        if rebuild_mrc_cache:
45            self.switcher.reboot_to_mode(to_mode='rec_force_mrc')
46        else:
47            self.switcher.reboot_to_mode(to_mode='rec')
48
49        self.check_state((self.checkers.crossystem_checker, {
50                'mainfw_type': 'recovery'
51        }))
52
53    def cache_exist(self):
54        """Checks the firmware log to ensure that the recovery cache exists.
55
56        @return True if cache exists
57        """
58        logging.info("Checking if device has RECOVERY_MRC_CACHE")
59
60        return self.faft_client.system.run_shell_command_check_output(
61                self.FMAP_CMD, self.RECOVERY_CACHE_SECTION)
62
63    def check_cache_used(self):
64        """Checks the firmware log to ensure that the recovery cache was used
65        during recovery boot.
66
67        @return True if cache used
68        """
69        logging.info('Checking if cache was used.')
70
71        return self.faft_client.system.run_shell_command_check_output(
72                self.FIRMWARE_LOG_CMD, self.USED_CACHE_MSG)
73
74    def check_cache_rebuilt(self):
75        """Checks the firmware log to ensure that the recovery cache was rebuilt
76        during recovery boot.
77
78        @return True if cache rebuilt
79        """
80        logging.info('Checking if cache was rebuilt.')
81
82        return self.faft_client.system.run_shell_command_check_output(
83                self.FIRMWARE_LOG_CMD, self.REBUILD_CACHE_MSG)
84
85    def run_once(self):
86        """Runs a single iteration of the test."""
87        if not self.cache_exist():
88            raise error.TestNAError('No RECOVERY_MRC_CACHE was found on DUT.')
89
90        logging.info('Ensure we\'ve done memory training.')
91        self.boot_to_recovery()
92
93        # With EFS, when the EC is in RO and we do a recovery boot, it
94        # causes the EC to do a soft reboot, which will in turn cause
95        # a PMIC reset (double reboot) on SKL/KBL power architectures.
96        # This causes us to lose the request to do MRC training for
97        # this test.  The solution is to make sure that the EC is in
98        # RW before doing a recovery boot to ensure that the double
99        # reboot does not occur and information/requests are not lost.
100        self.switcher.simple_reboot('cold')
101
102        logging.info('Checking recovery boot.')
103        self.boot_to_recovery()
104
105        if not self.check_cache_used():
106            raise error.TestFail('Recovery Cache was not used.')
107
108        self.switcher.simple_reboot('cold')
109
110        logging.info('Checking recovery boot with forced MRC cache training.')
111        self.boot_to_recovery(rebuild_mrc_cache=True)
112        self.switcher.wait_for_client()
113
114        if not self.check_cache_rebuilt():
115            raise error.TestFail('Recovery Cache was not rebuilt.')
116
117        logging.info('Reboot out of Recovery')
118        self.switcher.simple_reboot()
119