• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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