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.')