#!/usr/bin/env python3
# Copyright (c) 2006, 2010 Arastra, Inc.  All rights reserved.
# Arastra, Inc. Confidential and Proprietary.

# pylint: disable=consider-using-f-string

import seeprom
import array, optparse, sys, tempfile, Tac # pylint: disable=deprecated-module
import os

usage = """
macseeprom [options] read 
macseeprom [options] write xx:xx:xx:xx:xx:xx

  Read or write the mac serial eeprom with <address>.  The format of <address> is:

        xx:xx:xx:xx:xx:xx or xx-xx-xx-xx-xx-xx

  All numeric arguments can be specified in decimal, hex (prefixed by
  '0x'), or binary (prefixed by '0b')."""

parser = optparse.OptionParser(usage=usage)
parser.add_option( "-u", "--unlock", action="store_true",
                   help="unlock the mac seeprom" )
parser.add_option("--system", action="store", default='napa',
                  help="The system type")
( options, args ) = parser.parse_args()
if len( args ) < 1:
   parser.error( "Too few arguments" )

class Napa:
   def __init__( self ):
      self.busId = 1
      self.seepromId = 0x51
   def read( self ):
      result = seeprom.doRead( self.busId, self.seepromId, offset=0, length=6 )
      result = array.array('B', result)
      result.reverse()
      print( ":".join( [ "%02x" % i for i in result ] ) )
   def write( self, rawData ):
      data = [ int(i, 16) for i in re.split( "[:-]", rawData ) ]
      data.reverse()
      if len( data ) != 6:
         parser.error( "Illegal mac address format '" + data + "'" )
      data = "".join( ["%c" % i for i in data] )
      seeprom.doWrite( self.busId, self.seepromId, 0, data, options.unlock )

class BodegaRavenCrow:
   def __init__( self ):
      self.busId = 1
      self.seepromId = 0x51
   def read( self ):
      result = seeprom.doRead( self.busId, self.seepromId, offset=0, length=16 )
      result = array.array('B', result)
      legacyMac = result[0:6]
      legacyMac.reverse()
      print( "LegacyMac:", ":".join( [ "%02x" % i for i in legacyMac ] ) )
      print( "Version:", "".join( [ "%02x" % i for i in result[ 6:8 ] ] ) )
      mac = result[8:14]
      mac.reverse()
      print( "MacAddrBase:", ":".join( [ "%02x" % i for i in mac ] ) )
      print( "PcieFormat:", "".join( [ "%02x" % i for i in result[ 14:16 ] ] ) )
   def writePlatform( self, platform, rawData ):
      data = re.split( "[:-]", rawData )
      data.reverse()
      legacy = [ '00' ] * 6
      seepromFormat = [ '00', '01' ]
      pcie = [ '00', '01' ]
      dataBytes = legacy + seepromFormat + data + pcie
      macseeprom = "".join([ chr(int(byte, 16)) for byte in dataBytes ])

      tf = tempfile.NamedTemporaryFile() # pylint: disable=consider-using-with
      f = open( tf.name, 'w' ) # pylint: disable=consider-using-with
      f.write( macseeprom )
      f.close()
      Tac.run( [ "/bin/sh", "-c", 
                 "idseeprom -d %d.%d --unlock --cpu %s write < %s" %
                 ( self.busId, self.seepromId, platform, tf.name ) ] )

class BodegaRaven( BodegaRavenCrow ):
   def write( self, rawData ):
      self.writePlatform( 'raven', rawData )

class BodegaCrow( BodegaRavenCrow ):
   def write( self, rawData ):
      self.writePlatform( 'crow', rawData )

class Mendocino( BodegaRavenCrow ):
   def write( self, rawData ):
      self.writePlatform( 'mendocino', rawData )

class Magpie( BodegaRavenCrow ):
   def write( self, rawData ):
      self.writePlatform( 'magpie', rawData )


switch = None
if options.system.lower() == 'napa':
   switch = Napa()
elif options.system.lower() == 'bodega':
   if not os.system( "/bin/grep -q crow /proc/cmdline" ):
      switch = BodegaCrow()
   elif not os.system( r"/bin/grep -q 'mendocino\|island\|newport' /proc/cmdline" ):
      switch = Mendocino()
   else:
      switch = BodegaRaven()
elif options.system.lower() == 'alameda':
   if not os.system( "/bin/grep -q magpie /proc/cmdline" ):
      switch = Magpie()
else:
   print( "Error: unknown switch type [%s]" % options.cpu )
   sys.exit( 1 )

try:
   op = args[0]
   if options.unlock and op == "write":
      seeprom.unlock()

   if op == "read":
      if len(args) != 1:
         parser.error( "Too many arguments" )
      switch.read()
   elif op == "write":
      import re
      if len(args) != 2:
         parser.error( "Too few arguments" )
      switch.write( args[1] )
      if options.unlock:
         seeprom.restoreLock()
   else:
      parser.error( "Unknown operation: '" + op + "'" )
finally:
   if options.unlock:
      seeprom.restoreLock()

