From f0c0fac1627d526b9d4ce25ee806e4026090e38b Mon Sep 17 00:00:00 2001 From: Arun Saravanan Balachandran <52521751+ArunSaravananBalachandran@users.noreply.github.com> Date: Wed, 7 Aug 2019 04:23:07 +0530 Subject: [PATCH] DellEMC S6000 : Platform2.0 API implementation for EEPROM (#3295) --- .../s6000/sonic_platform/eeprom.py | 201 ++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py new file mode 100644 index 0000000000..b39b140c72 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC S6000 +# +# Module contains platform specific implementation of SONiC Platform +# Base API and provides the EEPROMs' information. +# +# The different EEPROMs available are as follows: +# - System EEPROM : Contains Serial number, Service tag, Base MA +# address, etc. in ONIE TlvInfo EEPROM format. +# - PSU EEPROM : Contains Serial number, Part number, Service Tag, +# PSU type, Revision. +# - Fan EEPROM : Contains Serial number, Part number, Service Tag, +# Fan type, Number of Fans in Fantray, Revision. +######################################################################## + + +try: + import os + from sonic_platform_base.sonic_eeprom.eeprom_base import EepromDecoder + from sonic_platform_base.sonic_eeprom.eeprom_tlvinfo import TlvInfoDecoder +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +# PSU eeprom fields in format required by EepromDecoder +psu_eeprom_format = [ + ('PPID', 's', 20), ('DPN Rev', 's', 3), ('Service Tag', 's', 7), + ('Part Number', 's', 10), ('Part Num Revision', 's', 3), + ('Mfg Test', 's', 2), ('PSU Type', 's', 1), ('Fab Rev', 's', 2) + ] + +# Fan eeprom fields in format required by EepromDecoder +fan_eeprom_format = [ + ('PPID', 's', 20), ('DPN Rev', 's', 3), ('Service Tag', 's', 7), + ('Part Number', 's', 10), ('Part Num Revision', 's', 3), + ('Mfg Test', 's', 2), ('Number of Fans', 's', 2), ('Fan Type', 's', 1), + ('Fab Rev', 's', 2) + ] + + +class Eeprom(TlvInfoDecoder): + """DellEMC Platform-specific EEPROM class""" + + I2C_DIR = "/sys/class/i2c-adapter/" + + def __init__(self, is_psu=False, psu_index=0, is_fan=False, fan_index=0): + self.is_psu_eeprom = is_psu + self.is_fan_eeprom = is_fan + self.is_sys_eeprom = not (is_psu | is_fan) + + if self.is_sys_eeprom: + self.start_offset = 0 + self.eeprom_path = self.I2C_DIR + "i2c-10/10-0053/eeprom" + # System EEPROM is in ONIE TlvInfo EEPROM format + super(Eeprom, self).__init__(self.eeprom_path, + self.start_offset, '', True) + self._load_system_eeprom() + else: + self.start_offset = 6 + if self.is_psu_eeprom: + self.index = psu_index + self.eeprom_path = self.I2C_DIR \ + + "i2c-1/1-005{}/eeprom".format(2 - self.index) + self.format = psu_eeprom_format + else: + self.index = fan_index + self.eeprom_path = self.I2C_DIR \ + + "i2c-11/11-005{}/eeprom".format(4 - self.index) + self.format = fan_eeprom_format + EepromDecoder.__init__(self, self.eeprom_path, self.format, + self.start_offset, '', True) + self._load_device_eeprom() + + def _load_system_eeprom(self): + """ + Reads the system EEPROM and retrieves the values corresponding + to the codes defined as per ONIE TlvInfo EEPROM format and fills + them in a dictionary. + """ + try: + # Read System EEPROM as per ONIE TlvInfo EEPROM format. + self.eeprom_data = self.read_eeprom() + except: + self.base_mac = 'NA' + self.serial_number = 'NA' + self.part_number = 'NA' + self.eeprom_tlv_dict = dict() + else: + eeprom = self.eeprom_data + self.eeprom_tlv_dict = dict() + + if not self.is_valid_tlvinfo_header(eeprom): + self.base_mac = 'NA' + self.serial_number = 'NA' + self.part_number = 'NA' + return + + total_length = (ord(eeprom[9]) << 8) | ord(eeprom[10]) + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + ord(eeprom[tlv_index + 1])] + code = "0x%02X" % (ord(tlv[0])) + + if ord(tlv[0]) == self._TLV_CODE_VENDOR_EXT: + value = str((ord(tlv[2]) << 24) | (ord(tlv[3]) << 16) | + (ord(tlv[4]) << 8) | ord(tlv[5])) + value += str(tlv[6:6 + ord(tlv[1])]) + else: + name, value = self.decoder(None, tlv) + + self.eeprom_tlv_dict[code] = value + if ord(eeprom[tlv_index]) == self._TLV_CODE_CRC_32: + break + + tlv_index += ord(eeprom[tlv_index+1]) + 2 + + self.base_mac = self.eeprom_tlv_dict.get( + hex(self._TLV_CODE_MAC_BASE), 'NA') + self.serial_number = self.eeprom_tlv_dict.get( + hex(self._TLV_CODE_SERIAL_NUMBER), 'NA') + self.part_number = self.eeprom_tlv_dict.get( + hex(self._TLV_CODE_PART_NUMBER), 'NA') + + def _load_device_eeprom(self): + """ + Reads the Fan/PSU EEPROM and retrieves the serial number and + model number of the device. + """ + try: + # Read Fan/PSU EEPROM as per the specified format. + self.eeprom_data = EepromDecoder.read_eeprom(self) + except: + self.serial_number = 'NA' + self.part_number = 'NA' + else: + (valid, data) = self._get_eeprom_field("PPID") + if valid: + ppid = data + self.serial_number = (ppid[:2] + "-" + ppid[2:8] + "-" + + ppid[8:13] + "-" + ppid[13:16] + + "-" + ppid[16:]) + (valid, data) = self._get_eeprom_field("DPN Rev") + if valid: + self.serial_number += "-" + data + else: + seld.serial_number = 'NA' + + (valid, data) = self._get_eeprom_field("Part Number") + if valid: + self.part_number = data + else: + self.part_number = 'NA' + + def _get_eeprom_field(self, field_name): + """ + For a field name specified in the EEPROM format, returns the + presence of the field and the value for the same. + """ + field_start = 0 + for field in self.format: + field_end = field_start + field[2] + if field[0] == field_name: + return (True, self.eeprom_data[field_start:field_end]) + field_start = field_end + + return (False, None) + + def serial_number_str(self): + """ + Returns the serial number. + """ + return self.serial_number + + def part_number_str(self): + """ + Returns the part number. + """ + return self.part_number + + # System EEPROM specific methods + def base_mac_addr(self): + """ + Returns the base MAC address found in the system EEPROM. + """ + return self.base_mac + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.eeprom_tlv_dict