Home | History | Annotate | Download | only in firmware_Mosys
      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 
      5 import logging
      6 import re
      7 
      8 from autotest_lib.client.common_lib import error
      9 from autotest_lib.client.common_lib import utils
     10 from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
     11 
     12 
     13 class 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