Browse Source

Patch from Trent Piepho:

This adds a "-x" option to decode-dimms.pl, which lets one supply a list of
file names to read SPD data from.  It can parse various hexdump formats, such
as the output from i2cdump, eeprog, and the util-linux and Busybox hexdump
progams run on a sysfs eeprom file.

Useful for decoding SPD data that you cut and pasted from a manufacturer's
website or from a DIMM installed on an embedded system that does not have
perl/etc, but does have a serial console with busybox.


git-svn-id: http://lm-sensors.org/svn/i2c-tools/trunk@5157 7894878c-1315-0410-8ee3-d5d059ff63e0
tags/v3.0.1
Jean Delvare 18 years ago
parent
commit
a56e6baf47
  1. 1
      CHANGES
  2. 111
      eeprom/decode-dimms.pl

1
CHANGES

@ -6,6 +6,7 @@ SVN
Update manufacturer IDs Update manufacturer IDs
Don't print anything by default if checksum fails Don't print anything by default if checksum fails
Decode all DDR2 SDRAM timing information Decode all DDR2 SDRAM timing information
Add support for reading SPD data from hexdumps
decode-vaio: Private data might not be readable by non-root users decode-vaio: Private data might not be readable by non-root users
Print the asset tag Print the asset tag
Fix the timestamp decoding Fix the timestamp decoding

111
eeprom/decode-dimms.pl

@ -46,8 +46,8 @@ require 5.004;
use strict; use strict;
use POSIX; use POSIX;
use Fcntl qw(:DEFAULT :seek); use Fcntl qw(:DEFAULT :seek);
use vars qw($opt_html $opt_body $opt_bodyonly $opt_igncheck $use_sysfs
@vendors %decode_callback $revision);
use vars qw($opt_html $opt_body $opt_bodyonly $opt_igncheck $use_sysfs $use_hexdump
@vendors %decode_callback $revision @dimm_list);
$revision = '$Revision$ ($Date$)'; $revision = '$Revision$ ($Date$)';
$revision =~ s/\$\w+: (.*?) \$/$1/g; $revision =~ s/\$\w+: (.*?) \$/$1/g;
@ -1100,10 +1100,61 @@ sub decode_intel_spec_freq($)
printl $l, $temp; printl $l, $temp;
} }
# Read various hex dump style formats: hexdump, hexdump -C, i2cdump, eeprog
# note that normal 'hexdump' format on a little-endian system byte-swaps
# words, using hexdump -C is better.
sub read_hexdump ($)
{
my $addr = 0;
my $repstart = 0;
my @bytes;
my $header = 1;
my $word = 0;
open F, '<', $_[0] or die "Unable to open: $_[0]";
while (<F>) {
chomp;
if (/^\*$/) {
$repstart = $addr;
next;
}
/^(?:0000 )?([a-f\d]{2,8}):?\s+((:?[a-f\d]{4}\s*){8}|(:?[a-f\d]{2}\s*){16})/i ||
/^(?:0000 )?([a-f\d]{2,8}):?\s*$/i;
next if (!defined $1 && $header); # skip leading unparsed lines
defined $1 or die "Unable to parse input";
$header = 0;
$addr = hex $1;
if ($repstart) {
@bytes[$repstart .. ($addr-1)] =
(@bytes[($repstart-16)..($repstart-1)]) x (($addr-$repstart)/16);
$repstart = 0;
}
last unless defined $2;
foreach (split(/\s+/, $2)) {
if (/^(..)(..)$/) {
$word |= 1;
$bytes[$addr++] = hex($1);
$bytes[$addr++] = hex($2);
} else {
$bytes[$addr++] = hex($_);
}
}
}
close F;
$header and die "Unable to parse any data from hexdump '$_[0]'";
$word and printc "Warning: Assuming big-endian order 16-bit hex dump";
return @bytes;
}
sub readspd64 ($$) { # reads 64 bytes from SPD-EEPROM sub readspd64 ($$) { # reads 64 bytes from SPD-EEPROM
my ($offset, $dimm_i) = @_; my ($offset, $dimm_i) = @_;
my @bytes; my @bytes;
if ($use_sysfs) {
if ($use_hexdump) {
@bytes = read_hexdump($dimm_i);
return @bytes[$offset..($offset+63)];
} elsif ($use_sysfs) {
# Kernel 2.6 with sysfs # Kernel 2.6 with sysfs
sysopen(HANDLE, "/sys/bus/i2c/drivers/eeprom/$dimm_i/eeprom", O_RDONLY) sysopen(HANDLE, "/sys/bus/i2c/drivers/eeprom/$dimm_i/eeprom", O_RDONLY)
or die "Cannot open /sys/bus/i2c/drivers/eeprom/$dimm_i/eeprom"; or die "Cannot open /sys/bus/i2c/drivers/eeprom/$dimm_i/eeprom";
@ -1123,19 +1174,30 @@ sub readspd64 ($$) { # reads 64 bytes from SPD-EEPROM
} }
for (@ARGV) { for (@ARGV) {
if (/-h/) {
print "Usage: $0 [-c] [-f [-b]]\n",
if (/^-?-h/) {
print "Usage: $0 [-c] [-f [-b]] [-x file [files..]]\n",
" $0 -h\n\n", " $0 -h\n\n",
" -f, --format print nice html output\n", " -f, --format print nice html output\n",
" -b, --bodyonly don't print html header\n", " -b, --bodyonly don't print html header\n",
" (useful for postprocessing the output)\n", " (useful for postprocessing the output)\n",
" -c, --checksum decode completely even if checksum fails\n", " -c, --checksum decode completely even if checksum fails\n",
" -x, Read data from hexdump files\n",
" -h, --help display this usage summary\n"; " -h, --help display this usage summary\n";
print <<"EOF";
Hexdumps can be the output from hexdump, hexdump -C, i2cdump, eeprog and
likely many other progams producing hex dumps of one kind or another. Note
that the default output of "hexdump" will be byte-swapped on little-endian
systems and will therefore not be parsed correctly. It is better to use
"hexdump -C", which is not ambiguous.
EOF
exit; exit;
} }
$opt_html = 1 if (/-f/);
$opt_bodyonly = 1 if (/-b/);
$opt_igncheck = 1 if (/-c/);
$opt_html = 1 if (/^-?-f/);
$opt_bodyonly = 1 if (/^-?-b/);
$opt_igncheck = 1 if (/^-?-c/);
$use_hexdump = 1 if (/^-x/);
push @dimm_list, $_ if ($use_hexdump && !/^-/);
} }
$opt_body = $opt_html && ! $opt_bodyonly; $opt_body = $opt_html && ! $opt_bodyonly;
@ -1155,21 +1217,23 @@ Jean Delvare and others';
my $dimm_count = 0; my $dimm_count = 0;
my @dimm_list;
my $dir; my $dir;
if ($use_sysfs) { $dir = '/sys/bus/i2c/drivers/eeprom'; }
else { $dir = '/proc/sys/dev/sensors'; }
if (-d $dir) {
@dimm_list = split(/\s+/, `ls $dir`);
} elsif (! -d '/sys/module/eeprom') {
print "No EEPROM found, are you sure the eeprom module is loaded?\n";
exit;
if (!$use_hexdump) {
if ($use_sysfs) { $dir = '/sys/bus/i2c/drivers/eeprom'; }
else { $dir = '/proc/sys/dev/sensors'; }
if (-d $dir) {
@dimm_list = split(/\s+/, `ls $dir`);
} elsif (! -d '/sys/module/eeprom') {
print "No EEPROM found, are you sure the eeprom module is loaded?\n";
exit;
}
} }
for my $i ( 0 .. $#dimm_list ) { for my $i ( 0 .. $#dimm_list ) {
$_ = $dimm_list[$i]; $_ = $dimm_list[$i];
if (($use_sysfs && /^\d+-\d+$/) if (($use_sysfs && /^\d+-\d+$/)
|| (!$use_sysfs && /^eeprom-/)) {
|| (!$use_sysfs && /^eeprom-/)
|| $use_hexdump) {
my @bytes = readspd64(0, $dimm_list[$i]); my @bytes = readspd64(0, $dimm_list[$i]);
my $dimm_checksum = 0; my $dimm_checksum = 0;
$dimm_checksum += $bytes[$_] foreach (0 .. 62); $dimm_checksum += $bytes[$_] foreach (0 .. 62);
@ -1179,15 +1243,18 @@ for my $i ( 0 .. $#dimm_list ) {
$dimm_count++; $dimm_count++;
print "<b><u>" if $opt_html; print "<b><u>" if $opt_html;
printl2 "\n\nDecoding EEPROM", ($use_sysfs ?
printl2 "\n\nDecoding EEPROM",
$use_hexdump ? $dimm_list[$i] : ($use_sysfs ?
"/sys/bus/i2c/drivers/eeprom/$dimm_list[$i]" : "/sys/bus/i2c/drivers/eeprom/$dimm_list[$i]" :
"/proc/sys/dev/sensors/$dimm_list[$i]"); "/proc/sys/dev/sensors/$dimm_list[$i]");
print "</u></b>" if $opt_html; print "</u></b>" if $opt_html;
print "<table border=1>\n" if $opt_html; print "<table border=1>\n" if $opt_html;
if (($use_sysfs && /^[^-]+-([^-]+)$/)
|| (!$use_sysfs && /^[^-]+-[^-]+-[^-]+-([^-]+)$/)) {
my $dimm_num = $1 - 49;
printl "Guessing DIMM is in", "bank $dimm_num";
if (!$use_hexdump) {
if (($use_sysfs && /^[^-]+-([^-]+)$/)
|| (!$use_sysfs && /^[^-]+-[^-]+-[^-]+-([^-]+)$/)) {
my $dimm_num = $1 - 49;
printl "Guessing DIMM is in", "bank $dimm_num";
}
} }
# Decode first 3 bytes (0-2) # Decode first 3 bytes (0-2)

Loading…
Cancel
Save