• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2014 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 import utils
10from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
11
12
13class firmware_Mosys(FirmwareTest):
14    """
15    Mosys commands test for Firmware values.
16
17    Execute
18    a. mosys -k smbios info bios
19    b. mosys -k ec info
20    c. mosys platform name
21    d. mosys eeprom map
22    e. mosys platform vendor
23    f. mosys -k pd info
24
25    """
26    version = 1
27
28
29    def initialize(self, host, cmdline_args, dev_mode=False):
30        # Parse arguments from command line
31        dict_args = utils.args_to_dict(cmdline_args)
32        super(firmware_Mosys, self).initialize(host, cmdline_args)
33        self.switcher.setup_mode('dev' if dev_mode else 'normal')
34        # a list contain failed execution.
35        self.failed_command = []
36        # Get a list of available mosys commands.
37        lines = self.run_cmd('mosys help')
38        self.command_list = []
39        cmdlist_start = False
40        for line in lines:
41            if cmdlist_start:
42                cmdlst = re.split('\s+', line)
43                if len(cmdlst) > 2:
44                    self.command_list.append(cmdlst[1])
45            elif 'Commands:' in line:
46                cmdlist_start = True
47        logging.info('Availabe commands: %s', ' '.join(self.command_list))
48
49    def run_cmd(self, command):
50        """
51        Log and execute command and return the output.
52
53        @param command: Command to executeon device.
54        @returns the output of command.
55
56        """
57        logging.info('Execute %s', command)
58        output = self.faft_client.system.run_shell_command_get_output(command)
59        logging.info('Output %s', output)
60        return output
61
62    def check_ec_version(self, command, exp_ec_version):
63        """
64        Compare output of 'ectool version' for the current firmware
65        copy to exp_ec_version.
66
67        @param command: command string
68        @param exp_ec_version: The exepected EC version string.
69
70        """
71        if self.faft_client.system.has_host():
72            lines = self.run_cmd('fwtool ec version')
73        else:
74            lines = self.run_cmd('ectool version')
75        fwcopy_pattern = re.compile('Firmware copy: (.*)$')
76        ver_pattern = re.compile('(R[OW]) version:    (.*)$')
77        version = {}
78        for line in lines:
79            ver_matched = ver_pattern.match(line)
80            if ver_matched:
81                version[ver_matched.group(1)] = ver_matched.group(2)
82            fwcopy_matched = fwcopy_pattern.match(line)
83            if fwcopy_matched:
84                fwcopy = fwcopy_matched.group(1)
85        if fwcopy in version:
86            actual_version = version[fwcopy]
87            logging.info('Expected ec version %s actual_version %s',
88                         exp_ec_version, actual_version)
89            if exp_ec_version != actual_version:
90               self._tag_failure(command)
91        else:
92            self._tag_failure(command)
93            logging.error('Failed to locate version from ectool')
94
95    def check_pd_version(self, command, exp_pd_version):
96        """
97        Compare output of 'ectool --dev 1 version' for the current PD firmware
98        copy to exp_pd_version.
99
100        @param command: command string
101        @param exp_pd_version: The exepected PD version string.
102
103        """
104        lines = self.run_cmd('ectool --dev 1 version')
105        fwcopy_pattern = re.compile('Firmware copy: (.*)$')
106        ver_pattern = re.compile('(R[OW]) version:    (.*)$')
107        version = {}
108        for line in lines:
109            ver_matched = ver_pattern.match(line)
110            if ver_matched:
111                version[ver_matched.group(1)] = ver_matched.group(2)
112            fwcopy_matched = fwcopy_pattern.match(line)
113            if fwcopy_matched:
114                fwcopy = fwcopy_matched.group(1)
115        if fwcopy in version:
116            actual_version = version[fwcopy]
117            logging.info('Expected pd version %s actual_version %s',
118                         exp_pd_version, actual_version)
119            if exp_pd_version != actual_version:
120               self._tag_failure(command)
121        else:
122            self._tag_failure(command)
123            logging.error('Failed to locate version from ectool')
124
125    def check_lsb_info(self, command, fieldname, exp_value):
126        """
127        Comapre output of fieldname in /etc/lsb-release to exp_value.
128
129        @param command: command string
130        @param fieldname: field name in lsd-release file.
131        @param exp_value: expected value for fieldname
132
133        """
134        lsb_info = 'cat /etc/lsb-release'
135        lines = self.run_cmd(lsb_info)
136        pattern = re.compile(fieldname + '=(.*)$')
137        for line in lines:
138            matched = pattern.match(line)
139            if matched:
140                actual = matched.group(1)
141                logging.info('Expected %s %s actual %s',
142                             fieldname, exp_value, actual)
143                # Some board will have prefix.  Example nyan_big for big.
144                if exp_value.lower() in actual.lower():
145                  return
146        self._tag_failure(command)
147
148    def check_adb_devices(self, command, fieldname, exp_value):
149        """
150        Compare output of fieldname in adb devices -l to exp_value.
151
152        @param command: command string
153        @param fieldname: field name from adb devices -l output.
154        @param exp_value: expected value for fieldname
155
156        """
157        device_info = 'adb devices -l'
158        lines = self.faft_client.host.run_shell_command_get_output(device_info)
159        logging.info(lines)
160        pattern = re.compile(fieldname + ':(\S+)\s+')
161        logging.info(pattern)
162        for line in lines:
163            matched = pattern.search(line)
164            if matched:
165                actual = matched.group(1)
166                logging.info('Expected %s %s actual %s',
167                             fieldname, exp_value, actual)
168                # Some board will have prefix.  Example nyan_big for big.
169                if exp_value.lower() in actual.lower():
170                  return
171        self._tag_failure(command)
172
173    def _tag_failure(self, cmd):
174        self.failed_command.append(cmd)
175        logging.error('Execute %s failed', cmd)
176
177    def run_once(self, dev_mode=False):
178        # a. mosys -k smbios info bios
179        command = 'mosys -k smbios info bios'
180        if 'smbios' in self.command_list:
181            output = self.run_cmd(command)[0]
182            p = re.compile('vendor="coreboot" version="(.*)"'
183                           ' release_date="[/0-9]+" size="[0-9]+ KB"')
184            v = p.match(output)
185            if not v:
186              self._tag_failure(command)
187            version = v.group(1)
188            if not self.checkers.crossystem_checker({'fwid': version}):
189              self._tag_failure(command)
190        else:
191            logging.warning('Skip "%s", command not available.', command)
192
193        # b. mosys -k ec info
194        command = 'mosys -k ec info'
195        if self.faft_config.chrome_ec:
196          output = self.run_cmd(command)[0]
197          p = re.compile(
198            'vendor="[A-Z]?[a-z]+" name="[ -~]+" fw_version="(.*)"')
199          v = p.match(output)
200          if v:
201             version = v.group(1)
202             self.check_ec_version(command, version)
203          else:
204            self._tag_failure(command)
205        else:
206          logging.info('Skip "%s", command not available.', command)
207
208        # c. mosys platform name
209        command = 'mosys platform name'
210        output = self.run_cmd(command)[0]
211        if self.faft_client.system.has_host():
212            self.check_adb_devices(command, 'product', output)
213        else:
214            self.check_lsb_info(command, 'CHROMEOS_RELEASE_BOARD', output)
215
216        # d. mosys eeprom map
217        command = 'mosys eeprom map|egrep "RW_SHARED|RW_SECTION_[AB]"'
218        lines = self.run_cmd(command)
219        if len(lines) != 3:
220          logging.error('Expect RW_SHARED|RW_SECTION_[AB] got "%s"', lines)
221          self._tag_failure(command)
222        emap = {'RW_SECTION_A': 0, 'RW_SECTION_B': 0, 'RW_SHARED': 0}
223        for line in lines:
224            row = line.split(' | ')
225            if row[1] in emap:
226                emap[row[1]] += 1
227            if row[2] == '0x00000000':
228                logging.error('Expect non zero but got %s instead(%s)',
229                              (row[2], line))
230                self._tag_failure(command)
231            if row[3] == '0x00000000':
232                logging.error('Expect non zero but got %s instead(%s)',
233                              (row[3], line))
234                self._tag_failure(command)
235        # Check that there are one A and one B.
236        if emap['RW_SECTION_A'] != 1 or emap['RW_SECTION_B'] != 1:
237            logging.error('Missing RW_SECTION A or B, %s', lines)
238            self._tag_failure(command)
239
240        # e. mosys platform vendor
241        # Output will be GOOGLE until launch, see crosbug/p/29755
242        command = 'mosys platform vendor'
243        output = self.run_cmd(command)[0]
244        p = re.compile('^[-\w\s]+$')
245        if not p.match(output):
246            logging.error('output is not a string Expect GOOGLE'
247                          'or name of maker.')
248            self._tag_failure(command)
249
250        # f. mosys -k pd info
251        command = 'mosys -k pd info'
252        if self.faft_config.chrome_usbpd and 'pd' in self.command_list:
253          output = self.run_cmd(command)[0]
254          p = re.compile('vendor="[a-z]+" name="[ -~]+" fw_version="(.*)"')
255          v = p.match(output)
256          if v:
257             version = v.group(1)
258             self.check_pd_version(command, version)
259          else:
260             self._tag_failure(command)
261        else:
262          logging.info('Skip "%s", command not available.', command)
263
264        # g. mosys -k memory spd print all (check no error output)
265        command = 'mosys -k memory spd print all'
266        output = self.run_cmd(command)
267        p = re.compile('^dimm=".*$')
268        # Each line should start with "dimm=".
269        for i in output:
270            if not p.match(i):
271                logging.error('output does not start with dimm=%s', i)
272                self._tag_failure(command)
273                break
274
275        # Add any other mosys commands or tests before this section.
276        # empty failed_command indicate all passed.
277        if self.failed_command:
278          raise error.TestFail('%d commands failed, detail above.  '
279                               'Failed commands are "%s"' %
280                               (len(self.failed_command),
281                               ','.join(self.failed_command)))
282