Home | History | Annotate | Download | only in firmware_Cr50SetBoardId
      1 # Copyright 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 
      7 from autotest_lib.client.common_lib import error
      8 from autotest_lib.client.common_lib.cros import cr50_utils
      9 from autotest_lib.server.cros.faft.cr50_test import Cr50Test
     10 
     11 
     12 class firmware_Cr50SetBoardId(Cr50Test):
     13     """Verify cr50-set-board-id.sh
     14 
     15     Verify cr50-set-board-id sets the correct board id and flags based on the
     16     given stage.
     17     """
     18     version = 1
     19 
     20     BID_SCRIPT = '/usr/share/cros/cr50-set-board-id.sh'
     21 
     22     # the command to get the brand name
     23     GET_BRAND = 'mosys platform brand'
     24 
     25     # Used when the flags were not initialized in the factory.
     26     UNKNOWN_FLAGS = 0xff00
     27     # Used for dev, proto, EVT, and DVT phases.
     28     DEVELOPMENT_FLAGS = 0x7f7f
     29     # Used for PVT and MP builds.
     30     RELEASE_FLAGS = 0x7f80
     31     PHASE_FLAGS_DICT = {
     32         'unknown' : UNKNOWN_FLAGS,
     33 
     34         'dev' : DEVELOPMENT_FLAGS,
     35         'proto' : DEVELOPMENT_FLAGS,
     36         'evt' : DEVELOPMENT_FLAGS,
     37         'dvt' : DEVELOPMENT_FLAGS,
     38 
     39         'mp' : RELEASE_FLAGS,
     40         'pvt' : RELEASE_FLAGS,
     41     }
     42 
     43     # The response strings from cr50-set-board-id
     44     SUCCESS = ["Successfully updated board ID to 'BID' with phase 'PHASE'.",
     45                0]
     46     ERROR_UNKNOWN_PHASE = ['Unknown phase (PHASE)', 1]
     47     ERROR_INVALID_RLZ = ['Invalid RLZ brand code (BID).', 1]
     48     ERROR_ALREADY_SET = ['Board ID and flag have already been set.', 2]
     49     ERROR_BID_SET_DIFFERENTLY = ['Board ID has been set differently.', 3]
     50     ERROR_FLAG_SET_DIFFERENTLY = ['Flag has been set differently.', 3]
     51 
     52     def initialize(self, host, cmdline_args, full_args, dev_path='', bid=''):
     53         # Restore the original image, rlz code, and board id during cleanup.
     54         super(firmware_Cr50SetBoardId, self).initialize(host, cmdline_args,
     55              full_args, restore_cr50_state=True, cr50_dev_path=dev_path)
     56         if self.cr50.using_ccd():
     57             raise error.TestNAError('Use a flex cable instead of CCD cable.')
     58 
     59         # Update to the dev image so we can erase the board id after we set it.
     60         # This test is verifying cr50-set-board-id and not the actual getting/
     61         # setting of the board id on the cr50 side, so it is ok if the cr50 is
     62         # running a dev image.
     63         self.cr50_update(self.get_saved_cr50_dev_path())
     64 
     65         if not self.cr50.has_command('bid'):
     66             raise error.TestNAError('Cr50 image does not support board id')
     67 
     68         if not self.host.path_exists(self.BID_SCRIPT):
     69             raise error.TestNAError('Device does not have "cr50-set-board-id"')
     70 
     71         result = self.host.run(self.GET_BRAND, ignore_status=True)
     72         platform_brand = result.stdout.strip()
     73         if result.exit_status or not platform_brand:
     74             raise error.TestNAError('Could not get "mosys platform brand"')
     75         self.platform_brand = platform_brand
     76         self.erase_bid()
     77         cr50_utils.StopTrunksd(self.host)
     78 
     79 
     80     def erase_bid(self):
     81         """Erase the current board id"""
     82         self.cr50.send_command('eraseflashinfo')
     83 
     84 
     85     def run_script(self, expected_result, phase, board_id=''):
     86         """Run the bid script with the given phase and board id
     87 
     88         Args:
     89             expected_result: a list with the result message and exit status
     90             phase: The phase string.
     91             board_id: The board id string.
     92 
     93         Raises:
     94             TestFail if the expected result message did not match the script
     95             output
     96         """
     97         message, exit_status = expected_result
     98 
     99         # If we expect an error ignore the exit status
    100         ignore_status = not not exit_status
    101 
    102         # Run the script with the phase and board id
    103         cmd = '%s %s %s' % (self.BID_SCRIPT, phase, board_id)
    104         result = self.host.run(cmd, ignore_status=ignore_status)
    105 
    106         # If we don't give the script a board id, it will use the platform
    107         # brand
    108         expected_board_id = board_id if board_id else self.platform_brand
    109         # Replace the placeholders with the expected board id and phase
    110         message = message.replace('BID', expected_board_id)
    111         message = message.replace('PHASE', phase)
    112 
    113         # Compare the expected script output to the actual script result
    114         if message not in result.stdout or exit_status != result.exit_status:
    115             logging.debug(result)
    116             raise error.TestFail('Expected "%s" got "%s"' % (message,
    117                                  result.stdout))
    118         logging.info(result.stdout)
    119 
    120 
    121     def run_once(self):
    122         """Verify cr50-set-board-id.sh"""
    123         # 'A' is too short to be a valid rlz code
    124         self.run_script(self.ERROR_INVALID_RLZ, 'dvt', 'A')
    125         # dummy_phase is not a valid phase
    126         self.run_script(self.ERROR_UNKNOWN_PHASE, 'dummy_phase')
    127         # The rlz code is checked before the phase
    128         self.run_script(self.ERROR_INVALID_RLZ, 'dummy_phase', 'A')
    129 
    130         # Set the board id so we can verify cr50-set-board-id has the correct
    131         # response to the board id already being set.
    132         self.run_script(self.SUCCESS, 'dvt', 'TEST')
    133         # mp has different flags than dvt
    134         self.run_script(self.ERROR_FLAG_SET_DIFFERENTLY, 'mp', 'TEST')
    135         # try setting the dvt flags with a different board id
    136         self.run_script(self.ERROR_BID_SET_DIFFERENTLY, 'dvt', 'test')
    137         # running with the same phase and board id will raise an error that the
    138         # board id is already set
    139         self.run_script(self.ERROR_ALREADY_SET, 'dvt', 'TEST')
    140 
    141         # Verify each stage sets the right flags
    142         for phase, flags in self.PHASE_FLAGS_DICT.iteritems():
    143             # Erase the board id so we can change it.
    144             self.erase_bid()
    145 
    146             # Run the script to set the board id and flags for the given phase.
    147             self.run_script(self.SUCCESS, phase)
    148 
    149             # Check that the board id and flags are actually set.
    150             cr50_utils.CheckChipBoardId(self.host, self.platform_brand, flags)
    151