# Copyright (c) 2014 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import logging import re from autotest_lib.client.common_lib import error from autotest_lib.client.common_lib import utils from autotest_lib.server.cros.faft.firmware_test import FirmwareTest class firmware_Mosys(FirmwareTest): """ Mosys commands test for Firmware values. Execute * mosys -k ec info * mosys platform name * mosys -k pd info """ version = 1 def initialize(self, host, cmdline_args, dev_mode=False): # Parse arguments from command line dict_args = utils.args_to_dict(cmdline_args) super(firmware_Mosys, self).initialize(host, cmdline_args) self.switcher.setup_mode('dev' if dev_mode else 'normal') # a list contain failed execution. self.failed_command = [] # Get a list of available mosys commands. lines = self.run_cmd('mosys help') self.command_list = [] cmdlist_start = False for line in lines: if cmdlist_start: cmdlst = re.split('\s+', line) if len(cmdlst) > 2: self.command_list.append(cmdlst[1]) elif 'Commands:' in line: cmdlist_start = True logging.info('Available commands: %s', ' '.join(self.command_list)) def check_for_errors(self, output, command): """ Check for known errors. 1. Bad system call (core dumped) We see this a lot now that mosys is in a minijail. Even if we see this error, mosys will return success, so we need to check stderr. """ for line in output: if "Bad system call" in line: logging.info("ERROR: Bad system call detected when calling mosys!") self._tag_failure(command) return 1 return 0 def run_cmd(self, command): """ Log and execute command and return the output. @param command: Command to execution device. @returns the output of command. """ logging.info('Execute %s', command) output = self.faft_client.system.run_shell_command_get_output( command, True) logging.info('Output %s', output) return output def check_ec_version(self, command, exp_ec_version): """ Compare output of 'ectool version' for the current firmware copy to exp_ec_version. @param command: command string @param exp_ec_version: The expected EC version string. """ lines = self.run_cmd('ectool version') fwcopy_pattern = re.compile('Firmware copy: (.*)$') ver_pattern = re.compile('(R[OW]) version: (.*)$') version = {} for line in lines: ver_matched = ver_pattern.match(line) if ver_matched: version[ver_matched.group(1)] = ver_matched.group(2) fwcopy_matched = fwcopy_pattern.match(line) if fwcopy_matched: fwcopy = fwcopy_matched.group(1) if fwcopy in version: actual_version = version[fwcopy] logging.info('Expected ec version %s actual_version %s', exp_ec_version, actual_version) if exp_ec_version != actual_version: self._tag_failure(command) else: self._tag_failure(command) logging.error('Failed to locate version from ectool') def check_pd_version(self, command, exp_pd_version): """ Compare output of 'ectool --dev 1 version' for the current PD firmware copy to exp_pd_version. @param command: command string @param exp_pd_version: The expected PD version string. """ lines = self.run_cmd('ectool --dev 1 version') fwcopy_pattern = re.compile('Firmware copy: (.*)$') ver_pattern = re.compile('(R[OW]) version: (.*)$') version = {} for line in lines: ver_matched = ver_pattern.match(line) if ver_matched: version[ver_matched.group(1)] = ver_matched.group(2) fwcopy_matched = fwcopy_pattern.match(line) if fwcopy_matched: fwcopy = fwcopy_matched.group(1) if fwcopy in version: actual_version = version[fwcopy] logging.info('Expected pd version %s actual_version %s', exp_pd_version, actual_version) if exp_pd_version != actual_version: self._tag_failure(command) else: self._tag_failure(command) logging.error('Failed to locate version from ectool') def _tag_failure(self, cmd): self.failed_command.append(cmd) logging.error('Execute %s failed', cmd) def run_once(self, dev_mode=False): """Runs a single iteration of the test.""" # mosys -k ec info command = 'mosys -k ec info' if self.faft_config.chrome_ec: output = self.run_cmd(command) self.check_for_errors(output, command) p = re.compile( 'vendor="[A-Z]?[a-z]+" name="[ -~]+" fw_version="(.*)"') v = p.match(output[0]) if v: version = v.group(1) self.check_ec_version(command, version) else: self._tag_failure(command) else: logging.info('Skip "%s", command not available.', command) # mosys platform name command = 'mosys platform name' output = self.run_cmd(command) self.check_for_errors(output, command) # mosys -k pd info command = 'mosys -k pd info' if self.faft_config.chrome_usbpd and 'pd' in self.command_list: output = self.run_cmd(command) self.check_for_errors(output, command) p = re.compile('vendor="[a-z]+" name="[ -~]+" fw_version="(.*)"') v = p.match(output[0]) if v: version = v.group(1) self.check_pd_version(command, version) else: self._tag_failure(command) else: logging.info('Skip "%s", command not available.', command) # mosys -k memory spd print all (check no error output) command = 'mosys -k memory spd print all' output = self.run_cmd(command) self.check_for_errors(output, command) p = re.compile('^dimm=".*$') # Each line should start with "dimm=". for i in output: if not p.match(i): logging.error('output does not start with dimm=%s', i) self._tag_failure(command) break # Add any other mosys commands or tests before this section. # empty failed_command indicate all passed. if self.failed_command: raise error.TestFail('%d commands failed, detail above. ' 'Failed commands are "%s"' % (len(self.failed_command), ','.join(self.failed_command)))