1# Copyright 2018 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.client.common_lib.cros import cr50_utils 10from autotest_lib.server.cros.faft.cr50_test import Cr50Test 11 12 13class firmware_Cr50GetName(Cr50Test): 14 """Verify cr50-get-name.sh 15 16 Verify cr50-get-name sets the correct board id and flags based on the 17 given stage. 18 """ 19 version = 1 20 21 GET_NAME_SCRIPT = '/usr/share/cros/cr50-get-name.sh' 22 # This translates to 'TEST' 23 TEST_BRAND = 0x54455354 24 MAX_VAL = 0xffffffff 25 26 27 def initialize(self, host, cmdline_args, dev_path='', full_args={}): 28 # Restore the original image, rlz code, and board id during cleanup. 29 super(firmware_Cr50GetName, self).initialize(host, cmdline_args, 30 full_args, restore_cr50_state=True, cr50_dev_path=dev_path) 31 32 if not self.host.path_exists(self.GET_NAME_SCRIPT): 33 raise error.TestNAError('Device does not have "cr50-get-name"') 34 35 # Update to the dev image so we can erase the board id after we set it. 36 # This test is verifying cr50-get-name, so it is ok if cr50 is running a 37 # dev image. 38 self.cr50_update(self.get_saved_cr50_dev_path()) 39 40 # Stop trunksd so it wont interfere with the update 41 cr50_utils.StopTrunksd(self.host) 42 43 # Get the current cr50 update messages. The test will keep track of the 44 # last message and separate the current output from actual test results. 45 self.get_result() 46 47 48 def erase_bid(self): 49 """Erase the cr50 board id""" 50 self.cr50.send_command('eraseflashinfo') 51 52 53 def get_result(self): 54 """Return the new cr50 update messages from /var/log/messages""" 55 # Get the cr50 messages 56 result = self.host.run('grep cr50 /var/log/messages').stdout.strip() 57 58 if hasattr(self, '_last_message'): 59 result = result.rsplit(self._last_message, 1)[-1] 60 61 # Save the last line. It will be used to separate the current results 62 # from later runs. 63 self._last_message = result.rsplit('\n', 1)[-1] 64 logging.debug('last cr50 update message: "%s"', self._last_message) 65 return result 66 67 68 def get_expected_result_re(self, brand, flags, erased): 69 """Return the expected update message re given the test flags 70 71 Args: 72 brand: The board id value to test. 73 flags: The flag value to test. 74 erased: True if the board id is erased 75 76 Returns: 77 A string with info that must be found in /var/log/messages for valid 78 update results. 79 """ 80 expected_result = [] 81 82 if erased: 83 board_id = 'ffffffff:ffffffff:ffffffff' 84 # If the board id is erased, the device should update to the prod 85 # image. 86 ext = 'prod' 87 expected_result.append('board ID is erased using prod image') 88 else: 89 board_id = '%08x:%08x:%08x' % (brand, brand ^ self.MAX_VAL, flags) 90 ext = 'prepvt' if flags & 0x10 else 'prod' 91 92 flag_str = board_id.rsplit(':', 1)[-1] 93 94 expected_result.append("board_id: '%s' board_flags: '0x%s', extension: " 95 "'%s'" % (board_id, flag_str, ext)) 96 expected_result.append('hashing /opt/google/cr50/firmware/cr50.bin.%s' % 97 ext) 98 return '(%s)' % '\n.*'.join(expected_result) 99 100 101 def check_result(self, brand, flags, erased): 102 """Verify the expected result string is found in the update messages 103 104 Args: 105 brand: The board id value to test. 106 flags: The flag value to test. 107 erased: True if the board id is erased 108 109 Raises: 110 TestFail if the expected result message did not match the update 111 output 112 """ 113 expected_result_re = self.get_expected_result_re(brand, flags, erased) 114 result = self.get_result() 115 match = re.search(expected_result_re, result) 116 117 logging.debug('EXPECT: %s', expected_result_re) 118 logging.debug('GOT: %s', result) 119 120 if not match: 121 raise error.TestFail('Unexpected result during update with %s' % 122 ('erased board id' if erased else '%x:%x' % (brand, flags))) 123 124 logging.info('FOUND UPDATE RESULT:\n%s', match.groups()[0]) 125 126 127 def run_update(self, brand, flags, clear_bid=False): 128 """Set the board id then run cr50-update 129 130 Args: 131 brand: The board id int to test. 132 flags: The flag int to test. 133 clear_bid: True if the board id should be erased and not reset. 134 """ 135 # Set the board id 136 self.erase_bid() 137 138 if not clear_bid: 139 self.cr50.send_command('bid 0x%x 0x%x' % (brand, flags)) 140 141 # Run the update script script 142 self.host.run('start cr50-update') 143 144 # Make sure cr50 used the right image. 145 self.check_result(brand, flags, clear_bid) 146 147 148 def run_once(self): 149 """Verify cr50-get-name.sh""" 150 # Test the MP flags 151 self.run_update(self.TEST_BRAND, 0x7f00) 152 153 # Test the pre-PVT flags 154 self.run_update(self.TEST_BRAND, 0x7f10) 155 156 # Erase the board id 157 self.run_update(0, 0, clear_bid=True) 158 159 # Make sure the script can tell the difference between an erased board 160 # id and one set to 0xffffffff:0xffffffff. 161 self.run_update(self.MAX_VAL, self.MAX_VAL) 162