__author__ = 'gabriele.sorrenti'
from pyfabil.base.definitions import *
from pyfabil.base.utils import *
from pyfabil.plugins.firmwareblock import FirmwareBlock
import logging
MAX_RETRY = 6000
[docs]
class Tpm_1_6_EEP(FirmwareBlock):
""" Tpm_1_6_EEP tests class """
@compatibleboards(BoardMake.Tpm16Board)
@friendlyname('tpm_eep')
@maxinstances(1)
def __init__(self, board, **kwargs):
""" Tpm_1_6_EEP initialiser
:param board: Pointer to board instance
"""
super(Tpm_1_6_EEP, self).__init__(board)
self.phy_addr = 0xA0
# self.ba = 0x40000000 #self.board["board.i2c"] # I2C IF Base Add
self.i2c_shadow = 0x90000270
self.i2c_req_reg = 0x50
self.i2c_ack_reg = 0x54
self.ticket_num = None
self.eep_sec = {
"ip_address": {"offset": 0x00, "size": 4, "name": "ip_address", "type": "ip",
"protected": False},
"netmask": {"offset": 0x04, "size": 4, "name": "netmask", "type": "ip",
"protected": False},
"gateway": {"offset": 0x08, "size": 4, "name": "gateway", "type": "ip",
"protected": False},
"password": {"offset": 0x0c, "size": 3, "name": "password", "type": "bytearray",
"protected": False},
"pre_adu_0": {"offset": 0x10, "size": 16, "name": "pre_adu_0", "type": "bytearray",
"protected": False},
"pre_adu_1": {"offset": 0x20, "size": 16, "name": "pre_adu_1", "type": "bytearray",
"protected": False},
"SN": {"offset": 0x40, "size": 16, "name": "SN", "type": "string",
"protected": True},
"PN": {"offset": 0x50, "size": 16, "name": "PN", "type": "string",
"protected": True},
"BOARD_MODE": {"offset": 0x60, "size": 1, "name": "BOARD_MODE", "type": "uint",
"protected": True}, # 0 ada,0xff no-ada
"HARDWARE_REV": {"offset": 0x61, "size": 3, "name": "HARDWARE_REV", "type": "bytearray",
"protected": True}, # v00.00.00
"PCB_REV": {"offset": 0x64, "size": 1, "name": "PCB_REV", "type": "string",
"protected": True},
"DDR_SIZE_GB": {"offset": 0x65, "size": 1, "name": "DDR_SIZE_GB", "type": "uint",
"protected": True},
"CABINET_LOCATION": {"offset": 0x66, "size": 2, "name": "CABINET_LOCATION", "type": "uint",
"protected": False},
"SUBRACK_LOCATION": {"offset": 0x68, "size": 1, "name": "SUBRACK_LOCATION", "type": "uint",
"protected": False},
"SLOT_LOCATION": {"offset": 0x69, "size": 1, "name": "SLOT_LOCATION", "type": "uint",
"protected": False},
"pre_adu_0_rev": {"offset": 0x70, "size": 1, "name": "pre_adu_0_rev", "type": "uint",
"protected": False},
"pre_adu_1_rev": {"offset": 0x71, "size": 1, "name": "pre_adu_1_rev", "type": "uint",
"protected": False},
"MAC": {"offset": 0xFA, "size": 6, "name": "MAC", "type": "bytearray",
"protected": True}, # READ-ONLY
}
#######################################################################################
[docs]
def poll_reg(self, reg, exit_condition, exception_val):
retry = 0
while True:
if (self.board[reg]) == exit_condition:
break
else:
time.sleep(0.001)
retry = retry + 1
if self.ticket_num is not None:
self.board["board.lock.lock_i2c"] = self.ticket_num
if retry >= MAX_RETRY:
logging.error("EEP Polling Reg timeout: ", exception_val)
raise LibraryError(exception_val)
[docs]
def rd8(self, offset, use_password=False):
""" Read 8-bit value from EEP ROM """
if self.board.i2c_old_mode:
self.set_passwd()
add = self.phy_addr >> 1
nof_rd_byte = 1
nof_wr_byte = 1
cmd = (nof_rd_byte << 12) + (nof_wr_byte << 8) + add
self.board["board.i2c.transmit"] = offset & 0xFF
self.board["board.i2c.command"] = cmd
while self.board["board.i2c.status"] != 0:
pass
self.remove_passwd()
return self.board["board.i2c.receive"]
else:
# Lock I2C interface to avoid MCU access conflict
logging.debug("I2C Read: Locking I2C interface to avoid MCU access conflict ")
locked = False
retry = 150
ticket_num = self.board["board.lock.queue_number"]
while retry > 0:
self.board["board.lock.lock_i2c"] = ticket_num
if self.board["board.lock.lock_i2c"] != ticket_num:
retry = retry-1
time.sleep(0.007)
else:
locked = True
self.ticket_num = ticket_num
break
if locked is False:
logging.error("ERROR: Can't Lock I2C interface")
raise LibraryError("ERROR: Can't Lock I2C interface")
# else:
# logging.info("I2C interface Locked")
if self.board[self.i2c_shadow + self.i2c_req_reg] == 1:
logging.warning("Detected Incomplete Previous I2C operation")
self.board[self.i2c_shadow + self.i2c_req_reg] = 0
self.poll_reg(self.i2c_shadow + self.i2c_ack_reg, 0, "I2C/EEP not ready!")
self.set_passwd()
add = self.phy_addr >> 1
nof_rd_byte = 1
nof_wr_byte = 1
cmd = (nof_rd_byte << 12) + (nof_wr_byte << 8) + add
self.board[self.i2c_shadow + 0x4] = offset & 0xFF
self.board[self.i2c_shadow + 0x0] = cmd
# send request
self.board[self.i2c_shadow+self.i2c_req_reg] = 1
# wait req acknowledge
logging.debug("i2c read wait req acknowledge")
self.poll_reg(self.i2c_shadow+self.i2c_ack_reg, 1, "I2C/EEP request not accepted!")
# check passwd
logging.debug("i2c read check passwd")
self.check_passwd()
# check i2c op status: 0 ok, 1 busy, 2 NACK
logging.debug("i2c read check status")
self.poll_reg(self.i2c_shadow + 0xC, 0, "I2C/EEP busy or not acknoledge!")
read_data = self.board[self.i2c_shadow + 0x8]
# self.remove_passwd()
# self.board[self.i2c_shadow+self.i2c_ack_reg] = 0
self.board[self.i2c_shadow + self.i2c_req_reg] = 0
logging.debug("i2c read check end operation")
self.poll_reg(self.i2c_shadow + self.i2c_ack_reg, 0, "I2C/EEP operation complete not detected!")
# Unlock I2C interface
self.board["board.lock.lock_i2c"] = 0
self.ticket_num = None
time.sleep(0.020)
return read_data
def rd16(self, offset):
rd = 0
for n in range(2):
rd = rd << 8
rd = rd | self.rd8(offset+n)
return rd
def rd32(self, offset):
""" Read 32-bit value from EEP ROM """
rd = 0
for n in range(4):
rd = rd << 8
rd = rd | self.rd8(offset + n)
return rd
[docs]
def wr8(self, offset, data):
""" Write 8-bit value to EEP ROM """
if self.board.i2c_old_mode:
self.set_passwd()
add = self.phy_addr >> 1
nof_rd_byte = 0
nof_wr_byte = 2
cmd = (nof_rd_byte << 12) + (nof_wr_byte << 8) + add
while True:
self.board["board.i2c.transmit"] = ((data & 0xFF) << 8) + (offset & 0xFF)
self.board["board.i2c.command"] = cmd
while True:
rd = self.board["board.i2c.status"]
if rd == 2:
time.sleep(0.1)
break
elif rd == 0:
time.sleep(0.005)
self.remove_passwd()
return
else:
time.sleep(0.1)
else:
# Lock I2C interface to avoid MCU access conflict
logging.debug("I2C Write: Locking I2C interface to avoid MCU access conflict ")
locked = False
retry = 15
ticket_num = self.board["board.lock.queue_number"]
while retry > 0:
self.board["board.lock.lock_i2c"] = ticket_num
if self.board["board.lock.lock_i2c"] != ticket_num:
retry = retry-1
time.sleep(0.01)
else:
locked = True
self.ticket_num = ticket_num
break
if locked is False:
logging.error("ERROR: Can't Lock I2C interface")
raise LibraryError("ERROR: Can't Lock I2C interface")
# else:
# logging.info("I2C interface Locked")
if self.board[self.i2c_shadow + self.i2c_req_reg] == 1:
logging.warning("Detected Incomplete Previous I2C operation")
self.board[self.i2c_shadow + self.i2c_req_reg] = 0
self.poll_reg(self.i2c_shadow + self.i2c_ack_reg, 0, "I2C/EEP not ready!")
self.set_passwd()
add = self.phy_addr >> 1
nof_rd_byte = 0
nof_wr_byte = 2
cmd = (nof_rd_byte << 12) + (nof_wr_byte << 8) + add
self.board[self.i2c_shadow + 0x4] = ((data & 0xFF) << 8) + (offset & 0xFF)
self.board[self.i2c_shadow + 0x0] = cmd
# send request
self.board[self.i2c_shadow + self.i2c_req_reg] = 1
# wait req acknowledge
logging.debug("wait req acknowledge")
self.poll_reg(self.i2c_shadow + self.i2c_ack_reg, 1, "I2C/EEP request not accepted!")
# check passwd
logging.debug("check passwd")
self.check_passwd()
# check i2c op status: 0 ok, 1 busy, 2 NACK
logging.debug("check status")
self.poll_reg(self.i2c_shadow + 0xC, 0, "I2C/EEP busy or not acknoledge!")
# read_data = self.board[self.i2c_shadow + 0x8]
# self.remove_passwd()
self.board[self.i2c_shadow + self.i2c_req_reg] = 0
logging.debug("check end operation")
self.poll_reg(self.i2c_shadow + self.i2c_ack_reg, 0, "I2C/EEP operation complete not detected!")
# Unlock I2C interface
self.board["board.lock.lock_i2c"] = 0
self.ticket_num = None
time.sleep(0.020)
[docs]
def rd16(self, offset):
rd = 0
for n in range(2):
rd = rd << 8
rd = rd | self.rd8(offset+n)
return rd
[docs]
def rd32(self, offset):
rd = 0
for n in range(4):
rd = rd << 8
rd = rd | self.rd8(offset+n)
return rd
[docs]
def wr32(self, offset, data):
for n in range(4):
self.wr8(offset+n, (data >> 8*(3-n)) & 0xFF)
return
[docs]
def wr_string(self, partition, string):
return self._wr_string(partition["offset"], string, partition["size"])
def _wr_string(self, offset, string, max_len=16):
addr = offset
for i in range(len(string)):
self.wr8(addr, ord(string[i]))
addr += 1
if addr >= offset + max_len:
break
if addr < offset + max_len:
self.wr8(addr, ord("\n"))
[docs]
def rd_string(self, partition):
return self._rd_string(partition["offset"], partition["size"])
def _rd_string(self, offset, max_len=16):
addr = offset
string = ""
for i in range(max_len):
byte = self.rd8(addr)
if byte == ord("\n") or byte == 0xff:
break
string += chr(byte)
addr += 1
return string
[docs]
def set_passwd(self):
if self.board.i2c_old_mode:
rd = self.board["board.i2c.mac_hi"]
self.board["board.i2c.password"] = rd
rd = self.board["board.i2c.mac_lo"]
self.board["board.i2c.password_lo"] = rd
rd = self.board["board.i2c.password"]
if rd & 0x10000 == 0:
raise LibraryError("I2C/EEP password not accepted!")
else:
rd = self.board["board.i2c.mac_hi"]
self.board[self.i2c_shadow+0x3C] = rd
rd = self.board["board.i2c.mac_lo"]
self.board[self.i2c_shadow+0x38] = rd
[docs]
def check_passwd(self):
rd = self.board[self.i2c_shadow+0x3C]
if (rd & 0x10000) != 0x10000:
logging.error("I2C/EEP password not accepted!")
raise LibraryError("I2C/EEP password not accepted!")
[docs]
def remove_passwd(self):
if self.board.i2c_old_mode:
self.board["board.i2c.password"] = 0
self.board["board.i2c.password_lo"] = 0
else:
self.board[self.i2c_shadow+0x3C] = 0
self.board[self.i2c_shadow+0x38] = 0
[docs]
def get_field(self, key):
if self.eep_sec[key]["type"] == "ip":
return long2ip(self.rd32(self.eep_sec[key]["offset"]))
elif self.eep_sec[key]["type"] == "bytearray":
arr = bytearray()
for offset in range(self.eep_sec[key]["size"]):
arr.append(self.rd8(self.eep_sec[key]["offset"]+offset))
return arr
elif self.eep_sec[key]["type"] == "string":
return self.rd_string(self.eep_sec[key])
elif self.eep_sec[key]["type"] == "uint":
val = 0
for offset in range(self.eep_sec[key]["size"]):
val = val * 256 + self.rd8(self.eep_sec[key]["offset"]+offset)
return val
[docs]
def set_field(self, key, value, override_protected=False):
if self.eep_sec[key]["protected"] is False or override_protected:
if self.eep_sec[key]["type"] == "ip":
self.wr32(self.eep_sec[key]["offset"], ip2long(value))
elif self.eep_sec[key]["type"] == "bytearray":
for offset in range(self.eep_sec[key]["size"]):
self.wr8(self.eep_sec[key]["offset"] + offset,
((value & (0xff << (8*(self.eep_sec[key]["size"]-1-offset))))
>> (8*(self.eep_sec[key]["size"]-1-offset))) & 0xff)
elif self.eep_sec[key]["type"] == "string":
self.wr_string(self.eep_sec[key], value)
elif self.eep_sec[key]["type"] == "uint":
val = value
for offset in range(self.eep_sec[key]["size"]):
self.wr8(self.eep_sec[key]["offset"]+offset, val & 0xff)
val = val >> 8
else:
raise LibraryError("Writing attempt on protected sector %s" % key)