#!/usr/bin/python3 import collections from bitarray import bitarray from datetime import datetime, timedelta __DEBUG__ = "N" class FruException(Exception): def __init__(self, message='fruerror', code=-100): err = 'errcode: {0} message:{1}'.format(code, message) Exception.__init__(self, err) self.code = code self.message = message def e_print(err): print("ERROR: " + err) def d_print(debug_info): if(__DEBUG__ == "Y"): print(debug_info) class FruUtil(): @staticmethod def decodeLength(value): a = bitarray(8) a.setall(True) a[0:1] = 0 a[1:2] = 0 x = ord(a.tobytes()) return x & ord(value) @staticmethod def minToData(): starttime = datetime(1996, 1, 1, 0, 0, 0) endtime = datetime.now() seconds = (endtime - starttime).total_seconds() mins = seconds // 60 m = int(round(mins)) return m @staticmethod def getTimeFormat(): return datetime.now().strftime('%Y-%m-%d') @staticmethod def getTypeLength(value): if value is None or len(value) == 0: return 0 a = bitarray(8) a.setall(False) a[0:1] = 1 a[1:2] = 1 x = ord(a.tobytes()) return x | len(value) @staticmethod def checksum(b): result = 0 for i in range(len(b)): result += ord(b[i]) return (0x100 - (result & 0xff)) & 0xff class BaseArea(object): SUGGESTED_SIZE_COMMON_HEADER = 8 SUGGESTED_SIZE_INTERNAL_USE_AREA = 72 SUGGESTED_SIZE_CHASSIS_INFO_AREA = 32 SUGGESTED_SIZE_BOARD_INFO_AREA = 80 SUGGESTED_SIZE_PRODUCT_INFO_AREA = 80 INITVALUE = b'\x00' resultvalue = INITVALUE * 256 COMMON_HEAD_VERSION = b'\x01' __childList = None def __init__(self, name="", size=0, offset=0): self.__childList = [] self._offset = offset self.name = name self._size = size self._isPresent = False self._data = b'\x00' * size self.__dataoffset = 0 @property def childList(self): return self.__childList @childList.setter def childList(self, value): self.__childList = value @property def offset(self): return self._offset @offset.setter def offset(self, value): self._offset = value @property def size(self): return self._size @size.setter def size(self, value): self._size = value @property def data(self): return self._data @data.setter def data(self, value): self._data = value @property def isPresent(self): return self._isPresent @isPresent.setter def isPresent(self, value): self._isPresent = value class InternalUseArea(BaseArea): pass class ChassisInfoArea(BaseArea): pass class BoardInfoArea(BaseArea): _boardTime = None _fields = None _mfg_date = None def __str__(self): formatstr = "version : %x\n" \ "length : %d \n" \ "language : %x \n" \ "mfg_date : %s \n" \ "boardManufacturer : %s \n" \ "boardProductName : %s \n" \ "boardSerialNumber : %s \n" \ "boardPartNumber : %s \n" \ "fruFileId : %s \n" tmpstr = formatstr % (ord(self.boardversion), self.size, self.language, self.getMfgRealData(), self.boardManufacturer, self.boardProductName, self.boardSerialNumber, self.boardPartNumber, self.fruFileId) for i in range(1, 11): valtmp = "boardextra%d" % i if hasattr(self, valtmp): valtmpval = getattr(self, valtmp) tmpstr += "boardextra%d : %s \n" % (i, valtmpval) else: break return tmpstr def todict(self): dic = collections.OrderedDict() dic["boardversion"] = ord(self.boardversion) dic["boardlength"] = self.size dic["boardlanguage"] = self.language dic["boardmfg_date"] = self.getMfgRealData() dic["boardManufacturer"] = self.boardManufacturer dic["boardProductName"] = self.boardProductName dic["boardSerialNumber"] = self.boardSerialNumber dic["boardPartNumber"] = self.boardPartNumber dic["boardfruFileId"] = self.fruFileId for i in range(1, 11): valtmp = "boardextra%d" % i if hasattr(self, valtmp): valtmpval = getattr(self, valtmp) dic[valtmp] = valtmpval else: break return dic def decodedata(self): index = 0 self.areaversion = self.data[index] index += 1 d_print("decode length :%d class size:%d" % ((ord(self.data[index]) * 8), self.size)) index += 2 timetmp = self.data[index: index + 3] self.mfg_date = ord(timetmp[0]) | ( ord(timetmp[1]) << 8) | (ord(timetmp[2]) << 16) d_print("decode getMfgRealData :%s" % self.getMfgRealData()) index += 3 templen = FruUtil.decodeLength(self.data[index]) self.boardManufacturer = self.data[index + 1: index + templen + 1] index += templen + 1 d_print("decode boardManufacturer:%s" % self.boardManufacturer) templen = FruUtil.decodeLength(self.data[index]) self.boardProductName = self.data[index + 1: index + templen + 1] index += templen + 1 d_print("decode boardProductName:%s" % self.boardProductName) templen = FruUtil.decodeLength(self.data[index]) self.boardSerialNumber = self.data[index + 1: index + templen + 1] index += templen + 1 d_print("decode boardSerialNumber:%s" % self.boardSerialNumber) templen = FruUtil.decodeLength(self.data[index]) self.boardPartNumber = self.data[index + 1: index + templen + 1] index += templen + 1 d_print("decode boardPartNumber:%s" % self.boardPartNumber) templen = FruUtil.decodeLength(self.data[index]) self.fruFileId = self.data[index + 1: index + templen + 1] index += templen + 1 d_print("decode fruFileId:%s" % self.fruFileId) for i in range(1, 11): valtmp = "boardextra%d" % i if self.data[index] != chr(0xc1): templen = FruUtil.decodeLength(self.data[index]) tmpval = self.data[index + 1: index + templen + 1] setattr(self, valtmp, tmpval) index += templen + 1 d_print("decode boardextra%d:%s" % (i, tmpval)) else: break return def recalcute(self): d_print("boardInfoArea version:%x" % ord(self.boardversion)) d_print("boardInfoArea length:%d" % self.size) d_print("boardInfoArea language:%x" % self.language) self.mfg_date = FruUtil.minToData() d_print("boardInfoArea mfg_date:%x" % self.mfg_date) self.data = chr(ord(self.boardversion)) + \ chr(self.size // 8) + chr(self.language) self.data += chr(self.mfg_date & 0xFF) self.data += chr((self.mfg_date >> 8) & 0xFF) self.data += chr((self.mfg_date >> 16) & 0xFF) d_print("boardInfoArea boardManufacturer:%s" % self.boardManufacturer) typelength = FruUtil.getTypeLength(self.boardManufacturer) self.data += chr(typelength) self.data += self.boardManufacturer d_print("boardInfoArea boardProductName:%s" % self.boardProductName) self.data += chr(FruUtil.getTypeLength(self.boardProductName)) self.data += self.boardProductName d_print("boardInfoArea boardSerialNumber:%s" % self.boardSerialNumber) self.data += chr(FruUtil.getTypeLength(self.boardSerialNumber)) self.data += self.boardSerialNumber d_print("boardInfoArea boardPartNumber:%s" % self.boardPartNumber) self.data += chr(FruUtil.getTypeLength(self.boardPartNumber)) self.data += self.boardPartNumber d_print("boardInfoArea fruFileId:%s" % self.fruFileId) self.data += chr(FruUtil.getTypeLength(self.fruFileId)) self.data += self.fruFileId for i in range(1, 11): valtmp = "boardextra%d" % i if hasattr(self, valtmp): valtmpval = getattr(self, valtmp) d_print("boardInfoArea boardextra%d:%s" % (i, valtmpval)) self.data += chr(FruUtil.getTypeLength(valtmpval)) if valtmpval is None: pass else: self.data += valtmpval else: break self.data += chr(0xc1) if len(self.data) > (self.size - 1): incr = (len(self.data) - self.size) // 8 + 1 self.size += incr * 8 self.data = self.data[0:1] + chr(self.size // 8) + self.data[2:] d_print("self data:%d" % len(self.data)) d_print("self size:%d" % self.size) d_print("adjust size:%d" % (self.size - len(self.data) - 1)) self.data = self.data.ljust((self.size - 1), chr(self.INITVALUE[0])) # checksum checksum = FruUtil.checksum(self.data) d_print("board info checksum:%x" % checksum) self.data += chr(checksum) def getMfgRealData(self): starttime = datetime(1996, 1, 1, 0, 0, 0) mactime = starttime + timedelta(minutes=self.mfg_date) return mactime @property def language(self): self._language = 25 return self._language @property def mfg_date(self): return self._mfg_date @mfg_date.setter def mfg_date(self, val): self._mfg_date = val @property def boardversion(self): self._boardversion = self.COMMON_HEAD_VERSION return self._boardversion @property def fruFileId(self): return self._FRUFileID @fruFileId.setter def fruFileId(self, val): self._FRUFileID = val @property def boardPartNumber(self): return self._boardPartNumber @boardPartNumber.setter def boardPartNumber(self, val): self._boardPartNumber = val @property def boardSerialNumber(self): return self._boardSerialNumber @boardSerialNumber.setter def boardSerialNumber(self, val): self._boardSerialNumber = val @property def boardProductName(self): return self._boradProductName @boardProductName.setter def boardProductName(self, val): self._boradProductName = val @property def boardManufacturer(self): return self._boardManufacturer @boardManufacturer.setter def boardManufacturer(self, val): self._boardManufacturer = val @property def boardTime(self): return self._boardTime @boardTime.setter def boardTime(self, val): self._boardTime = val @property def fields(self): return self._fields @fields.setter def fields(self, val): self._fields = val class ProductInfoArea(BaseArea): _productManufacturer = None _productAssetTag = None _FRUFileID = None def __str__(self): formatstr = "version : %x\n" \ "length : %d \n" \ "language : %x \n" \ "productManufacturer : %s \n" \ "productName : %s \n" \ "productPartModelName: %s \n" \ "productVersion : %s \n" \ "productSerialNumber : %s \n" \ "productAssetTag : %s \n" \ "fruFileId : %s \n" tmpstr = formatstr % (ord(self.areaversion), self.size, self.language, self.productManufacturer, self.productName, self.productPartModelName, self.productVersion, self.productSerialNumber, self.productAssetTag, self.fruFileId) for i in range(1, 11): valtmp = "productextra%d" % i if hasattr(self, valtmp): valtmpval = getattr(self, valtmp) tmpstr += "productextra%d : %s \n" % (i, valtmpval) else: break return tmpstr def todict(self): dic = collections.OrderedDict() dic["productversion"] = ord(self.areaversion) dic["productlength"] = self.size dic["productlanguage"] = self.language dic["productManufacturer"] = self.productManufacturer dic["productName"] = self.productName dic["productPartModelName"] = self.productPartModelName dic["productVersion"] = int(self.productVersion, 16) dic["productSerialNumber"] = self.productSerialNumber dic["productAssetTag"] = self.productAssetTag dic["productfruFileId"] = self.fruFileId for i in range(1, 11): valtmp = "productextra%d" % i if hasattr(self, valtmp): valtmpval = getattr(self, valtmp) dic[valtmp] = valtmpval else: break return dic def decodedata(self): index = 0 self.areaversion = self.data[index] # 0 index += 1 d_print("decode length %d" % (ord(self.data[index]) * 8)) d_print("class size %d" % self.size) index += 2 templen = FruUtil.decodeLength(self.data[index]) self.productManufacturer = self.data[index + 1: index + templen + 1] index += templen + 1 d_print("decode productManufacturer:%s" % self.productManufacturer) templen = FruUtil.decodeLength(self.data[index]) self.productName = self.data[index + 1: index + templen + 1] index += templen + 1 d_print("decode productName:%s" % self.productName) templen = FruUtil.decodeLength(self.data[index]) self.productPartModelName = self.data[index + 1: index + templen + 1] index += templen + 1 d_print("decode productPartModelName:%s" % self.productPartModelName) templen = FruUtil.decodeLength(self.data[index]) self.productVersion = self.data[index + 1: index + templen + 1] index += templen + 1 d_print("decode productVersion:%s" % self.productVersion) templen = FruUtil.decodeLength(self.data[index]) self.productSerialNumber = self.data[index + 1: index + templen + 1] index += templen + 1 d_print("decode productSerialNumber:%s" % self.productSerialNumber) templen = FruUtil.decodeLength(self.data[index]) self.productAssetTag = self.data[index + 1: index + templen + 1] index += templen + 1 d_print("decode productAssetTag:%s" % self.productAssetTag) templen = FruUtil.decodeLength(self.data[index]) self.fruFileId = self.data[index + 1: index + templen + 1] index += templen + 1 d_print("decode fruFileId:%s" % self.fruFileId) for i in range(1, 11): valtmp = "productextra%d" % i if self.data[index] != chr(0xc1) and index < self.size - 1: templen = FruUtil.decodeLength(self.data[index]) if templen == 0: break tmpval = self.data[index + 1: index + templen + 1] d_print("decode boardextra%d:%s" % (i, tmpval)) setattr(self, valtmp, tmpval) index += templen + 1 else: break @property def productVersion(self): return self._productVersion @productVersion.setter def productVersion(self, name): self._productVersion = name @property def areaversion(self): self._areaversion = self.COMMON_HEAD_VERSION return self._areaversion @areaversion.setter def areaversion(self, name): self._areaversion = name @property def language(self): self._language = 25 return self._language @property def productManufacturer(self): return self._productManufacturer @productManufacturer.setter def productManufacturer(self, name): self._productManufacturer = name @property def productName(self): return self._productName @productName.setter def productName(self, name): self._productName = name @property def productPartModelName(self): return self._productPartModelName @productPartModelName.setter def productPartModelName(self, name): self._productPartModelName = name @property def productSerialNumber(self): return self._productSerialNumber @productSerialNumber.setter def productSerialNumber(self, name): self._productSerialNumber = name @property def productAssetTag(self): return self._productAssetTag @productAssetTag.setter def productAssetTag(self, name): self._productAssetTag = name @property def fruFileId(self): return self._FRUFileID @fruFileId.setter def fruFileId(self, name): self._FRUFileID = name def recalcute(self): d_print("product version:%x" % ord(self.areaversion)) d_print("product length:%d" % self.size) d_print("product language:%x" % self.language) self.data = chr(ord(self.areaversion)) + \ chr(self.size // 8) + chr(self.language) typelength = FruUtil.getTypeLength(self.productManufacturer) self.data += chr(typelength) self.data += self.productManufacturer self.data += chr(FruUtil.getTypeLength(self.productName)) self.data += self.productName self.data += chr(FruUtil.getTypeLength(self.productPartModelName)) self.data += self.productPartModelName self.data += chr(FruUtil.getTypeLength(self.productVersion)) self.data += self.productVersion self.data += chr(FruUtil.getTypeLength(self.productSerialNumber)) self.data += self.productSerialNumber self.data += chr(FruUtil.getTypeLength(self.productAssetTag)) if self.productAssetTag is not None: self.data += self.productAssetTag self.data += chr(FruUtil.getTypeLength(self.fruFileId)) self.data += self.fruFileId for i in range(1, 11): valtmp = "productextra%d" % i if hasattr(self, valtmp): valtmpval = getattr(self, valtmp) d_print("boardInfoArea productextra%d:%s" % (i, valtmpval)) self.data += chr(FruUtil.getTypeLength(valtmpval)) if valtmpval is None: pass else: self.data += valtmpval else: break self.data += chr(0xc1) if len(self.data) > (self.size - 1): incr = (len(self.data) - self.size) // 8 + 1 self.size += incr * 8 d_print("self.data:%d" % len(self.data)) d_print("self.size:%d" % self.size) self.data = self.data[0:1] + chr(self.size // 8) + self.data[2:] self.data = self.data.ljust((self.size - 1), chr(self.INITVALUE[0])) checksum = FruUtil.checksum(self.data) d_print("board info checksum:%x" % checksum) self.data += chr(checksum) class MultiRecordArea(BaseArea): pass class Field(object): def __init__(self, fieldType="ASCII", fieldData=""): self.fieldData = fieldData self.fieldType = fieldType @property def data(self): return self._data @property def fieldType(self): return self._fieldType @property def fieldData(self): return self._fieldData class ipmifru(BaseArea): _BoardInfoArea = None _ProductInfoArea = None _InternalUseArea = None _ChassisInfoArea = None _multiRecordArea = None _productinfoAreaOffset = BaseArea.INITVALUE _boardInfoAreaOffset = BaseArea.INITVALUE _internalUserAreaOffset = BaseArea.INITVALUE _chassicInfoAreaOffset = BaseArea.INITVALUE _multiRecordAreaOffset = BaseArea.INITVALUE _bindata = None _bodybin = None _version = BaseArea.COMMON_HEAD_VERSION _zeroCheckSum = None _frusize = 256 def __str__(self): tmpstr = "" if self.boardInfoArea.isPresent: tmpstr += "\nboardinfoarea: \n" tmpstr += self.boardInfoArea.__str__() if self.productInfoArea.isPresent: tmpstr += "\nproductinfoarea: \n" tmpstr += self.productInfoArea.__str__() return tmpstr def decodeBin(self, eeprom): commonHead = eeprom[0:8] d_print("decode version %x" % ord(commonHead[0])) if ord(self.COMMON_HEAD_VERSION) != ord(commonHead[0]): raise FruException("HEAD VERSION error,not Fru format!", -10) if FruUtil.checksum(commonHead[0:7]) != ord(commonHead[7]): strtemp = "check header checksum error [cal:%02x data:%02x]" % ( FruUtil.checksum(commonHead[0:7]), ord(commonHead[7])) raise FruException(strtemp, -3) if ord(commonHead[1]) != ord(self.INITVALUE): d_print("Internal Use Area is present") self.internalUseArea = InternalUseArea( name="Internal Use Area", size=self.SUGGESTED_SIZE_INTERNAL_USE_AREA) self.internalUseArea.isPresent = True self.internalUserAreaOffset = ord(commonHead[1]) self.internalUseArea.data = eeprom[self.internalUserAreaOffset * 8: ( self.internalUserAreaOffset * 8 + self.internalUseArea.size)] if ord(commonHead[2]) != ord(self.INITVALUE): d_print("Chassis Info Area is present") self.chassisInfoArea = ChassisInfoArea( name="Chassis Info Area", size=self.SUGGESTED_SIZE_CHASSIS_INFO_AREA) self.chassisInfoArea.isPresent = True self.chassicInfoAreaOffset = ord(commonHead[2]) self.chassisInfoArea.data = eeprom[self.chassicInfoAreaOffset * 8: ( self.chassicInfoAreaOffset * 8 + self.chassisInfoArea.size)] if ord(commonHead[3]) != ord(self.INITVALUE): self.boardInfoArea = BoardInfoArea( name="Board Info Area", size=self.SUGGESTED_SIZE_BOARD_INFO_AREA) self.boardInfoArea.isPresent = True self.boardInfoAreaOffset = ord(commonHead[3]) self.boardInfoArea.size = ord( eeprom[self.boardInfoAreaOffset * 8 + 1]) * 8 d_print("Board Info Area is present size:%d" % (self.boardInfoArea.size)) self.boardInfoArea.data = eeprom[self.boardInfoAreaOffset * 8: ( self.boardInfoAreaOffset * 8 + self.boardInfoArea.size)] if FruUtil.checksum(self.boardInfoArea.data[:-1]) != ord(self.boardInfoArea.data[-1:]): strtmp = "check boardInfoArea checksum error[cal:%02x data:%02x]" % \ (FruUtil.checksum( self.boardInfoArea.data[:-1]), ord(self.boardInfoArea.data[-1:])) raise FruException(strtmp, -3) self.boardInfoArea.decodedata() if ord(commonHead[4]) != ord(self.INITVALUE): d_print("Product Info Area is present") self.productInfoArea = ProductInfoArea( name="Product Info Area ", size=self.SUGGESTED_SIZE_PRODUCT_INFO_AREA) self.productInfoArea.isPresent = True self.productinfoAreaOffset = ord(commonHead[4]) d_print("length offset value: %02x" % ord(eeprom[self.productinfoAreaOffset * 8 + 1])) self.productInfoArea.size = ord( eeprom[self.productinfoAreaOffset * 8 + 1]) * 8 d_print("Product Info Area is present size:%d" % (self.productInfoArea.size)) self.productInfoArea.data = eeprom[self.productinfoAreaOffset * 8: ( self.productinfoAreaOffset * 8 + self.productInfoArea.size)] if FruUtil.checksum(self.productInfoArea.data[:-1]) != ord(self.productInfoArea.data[-1:]): strtmp = "check productInfoArea checksum error [cal:%02x data:%02x]" % ( FruUtil.checksum(self.productInfoArea.data[:-1]), ord(self.productInfoArea.data[-1:])) raise FruException(strtmp, -3) self.productInfoArea.decodedata() if ord(commonHead[5]) != ord(self.INITVALUE): self.multiRecordArea = MultiRecordArea( name="MultiRecord record Area ") d_print("MultiRecord record present") self.multiRecordArea.isPresent = True self.multiRecordAreaOffset = ord(commonHead[5]) self.multiRecordArea.data = eeprom[self.multiRecordAreaOffset * 8: ( self.multiRecordAreaOffset * 8 + self.multiRecordArea.size)] def initDefault(self): self.version = self.COMMON_HEAD_VERSION self.internalUserAreaOffset = self.INITVALUE self.chassicInfoAreaOffset = self.INITVALUE self.boardInfoAreaOffset = self.INITVALUE self.productinfoAreaOffset = self.INITVALUE self.multiRecordAreaOffset = self.INITVALUE self.PAD = self.INITVALUE self.zeroCheckSum = self.INITVALUE self.offset = self.SUGGESTED_SIZE_COMMON_HEADER self.productInfoArea = None self.internalUseArea = None self.boardInfoArea = None self.chassisInfoArea = None self.multiRecordArea = None # self.recalcute() @property def version(self): return self._version @version.setter def version(self, name): self._version = name @property def internalUserAreaOffset(self): return self._internalUserAreaOffset @internalUserAreaOffset.setter def internalUserAreaOffset(self, obj): self._internalUserAreaOffset = obj @property def chassicInfoAreaOffset(self): return self._chassicInfoAreaOffset @chassicInfoAreaOffset.setter def chassicInfoAreaOffset(self, obj): self._chassicInfoAreaOffset = obj @property def productinfoAreaOffset(self): return self._productinfoAreaOffset @productinfoAreaOffset.setter def productinfoAreaOffset(self, obj): self._productinfoAreaOffset = obj @property def boardInfoAreaOffset(self): return self._boardInfoAreaOffset @boardInfoAreaOffset.setter def boardInfoAreaOffset(self, obj): self._boardInfoAreaOffset = obj @property def multiRecordAreaOffset(self): return self._multiRecordAreaOffset @multiRecordAreaOffset.setter def multiRecordAreaOffset(self, obj): self._multiRecordAreaOffset = obj @property def zeroCheckSum(self): return self._zeroCheckSum @zeroCheckSum.setter def zeroCheckSum(self, obj): self._zeroCheckSum = obj @property def productInfoArea(self): return self._ProductInfoArea @productInfoArea.setter def productInfoArea(self, obj): self._ProductInfoArea = obj @property def internalUseArea(self): return self._InternalUseArea @internalUseArea.setter def internalUseArea(self, obj): self.internalUseArea = obj @property def boardInfoArea(self): return self._BoardInfoArea @boardInfoArea.setter def boardInfoArea(self, obj): self._BoardInfoArea = obj @property def chassisInfoArea(self): return self._ChassisInfoArea @chassisInfoArea.setter def chassisInfoArea(self, obj): self._ChassisInfoArea = obj @property def multiRecordArea(self): return self._multiRecordArea @multiRecordArea.setter def multiRecordArea(self, obj): self._multiRecordArea = obj @property def bindata(self): return self._bindata @bindata.setter def bindata(self, obj): self._bindata = obj @property def bodybin(self): return self._bodybin @bodybin.setter def bodybin(self, obj): self._bodybin = obj def recalcuteCommonHead(self): self.bindata = "" self.offset = self.SUGGESTED_SIZE_COMMON_HEADER d_print("common Header %d" % self.offset) d_print("fru eeprom size %d" % self._frusize) if self.internalUseArea is not None and self.internalUseArea.isPresent: self.internalUserAreaOffset = self.offset // 8 self.offset += self.internalUseArea.size d_print("internalUseArea is present offset:%d" % self.offset) if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent: self.chassicInfoAreaOffset = self.offset // 8 self.offset += self.chassisInfoArea.size d_print("chassisInfoArea is present offset:%d" % self.offset) if self.boardInfoArea is not None and self.boardInfoArea.isPresent: self.boardInfoAreaOffset = self.offset // 8 self.offset += self.boardInfoArea.size d_print("boardInfoArea is present offset:%d" % self.offset) d_print("boardInfoArea is present size:%d" % self.boardInfoArea.size) if self.productInfoArea is not None and self.productInfoArea.isPresent: self.productinfoAreaOffset = self.offset // 8 self.offset += self.productInfoArea.size d_print("productInfoArea is present offset:%d" % self.offset) if self.multiRecordArea is not None and self.multiRecordArea.isPresent: self.multiRecordAreaOffset = self.offset // 8 d_print("multiRecordArea is present offset:%d" % self.offset) if self.internalUserAreaOffset == self.INITVALUE: self.internalUserAreaOffset = 0 if self.productinfoAreaOffset == self.INITVALUE: self.productinfoAreaOffset = 0 if self.chassicInfoAreaOffset == self.INITVALUE: self.chassicInfoAreaOffset = 0 if self.boardInfoAreaOffset == self.INITVALUE: self.boardInfoAreaOffset = 0 if self.multiRecordAreaOffset == self.INITVALUE: self.multiRecordAreaOffset = 0 self.zeroCheckSum = (0x100 - ord(self.version) - self.internalUserAreaOffset - self.chassicInfoAreaOffset - self.productinfoAreaOffset - self.boardInfoAreaOffset - self.multiRecordAreaOffset) & 0xff d_print("zerochecksum:%x" % self.zeroCheckSum) self.data = "" self.data += chr(self.version[0]) + chr(self.internalUserAreaOffset) + chr(self.chassicInfoAreaOffset) + chr( self.boardInfoAreaOffset) + chr(self.productinfoAreaOffset) + chr(self.multiRecordAreaOffset) + chr(self.INITVALUE[0]) + chr(self.zeroCheckSum) self.bindata = self.data + self.bodybin totallen = len(self.bindata) d_print("totallen %d" % totallen) if (totallen < self._frusize): self.bindata = self.bindata.ljust(self._frusize, chr(self.INITVALUE[0])) else: raise FruException('bin data more than %d' % self._frusize, -2) def recalcutebin(self): self.bodybin = "" if self.internalUseArea is not None and self.internalUseArea.isPresent: d_print("internalUseArea present") self.bodybin += self.internalUseArea.data if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent: d_print("chassisInfoArea present") self.bodybin += self.chassisInfoArea.data if self.boardInfoArea is not None and self.boardInfoArea.isPresent: d_print("boardInfoArea present") self.boardInfoArea.recalcute() self.bodybin += self.boardInfoArea.data if self.productInfoArea is not None and self.productInfoArea.isPresent: d_print("productInfoAreapresent") self.productInfoArea.recalcute() self.bodybin += self.productInfoArea.data if self.multiRecordArea is not None and self.multiRecordArea.isPresent: d_print("multiRecordArea present") self.bodybin += self.productInfoArea.data def recalcute(self, fru_eeprom_size=256): self._frusize = fru_eeprom_size self.recalcutebin() self.recalcuteCommonHead()