diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py index 4525987736..005fdd15b2 100755 --- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py @@ -18,6 +18,7 @@ try: from sonic_platform.fan import Fan from sonic_platform.psu import Psu from sonic_platform.thermal import Thermal + from sonic_platform.component import Component except ImportError as e: raise ImportError(str(e) + "- required module not found") @@ -25,17 +26,7 @@ except ImportError as e: MAX_S6000_FAN = 3 MAX_S6000_PSU = 2 MAX_S6000_THERMAL = 10 - -BIOS_QUERY_VERSION_COMMAND = "dmidecode -s system-version" -#components definitions -COMPONENT_BIOS = "BIOS" -COMPONENT_CPLD1 = "CPLD1" -COMPONENT_CPLD2 = "CPLD2" -COMPONENT_CPLD3 = "CPLD3" - -CPLD1_VERSION = 'system_cpld_ver' -CPLD2_VERSION = 'master_cpld_ver' -CPLD3_VERSION = 'slave_cpld_ver' +MAX_S6000_COMPONENT = 4 class Chassis(ChassisBase): @@ -87,11 +78,9 @@ class Chassis(ChassisBase): thermal = Thermal(i) self._thermal_list.append(thermal) - # Initialize component list - self._component_name_list.append(COMPONENT_BIOS) - self._component_name_list.append(COMPONENT_CPLD1) - self._component_name_list.append(COMPONENT_CPLD2) - self._component_name_list.append(COMPONENT_CPLD3) + for i in range(MAX_S6000_COMPONENT): + component = Component(i) + self._component_list.append(component) def _get_cpld_register(self, reg_name): rv = 'ERR' @@ -178,7 +167,7 @@ class Chassis(ChassisBase): Returns: A dictionary where keys are the type code defined in - OCP ONIE TlvInfo EEPROM format and values are their + OCP ONIE TlvInfo EEPROM format and values are their corresponding values. """ return self.sys_eeprom.system_eeprom_info() @@ -200,46 +189,6 @@ class Chassis(ChassisBase): return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None) - def _get_command_result(self, cmdline): - try: - proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE, - shell=True, stderr=subprocess.STDOUT) - stdout = proc.communicate()[0] - proc.wait() - result = stdout.rstrip('\n') - except OSError: - result = '' - - return result - - def _get_cpld_version(self,cpld_name): - """ - Cpld Version - """ - cpld_ver = int(self._get_cpld_register(cpld_name),16) - return cpld_ver - - def get_firmware_version(self, component_name): - """ - Retrieves platform-specific hardware/firmware versions for - chassis componenets such as BIOS, CPLD, FPGA, etc. - Args: - component_name: A string, the component name. - Returns: - A string containing platform-specific component versions - """ - if component_name in self._component_name_list : - if component_name == COMPONENT_BIOS: - return self._get_command_result(BIOS_QUERY_VERSION_COMMAND) - elif component_name == COMPONENT_CPLD1: - return self._get_cpld_version(CPLD1_VERSION) - elif component_name == COMPONENT_CPLD2: - return self._get_cpld_version(CPLD2_VERSION) - elif component_name == COMPONENT_CPLD3: - return self._get_cpld_version(CPLD3_VERSION) - - return None - def _get_transceiver_status(self): presence_ctrl = self.sfp_control + 'qsfp_modprs' try: diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/component.py new file mode 100644 index 0000000000..daa30eaafa --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/component.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python + +######################################################################## +# DELLEMC S6000 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, etc.) available in +# the platform +# +######################################################################## + +try: + import os + import subprocess + from sonic_platform_base.component_base import ComponentBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BIOS_QUERY_VERSION_COMMAND = "dmidecode -s system-version" + + +class Component(ComponentBase): + """DellEMC Platform-specific Component class""" + + CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0" + + CHASSIS_COMPONENTS = [ + ["BIOS", ("Performs initialization of hardware components during " + "booting")], + ["System-CPLD", "Used for managing CPU board devices and power"], + ["Master-CPLD", ("Used for managing Fan, PSU, system LEDs, QSFP " + "modules (1-16)")], + ["Slave-CPLD", "Used for managing QSFP modules (17-32)"] + ] + + def __init__(self, component_index): + self.index = component_index + self.name = self.CHASSIS_COMPONENTS[self.index][0] + self.description = self.CHASSIS_COMPONENTS[self.index][1] + + def _get_cpld_register(self, reg_name): + rv = 'ERR' + mb_reg_file = self.CPLD_DIR+'/'+reg_name + + if (not os.path.isfile(mb_reg_file)): + return rv + + try: + with open(mb_reg_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _get_command_result(self, cmdline): + try: + proc = subprocess.Popen(cmdline.split(), stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.rstrip('\n') + except OSError: + result = None + + return result + + def _get_cpld_version(self, cpld_number): + cpld_version_reg = { + 1: "system_cpld_ver", + 2: "master_cpld_ver", + 3: "slave_cpld_ver" + } + + cpld_version = self._get_cpld_register(cpld_version_reg[cpld_number]) + + if cpld_version != 'ERR': + return str(int(cpld_version, 16)) + else: + return 'NA' + + def get_name(self): + """ + Retrieves the name of the component + + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + + Returns: + A string containing the firmware version of the component + """ + if self.index == 0: + bios_ver = self._get_command_result(BIOS_QUERY_VERSION_COMMAND) + + if not bios_ver: + return 'NA' + else: + return bios_ver + + elif self.index <= 3: + return self._get_cpld_version(self.index) + + def install_firmware(self, image_path): + """ + Installs firmware to the component + + Args: + image_path: A string, path to firmware image + + Returns: + A boolean, True if install was successful, False if not + """ + return False diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py index fd9816d6ed..e39e8480e2 100755 --- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py @@ -10,11 +10,6 @@ try: import os - import sys - import click - import subprocess - import glob - import sonic_device_util from sonic_platform_base.platform_base import PlatformBase from sonic_platform_base.chassis_base import ChassisBase from sonic_platform.sfp import Sfp @@ -22,6 +17,7 @@ try: from sonic_platform.fan import Fan from sonic_platform.module import Module from sonic_platform.thermal import Thermal + from sonic_platform.component import Component from eeprom import Eeprom except ImportError as e: raise ImportError(str(e) + "- required module not found") @@ -30,12 +26,7 @@ MAX_S6100_MODULE = 4 MAX_S6100_FAN = 4 MAX_S6100_PSU = 2 MAX_S6100_THERMAL = 10 - -BIOS_QUERY_VERSION_COMMAND = "dmidecode -s system-version" -#components definitions -COMPONENT_BIOS = "BIOS" -SWITCH_CPLD = "CPLD" -SMF_FPGA = "FPGA1" +MAX_S6100_COMPONENT = 3 class Chassis(ChassisBase): @@ -80,10 +71,9 @@ class Chassis(ChassisBase): thermal = Thermal(i) self._thermal_list.append(thermal) - # Initialize component list - self._component_name_list.append(COMPONENT_BIOS) - self._component_name_list.append(SWITCH_CPLD) - self._component_name_list.append(SMF_FPGA) + for i in range(MAX_S6100_COMPONENT): + component = Component(i) + self._component_list.append(component) def _get_reboot_reason_smf_register(self): # Returns 0xAA on software reload @@ -111,19 +101,6 @@ class Chassis(ChassisBase): rv = rv.lstrip(" ") return rv - # Run bash command and print output to stdout - def run_command(self, command): - click.echo(click.style("Command: ", fg='cyan') + - click.style(command, fg='green')) - - proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) - (out, err) = proc.communicate() - - click.echo(out) - - if proc.returncode != 0: - sys.exit(proc.returncode) - def get_name(self): """ Retrieves the name of the chassis @@ -234,147 +211,3 @@ class Chassis(ChassisBase): return (self.reset_reason_dict[reset_reason], None) return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason") - - def _get_command_result(self, cmdline): - try: - proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE, - shell=True, stderr=subprocess.STDOUT) - stdout = proc.communicate()[0] - proc.wait() - result = stdout.rstrip('\n') - except OSError: - result = '' - - return result - - def _get_cpld_version(self): - io_resource = "/dev/port" - CPLD1_VERSION_ADDR = 0x100 - - fd = os.open(io_resource, os.O_RDONLY) - if (fd < 0): - return 'NA' - if (os.lseek(fd, CPLD1_VERSION_ADDR, os.SEEK_SET) - != CPLD1_VERSION_ADDR): - return 'NA' - - buf = os.read(fd, 1) - cpld_version = ord(buf) - os.close(fd) - - return "%d.%d" % (((cpld_version & 0xF0) >> 4), cpld_version & 0xF) - - def _get_fpga_version(self): - fpga_ver = float(self._get_pmc_register('smf_firmware_ver')) - return fpga_ver - - def get_firmware_version(self, component_name): - """ - Retrieves platform-specific hardware/firmware versions for - chassis componenets such as BIOS, CPLD, FPGA, etc. - Args: - component_name: A string, the component name. - Returns: - A string containing platform-specific component versions - """ - if component_name in self._component_name_list : - if component_name == COMPONENT_BIOS: - return self._get_command_result(BIOS_QUERY_VERSION_COMMAND) - elif component_name == SWITCH_CPLD: - return self._get_cpld_version() - elif component_name == SMF_FPGA: - return self._get_fpga_version() - - return None - - def install_component_firmware(self, component_name, image_path): - - bios_image = None - bios_version = "3.25.0." - bios_file_name = "S6100*BIOS*" - flashrom = "/usr/local/bin/flashrom" - PLATFORM_ROOT_PATH = '/usr/share/sonic/device' - machine_info = sonic_device_util.get_machine_info() - platform = sonic_device_util.get_platform_info(machine_info) - platform_path = "/".join([PLATFORM_ROOT_PATH, platform, "bin"]) - - warning = """ - ******************************************************************** - * Warning - Upgrading BIOS is inherently risky and should only be * - * attempted when necessary. A failure at this upgrade may cause * - * a board RMA. Proceed with caution ! * - ******************************************************************** - """ - - if component_name in self._component_name_list: - if component_name == COMPONENT_BIOS: # BIOS - - # current BIOS version - current_bios_version = self.get_firmware_version("BIOS") - - # Construct BIOS image path - if image_path is not None: - image_path = image_path + platform_path - for name in glob.glob( - os.path.join(image_path, bios_file_name)): - bios_image = image_path = name - - if not bios_image: - print "BIOS image file not found:", image_path - return False - - # Extract BIOS image version - bios_image = os.path.basename(bios_image) - bios_image = bios_image.strip('S6100-BIOS-') - bios_image_version = bios_image.strip('.bin') - - if bios_image_version.startswith(bios_version): - bios_image_minor = bios_image_version.replace( - bios_image_version[:7], '') - if bios_image_minor.startswith("2"): - bios_image_minor = bios_image_minor.split("-")[1] - - if current_bios_version.startswith(bios_version): - current_bios_minor = current_bios_version.replace( - current_bios_version[:7], '') - if current_bios_minor.startswith("2"): - current_bios_minor = current_bios_minor.split("-")[1] - - # BIOS version check - if bios_image_minor > current_bios_minor: - - print warning - prompt_text = "New BIOS image " + bios_image_version + \ - " available to install, continue?" - yes = click.confirm(prompt_text) - - elif current_bios_minor > bios_image_minor: - - print warning - prompt_text = "Do you want to downgrade BIOS image from " \ - + current_bios_version + " to " + \ - bios_image_version + " continue?" - - yes = click.confirm(prompt_text) - - else: - print("BIOS is already with {} latest version".format( - current_bios_version)) - return True - - if yes: - command = flashrom + " -p" + " internal" + " -w " + \ - image_path - self.run_command(command) - - elif component_name == SWITCH_CPLD: # CPLD - return False - - elif component_name == SMF_FPGA: # SMF - return False - else: - print "Invalid component Name:", component_name - - return True - - diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/component.py new file mode 100644 index 0000000000..a92ab5c85d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/component.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python + +######################################################################## +# DELLEMC S6100 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, etc.) available in +# the platform +# +######################################################################## + +try: + import os + import subprocess + from sonic_platform_base.component_base import ComponentBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BIOS_QUERY_VERSION_COMMAND = "dmidecode -s system-version" + + +class Component(ComponentBase): + """DellEMC Platform-specific Component class""" + + HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" + HWMON_NODE = os.listdir(HWMON_DIR)[0] + MAILBOX_DIR = HWMON_DIR + HWMON_NODE + + CHASSIS_COMPONENTS = [ + ["BIOS", ("Performs initialization of hardware components during " + "booting")], + ["CPLD", "Used for managing IO modules, SFP+ modules and system LEDs"], + ["FPGA", ("Platform management controller for on-board temperature " + "monitoring, in-chassis power, Fan and LED control")] + ] + MODULE_COMPONENT = [ + "IOM{}-CPLD", + "Used for managing QSFP+ modules ({0}-{1})" + ] + + def __init__(self, component_index=0, + is_module=False, iom_index=0, i2c_line=0): + + self.is_module_component = is_module + + if self.is_module_component: + self.index = iom_index + self.name = self.MODULE_COMPONENT[0].format(self.index) + self.description = self.MODULE_COMPONENT[1].format( + ((self.index - 1) * 16) + 1, self.index * 16) + self.cpld_version_file = ("/sys/class/i2c-adapter/i2c-{0}/{0}-003e" + "/iom_cpld_vers").format(i2c_line) + else: + self.index = component_index + self.name = self.CHASSIS_COMPONENTS[self.index][0] + self.description = self.CHASSIS_COMPONENTS[self.index][1] + + def _read_sysfs_file(self, sysfs_file): + # On successful read, returns the value read from given + # sysfs_file and on failure returns 'ERR' + rv = 'ERR' + + if (not os.path.isfile(sysfs_file)): + return rv + + try: + with open(sysfs_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _get_command_result(self, cmdline): + try: + proc = subprocess.Popen(cmdline.split(), stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.rstrip('\n') + except OSError: + result = None + + return result + + def _get_cpld_version(self): + io_resource = "/dev/port" + CPLD_VERSION_ADDR = 0x100 + + fd = os.open(io_resource, os.O_RDONLY) + if (fd < 0): + return 'NA' + + if (os.lseek(fd, CPLD_VERSION_ADDR, os.SEEK_SET) != CPLD_VERSION_ADDR): + os.close(fd) + return 'NA' + + buf = os.read(fd, 1) + cpld_version = str(ord(buf)) + os.close(fd) + + return cpld_version + + def _get_iom_cpld_version(self): + ver_str = self._read_sysfs_file(self.cpld_version_file) + if (ver_str != 'ERR'): + if ver_str == 'read error': + return 'NA' + + ver_str = ver_str.rstrip('\r\n') + cpld_version = str(int(ver_str.split(':')[1], 16)) + return cpld_version + else: + return 'NA' + + def _get_fpga_version(self): + fpga_ver_file = self.MAILBOX_DIR + '/smf_firmware_ver' + fpga_ver = self._read_sysfs_file(fpga_ver_file) + if (fpga_ver != 'ERR'): + return fpga_ver + else: + return 'NA' + + def get_name(self): + """ + Retrieves the name of the component + + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + + Returns: + A string containing the firmware version of the component + """ + if self.is_module_component: # IOM CPLD + return self._get_iom_cpld_version() + else: + if self.index == 0: # BIOS + bios_ver = self._get_command_result(BIOS_QUERY_VERSION_COMMAND) + + if not bios_ver: + return 'NA' + else: + return bios_ver + + elif self.index == 1: # SwitchCard CPLD + return self._get_cpld_version() + elif self.index == 2: # FPGA + return self._get_fpga_version() + + def install_firmware(self, image_path): + """ + Installs firmware to the component + + Args: + image_path: A string, path to firmware image + + Returns: + A boolean, True if install was successful, False if not + """ + return False diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/module.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/module.py index 6b950c4e83..265dc206ad 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/module.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/module.py @@ -13,6 +13,7 @@ try: import os from sonic_platform_base.module_base import ModuleBase from sonic_platform.sfp import Sfp + from sonic_platform.component import Component except ImportError as e: raise ImportError(str(e) + "- required module not found") @@ -54,16 +55,20 @@ class Module(ModuleBase): self.port_start = (self.index - 1) * 16 self.port_end = (self.index * 16) - 1 self.port_i2c_line = self.IOM_I2C_MAPPING[self.index] - self._component_name_list = ['CPLD'] self.eeprom_tlv_dict = dict() self.iom_status_reg = "iom_status" self.iom_presence_reg = "iom_presence" - # Overriding _sfp_list class variable defined in ModuleBase, to - # make it unique per Module object + # Overriding _component_list and _sfp_list class variables defined in + # ModuleBase, to make them unique per Module object + self._component_list = [] self._sfp_list = [] + component = Component(is_module=True, iom_index=self.index, + i2c_line=self.port_i2c_line) + self._component_list.append(component) + eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/i2c-{1}/{1}-0050/eeprom" sfp_ctrl_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-003e/" @@ -188,39 +193,3 @@ class Module(ModuleBase): ‘0x26’:’01’, ‘0x27’:’REV01’, ‘0x28’:’AG9064-C2358-16G’} """ return self.eeprom_tlv_dict - - def get_firmware_version(self, component_name): - """ - Retrieves platform-specific hardware/firmware versions for module - componenets such as BIOS, CPLD, FPGA, etc. - - Args: - component_name: A string, the component name. - - Returns: - A string containing platform-specific component versions - """ - if component_name == 'CPLD': - cpld_version_file = ("/sys/class/i2c-adapter/i2c-{0}/{0}-003e/" - "iom_cpld_vers").format(self.port_i2c_line) - - if (not os.path.isfile(cpld_version_file)): - return 'NA' - - try: - with open(cpld_version_file, 'r') as fd: - ver_str = fd.read() - except Exception as error: - return 'NA' - - if ver_str == 'read error': - return 'NA' - - ver_str = ver_str.rstrip('\r\n') - cpld_version = int(ver_str.split(':')[1], 16) - major_version = (cpld_version & 0xF0) >> 4 - minor_version = cpld_version & 0xF - - return "%d.%d" % (major_version, minor_version) - else: - return 'NA' diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py index c3568b3b1e..3472bb3e7f 100755 --- a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py @@ -17,6 +17,7 @@ try: from sonic_platform.fan import Fan from sonic_platform.psu import Psu from sonic_platform.thermal import Thermal + from sonic_platform.component import Component from eeprom import Eeprom except ImportError as e: raise ImportError(str(e) + "- required module not found") @@ -26,15 +27,7 @@ MAX_Z9100_FANTRAY = 5 MAX_Z9100_FAN = 2 MAX_Z9100_PSU = 2 MAX_Z9100_THERMAL = 8 - -BIOS_QUERY_VERSION_COMMAND = "dmidecode -s system-version" -#components definitions -COMPONENT_BIOS = "BIOS" -SWITCH_CPLD1 = "CPLD1" -SWITCH_CPLD2 = "CPLD2" -SWITCH_CPLD3 = "CPLD3" -SWITCH_CPLD4 = "CPLD4" -SMF_FPGA = "FPGA1" +MAX_Z9100_COMPONENT = 6 class Chassis(ChassisBase): @@ -115,13 +108,9 @@ class Chassis(ChassisBase): thermal = Thermal(i) self._thermal_list.append(thermal) - # Initialize component list - self._component_name_list.append(COMPONENT_BIOS) - self._component_name_list.append(SWITCH_CPLD1) - self._component_name_list.append(SWITCH_CPLD2) - self._component_name_list.append(SWITCH_CPLD3) - self._component_name_list.append(SWITCH_CPLD4) - self._component_name_list.append(SMF_FPGA) + for i in range(MAX_Z9100_COMPONENT): + component = Component(i) + self._component_list.append(component) def _get_pmc_register(self, reg_name): # On successful read, returns the value read from given @@ -241,82 +230,3 @@ class Chassis(ChassisBase): return (self.reset_reason_dict[reset_reason], None) return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason") - - def _get_command_result(self, cmdline): - try: - proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE, - shell=True, stderr=subprocess.STDOUT) - stdout = proc.communicate()[0] - proc.wait() - result = stdout.rstrip('\n') - except OSError: - result = '' - - return result - - def _get_cpld_version(self,cpld_number): - io_resource = "/dev/port" - CPLD1_VERSION_ADDR = 0x100 - - if (cpld_number == 1): - fd = os.open(io_resource, os.O_RDONLY) - if (fd < 0): - return 'NA' - if (os.lseek(fd, CPLD1_VERSION_ADDR, os.SEEK_SET) - != CPLD1_VERSION_ADDR): - return 'NA' - - buf = os.read(fd, 1) - cpld_version = ord(buf) - os.close(fd) - - return "%d.%d" % (((cpld_version & 0xF0) >> 4), cpld_version & 0xF) - else: - cpld_version_file = ("/sys/class/i2c-adapter/i2c-{0}/{0}-003e" - "/iom_cpld_vers").format(12 + cpld_number) - - if (not os.path.isfile(cpld_version_file)): - return 'NA' - - try: - with open(cpld_version_file, 'r') as fd: - ver_str = fd.read() - except Exception as error: - return 'NA' - - if ver_str == "read error": - return 'NA' - else: - ver_str = ver_str.rstrip("\r\n") - cpld_version = int(ver_str.split(":")[1], 16) - - return "%d.%d" % (((cpld_version & 0xF0) >> 4), cpld_version & 0xF) - - def _get_fpga_version(self): - fpga_ver = float(self._get_pmc_register('smf_firmware_ver')) - return fpga_ver - - def get_firmware_version(self, component_name): - """ - Retrieves platform-specific hardware/firmware versions for chassis - componenets such as BIOS, CPLD, FPGA, etc. - Args: - component_name: A string, the component name. - Returns: - A string containing platform-specific component versions - """ - if component_name in self._component_name_list : - if component_name == COMPONENT_BIOS: - return self._get_command_result(BIOS_QUERY_VERSION_COMMAND) - elif component_name == SWITCH_CPLD1: - return self._get_cpld_version(1) - elif component_name == SWITCH_CPLD2: - return self._get_cpld_version(2) - elif component_name == SWITCH_CPLD3: - return self._get_cpld_version(3) - elif component_name == SWITCH_CPLD4: - return self._get_cpld_version(4) - elif component_name == SMF_FPGA: - return self._get_fpga_version() - - return None diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/component.py new file mode 100644 index 0000000000..dccb8f6ac2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/component.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python + +######################################################################## +# DELLEMC Z9100 +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, etc.) available in +# the platform +# +######################################################################## + +try: + import os + import subprocess + from sonic_platform_base.component_base import ComponentBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +BIOS_QUERY_VERSION_COMMAND = "dmidecode -s system-version" + + +class Component(ComponentBase): + """DellEMC Platform-specific Component class""" + + HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" + HWMON_NODE = os.listdir(HWMON_DIR)[0] + MAILBOX_DIR = HWMON_DIR + HWMON_NODE + + CHASSIS_COMPONENTS = [ + ["BIOS", ("Performs initialization of hardware components during " + "booting")], + ["CPLD1", "Used for managing the system LEDs"], + ["CPLD2", "Used for managing QSFP28 modules (1-12)"], + ["CPLD3", "Used for managing QSFP28 modules (13-22)"], + ["CPLD4", ("Used for managing QSFP28 modules (23-32) and SFP+ " + "modules")], + ["FPGA", ("Platform management controller for on-board temperature " + "monitoring, in-chassis power, Fan and LED control")] + ] + + def __init__(self, component_index=0): + self.index = component_index + self.name = self.CHASSIS_COMPONENTS[self.index][0] + self.description = self.CHASSIS_COMPONENTS[self.index][1] + + def _read_sysfs_file(self, sysfs_file): + # On successful read, returns the value read from given + # sysfs_file and on failure returns 'ERR' + rv = 'ERR' + + if (not os.path.isfile(sysfs_file)): + return rv + + try: + with open(sysfs_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _get_command_result(self, cmdline): + try: + proc = subprocess.Popen(cmdline.split(), stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.rstrip('\n') + except OSError: + result = None + + return result + + def _get_cpld_version(self, cpld_number): + io_resource = "/dev/port" + CPLD1_VERSION_ADDR = 0x100 + + if (cpld_number == 1): + fd = os.open(io_resource, os.O_RDONLY) + if (fd < 0): + return 'NA' + + if (os.lseek(fd, CPLD1_VERSION_ADDR, os.SEEK_SET) + != CPLD1_VERSION_ADDR): + os.close(fd) + return 'NA' + + buf = os.read(fd, 1) + cpld_version = str(ord(buf)) + os.close(fd) + + return cpld_version + else: + cpld_version_file = ("/sys/class/i2c-adapter/i2c-{0}/{0}-003e" + "/iom_cpld_vers").format(12 + cpld_number) + ver_str = self._read_sysfs_file(cpld_version_file) + + if (ver_str == "read error") or (ver_str == 'ERR'): + return 'NA' + + ver_str = ver_str.rstrip("\r\n") + cpld_version = str(int(ver_str.split(":")[1], 16)) + + return cpld_version + + def _get_fpga_version(self): + fpga_ver_file = self.MAILBOX_DIR + '/smf_firmware_ver' + fpga_ver = self._read_sysfs_file(fpga_ver_file) + if (fpga_ver != 'ERR'): + return fpga_ver + else: + return 'NA' + + def get_name(self): + """ + Retrieves the name of the component + + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + + Returns: + A string containing the firmware version of the component + """ + if self.index == 0: # BIOS + bios_ver = self._get_command_result(BIOS_QUERY_VERSION_COMMAND) + + if not bios_ver: + return 'NA' + else: + return bios_ver + + elif self.index < 5: # CPLD + return self._get_cpld_version(self.index) + elif self.index == 5: # FPGA + return self._get_fpga_version() + + def install_firmware(self, image_path): + """ + Installs firmware to the component + + Args: + image_path: A string, path to firmware image + + Returns: + A boolean, True if install was successful, False if not + """ + return False