pyghmi/pyghmi/ipmi/private/spd.py

840 lines
26 KiB
Python

# 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 math
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",
0x12: "DDR5 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,
}
def speed_from_clock(clock):
return int(clock * 8 - (clock * 8 % 100))
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()
elif spd[2] == 0x12: # ddr5
self._decode_ddr5()
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 = math.floor(2 / ((mtb * spd[12] + fineoffset) * 10 ** -3))
self.info['speed'] = speed_from_clock(clock)
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['serial'] = hex(struct.unpack(
'>I', struct.pack('4B', *spd[122:126]))[0])[2:].rjust(8, '0')
self.info['model'] = struct.pack('20B', *spd[128:148]).strip(
b'\x00\xff ')
def _decode_ddr5(self):
spd = self.rawdata
modtypes = {
1: 'RDIMM',
2: 'UDIMM',
3: 'SODIMM',
}
sdramdensities = {
1: 4,
2: 8,
3: 12,
4: 16,
5: 24,
6: 32,
7: 48,
8: 64,
}
ddp = {
0: 1,
1: 2,
2: 2,
3: 4,
4: 8,
6: 16,
}
self.info['module_type'] = modtypes.get(
spd[3], 'Unknown')
self.info['manufacturer'] = decode_manufacturer(spd[512], spd[513])
self.info['model'] = struct.pack('30B', *spd[521:551]).strip(
b'\x00\xff ')
self.info['serial'] = hex(struct.unpack(
'>I', struct.pack('4B', *spd[517:521]))[0])[2:].rjust(8, '0')
self.info['manufacture_date'] = decode_spd_date(spd[515], spd[516])
self.info['manufacture_location'] = spd[514]
self.info['ecc'] = (spd[235] & 0b11000) != 0
if spd[19] == 0:
tckmin = struct.unpack('<H', spd[20:22])[0]
self.info['speed'] = math.floor(160000.0 / tckmin) * 100
else:
self.info['speed'] = 'Unknown'
asymmetric = bool(spd[234] & 64)
numrankspersubchannel = ((spd[234] & 56) >> 3) + 1
subchannels = ((spd[235] & 0b01100000) >> 5) + 1
buswidthpersubchannel = 2 ** ((spd[235] & 0b111) + 3)
# these bits are either all, or for half the ranks in asymettric
densityperdie = spd[4]
sdramiowidth = 2**((spd[6] >> 5) + 2)
densityperdie = sdramdensities.get(spd[4] & 0b11111, 0)
diesperpackage = ddp.get(spd[4] >> 5, 1)
capacity = (subchannels
* (buswidthpersubchannel / sdramiowidth)
* diesperpackage * densityperdie / 8
* numrankspersubchannel)
if asymmetric:
capacity = capacity // 2 # the calculation is halved to make room for the odd ranks
densityperdie = spd[8]
sdramiowidth = 2**((spd[10] >> 5) + 2)
densityperdie = sdramdensities.get(spd[8] & 0b11111, 0)
diesperpackage = ddp.get(spd[8] >> 5, 1)
oddcapacity = (subchannels
* (buswidthpersubchannel / sdramiowidth)
* diesperpackage * densityperdie / 8
* numrankspersubchannel)
oddcapacity = oddcapacity // 2 # this is halved, since this is only half the ranks
capacity += oddcapacity
self.info['capacity_mb'] = capacity * 1024
def _decode_ddr4(self):
spd = self.rawdata
if spd[17] == 0:
fineoffset = spd[125]
if fineoffset & 0b10000000:
fineoffset = 0 - ((fineoffset ^ 0xff) + 1)
clock = math.floor(
2 / ((0.125 * spd[18] + fineoffset * 0.001) * 0.001))
self.info['speed'] = speed_from_clock(clock)
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]
if spd[6] & 0b11 == 0b10:
ranks = ranks * (((spd[6] >> 4) & 0b111) + 1)
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['serial'] = hex(struct.unpack(
'>I', struct.pack('4B', *spd[325:329]))[0])[2:].rjust(8, '0')
self.info['model'] = struct.pack('20B', *spd[329:349]).strip(
b'\x00\xff ')