File: //lib64/mft/python_tools/mstdump/mstdump.py
# --
# - Mellanox Confidential and Proprietary -
#
# Copyright (C) Jan 2013, Mellanox Technologies Ltd. ALL RIGHTS RESERVED.
#
# Except as specifically permitted herein, no portion of the information,
# including but not limited to object code and source code, may be reproduced,
# modified, distributed, republished or otherwise exploited in any form or by
# any means for any purpose without the prior written permission of Mellanox
# Technologies Ltd. Use of software subject to the terms and conditions
# detailed in the file "LICENSE.txt".
# --
# Author: Mahmoud Hasan 11.6.2017
# Python Imports ######################
try:
import sys
import os
import re
import platform
import logging
import subprocess
import tools_version
except Exception as e:
print("-E- could not import : %s" % str(e))
sys.exit(1)
# Constants ###########################
PROG = "mstdump"
TOOL_VERSION = ""
CAUSE_FLAG = "--cause"
DEV_EXAMPLE = "/dev/mst/mt4099_pci_cr0"
DEVICE_KEY = "DEVICE"
IS_FULL_KEY = "IS_FULL"
I2C_SLAVE_KEY = "I2C_SLAVE_KEY"
CAUSE_ADDR_KEY = "CAUSE_ADDR"
CAUSE_ADDR_OFFSET = "CAUSE_OFFSET"
MSTDUMP_ARGS = ['-h', '-help', '--help', '-v', '-version', '--version', '--cause', '-full']
HELP_MESSAGE = ''' Mellanox %s utility, dumps device internal configuration data\n\
Usage: %s [-full] <device> [i2c-slave] [-v[ersion] [-h[elp]]]\n\n\
-full : Dump more expanded list of addresses\n\
Note : be careful when using this flag, None safe addresses might be read.\n\
-v | --version : Display version info\n\
-h | --help : Print this help message\n\
Example :\n\
%s %s\n
'''
######################################################################
# Description: Execute command and get (rc, stdout-output, stderr-output)
######################################################################
def cmd_exec(cmd):
logging.debug("Executing: %s" % cmd)
p = subprocess.Popen(cmd,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
shell=True)
res = p.communicate()
stat = p.wait()
return stat, res[0], res[1] # RC, Stdout, Stderr
######################################################################
# Description: Print help message
######################################################################
def print_help_message():
print(HELP_MESSAGE % (PROG, PROG, PROG, DEV_EXAMPLE))
######################################################################
# Description: Print version
######################################################################
def print_version():
print(tools_version.GetVersionString(PROG, TOOL_VERSION))
######################################################################
# Description: Parse arguments
######################################################################
def parse_args(args):
mstdump_args = {DEVICE_KEY: "",
IS_FULL_KEY: 0,
I2C_SLAVE_KEY: None,
CAUSE_ADDR_KEY: -1,
CAUSE_ADDR_OFFSET: -1}
if len(args) < 2 or len(args) > 4:
return None
cause_idx = -1
for i in range(1, len(args)):
if args[i].startswith('-') and not args[i] in MSTDUMP_ARGS:
print_help_message()
sys.exit(1)
if args[i] == '-h' or args[i] == '-help' or args[i] == '--help':
print_help_message()
sys.exit(0)
elif args[i] == '-v' or args[i] == '-version' or args[i] == '--version':
print_version()
sys.exit(0)
elif '--cause' in args[i]:
cause = re.compile("--cause=[0-9a-fA-F]+\.[0-9a-fA-F]+")
if not cause.match(args[i]):
print("Invalid parameters to %s flag" % CAUSE_FLAG)
print_help_message()
sys.exit(1)
cause_addr = args[i].split(CAUSE_FLAG)[1].split('.')[0]
cause_offset = args[i].split(CAUSE_FLAG)[1].split('.')[1]
cause_idx = i
if cause_addr < 0 or cause_offset < 0:
print("Parameters to %s flag must be non-negative values" % CAUSE_FLAG)
sys.exit(1)
else:
mstdump_args[CAUSE_ADDR_KEY] = cause_addr
mstdump_args[CAUSE_ADDR_OFFSET] = cause_offset
is_full = 0
dev_idx = 1
if args[1] == '-full':
is_full = 1
dev_idx = 2
mstdump_args[IS_FULL_KEY] = is_full
if is_full and len(args) < 3:
print("Device is not specified in command line. Exiting.")
print_help_message()
sys.exit(1)
else:
mstdump_args[DEVICE_KEY] = args[dev_idx]
if dev_idx < len(args) - 1:
if cause_idx != -1 and cause_idx < len(args) - 1:
i2c_slave_idx = cause_idx + 1
else:
i2c_slave_idx = len(args) - 1
mstdump_args[I2C_SLAVE_KEY] = args[i2c_slave_idx]
return mstdump_args
######################################################################
# Description: Build and run the mlxdump command
######################################################################
def check_args(mstdump_args):
ret = 0
if mstdump_args is None:
print("-E- No mstdump_args were passed")
return 1
if mstdump_args[DEVICE_KEY] is None:
print("-E- Please supply an mst device")
ret = 1
return ret
######################################################################
# Description: Build and run the mlxdump command
######################################################################
def run_mlxdump(mstdump_args):
try:
MFT_BIN_DIR = os.environ['MFT_BIN_DIR'] + os.sep
except:
MFT_BIN_DIR = ""
executbale_path = MFT_BIN_DIR + "mlxdump"
sub_command_str = "mstdump"
device_str = "-d %s" % mstdump_args[DEVICE_KEY]
full_str = ""
if mstdump_args[IS_FULL_KEY] == 1:
full_str = "--full"
cause_str = ""
if mstdump_args[CAUSE_ADDR_KEY] != -1 and mstdump_args[CAUSE_ADDR_OFFSET] != -1:
cause_str = "--cause_address %s --cause_offset %s" % (mstdump_args[CAUSE_ADDR_KEY],
mstdump_args[CAUSE_ADDR_OFFSET])
try:
i2c_slave_str = ""
if mstdump_args[I2C_SLAVE_KEY] is not None:
i2c_slave_str = "--i2c_slave %s" % str(eval(mstdump_args[I2C_SLAVE_KEY]))
except:
print("Invalid i2c-slave %s" % mstdump_args[I2C_SLAVE_KEY])
sys.exit(1)
mlxdump_cmd = "%s %s %s %s %s %s" % (executbale_path, device_str, sub_command_str, full_str, cause_str,
i2c_slave_str)
return cmd_exec(mlxdump_cmd)
######################################################################
# Description: Modify the output of mlxdump and get the needed part
######################################################################
def modify_output(mlxdump_output):
data = mlxdump_output.splitlines(True)
for line in data[3:]:
print(line.strip())
######################################################################
# Description: Modify the output of mlxdump and get the needed part
######################################################################
def modify_error_message(err_msg, parsed_arguments):
if "Failed to open device:" in err_msg:
return "Unable to open device %s. Exiting." % parsed_arguments[DEVICE_KEY]
return err_msg
######################################################################
# Description: Main
######################################################################
if __name__ == "__main__":
if platform.system() != "Windows" and os.geteuid() != 0:
print("-E- Permission denied: User is not root")
sys.exit(1)
parsed_arguments = parse_args(sys.argv)
if check_args(parsed_arguments):
sys.exit(1)
rc, output, err = run_mlxdump(parsed_arguments)
if rc:
print(modify_error_message(output, parsed_arguments))
sys.exit(1)
modify_output(output)