sonic-buildimage/device/arista/x86_64-arista_7050_qx32/plugins/eeprom.py
Joe LeVeque 2a551d3c60 Consolidate device-specific files; install as a Debian package (#316)
( All device-specific files now reside under /device directory in a <vendor-name>/<platform-string>/<hardware-SKU> directory structure in repo.

* Device-specific files are now packaged into a Debian package (sonic-device-data) and are now installed to /usr/share/sonic/device/<platform-string>/<hardware-SKU>/ directory on switch.
2017-02-27 00:13:36 -08:00

221 lines
6.9 KiB
Python

#!/usr/bin/env python
#############################################################################
# Arista 7050-QX32
#
# Platform and model specific eeprom subclass, inherits from the base class,
# and provides the followings:
# - the eeprom format definition
# - specific encoder/decoder if there is special need
#############################################################################
try:
import exceptions
import binascii
import time
import optparse
import warnings
import os
import sys
import subprocess
import re
import struct
import zlib
import StringIO
from sonic_eeprom import eeprom_base
from sonic_eeprom import eeprom_tlvinfo
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
def showMac( m ):
return ":".join([m[0:2], m[2:4], m[4:6], m[6:8], m[8:10], m[10:12]])
typeMap = {
"END" : ( "00", None, None, None, False ),
"SKU" : ( "03", None, None, None, False ),
"MAC" : ( "05", None, showMac, None, False ),
"SerialNumber" : ( "0E", None, None, None, False ),
}
idToNameMap = {}
for k, v in typeMap.iteritems():
idToNameMap[ v[0] ] = k
class board(eeprom_tlvinfo.TlvInfoDecoder):
_TLV_INFO_MAX_LEN = 256
_TLV_HDR_ENABLED = 0
pFdl = None
def __init__(self, name, path, cpld_root, ro):
self.eeprom_path = "/sys/bus/i2c/drivers/eeprom/1-0052/eeprom"
super(board, self).__init__(self.eeprom_path, 0, '', True)
def _decode_eeprom(self, e):
# For format 0002 and more recent fdls use the new Prefdl class
data = e[0:4]
if data in ("0002", "0003"):
fp = StringIO.StringIO(e[4:])
self.pFdl = PreFdl( fp, data, data )
def decode_eeprom(self, e):
self._decode_eeprom(e)
return self.pFdl.show()
def is_checksum_valid(self, e):
self._decode_eeprom(e)
return (True, self.pFdl.get_crc())
def serial_number_str(self, e):
self._decode_eeprom(e)
return self.pFdl.get_field('SerialNumber')
def mgmtaddrstr(self,e):
self._decode_eeprom(e)
return self.pFdl.get_field('MAC')
def crc32( data ):
return struct.unpack("I",struct.pack("i",zlib.crc32( data )))[0]
def validSerial( x ):
x = x.replace( " ", "" )
x = x.replace( "-", "" )
# All serial numbers are upper case
x = x.upper()
if re.compile( "[A-Z]{3}\d{4}[A-Z0-9]{4}$" ).match( x ):
return x
return None
class PreFdlField( ):
def __init__( self, name, valid, show, optionName, data=None, append=False ):
self.name = name
if valid:
self.valid = valid
else:
self.valid = lambda x: x
self.show = show
self.optionName = optionName
self.data = []
self.append = append
if data:
self.dataIs( data )
def dataIs( self, data ):
vd = self.valid( data )
if not vd:
raise InvalidPrefdlData( "Invalid %s: %s" % ( self.name, data ) )
if self.append:
self.data.append( vd )
else:
self.data = [ vd ]
class TlvField( PreFdlField ):
def __init__( self, name ):
args = typeMap.get( name )
valid = None
show = None
optionName = None
append = False
if args:
self.id, valid, show, optionName, append = args
PreFdlField.__init__( self, name, valid, show, optionName, append=append )
class PreFdl():
def __init__( self, fp=None, preFdlStr=None, version="0002" ):
# populate the required fields
self.requiredFields = []
self.mac = None
self.serial = None
if version == "0002":
preFdlStr, offset = self.initPreFdl2( fp, preFdlStr )
elif version == "0003":
preFdlStr, offset = self.initPreFdl3( fp, preFdlStr )
else:
raise NotImplementedError(
"Only Prefdl data format version 0002 or 0003 are supported" )
# populate the tlv fileds
self.tlvFields = {}
for k in typeMap.keys():
self.tlvFields[ k ] = TlvField( k )
# create the map option to field
self.optionMap = {}
for f in self.requiredFields + self.tlvFields.values():
# Do not add the option from TLV if already added by required fields
if f.optionName and f.optionName not in self.optionMap:
self.optionMap[ f.optionName ] = f
# save the current tlv fields
if fp:
while True:
tlv = fp.read( 6 )
( id, lengthStr ) = ( tlv[0:2], tlv[2:6] )
length = int( lengthStr, base=16 )
bytes = fp.read( length )
what = None if id not in idToNameMap.keys() else idToNameMap[ id ]
if what and what != "END":
self.tlvFields[ what ].dataIs( bytes )
preFdlStr += tlv + bytes
offset += 6 + length
if what == "END":
# End of the tlv list
break
self.crc = fp.read( 8 )
# Check the CRC
computed = crc32( preFdlStr )
if int( self.crc, 16 ) != computed:
raise Exception( "Invalid CRC -- saw %s expected %8X" %
( self.crc, computed ) )
# Initialize and parse fixed section for prefdl version 2. Return the offset
# to where the TLV section starts.
def initPreFdl2( self, fp, preFdlStr ):
# if we start with an existing file
if fp:
# if no preFdlStr is specified, read the fixed section, 30 bytes.
# Otherwise, only the 4 byte data version section was written and
# read the remaining 26 bytes from the fixed section.
if not preFdlStr:
preFdlStr = fp.read( 30 ).strip()
elif preFdlStr == "0002":
preFdlStr += fp.read( 26 ).strip()
else:
raise ValueError( "preFdlStr arg has invalid data format" )
if len( preFdlStr ) < 12:
fatal( "prefdl is too short exiting" )
data = None if not preFdlStr else preFdlStr[ 16:16 + 11 ]
self.requiredFields.append(
PreFdlField( "SerialNumber", validSerial, None, None, data ) )
return preFdlStr, 30
# Initialize and parse fixed section for prefdl version 3. Return the offset
# to where the TLV section starts.
def initPreFdl3( self, fp, preFdlStr ):
# if we start with an existing file
currPtr = 0
if fp and not preFdlStr:
preFdlStr = fp.read( 4 ).strip()
if len( preFdlStr ) < 4:
fatal( "prefdl is too short exiting" )
return preFdlStr, 4
def show( self ):
for f in self.requiredFields + self.tlvFields.values():
for d in f.data:
dStr = d if f.show is None else f.show( d )
print "%s: %s" % ( f.name, dStr )
def get_field( self, name ):
for f in self.requiredFields + self.tlvFields.values():
for d in f.data:
if f.name == name:
dStr = d if f.show is None else f.show( d )
return dStr
def get_crc( self ):
return self.crc