• 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, tpm_utils
9from autotest_lib.server.cros.faft.cr50_test import Cr50Test
10
11
12class 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 = 0xff7f
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, 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            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 cleanup(self):
81        """Clear the TPM Owner"""
82        super(firmware_Cr50SetBoardId, self).cleanup()
83        tpm_utils.ClearTPMOwnerRequest(self.host)
84
85
86    def erase_bid(self):
87        """Erase the current board id"""
88        self.cr50.send_command('eraseflashinfo')
89
90
91    def run_script(self, expected_result, phase, board_id=''):
92        """Run the bid script with the given phase and board id
93
94        Args:
95            expected_result: a list with the result message and exit status
96            phase: The phase string.
97            board_id: The board id string.
98
99        Raises:
100            TestFail if the expected result message did not match the script
101            output
102        """
103        message, exit_status = expected_result
104
105        # If we expect an error ignore the exit status
106        ignore_status = not not exit_status
107
108        # Run the script with the phase and board id
109        cmd = '%s %s %s' % (self.BID_SCRIPT, phase, board_id)
110        result = self.host.run(cmd, ignore_status=ignore_status)
111
112        # If we don't give the script a board id, it will use the platform
113        # brand
114        expected_board_id = board_id if board_id else self.platform_brand
115        # Replace the placeholders with the expected board id and phase
116        message = message.replace('BID', expected_board_id)
117        message = message.replace('PHASE', phase)
118
119        # Compare the expected script output to the actual script result
120        if message not in result.stdout or exit_status != result.exit_status:
121            logging.debug(result)
122            raise error.TestFail('Expected "%s" got "%s"' % (message,
123                                 result.stdout))
124        logging.info(result.stdout)
125
126
127    def run_once(self):
128        """Verify cr50-set-board-id.sh"""
129        # 'A' is too short to be a valid rlz code
130        self.run_script(self.ERROR_INVALID_RLZ, 'dvt', 'A')
131        # dummy_phase is not a valid phase
132        self.run_script(self.ERROR_UNKNOWN_PHASE, 'dummy_phase')
133        # The rlz code is checked before the phase
134        self.run_script(self.ERROR_INVALID_RLZ, 'dummy_phase', 'A')
135
136        # Set the board id so we can verify cr50-set-board-id has the correct
137        # response to the board id already being set.
138        self.run_script(self.SUCCESS, 'dvt', 'TEST')
139        # mp has different flags than dvt
140        self.run_script(self.ERROR_FLAG_SET_DIFFERENTLY, 'mp', 'TEST')
141        # try setting the dvt flags with a different board id
142        self.run_script(self.ERROR_BID_SET_DIFFERENTLY, 'dvt', 'test')
143        # running with the same phase and board id will raise an error that the
144        # board id is already set
145        self.run_script(self.ERROR_ALREADY_SET, 'dvt', 'TEST')
146
147        # Verify each stage sets the right flags
148        for phase, flags in self.PHASE_FLAGS_DICT.iteritems():
149            # Erase the board id so we can change it.
150            self.erase_bid()
151
152            # Run the script to set the board id and flags for the given phase.
153            self.run_script(self.SUCCESS, phase)
154
155            # Check that the board id and flags are actually set.
156            cr50_utils.CheckChipBoardId(self.host, self.platform_brand, flags)
157