Browse Source

Move checksum to a separate function. Handle CRC of FB-DIMM and DDR3

SDRAM memory modules. Based on an original patch from Paul Goyette.


git-svn-id: http://lm-sensors.org/svn/i2c-tools/trunk@5543 7894878c-1315-0410-8ee3-d5d059ff63e0
tags/v3.0.3
Jean Delvare 17 years ago
parent
commit
25dae9734d
  1. 1
      CHANGES
  2. 129
      eeprom/decode-dimms

1
CHANGES

@ -2,6 +2,7 @@ i2c-tools CHANGES
----------------- -----------------
SVN SVN
decode-dimms: Handle CRC of FB-DIMM and DDR3 SDRAM memory modules
i2c-stub-from-dump: Use udev settle to speed up initialization i2c-stub-from-dump: Use udev settle to speed up initialization
3.0.2 (2008-11-29) 3.0.2 (2008-11-29)

129
eeprom/decode-dimms

@ -1221,6 +1221,37 @@ sub read_hexdump($)
return @bytes; return @bytes;
} }
# Returns the (total, used) number of bytes in the EEPROM,
# assuming it is an SPD EEPROM.
sub spd_sizes($)
{
my $bytes = shift;
if ($bytes->[2] >= 9) {
# For FB-DIMM and newer, decode number of bytes written
my $spd_len = ($bytes->[0] >> 4) & 7;
my $size = 64 << ($bytes->[0] & 15);
if ($spd_len == 0) {
return ($size, 128);
} elsif ($spd_len == 1) {
return ($size, 176);
} elsif ($spd_len == 2) {
return ($size, 256);
} else {
return (64, 64);
}
} else {
my $size;
if ($bytes->[1] <= 14) {
$size = 1 << $bytes->[1];
} elsif ($bytes->[1] == 0) {
$size = "RFU";
} else { $size = "ERROR!" }
return ($size, ($bytes->[0] < 64) ? 64 : $bytes->[0]);
}
}
sub readspd($$) # reads bytes from SPD-EEPROM sub readspd($$) # reads bytes from SPD-EEPROM
{ {
my ($size, $dimm_i) = @_; my ($size, $dimm_i) = @_;
@ -1247,6 +1278,51 @@ sub readspd($$) # reads bytes from SPD-EEPROM
return @bytes; return @bytes;
} }
# Calculate and verify checksum of first 63 bytes
sub checksum($)
{
my $bytes = shift;
my $dimm_checksum = 0;
local $_;
$dimm_checksum += $bytes->[$_] foreach (0 .. 62);
$dimm_checksum &= 0xff;
return ("EEPROM Checksum of bytes 0-62",
($bytes->[63] == $dimm_checksum) ? 1 : 0,
sprintf('0x%02X', $bytes->[63]),
sprintf('0x%02X', $dimm_checksum));
}
# Calculate and verify CRC
sub check_crc($)
{
my $bytes = shift;
my $crc = 0;
my $crc_cover = $bytes->[0] & 0x80 ? 116 : 125;
my $crc_ptr = 0;
my $crc_bit;
while ($crc_ptr <= $crc_cover) {
$crc = $crc ^ ($bytes->[$crc_ptr] << 8);
for ($crc_bit = 0; $crc_bit < 8; $crc_bit++) {
if ($crc & 0x8000) {
$crc = ($crc << 1) ^ 0x1021;
} else {
$crc = $crc << 1
}
}
$crc_ptr++;
}
$crc &= 0xffff;
my $dimm_crc = ($bytes->[127] << 8) | $bytes->[126];
return ("EEPROM CRC of bytes 0-$crc_cover",
($dimm_crc == $crc) ? 1 : 0,
sprintf("0x%04X", $dimm_crc),
sprintf("0x%04X", $crc));
}
# Parse command-line # Parse command-line
foreach (@ARGV) { foreach (@ARGV) {
if ($_ eq '-h' || $_ eq '--help') { if ($_ eq '-h' || $_ eq '--help') {
@ -1333,11 +1409,17 @@ for my $i ( 0 .. $#dimm_list ) {
|| (!$use_sysfs && /^eeprom-/) || (!$use_sysfs && /^eeprom-/)
|| $use_hexdump) { || $use_hexdump) {
my @bytes = readspd(128, $dimm_list[$i]); my @bytes = readspd(128, $dimm_list[$i]);
my $dimm_checksum = 0;
$dimm_checksum += $bytes[$_] foreach (0 .. 62);
$dimm_checksum &= 0xff;
my ($spd_size, $spd_used) = spd_sizes(\@bytes);
my ($l, $chk_valid, $chk_spd, $chk_calc);
if ($bytes[2] < 9) {
($l, $chk_valid, $chk_spd, $chk_calc) =
checksum(\@bytes);
} else {
($l, $chk_valid, $chk_spd, $chk_calc) =
check_crc(\@bytes);
}
next unless $bytes[63] == $dimm_checksum || $opt_igncheck;
next unless $chk_valid || $opt_igncheck;
$dimm_count++; $dimm_count++;
print "<b><u>" if $opt_html; print "<b><u>" if $opt_html;
@ -1358,11 +1440,10 @@ for my $i ( 0 .. $#dimm_list ) {
# Decode first 3 bytes (0-2) # Decode first 3 bytes (0-2)
prints "SPD EEPROM Information"; prints "SPD EEPROM Information";
my $l = "EEPROM Checksum of bytes 0-62";
printl $l, ($bytes[63] == $dimm_checksum ?
sprintf("OK (0x%.2X)", $bytes[63]):
sprintf("Bad\n(found 0x%.2X, calculated 0x%.2X)\n",
$bytes[63], $dimm_checksum));
printl $l, ($chk_valid ?
sprintf("OK (%s)", $chk_calc) :
sprintf("Bad\n(found %s, calculated %s)\n",
$chk_spd, $chk_calc));
# Simple heuristic to detect Rambus # Simple heuristic to detect Rambus
my $is_rambus = $bytes[0] < 4; my $is_rambus = $bytes[0] < 4;
@ -1374,31 +1455,29 @@ for my $i ( 0 .. $#dimm_list ) {
else { $temp = "Reserved"; } else { $temp = "Reserved"; }
printl "SPD Revision", $temp; printl "SPD Revision", $temp;
} else { } else {
printl "# of bytes written to SDRAM EEPROM",
$bytes[0];
printl "# of bytes written to SDRAM EEPROM", $spd_used;
} }
$l = "Total number of bytes in EEPROM"; $l = "Total number of bytes in EEPROM";
if ($bytes[1] <= 14) {
printl $l, 2**$bytes[1];
} elsif ($bytes[1] == 0) {
printl $l, "RFU";
} else { printl $l, "ERROR!"; }
printl $l, $spd_size;
$l = "Fundamental Memory type"; $l = "Fundamental Memory type";
my $type = "Unknown";
my $type = sprintf("Unknown (0x%02x)", $bytes[2]);
if ($is_rambus) { if ($is_rambus) {
if ($bytes[2] == 1) { $type = "Direct Rambus"; } if ($bytes[2] == 1) { $type = "Direct Rambus"; }
elsif ($bytes[2] == 17) { $type = "Rambus"; } elsif ($bytes[2] == 17) { $type = "Rambus"; }
} else { } else {
if ($bytes[2] == 1) { $type = "FPM DRAM"; }
elsif ($bytes[2] == 2) { $type = "EDO"; }
elsif ($bytes[2] == 3) { $type = "Pipelined Nibble"; }
elsif ($bytes[2] == 4) { $type = "SDR SDRAM"; }
elsif ($bytes[2] == 5) { $type = "Multiplexed ROM"; }
elsif ($bytes[2] == 6) { $type = "DDR SGRAM"; }
elsif ($bytes[2] == 7) { $type = "DDR SDRAM"; }
elsif ($bytes[2] == 8) { $type = "DDR2 SDRAM"; }
my @type_list = (
"Reserved", "FPM DRAM", # 0, 1
"EDO", "Pipelined Nibble", # 2, 3
"SDR SDRAM", "Multiplexed ROM", # 4, 5
"DDR SGRAM", "DDR SDRAM", # 6, 7
"DDR2 SDRAM", "FB-DIMM", # 8, 9
"FB-DIMM Probe", "DDR3 SDRAM", # 10, 11
);
if ($bytes[2] < @type_list) {
$type = $type_list[$bytes[2]];
}
} }
printl $l, $type; printl $l, $type;

Loading…
Cancel
Save