diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py index b18d780fab..341a4407fe 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py @@ -26,6 +26,23 @@ MAX_SELECT_DELAY = 3600 MLNX_NUM_PSU = 2 +DMI_FILE = '/sys/firmware/dmi/entries/2-0/raw' +DMI_HEADER_LEN = 15 +DMI_PRODUCT_NAME = "Product Name" +DMI_MANUFACTURER = "Manufacturer" +DMI_VERSION = "Version" +DMI_SERIAL = "Serial Number" +DMI_ASSET_TAG = "Asset Tag" +DMI_LOC = "Location In Chassis" +DMI_TABLE_MAP = { + DMI_PRODUCT_NAME: 0, + DMI_MANUFACTURER: 1, + DMI_VERSION: 2, + DMI_SERIAL: 3, + DMI_ASSET_TAG: 4, + DMI_LOC: 5 + } + EEPROM_CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' EEPROM_CACHE_FILE = 'syseeprom_cache' @@ -67,6 +84,9 @@ class Chassis(ChassisBase): # Initialize Platform name self.platform_name = device_info.get_platform() + # Initialize DMI data + self.dmi_data = None + # move the initialization of each components to their dedicated initializer # which will be called from platform # @@ -240,6 +260,18 @@ class Chassis(ChassisBase): string: Model/part number of device """ return self.model + + def get_revision(self): + """ + Retrieves the hardware revision of the device + + Returns: + string: Revision value of device + """ + if self.dmi_data is None: + self.dmi_data = self._parse_dmi(DMI_FILE) + + return self.dmi_data.get(DMI_VERSION, "N/A") ############################################## # SFP methods @@ -394,6 +426,31 @@ class Chassis(ChassisBase): return '0' + def _parse_dmi(self, filename): + """ + Read DMI data chassis data and returns a dictionary of values + + Returns: + A dictionary containing the dmi table of the switch chassis info + """ + result = {} + try: + fileobj = open(filename, "rb") + data = fileobj.read() + fileobj.close() + + body = data[DMI_HEADER_LEN:] + records = body.split(b'\x00') + + for k, v in DMI_TABLE_MAP.items(): + result[k] = records[v].decode("utf-8") + + except Exception as e: + logger.log_error("Fail to decode DMI {} due to {}".format(filename, repr(e))) + + return result + + def _verify_reboot_cause(self, filename): ''' Open and read the reboot cause file in diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py b/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py index 12b7a35b7a..e357a39141 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py @@ -31,6 +31,7 @@ PSU_VPD = "vpd" SN_VPD_FIELD = "SN_VPD_FIELD" PN_VPD_FIELD = "PN_VPD_FIELD" +REV_VPD_FIELD = "REV_VPD_FIELD" # in most platforms the file psuX_curr, psuX_volt and psuX_power contain current, voltage and power data respectively. # but there are exceptions which will be handled by the following dictionary @@ -105,6 +106,12 @@ class Psu(PsuBase): self.serial = "" logger.log_error("Fail to read PSU{} serial number: No key {} in VPD {}".format(self.index, SN_VPD_FIELD, self.psu_vpd)) + if REV_VPD_FIELD in self.vpd_data: + self.rev = self.vpd_data[REV_VPD_FIELD] + else: + self.rev = "" + logger.log_error("Fail to read PSU{} serial number: No key {} in VPD {}".format(self.index, REV_VPD_FIELD, self.psu_vpd)) + else: logger.log_info("Not reading PSU{} VPD data: Platform is fixed".format(self.index)) @@ -210,6 +217,16 @@ class Psu(PsuBase): return self.serial + def get_revision(self): + """ + Retrieves the hardware revision of the device + + Returns: + string: Revision value of device + """ + return self.rev + + def get_powergood_status(self): """ Retrieves the operational status of power supply unit (PSU) defined