Home | History | Annotate | Download | only in firmware_RecoveryCacheBootKeys
      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 
      5 import logging
      6 import re
      7 
      8 from autotest_lib.client.common_lib import error
      9 from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
     10 from autotest_lib.server.cros.faft.firmware_test import ConnectionError
     11 
     12 class 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.')