mirror of
https://opendev.org/x/pyghmi
synced 2025-01-28 20:07:42 +00:00
Implement FRU inventory
Implement parsing of FRU data. This phase omits Multirecord area. Provide access to either just the names or names and extended information. Change-Id: I8b0adf649769a880bf40cbe973864e889f1a6959
This commit is contained in:
parent
77593758f7
commit
c60b684d23
@ -19,6 +19,7 @@
|
||||
import pyghmi.constants as const
|
||||
import pyghmi.exceptions as exc
|
||||
|
||||
import pyghmi.ipmi.fru as fru
|
||||
from pyghmi.ipmi.private import session
|
||||
import pyghmi.ipmi.sdr as sdr
|
||||
|
||||
@ -337,6 +338,35 @@ class Command(object):
|
||||
if 'error' in response:
|
||||
raise exc.IpmiException(response['error'])
|
||||
|
||||
def get_inventory_descriptions(self):
|
||||
"""Retrieve list of things that could be inventoried
|
||||
|
||||
This permits a caller to examine the available items
|
||||
without actually causing the inventory data to be gathered. It
|
||||
returns an iterable of string descriptions
|
||||
"""
|
||||
yield "System"
|
||||
if self._sdr is None:
|
||||
self._sdr = sdr.SDR(self)
|
||||
for fruid in self._sdr.fru:
|
||||
yield self._sdr.fru[fruid].fru_name
|
||||
|
||||
def get_inventory(self):
|
||||
"""Retrieve inventory of system
|
||||
|
||||
Retrieve inventory of the targeted system. This frequently includes
|
||||
serial numbers, sometimes hardware addresses, sometimes memory modules
|
||||
This function will retrieve whatever the underlying platform provides
|
||||
and apply some structure. Iterating over the return yields tuples
|
||||
of a name for the inventoried item and
|
||||
"""
|
||||
yield ("System", fru.FRU(ipmicmd=self, fruid=0).info)
|
||||
if self._sdr is None:
|
||||
self._sdr = sdr.SDR(self)
|
||||
for fruid in self._sdr.fru:
|
||||
yield (self._sdr.fru[fruid].fru_name, fru.FRU(
|
||||
ipmicmd=self, fruid=fruid, sdr=self._sdr.fru[fruid]).info)
|
||||
|
||||
def get_health(self):
|
||||
"""Summarize health of managed system
|
||||
|
||||
|
309
pyghmi/ipmi/fru.py
Normal file
309
pyghmi/ipmi/fru.py
Normal file
@ -0,0 +1,309 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
# coding=utf8
|
||||
|
||||
# Copyright 2015 Lenovo
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# This module provides access to SDR offered by a BMC
|
||||
# This data is common between 'sensors' and 'inventory' modules since SDR
|
||||
# is both used to enumerate sensors for sensor commands and FRU ids for FRU
|
||||
# commands
|
||||
|
||||
# For now, we will not offer persistent SDR caching as we do in xCAT's IPMI
|
||||
# code. Will see if it is adequate to advocate for high object reuse in a
|
||||
# persistent process for the moment.
|
||||
|
||||
# Focus is at least initially on the aspects that make the most sense for a
|
||||
# remote client to care about. For example, smbus information is being
|
||||
# skipped for now
|
||||
|
||||
# This file handles parsing of fru format records as presented by IPMI
|
||||
# devices. This format is documented in the 'Platform Management FRU
|
||||
# Information Storage Definition (Document Revision 1.2)
|
||||
|
||||
import pyghmi.exceptions as iexc
|
||||
import pyghmi.ipmi.private.spd as spd
|
||||
import struct
|
||||
import time
|
||||
|
||||
fruepoch = time.mktime(time.strptime('1/1/1996', "%m/%d/%Y"))
|
||||
|
||||
# This is from SMBIOS specification Table 16
|
||||
enclosure_types = {
|
||||
1: 'Other',
|
||||
2: 'Unknown',
|
||||
3: 'Desktop',
|
||||
4: 'Low Profile Desktop',
|
||||
5: 'Pizza Box',
|
||||
6: 'Mini Tower',
|
||||
7: 'Tower',
|
||||
8: 'Portable',
|
||||
9: 'Laptop',
|
||||
0xa: 'Notebook',
|
||||
0xb: 'Hand Held',
|
||||
0xc: 'Docking Station',
|
||||
0xd: 'All in One',
|
||||
0xe: 'Sub Notebook',
|
||||
0xf: 'Space-saving',
|
||||
0x10: 'Lunch Box',
|
||||
0x11: 'Main Server Chassis',
|
||||
0x12: 'Expansion Chassis',
|
||||
0x13: 'SubChassis',
|
||||
0x14: 'Bus Expansion Chassis',
|
||||
0x15: 'Peripheral Chassis',
|
||||
0x16: 'RAID Chassis',
|
||||
0x17: 'Rack Mount Chassis',
|
||||
0x18: 'Sealed-case PC',
|
||||
0x19: 'Multi-system Chassis',
|
||||
0x1a: 'Compact PCI',
|
||||
0x1b: 'Advanced TCA',
|
||||
0x1c: 'Blade',
|
||||
0x1d: 'Blade Enclosure',
|
||||
}
|
||||
|
||||
|
||||
def unpack6bitascii(inputdata):
|
||||
# This is a text encoding scheme that seems unique
|
||||
# to IPMI FRU. It seems to be relatively rare in practice
|
||||
result = ''
|
||||
while len(inputdata) > 0:
|
||||
currchunk = inputdata[:3]
|
||||
del inputdata[:3]
|
||||
currchar = currchunk[0] & 0b111111
|
||||
result += chr(0x20 + currchar)
|
||||
currchar = (currchunk[0] & 0b11000000) >> 6
|
||||
currchar |= (currchunk[1] & 0b1111) << 2
|
||||
result += chr(0x20 + currchar)
|
||||
currchar = (currchunk[1] & 0b1111000) >> 4
|
||||
currchar |= (currchunk[2] & 0b11) << 4
|
||||
result += chr(0x20 + currchar)
|
||||
currchar = (currchunk[2] & 0b11111100) >> 2
|
||||
result += chr(0x20 + currchar)
|
||||
return result
|
||||
|
||||
|
||||
def decode_fru_date(datebytes):
|
||||
# Returns ISO
|
||||
datebytes.append(0)
|
||||
minutesfromepoch = struct.unpack('<I', struct.pack('4B', *datebytes))[0]
|
||||
# Some data in the field has had some data less than 800
|
||||
# At this juncture, it's far more likely for this noise
|
||||
# to be incorrect than anything in particular
|
||||
if minutesfromepoch < 800:
|
||||
return None
|
||||
return time.strftime('%Y-%m-%dT%H:%M',
|
||||
time.gmtime((minutesfromepoch * 60) + fruepoch))
|
||||
|
||||
|
||||
class FRU(object):
|
||||
"""An object representing structure
|
||||
|
||||
FRU (Field Replaceable Unit) is the usual format for inventory in IPMI
|
||||
devices. This covers most standards compliant inventory data
|
||||
as well as presenting less well defined fields in a structured way.
|
||||
|
||||
:param rawdata: A binary string/bytearray of raw data from BMC or dump
|
||||
:param ipmicmd: An ipmi command object to fetch data live
|
||||
:param fruid: The identifier number of the FRU
|
||||
:param sdr: The sdr locator entry to help clarify how to parse data
|
||||
"""
|
||||
|
||||
def __init__(self, rawdata=None, ipmicmd=None, fruid=0, sdr=None):
|
||||
self.rawfru = rawdata
|
||||
self.databytes = None
|
||||
self.info = None
|
||||
self.sdr = sdr
|
||||
if self.rawfru is not None:
|
||||
self.parsedata()
|
||||
elif ipmicmd is not None:
|
||||
self.ipmicmd = ipmicmd
|
||||
# Use the ipmicmd to fetch the data
|
||||
try:
|
||||
self.fetch_fru(fruid)
|
||||
except iexc.IpmiException as ie:
|
||||
if ie.ipmicode == 203:
|
||||
self.info = 'Not Present'
|
||||
return
|
||||
self.parsedata()
|
||||
else:
|
||||
raise TypeError('Either rawdata or ipmicmd must be specified')
|
||||
|
||||
def fetch_fru(self, fruid):
|
||||
response = self.ipmicmd.raw_command(
|
||||
netfn=0xa, command=0x10, data=[fruid])
|
||||
if 'error' in response:
|
||||
raise iexc.IpmiException(response['error'], code=response['code'])
|
||||
frusize = response['data'][0] | (response['data'][1] << 8)
|
||||
# In our case, we don't need to think too hard about whether
|
||||
# the FRU is word or byte, we just process what we get back in the
|
||||
# payload
|
||||
chunksize = 240
|
||||
# Selected as it is accomodated by most tested things
|
||||
# and many tested things broke after going much
|
||||
# bigger
|
||||
if chunksize > frusize:
|
||||
chunksize = frusize
|
||||
offset = 0
|
||||
self.rawfru = bytearray([])
|
||||
while chunksize:
|
||||
response = self.ipmicmd.raw_command(
|
||||
netfn=0xa, command=0x11, data=[fruid, offset & 0xff,
|
||||
offset >> 8, chunksize])
|
||||
if response['code'] == 201:
|
||||
# if it was too big, back off and try smaller
|
||||
# Try just over half to mitigate the chance of
|
||||
# one request becoming three rather than just two
|
||||
if chunksize == 3:
|
||||
raise iexc.IpmiException(response['error'])
|
||||
chunksize //= 2
|
||||
chunksize += 2
|
||||
continue
|
||||
elif 'error' in response:
|
||||
raise iexc.IpmiException(response['error'])
|
||||
self.rawfru.extend(response['data'][1:])
|
||||
offset += response['data'][0]
|
||||
if offset + chunksize > frusize:
|
||||
chunksize = frusize - offset
|
||||
|
||||
def parsedata(self):
|
||||
self.info = {}
|
||||
rawdata = self.rawfru
|
||||
self.databytes = bytearray(rawdata)
|
||||
if self.sdr is not None:
|
||||
frutype = self.sdr.fru_type_and_modifier >> 8
|
||||
frusubtype = self.sdr.fru_type_and_modifier & 0xff
|
||||
if frutype > 0x10 or frutype < 0x8 or frusubtype not in (0, 1, 2):
|
||||
raise iexc.PyghmiException(
|
||||
'Unsupported FRU device: {0:x}h, {1:x}h'.format(frutype,
|
||||
frusubtype
|
||||
))
|
||||
elif frusubtype == 1:
|
||||
self.myspd = spd.SPD(self.databytes)
|
||||
self.info = self.myspd.info
|
||||
return
|
||||
if self.databytes[0] != 1:
|
||||
raise iexc.BmcErrorException("Invalid/Unsupported FRU format")
|
||||
# Ignore the internal use even if present.
|
||||
self._parse_chassis()
|
||||
self._parse_board()
|
||||
self._parse_prod()
|
||||
# TODO(jjohnson2): Multi Record area
|
||||
|
||||
def _decode_tlv(self, offset, lang=0):
|
||||
currtlv = self.databytes[offset]
|
||||
currlen = currtlv & 0b111111
|
||||
currtype = (currtlv & 0b11000000) >> 6
|
||||
retinfo = self.databytes[offset + 1:offset + currlen]
|
||||
newoffset = offset + currlen + 1
|
||||
if currlen == 0:
|
||||
return None, newoffset
|
||||
if currtype == 0:
|
||||
# return it as a bytearray, not much to be done for it
|
||||
return retinfo, newoffset
|
||||
elif currtype == 3: # text string
|
||||
if lang == 0:
|
||||
retinfo = retinfo.decode('utf-8')
|
||||
else:
|
||||
retinfo = retinfo.decode('utf-16le')
|
||||
retinfo = retinfo.replace('\x00', '')
|
||||
return retinfo, newoffset
|
||||
elif currtype == 1: # BCD 'plus'
|
||||
retdata = ''
|
||||
for byte in retinfo:
|
||||
byte = hex(byte).replace('0x', '').replace('a', ' ').replace(
|
||||
'b', '-').replace('c', '.')
|
||||
retdata += byte
|
||||
return retdata, newoffset
|
||||
elif currtype == 2: # 6-bit ascii
|
||||
retinfo = unpack6bitascii(retinfo)
|
||||
return retinfo, newoffset
|
||||
|
||||
def _parse_chassis(self):
|
||||
offset = 8 * self.databytes[2]
|
||||
if offset == 0:
|
||||
return
|
||||
if self.databytes[offset] & 0b1111 != 1:
|
||||
raise iexc.BmcErrorException("Invallid/Unsupported chassis area")
|
||||
inf = self.info
|
||||
# ignore length field, just process the data
|
||||
inf['chassis_type'] = enclosure_types[self.databytes[offset + 2]]
|
||||
inf['chassis_part_number'], offset = self._decode_tlv(offset + 3)
|
||||
inf['chassis_serial'], offset = self._decode_tlv(offset)
|
||||
inf['chassis_extra'] = []
|
||||
while self.databytes[offset] != 0xc1:
|
||||
fielddata, offset = self._decode_tlv(offset)
|
||||
inf['chassis_extra'].append(fielddata)
|
||||
|
||||
def _parse_board(self):
|
||||
offset = 8 * self.databytes[3]
|
||||
if offset == 0:
|
||||
return
|
||||
if self.databytes[offset] & 0b1111 != 1:
|
||||
raise iexc.BmcErrorException("Invalid/Unsupported board info area")
|
||||
inf = self.info
|
||||
language = self.databytes[offset + 2]
|
||||
inf['board_mfg_date'] = decode_fru_date(
|
||||
self.databytes[offset + 3:offset + 6])
|
||||
inf['board_manufacturer'], offset = self._decode_tlv(offset + 6)
|
||||
inf['board_product'], offset = self._decode_tlv(offset, language)
|
||||
inf['board_serial'], offset = self._decode_tlv(offset, language)
|
||||
inf['board_model'], offset = self._decode_tlv(offset, language)
|
||||
_, offset = self._decode_tlv(offset, language) # decode but discard
|
||||
inf['board_extra'] = []
|
||||
while self.databytes[offset] != 0xc1:
|
||||
fielddata, offset = self._decode_tlv(offset, language)
|
||||
inf['board_extra'].append(fielddata)
|
||||
|
||||
def _parse_prod(self):
|
||||
offset = 8 * self.databytes[4]
|
||||
if offset == 0:
|
||||
return
|
||||
inf = self.info
|
||||
language = self.databytes[offset + 2]
|
||||
inf['product_manufacturer'], offset = self._decode_tlv(offset + 3,
|
||||
language)
|
||||
inf['product_name'], offset = self._decode_tlv(offset, language)
|
||||
inf['product_model'], offset = self._decode_tlv(offset, language)
|
||||
inf['product_version'], offset = self._decode_tlv(offset, language)
|
||||
inf['product_serial'], offset = self._decode_tlv(offset, language)
|
||||
inf['product_asset'], offset = self._decode_tlv(offset, language)
|
||||
_, offset = self._decode_tlv(offset, language)
|
||||
inf['product_extra'] = []
|
||||
while self.databytes[offset] != 0xc1:
|
||||
fielddata, offset = self._decode_tlv(offset, language)
|
||||
inf['product_extra'].append(fielddata)
|
||||
|
||||
def __repr__(self):
|
||||
return repr(self.info)
|
||||
# retdata = 'Chassis data\n'
|
||||
# retdata += ' Type: ' + repr(self.chassis_type) + '\n'
|
||||
# retdata += ' Part Number: ' + repr(self.chassis_part_number) + '\n'
|
||||
# retdata += ' Serial Number: ' + repr(self.chassis_serial) + '\n'
|
||||
# retdata += ' Extra: ' + repr(self.chassis_extra) + '\n'
|
||||
# retdata += 'Board data\n'
|
||||
# retdata += ' Manufacturer: ' + repr(self.board_manufacturer) + '\n'
|
||||
# retdata += ' Date: ' + repr(self.board_mfg_date) + '\n'
|
||||
# retdata += ' Product' + repr(self.board_product) + '\n'
|
||||
# retdata += ' Serial: ' + repr(self.board_serial) + '\n'
|
||||
# retdata += ' Model: ' + repr(self.board_model) + '\n'
|
||||
# retdata += ' Extra: ' + repr(self.board_extra) + '\n'
|
||||
# retdata += 'Product data\n'
|
||||
# retdata += ' Manufacturer: ' + repr(self.product_manufacturer)+'\n'
|
||||
# retdata += ' Name: ' + repr(self.product_name) + '\n'
|
||||
# retdata += ' Model: ' + repr(self.product_model) + '\n'
|
||||
# retdata += ' Version: ' + repr(self.product_version) + '\n'
|
||||
# retdata += ' Serial: ' + repr(self.product_serial) + '\n'
|
||||
# retdata += ' Asset: ' + repr(self.product_asset) + '\n'
|
||||
# retdata += ' Extra: ' + repr(self.product_extra) + '\n'
|
||||
# return retdata
|
768
pyghmi/ipmi/private/spd.py
Normal file
768
pyghmi/ipmi/private/spd.py
Normal file
@ -0,0 +1,768 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
# coding=utf8
|
||||
|
||||
# Copyright 2015 Lenovo
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# This implements parsing of DDR SPD data. This is offered up in a pass
|
||||
# through fashion by some service processors.
|
||||
|
||||
# For now, just doing DDR3 and DDR4
|
||||
|
||||
# In many cases, astute readers will note that some of the lookup tables
|
||||
# should be a matter of math rather than lookup. However the SPD
|
||||
# specification explicitly reserves values not in the lookup tables for
|
||||
# future use. It has happened, for example, that a spec was amended
|
||||
# with discontinuous values for a field that was until that point
|
||||
# possible to derive in a formulaic way
|
||||
|
||||
import struct
|
||||
|
||||
jedec_ids = [
|
||||
{
|
||||
0x01: "AMD",
|
||||
0x02: "AMI",
|
||||
0x83: "Fairchild",
|
||||
0x04: "Fujitsu",
|
||||
0x85: "GTE",
|
||||
0x86: "Harris",
|
||||
0x07: "Hitachi",
|
||||
0x08: "Inmos",
|
||||
0x89: "Intel",
|
||||
0x8a: "I.T.T.",
|
||||
0x0b: "Intersil",
|
||||
0x8c: "Monolithic Memories",
|
||||
0x0d: "Mostek",
|
||||
0x0e: "Motorola",
|
||||
0x8f: "National",
|
||||
0x10: "NEC",
|
||||
0x91: "RCA",
|
||||
0x92: "Raytheon",
|
||||
0x13: "Conexant (Rockwell)",
|
||||
0x94: "Seeq",
|
||||
0x15: "Philips Semi. (Signetics)",
|
||||
0x16: "Synertek",
|
||||
0x97: "Texas Instruments",
|
||||
0x98: "Toshiba",
|
||||
0x19: "Xicor",
|
||||
0x1a: "Zilog",
|
||||
0x9b: "Eurotechnique",
|
||||
0x1c: "Mitsubishi",
|
||||
0x9d: "Lucent (AT&T)",
|
||||
0x9e: "Exel",
|
||||
0x1f: "Atmel",
|
||||
0x20: "SGS/Thomson",
|
||||
0xa1: "Lattice Semi.",
|
||||
0xa2: "NCR",
|
||||
0x23: "Wafer Scale Integration",
|
||||
0xa4: "IBM",
|
||||
0x25: "Tristar",
|
||||
0x26: "Visic",
|
||||
0xa7: "Intl. CMOS Technology",
|
||||
0xa8: "SSSI",
|
||||
0x29: "Microchip Technology",
|
||||
0x2a: "Ricoh Ltd.",
|
||||
0xab: "VLSI",
|
||||
0x2c: "Micron Technology",
|
||||
0xad: "Hyundai Electronics",
|
||||
0xae: "OKI Semiconductor",
|
||||
0x2f: "ACTEL",
|
||||
0xb0: "Sharp",
|
||||
0x31: "Catalyst",
|
||||
0x32: "Panasonic",
|
||||
0xb3: "IDT",
|
||||
0x34: "Cypress",
|
||||
0xb5: "DEC",
|
||||
0xb6: "LSI Logic",
|
||||
0x37: "Zarlink",
|
||||
0x38: "UTMC",
|
||||
0xb9: "Thinking Machine",
|
||||
0xba: "Thomson CSF",
|
||||
0x3b: "Integrated CMOS(Vertex)",
|
||||
0xbc: "Honeywell",
|
||||
0x3d: "Tektronix",
|
||||
0x3e: "Sun Microsystems",
|
||||
0xbf: "SST",
|
||||
0x40: "MOSEL",
|
||||
0xc1: "Infineon",
|
||||
0xc2: "Macronix",
|
||||
0x43: "Xerox",
|
||||
0xc4: "Plus Logic",
|
||||
0x45: "SunDisk",
|
||||
0x46: "Elan Circuit Tech.",
|
||||
0xc7: "European Silicon Str.",
|
||||
0xc8: "Apple Computer",
|
||||
0xc9: "Xilinx",
|
||||
0x4a: "Compaq",
|
||||
0xcb: "Protocol Engines",
|
||||
0x4c: "SCI",
|
||||
0xcd: "Seiko Instruments",
|
||||
0xce: "Samsung",
|
||||
0x4f: "I3 Design System",
|
||||
0xd0: "Klic",
|
||||
0x51: "Crosspoint Solutions",
|
||||
0x52: "Alliance Semiconductor",
|
||||
0xd3: "Tandem",
|
||||
0x54: "Hewlett-Packard",
|
||||
0xd5: "Intg. Silicon Solutions",
|
||||
0xd6: "Brooktree",
|
||||
0x57: "New Media",
|
||||
0x58: "MHS Electronic",
|
||||
0xd9: "Performance Semi.",
|
||||
0xda: "Winbond Electronic",
|
||||
0x5b: "Kawasaki Steel",
|
||||
0xdc: "Bright Micro",
|
||||
0x5d: "TECMAR",
|
||||
0x5e: "Exar",
|
||||
0xdf: "PCMCIA",
|
||||
0xe0: "LG Semiconductor",
|
||||
0x61: "Northern Telecom",
|
||||
0x62: "Sanyo",
|
||||
0xe3: "Array Microsystems",
|
||||
0x64: "Crystal Semiconductor",
|
||||
0xe5: "Analog Devices",
|
||||
0xe6: "PMC-Sierra",
|
||||
0x67: "Asparix",
|
||||
0x68: "Convex Computer",
|
||||
0xe9: "Quality Semiconductor",
|
||||
0xea: "Nimbus Technology",
|
||||
0x6b: "Transwitch",
|
||||
0xec: "Micronas (ITT Intermetall)",
|
||||
0x6d: "Cannon",
|
||||
0x6e: "Altera",
|
||||
0xef: "NEXCOM",
|
||||
0x70: "QUALCOMM",
|
||||
0xf1: "Sony",
|
||||
0xf2: "Cray Research",
|
||||
0x73: "AMS (Austria Micro)",
|
||||
0xf4: "Vitesse",
|
||||
0x75: "Aster Electronics",
|
||||
0x76: "Bay Networks (Synoptic)",
|
||||
0xf7: "Zentrum",
|
||||
0xf8: "TRW",
|
||||
0x79: "Thesys",
|
||||
0x7a: "Solbourne Computer",
|
||||
0xfb: "Allied-Signal",
|
||||
0x7c: "Dialog",
|
||||
0xfd: "Media Vision",
|
||||
0xfe: "Level One Communication",
|
||||
},
|
||||
{
|
||||
0x01: "Cirrus Logic",
|
||||
0x02: "National Instruments",
|
||||
0x83: "ILC Data Device",
|
||||
0x04: "Alcatel Mietec",
|
||||
0x85: "Micro Linear",
|
||||
0x86: "Univ. of NC",
|
||||
0x07: "JTAG Technologies",
|
||||
0x08: "Loral",
|
||||
0x89: "Nchip",
|
||||
0x8A: "Galileo Tech",
|
||||
0x0B: "Bestlink Systems",
|
||||
0x8C: "Graychip",
|
||||
0x0D: "GENNUM",
|
||||
0x0E: "VideoLogic",
|
||||
0x8F: "Robert Bosch",
|
||||
0x10: "Chip Express",
|
||||
0x91: "DATARAM",
|
||||
0x92: "United Microelec Corp.",
|
||||
0x13: "TCSI",
|
||||
0x94: "Smart Modular",
|
||||
0x15: "Hughes Aircraft",
|
||||
0x16: "Lanstar Semiconductor",
|
||||
0x97: "Qlogic",
|
||||
0x98: "Kingston",
|
||||
0x19: "Music Semi",
|
||||
0x1A: "Ericsson Components",
|
||||
0x9B: "SpaSE",
|
||||
0x1C: "Eon Silicon Devices",
|
||||
0x9D: "Programmable Micro Corp",
|
||||
0x9E: "DoD",
|
||||
0x1F: "Integ. Memories Tech.",
|
||||
0x20: "Corollary Inc.",
|
||||
0xA1: "Dallas Semiconductor",
|
||||
0xA2: "Omnivision",
|
||||
0x23: "EIV(Switzerland)",
|
||||
0xA4: "Novatel Wireless",
|
||||
0x25: "Zarlink (formerly Mitel)",
|
||||
0x26: "Clearpoint",
|
||||
0xA7: "Cabletron",
|
||||
0xA8: "Silicon Technology",
|
||||
0x29: "Vanguard",
|
||||
0x2A: "Hagiwara Sys-Com",
|
||||
0xAB: "Vantis",
|
||||
0x2C: "Celestica",
|
||||
0xAD: "Century",
|
||||
0xAE: "Hal Computers",
|
||||
0x2F: "Rohm Company Ltd.",
|
||||
0xB0: "Juniper Networks",
|
||||
0x31: "Libit Signal Processing",
|
||||
0x32: "Enhanced Memories Inc.",
|
||||
0xB3: "Tundra Semiconductor",
|
||||
0x34: "Adaptec Inc.",
|
||||
0xB5: "LightSpeed Semi.",
|
||||
0xB6: "ZSP Corp.",
|
||||
0x37: "AMIC Technology",
|
||||
0x38: "Adobe Systems",
|
||||
0xB9: "Dynachip",
|
||||
0xBA: "PNY Electronics",
|
||||
0x3B: "Newport Digital",
|
||||
0xBC: "MMC Networks",
|
||||
0x3D: "T Square",
|
||||
0x3E: "Seiko Epson",
|
||||
0xBF: "Broadcom",
|
||||
0x40: "Viking Components",
|
||||
0xC1: "V3 Semiconductor",
|
||||
0xC2: "Flextronics (formerly Orbit)",
|
||||
0x43: "Suwa Electronics",
|
||||
0xC4: "Transmeta",
|
||||
0x45: "Micron CMS",
|
||||
0x46: "American Computer & Digital Components Inc",
|
||||
0xC7: "Enhance 3000 Inc",
|
||||
0xC8: "Tower Semiconductor",
|
||||
0x49: "CPU Design",
|
||||
0x4A: "Price Point",
|
||||
0xCB: "Maxim Integrated Product",
|
||||
0x4C: "Tellabs",
|
||||
0xCD: "Centaur Technology",
|
||||
0xCE: "Unigen Corporation",
|
||||
0x4F: "Transcend Information",
|
||||
0xD0: "Memory Card Technology",
|
||||
0x51: "CKD Corporation Ltd.",
|
||||
0x52: "Capital Instruments, Inc.",
|
||||
0xD3: "Aica Kogyo, Ltd.",
|
||||
0x54: "Linvex Technology",
|
||||
0xD5: "MSC Vertriebs GmbH",
|
||||
0xD6: "AKM Company, Ltd.",
|
||||
0x57: "Dynamem, Inc.",
|
||||
0x58: "NERA ASA",
|
||||
0xD9: "GSI Technology",
|
||||
0xDA: "Dane-Elec (C Memory)",
|
||||
0x5B: "Acorn Computers",
|
||||
0xDC: "Lara Technology",
|
||||
0x5D: "Oak Technology, Inc.",
|
||||
0x5E: "Itec Memory",
|
||||
0xDF: "Tanisys Technology",
|
||||
0xE0: "Truevision",
|
||||
0x61: "Wintec Industries",
|
||||
0x62: "Super PC Memory",
|
||||
0xE3: "MGV Memory",
|
||||
0x64: "Galvantech",
|
||||
0xE5: "Gadzoox Nteworks",
|
||||
0xE6: "Multi Dimensional Cons.",
|
||||
0x67: "GateField",
|
||||
0x68: "Integrated Memory System",
|
||||
0xE9: "Triscend",
|
||||
0xEA: "XaQti",
|
||||
0x6B: "Goldenram",
|
||||
0xEC: "Clear Logic",
|
||||
0x6D: "Cimaron Communications",
|
||||
0x6E: "Nippon Steel Semi. Corp.",
|
||||
0xEF: "Advantage Memory",
|
||||
0x70: "AMCC",
|
||||
0xF1: "LeCroy",
|
||||
0xF2: "Yamaha Corporation",
|
||||
0x73: "Digital Microwave",
|
||||
0xF4: "NetLogic Microsystems",
|
||||
0x75: "MIMOS Semiconductor",
|
||||
0x76: "Advanced Fibre",
|
||||
0xF7: "BF Goodrich Data.",
|
||||
0xF8: "Epigram",
|
||||
0x79: "Acbel Polytech Inc.",
|
||||
0x7A: "Apacer Technology",
|
||||
0xFB: "Admor Memory",
|
||||
0x7C: "FOXCONN",
|
||||
0xFD: "Quadratics Superconductor",
|
||||
0xFE: "3COM",
|
||||
},
|
||||
{
|
||||
0x01: "Camintonn Corporation",
|
||||
0x02: "ISOA Incorporated",
|
||||
0x83: "Agate Semiconductor",
|
||||
0x04: "ADMtek Incorporated",
|
||||
0x85: "HYPERTEC",
|
||||
0x86: "Adhoc Technologies",
|
||||
0x07: "MOSAID Technologies",
|
||||
0x08: "Ardent Technologies",
|
||||
0x89: "Switchcore",
|
||||
0x8A: "Cisco Systems, Inc.",
|
||||
0x0B: "Allayer Technologies",
|
||||
0x8C: "WorkX AG",
|
||||
0x0D: "Oasis Semiconductor",
|
||||
0x0E: "Novanet Semiconductor",
|
||||
0x8F: "E-M Solutions",
|
||||
0x10: "Power General",
|
||||
0x91: "Advanced Hardware Arch.",
|
||||
0x92: "Inova Semiconductors GmbH",
|
||||
0x13: "Telocity",
|
||||
0x94: "Delkin Devices",
|
||||
0x15: "Symagery Microsystems",
|
||||
0x16: "C-Port Corporation",
|
||||
0x97: "SiberCore Technologies",
|
||||
0x98: "Southland Microsystems",
|
||||
0x19: "Malleable Technologies",
|
||||
0x1A: "Kendin Communications",
|
||||
0x9B: "Great Technology Microcomputer",
|
||||
0x1C: "Sanmina Corporation",
|
||||
0x9D: "HADCO Corporation",
|
||||
0x9E: "Corsair",
|
||||
0x1F: "Actrans System Inc.",
|
||||
0x20: "ALPHA Technologies",
|
||||
0xA1: "Cygnal Integrated Products Incorporated",
|
||||
0xA2: "Artesyn Technologies",
|
||||
0x23: "Align Manufacturing",
|
||||
0xA4: "Peregrine Semiconductor",
|
||||
0x25: "Chameleon Systems",
|
||||
0x26: "Aplus Flash Technology",
|
||||
0xA7: "MIPS Technologies",
|
||||
0xA8: "Chrysalis ITS",
|
||||
0x29: "ADTEC Corporation",
|
||||
0x2A: "Kentron Technologies",
|
||||
0xAB: "Win Technologies",
|
||||
0x2C: "ASIC Designs Inc",
|
||||
0xAD: "Extreme Packet Devices",
|
||||
0xAE: "RF Micro Devices",
|
||||
0x2F: "Siemens AG",
|
||||
0xB0: "Sarnoff Corporation",
|
||||
0x31: "Itautec Philco SA",
|
||||
0x32: "Radiata Inc.",
|
||||
0xB3: "Benchmark Elect. (AVEX)",
|
||||
0x34: "Legend",
|
||||
0xB5: "SpecTek Incorporated",
|
||||
0xB6: "Hi/fn",
|
||||
0x37: "Enikia Incorporated",
|
||||
0x38: "SwitchOn Networks",
|
||||
0xB9: "AANetcom Incorporated",
|
||||
0xBA: "Micro Memory Bank",
|
||||
0x3B: "ESS Technology",
|
||||
0xBC: "Virata Corporation",
|
||||
0x3D: "Excess Bandwidth",
|
||||
0x3E: "West Bay Semiconductor",
|
||||
0xBF: "DSP Group",
|
||||
0x40: "Newport Communications",
|
||||
0xC1: "Chip2Chip Incorporated",
|
||||
0xC2: "Phobos Corporation",
|
||||
0x43: "Intellitech Corporation",
|
||||
0xC4: "Nordic VLSI ASA",
|
||||
0x45: "Ishoni Networks",
|
||||
0x46: "Silicon Spice",
|
||||
0xC7: "Alchemy Semiconductor",
|
||||
0xC8: "Agilent Technologies",
|
||||
0x49: "Centillium Communications",
|
||||
0x4A: "W.L. Gore",
|
||||
0xCB: "HanBit Electronics",
|
||||
0x4C: "GlobeSpan",
|
||||
0xCD: "Element 14",
|
||||
0xCE: "Pycon",
|
||||
0x4F: "Saifun Semiconductors",
|
||||
0xD0: "Sibyte, Incorporated",
|
||||
0x51: "MetaLink Technologies",
|
||||
0x52: "Feiya Technology",
|
||||
0xD3: "I & C Technology",
|
||||
0x54: "Shikatronics",
|
||||
0xD5: "Elektrobit",
|
||||
0xD6: "Megic",
|
||||
0x57: "Com-Tier",
|
||||
0x58: "Malaysia Micro Solutions",
|
||||
0xD9: "Hyperchip",
|
||||
0xDA: "Gemstone Communications",
|
||||
0x5B: "Anadyne Microelectronics",
|
||||
0xDC: "3ParData",
|
||||
0x5D: "Mellanox Technologies",
|
||||
0x5E: "Tenx Technologies",
|
||||
0xDF: "Helix AG",
|
||||
0xE0: "Domosys",
|
||||
0x61: "Skyup Technology",
|
||||
0x62: "HiNT Corporation",
|
||||
0xE3: "Chiaro",
|
||||
0x64: "MCI Computer GMBH",
|
||||
0xE5: "Exbit Technology A/S",
|
||||
0xE6: "Integrated Technology Express",
|
||||
0x67: "AVED Memory",
|
||||
0x68: "Legerity",
|
||||
0xE9: "Jasmine Networks",
|
||||
0xEA: "Caspian Networks",
|
||||
0x6B: "nCUBE",
|
||||
0xEC: "Silicon Access Networks",
|
||||
0x6D: "FDK Corporation",
|
||||
0x6E: "High Bandwidth Access",
|
||||
0xEF: "MultiLink Technology",
|
||||
0x70: "BRECIS",
|
||||
0xF1: "World Wide Packets",
|
||||
0xF2: "APW",
|
||||
0x73: "Chicory Systems",
|
||||
0xF4: "Xstream Logic",
|
||||
0x75: "Fast-Chip",
|
||||
0x76: "Zucotto Wireless",
|
||||
0xF7: "Realchip",
|
||||
0xF8: "Galaxy Power",
|
||||
0x79: "eSilicon",
|
||||
0x7A: "Morphics Technology",
|
||||
0xFB: "Accelerant Networks",
|
||||
0x7C: "Silicon Wave",
|
||||
0xFD: "SandCraft",
|
||||
0xFE: "Elpida",
|
||||
},
|
||||
{
|
||||
0x01: "Solectron",
|
||||
0x02: "Optosys Technologies",
|
||||
0x83: "Buffalo (Formerly Melco)",
|
||||
0x04: "TriMedia Technologies",
|
||||
0x85: "Cyan Technologies",
|
||||
0x86: "Global Locate",
|
||||
0x07: "Optillion",
|
||||
0x08: "Terago Communications",
|
||||
0x89: "Ikanos Communications",
|
||||
0x8A: "Princeton Technology",
|
||||
0x0B: "Nanya Technology",
|
||||
0x8C: "Elite Flash Storage",
|
||||
0x0D: "Mysticom",
|
||||
0x0E: "LightSand Communications",
|
||||
0x8F: "ATI Technologies",
|
||||
0x10: "Agere Systems",
|
||||
0x91: "NeoMagic",
|
||||
0x92: "AuroraNetics",
|
||||
0x13: "Golden Empire",
|
||||
0x94: "Muskin",
|
||||
0x15: "Tioga Technologies",
|
||||
0x16: "Netlist",
|
||||
0x97: "TeraLogic",
|
||||
0x98: "Cicada Semiconductor",
|
||||
0x19: "Centon Electronics",
|
||||
0x1A: "Tyco Electronics",
|
||||
0x9B: "Magis Works",
|
||||
0x1C: "Zettacom",
|
||||
0x9D: "Cogency Semiconductor",
|
||||
0x9E: "Chipcon AS",
|
||||
0x1F: "Aspex Technology",
|
||||
0x20: "F5 Networks",
|
||||
0xA1: "Programmable Silicon Solutions",
|
||||
0xA2: "ChipWrights",
|
||||
0x23: "Acorn Networks",
|
||||
0xA4: "Quicklogic",
|
||||
0x25: "Kingmax Semiconductor",
|
||||
0x26: "BOPS",
|
||||
0xA7: "Flasys",
|
||||
0xA8: "BitBlitz Communications",
|
||||
0x29: "eMemory Technology",
|
||||
0x2A: "Procket Networks",
|
||||
0xAB: "Purple Ray",
|
||||
0x2C: "Trebia Networks",
|
||||
0xAD: "Delta Electronics",
|
||||
0xAE: "Onex Communications",
|
||||
0x2F: "Ample Communications",
|
||||
0xB0: "Memory Experts Intl",
|
||||
0x31: "Astute Networks",
|
||||
0x32: "Azanda Network Devices",
|
||||
0xB3: "Dibcom",
|
||||
0x34: "Tekmos",
|
||||
0xB5: "API NetWorks",
|
||||
0xB6: "Bay Microsystems",
|
||||
0x37: "Firecron Ltd",
|
||||
0x38: "Resonext Communications",
|
||||
0xB9: "Tachys Technologies",
|
||||
0xBA: "Equator Technology",
|
||||
0x3B: "Concept Computer",
|
||||
0xBC: "SILCOM",
|
||||
0x3D: "3Dlabs",
|
||||
0x3E: "ct Magazine",
|
||||
0xBF: "Sanera Systems",
|
||||
0x40: "Silicon Packets",
|
||||
0xC1: "Viasystems Group",
|
||||
0xC2: "Simtek",
|
||||
0x43: "Semicon Devices Singapore",
|
||||
0xC4: "Satron Handelsges",
|
||||
0x45: "Improv Systems",
|
||||
0x46: "INDUSYS GmbH",
|
||||
0xC7: "Corrent",
|
||||
0xC8: "Infrant Technologies",
|
||||
0x49: "Ritek Corp",
|
||||
0x4A: "empowerTel Networks",
|
||||
0xCB: "Hypertec",
|
||||
0x4C: "Cavium Networks",
|
||||
0xCD: "PLX Technology",
|
||||
0xCE: "Massana Design",
|
||||
0x4F: "Intrinsity",
|
||||
0xD0: "Valence Semiconductor",
|
||||
0x51: "Terawave Communications",
|
||||
0x52: "IceFyre Semiconductor",
|
||||
0xD3: "Primarion",
|
||||
0x54: "Picochip Designs Ltd",
|
||||
0xD5: "Silverback Systems",
|
||||
0xD6: "Jade Star Technologies",
|
||||
0x57: "Pijnenburg Securealink",
|
||||
0x58: "MemorySolutioN",
|
||||
0xD9: "Cambridge Silicon Radio",
|
||||
0xDA: "Swissbit",
|
||||
0x5B: "Nazomi Communications",
|
||||
0xDC: "eWave System",
|
||||
0x5D: "Rockwell Collins",
|
||||
0x5E: "PAION",
|
||||
0xDF: "Alphamosaic Ltd",
|
||||
0xE0: "Sandburst",
|
||||
0x61: "SiCon Video",
|
||||
0x62: "NanoAmp Solutions",
|
||||
0xE3: "Ericsson Technology",
|
||||
0x64: "PrairieComm",
|
||||
0xE5: "Mitac International",
|
||||
0xE6: "Layer N Networks",
|
||||
0x67: "Atsana Semiconductor",
|
||||
0x68: "Allegro Networks",
|
||||
0xE9: "Marvell Semiconductors",
|
||||
0xEA: "Netergy Microelectronic",
|
||||
0x6B: "NVIDIA",
|
||||
0xEC: "Internet Machines",
|
||||
0x6D: "Peak Electronics",
|
||||
0xEF: "Accton Technology",
|
||||
0x70: "Teradiant Networks",
|
||||
0xF1: "Europe Technologies",
|
||||
0xF2: "Cortina Systems",
|
||||
0x73: "RAM Components",
|
||||
0xF4: "Raqia Networks",
|
||||
0x75: "ClearSpeed",
|
||||
0x76: "Matsushita Battery",
|
||||
0xF7: "Xelerated",
|
||||
0xF8: "SimpleTech",
|
||||
0x79: "Utron Technology",
|
||||
0x7A: "Astec International",
|
||||
0xFB: "AVM gmbH",
|
||||
0x7C: "Redux Communications",
|
||||
0xFD: "Dot Hill Systems",
|
||||
0xFE: "TeraChip",
|
||||
},
|
||||
{
|
||||
0x01: "T-RAM Incorporated",
|
||||
0x02: "Innovics Wireless",
|
||||
0x83: "Teknovus",
|
||||
0x04: "KeyEye Communications",
|
||||
0x85: "Runcom Technologies",
|
||||
0x86: "RedSwitch",
|
||||
0x07: "Dotcast",
|
||||
0x08: "Silicon Mountain Memory",
|
||||
0x89: "Signia Technologies",
|
||||
0x8A: "Pixim",
|
||||
0x0B: "Galazar Networks",
|
||||
0x8C: "White Electronic Designs",
|
||||
0x0D: "Patriot Scientific",
|
||||
0x0E: "Neoaxiom Corporation",
|
||||
0x8F: "3Y Power Technology",
|
||||
0x10: "Europe Technologies",
|
||||
0x91: "Potentia Power Systems",
|
||||
0x92: "C-guys Incorporated",
|
||||
0x13: "Digital Communications Technology Incorporated",
|
||||
0x94: "Silicon-Based Technology",
|
||||
0x15: "Fulcrum Microsystems",
|
||||
0x16: "Positivo Informatica Ltd",
|
||||
0x97: "XIOtech Corporation",
|
||||
0x98: "PortalPlayer",
|
||||
0x19: "Zhiying Software",
|
||||
0x1A: "Direct2Data",
|
||||
0x9B: "Phonex Broadband",
|
||||
0x1C: "Skyworks Solutions",
|
||||
0x9D: "Entropic Communications",
|
||||
0x9E: "Pacific Force Technology",
|
||||
0x1F: "Zensys A/S",
|
||||
0x20: "Legend Silicon Corp.",
|
||||
0xA1: "sci-worx GmbH",
|
||||
0xA2: "Oasis Silicon Systems",
|
||||
0x23: "Renesas Technology",
|
||||
0xA4: "Raza Microelectronics",
|
||||
0x25: "Phyworks",
|
||||
0x26: "MediaTek",
|
||||
0xA7: "Non-cents Productions",
|
||||
0xA8: "US Modular",
|
||||
0x29: "Wintegra Ltd",
|
||||
0x2A: "Mathstar",
|
||||
0xAB: "StarCore",
|
||||
0x2C: "Oplus Technologies",
|
||||
0xAD: "Mindspeed",
|
||||
0xAE: "Just Young Computer",
|
||||
0x2F: "Radia Communications",
|
||||
0xB0: "OCZ",
|
||||
0x31: "Emuzed",
|
||||
0x32: "LOGIC Devices",
|
||||
0xB3: "Inphi Corporation",
|
||||
0x34: "Quake Technologies",
|
||||
0xB5: "Vixel",
|
||||
0xB6: "SolusTek",
|
||||
0x37: "Kongsberg Maritime",
|
||||
0x38: "Faraday Technology",
|
||||
0xB9: "Altium Ltd.",
|
||||
0xBA: "Insyte",
|
||||
0x3B: "ARM Ltd.",
|
||||
0xBC: "DigiVision",
|
||||
0x3D: "Vativ Technologies",
|
||||
0x3E: "Endicott Interconnect Technologies",
|
||||
0xBF: "Pericom",
|
||||
0x40: "Bandspeed",
|
||||
0xC1: "LeWiz Communications",
|
||||
0xC2: "CPU Technology",
|
||||
0x43: "Ramaxel Technology",
|
||||
0xC4: "DSP Group",
|
||||
0x45: "Axis Communications",
|
||||
0x46: "Legacy Electronics",
|
||||
0xC7: "Chrontel",
|
||||
0xC8: "Powerchip Semiconductor",
|
||||
0x49: "MobilEye Technologies",
|
||||
0x4A: "Excel Semiconductor",
|
||||
0xCB: "A-DATA Technology",
|
||||
0x4C: "VirtualDigm",
|
||||
},
|
||||
]
|
||||
|
||||
memory_types = {
|
||||
1: "STD FPM DRAM",
|
||||
2: "EDO",
|
||||
3: "Pipelined Nibble",
|
||||
4: "SDRAM",
|
||||
5: "ROM",
|
||||
6: "DDR SGRAM",
|
||||
7: "DDR SDRAM",
|
||||
8: "DDR2 SDRAM",
|
||||
9: "DDR2 SDRAM FB-DIMM",
|
||||
10: "DDR2 SDRAM FB-DIMM PROBE",
|
||||
11: "DDR3 SDRAM",
|
||||
12: "DDR4 SDRAM",
|
||||
}
|
||||
|
||||
module_types = {
|
||||
1: "RDIMM",
|
||||
2: "UDIMM",
|
||||
3: "SODIMM",
|
||||
4: "Micro-DIMM",
|
||||
5: "Mini-RDIMM",
|
||||
6: "Mini-UDIMM",
|
||||
}
|
||||
|
||||
ddr3_module_capacity = {
|
||||
0: 256,
|
||||
1: 512,
|
||||
2: 1024,
|
||||
3: 2048,
|
||||
4: 4096,
|
||||
5: 8192,
|
||||
6: 16384,
|
||||
7: 32768,
|
||||
}
|
||||
|
||||
ddr3_dev_width = {
|
||||
0: 4,
|
||||
1: 8,
|
||||
2: 16,
|
||||
3: 32,
|
||||
}
|
||||
|
||||
ddr3_ranks = {
|
||||
0: 1,
|
||||
1: 2,
|
||||
2: 3,
|
||||
3: 4
|
||||
}
|
||||
|
||||
ddr3_bus_width = {
|
||||
0: 8,
|
||||
1: 16,
|
||||
2: 32,
|
||||
3: 64,
|
||||
}
|
||||
|
||||
speed_by_clock = {
|
||||
800: 6400,
|
||||
1066: 8500,
|
||||
1333: 10600,
|
||||
1600: 12800,
|
||||
1867: 14900,
|
||||
2132: 17000,
|
||||
2133: 17000,
|
||||
2134: 17000,
|
||||
}
|
||||
|
||||
|
||||
def decode_manufacturer(index, mfg):
|
||||
index &= 0x7f
|
||||
try:
|
||||
return jedec_ids[index][mfg]
|
||||
except (KeyError, IndexError):
|
||||
return 'Unknown ({0}, {1})'.format(index, mfg)
|
||||
|
||||
|
||||
def decode_spd_date(year, week):
|
||||
if year == 0 and week == 0:
|
||||
return 'Unknown'
|
||||
return '20{0:02x}-W{1:x}'.format(year, week)
|
||||
|
||||
|
||||
class SPD(object):
|
||||
def __init__(self, bytedata):
|
||||
"""Parsed memory information
|
||||
|
||||
Parse bytedata input and provide a structured detail about the
|
||||
described memory component
|
||||
|
||||
:param bytedata: A bytearray of data to decode
|
||||
:return:
|
||||
"""
|
||||
self.rawdata = bytearray(bytedata)
|
||||
spd = self.rawdata
|
||||
self.info = {'memory_type': memory_types.get(spd[2], 'Unknown')}
|
||||
if spd[2] == 11:
|
||||
self._decode_ddr3()
|
||||
elif spd[2] == 12:
|
||||
self._decode_ddr4()
|
||||
|
||||
def _decode_ddr3(self):
|
||||
spd = self.rawdata
|
||||
finetime = (spd[9] >> 4) / (spd[9] & 0xf)
|
||||
fineoffset = spd[34]
|
||||
if fineoffset & 0b10000000:
|
||||
# Take two's complement for negative offset
|
||||
fineoffset = 0 - ((fineoffset ^ 0xff) + 1)
|
||||
fineoffset = (finetime * fineoffset) * 10**-3
|
||||
mtb = spd[10] / float(spd[11])
|
||||
clock = 2 // ((mtb * spd[12] + fineoffset)*10**-3)
|
||||
self.info['speed'] = speed_by_clock.get(clock, 'Unknown')
|
||||
self.info['ecc'] = (spd[8] & 0b11000) != 0
|
||||
self.info['module_type'] = module_types.get(spd[3] & 0xf, 'Unknown')
|
||||
sdramcap = ddr3_module_capacity[spd[4] & 0xf]
|
||||
buswidth = ddr3_bus_width[spd[8] & 0b111]
|
||||
sdramwidth = ddr3_dev_width[spd[7] & 0b111]
|
||||
ranks = ddr3_ranks[(spd[7] & 0b111000) >> 3]
|
||||
self.info['capacity_mb'] = sdramcap / 8 * buswidth / sdramwidth * ranks
|
||||
self.info['manufacturer'] = decode_manufacturer(spd[117], spd[118])
|
||||
self.info['manufacture_location'] = spd[119]
|
||||
self.info['manufacture_date'] = decode_spd_date(spd[120], spd[121])
|
||||
self.info['model'] = struct.pack('18B', *spd[128:146])
|
||||
|
||||
def _decode_ddr4(self):
|
||||
spd = self.rawdata
|
||||
if spd[17] == 0:
|
||||
fineoffset = spd[125]
|
||||
if fineoffset & 0b10000000:
|
||||
fineoffset = 0 - ((fineoffset ^ 0xff) + 1)
|
||||
clock = 2 // ((0.125 * spd[18] + fineoffset * 0.001) * 0.001)
|
||||
self.info['speed'] = speed_by_clock.get(clock, 'Unknown')
|
||||
else:
|
||||
self.info['speed'] = 'Unknown'
|
||||
self.info['ecc'] = (spd[13] & 0b11000) == 0b1000
|
||||
self.info['module_type'] = module_types.get(spd[3] & 0xf,
|
||||
'Unknown')
|
||||
sdramcap = ddr3_module_capacity[spd[4] & 0xf]
|
||||
buswidth = ddr3_bus_width[spd[13] & 0b111]
|
||||
sdramwidth = ddr3_dev_width[spd[12] & 0b111]
|
||||
ranks = ddr3_ranks[(spd[12] & 0b111000) >> 3]
|
||||
self.info['capacity_mb'] = sdramcap / 8 * buswidth / sdramwidth * ranks
|
||||
self.info['manufacturer'] = decode_manufacturer(spd[320], spd[321])
|
||||
self.info['manufacture_location'] = spd[322]
|
||||
self.info['manufacture_date'] = decode_spd_date(spd[323], spd[324])
|
||||
self.info['model'] = struct.pack('18B', *spd[329:347])
|
@ -2,6 +2,7 @@
|
||||
# coding=utf8
|
||||
|
||||
# Copyright 2014 IBM Corporation
|
||||
# Copyright 2015 Lenovo
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@ -269,9 +270,6 @@ class SDREntry(object):
|
||||
self.sdrtype = TYPE_UNKNOWN # assume undefined
|
||||
self.oem_decode(entrybytes[5:])
|
||||
elif self.reportunsupported:
|
||||
#will remove once I see it stop being thrown for now
|
||||
#perhaps need some explicit mode to check for
|
||||
#unsupported things, but make do otherwise
|
||||
raise NotImplementedError
|
||||
else:
|
||||
self.sdrtype = TYPE_UNKNOWN
|
||||
@ -301,6 +299,9 @@ class SDREntry(object):
|
||||
self.sdrtype = TYPE_FRU
|
||||
self.fru_name = self.tlv_decode(entry[10], entry[11:])
|
||||
self.fru_number = entry[1]
|
||||
self.fru_logical = (entry[2] & 0b10000000) == 0b10000000
|
||||
# 0x8 to 0x10.. 0 unspecified except on 0x10, 1 is dimm
|
||||
self.fru_type_and_modifier = (entry[5] << 8) + entry[6]
|
||||
|
||||
def association_decode(self, entry):
|
||||
# table 43-4 Entity Associaition Record
|
||||
|
Loading…
x
Reference in New Issue
Block a user