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