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

import optparse # pylint: disable=deprecated-module
import os
import sys

import Tac

import seeprom
import twoByteAddrShimSeeprom

usage = """
idseeprom [options] read
  Read idprom contents and write to stdout, in binary

  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( "-v", "--verbose", action="store_true",
                   help="enable verbose output" )
parser.add_option( "--debug", action="store_true",
                   help="enable debugging" )
parser.add_option( "-d", "--device", action="append",
                   help="specify device (bus.address)" )
parser.add_option( "-o", "--offset", action="store",
                   help="offset within seeprom to start from", default='0' )
parser.add_option( "-l", "--length", action="store",
                   help="length, in bytes, to read" )
parser.add_option( "-u", "--unlock", action="store_true",
                   help="unlock the mac seeprom" )
parser.add_option("--cpu", action="store", default='napa',
                  help="The cpu system")
parser.add_option( "--twoByteAddrShim", action="store_true", default=False,
                   help="use two-byte addressing for seeprom access. by default"
                   " will only read prefdl" )
parser.add_option( "--skipHeader", action="store_true", default=False,
                   help="skip reading prefdl header, starting from byte 0."
                   " Used with two-byte addressing for seeprom access"
                   " for certain platforms ( e.g. Willamette)." )
parser.add_option( "--eepromSize", action="store", type=int, 
                   default=twoByteAddrShimSeeprom.DEFAULT_EEPROM_SIZE,
                   help="used in conjunction with --skipHeader. This is"
                   " used to pad the prefdl" )

( options, args ) = parser.parse_args()
if len( args ) < 1:
   parser.error( "Too few arguments" )

if not options.device:
   parser.error( "Mandatory device missing." )
deviceList = []
if options.device == ["all"]:
   for bank in range( 80, 88 ):
      deviceList = deviceList + [ ( 1, bank ) ]
else:
   for device in options.device:
      (busId, seepromId) = device.split(".")
      deviceList = deviceList + [ ( seeprom.strToInt( busId ),
                                    seeprom.strToInt( seepromId ) ) ]

op = args[0]
l = len( args )

if options.offset: 
   offset = seeprom.strToInt( options.offset )
else: 
   offset = 0

if options.length:
   length = seeprom.strToInt( options.length )
else:
   length = 256

def readSeeprom( busNum, seepromAddr, readOffset, readLength ):
   if options.twoByteAddrShim:
      return twoByteAddrShimSeeprom.doReadPrefdl( busNum, seepromAddr,
                                            options.skipHeader,
                                            eepromSize=options.eepromSize )
   else:
      return seeprom.doRead( busNum, seepromAddr, readOffset, readLength )

try:
   if op == "read":
      if l != 1:
         parser.error( "Too many arguments" )
      try:
         for (busId, seepromId ) in deviceList:
            if options.verbose:
               print( "reading bus", busId, "device", seepromId, "offset",
                      offset, "length", length )
            os.write( sys.stdout.fileno(),
                      readSeeprom( busId, seepromId, offset, length ) )
      except Tac.SystemCommandError as e:
         # pylint: disable-next=consider-using-f-string
         sys.stdout.write( "Read Error: %s  (Invalid device?)\n" % e )
   else:
      parser.error( "Unknown operation: '" + op + "'" )
finally:
   pass

sys.exit( 0 )

