DellEMC : Platform2.0 API Implementation for Component [S6000, S6100, Z9100] (#3588)

This commit is contained in:
Arun Saravanan Balachandran 2019-10-17 06:27:32 +05:30 committed by Joe LeVeque
parent 2d87ca4a18
commit ee4ca2c0c5
7 changed files with 495 additions and 363 deletions

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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'

View File

@ -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

View File

@ -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