# Copyright 2017 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import logging from autotest_lib.client.common_lib import error from autotest_lib.client.common_lib.cros import cr50_utils from autotest_lib.server.cros.faft.cr50_test import Cr50Test class firmware_Cr50SetBoardId(Cr50Test): """Verify cr50-set-board-id.sh Verify cr50-set-board-id sets the correct board id and flags based on the given stage. """ version = 1 BID_SCRIPT = '/usr/share/cros/cr50-set-board-id.sh' # the command to get the brand name GET_BRAND = 'mosys platform brand' # Used when the flags were not initialized in the factory. UNKNOWN_FLAGS = 0xff00 # Used for dev, proto, EVT, and DVT phases. DEVELOPMENT_FLAGS = 0x7f7f # Used for PVT and MP builds. RELEASE_FLAGS = 0x7f80 PHASE_FLAGS_DICT = { 'unknown' : UNKNOWN_FLAGS, 'dev' : DEVELOPMENT_FLAGS, 'proto' : DEVELOPMENT_FLAGS, 'evt' : DEVELOPMENT_FLAGS, 'dvt' : DEVELOPMENT_FLAGS, 'mp' : RELEASE_FLAGS, 'pvt' : RELEASE_FLAGS, } # The response strings from cr50-set-board-id SUCCESS = ["Successfully updated board ID to 'BID' with phase 'PHASE'.", 0] ERROR_UNKNOWN_PHASE = ['Unknown phase (PHASE)', 1] ERROR_INVALID_RLZ = ['Invalid RLZ brand code (BID).', 1] ERROR_ALREADY_SET = ['Board ID and flag have already been set.', 2] ERROR_BID_SET_DIFFERENTLY = ['Board ID has been set differently.', 3] ERROR_FLAG_SET_DIFFERENTLY = ['Flag has been set differently.', 3] def initialize(self, host, cmdline_args, full_args, dev_path='', bid=''): # Restore the original image, rlz code, and board id during cleanup. super(firmware_Cr50SetBoardId, self).initialize(host, cmdline_args, full_args, restore_cr50_state=True, cr50_dev_path=dev_path) if self.cr50.using_ccd(): raise error.TestNAError('Use a flex cable instead of CCD cable.') # Update to the dev image so we can erase the board id after we set it. # This test is verifying cr50-set-board-id and not the actual getting/ # setting of the board id on the cr50 side, so it is ok if the cr50 is # running a dev image. self.cr50_update(self.get_saved_cr50_dev_path()) if not self.cr50.has_command('bid'): raise error.TestNAError('Cr50 image does not support board id') if not self.host.path_exists(self.BID_SCRIPT): raise error.TestNAError('Device does not have "cr50-set-board-id"') result = self.host.run(self.GET_BRAND, ignore_status=True) platform_brand = result.stdout.strip() if result.exit_status or not platform_brand: raise error.TestNAError('Could not get "mosys platform brand"') self.platform_brand = platform_brand self.erase_bid() cr50_utils.StopTrunksd(self.host) def erase_bid(self): """Erase the current board id""" self.cr50.send_command('eraseflashinfo') def run_script(self, expected_result, phase, board_id=''): """Run the bid script with the given phase and board id Args: expected_result: a list with the result message and exit status phase: The phase string. board_id: The board id string. Raises: TestFail if the expected result message did not match the script output """ message, exit_status = expected_result # If we expect an error ignore the exit status ignore_status = not not exit_status # Run the script with the phase and board id cmd = '%s %s %s' % (self.BID_SCRIPT, phase, board_id) result = self.host.run(cmd, ignore_status=ignore_status) # If we don't give the script a board id, it will use the platform # brand expected_board_id = board_id if board_id else self.platform_brand # Replace the placeholders with the expected board id and phase message = message.replace('BID', expected_board_id) message = message.replace('PHASE', phase) # Compare the expected script output to the actual script result if message not in result.stdout or exit_status != result.exit_status: logging.debug(result) raise error.TestFail('Expected "%s" got "%s"' % (message, result.stdout)) logging.info(result.stdout) def run_once(self): """Verify cr50-set-board-id.sh""" # 'A' is too short to be a valid rlz code self.run_script(self.ERROR_INVALID_RLZ, 'dvt', 'A') # dummy_phase is not a valid phase self.run_script(self.ERROR_UNKNOWN_PHASE, 'dummy_phase') # The rlz code is checked before the phase self.run_script(self.ERROR_INVALID_RLZ, 'dummy_phase', 'A') # Set the board id so we can verify cr50-set-board-id has the correct # response to the board id already being set. self.run_script(self.SUCCESS, 'dvt', 'TEST') # mp has different flags than dvt self.run_script(self.ERROR_FLAG_SET_DIFFERENTLY, 'mp', 'TEST') # try setting the dvt flags with a different board id self.run_script(self.ERROR_BID_SET_DIFFERENTLY, 'dvt', 'test') # running with the same phase and board id will raise an error that the # board id is already set self.run_script(self.ERROR_ALREADY_SET, 'dvt', 'TEST') # Verify each stage sets the right flags for phase, flags in self.PHASE_FLAGS_DICT.iteritems(): # Erase the board id so we can change it. self.erase_bid() # Run the script to set the board id and flags for the given phase. self.run_script(self.SUCCESS, phase) # Check that the board id and flags are actually set. cr50_utils.CheckChipBoardId(self.host, self.platform_brand, flags)