The regex for parsing hexdump -C was wrong. I remember fixing that before,
so I think some old code got in these patches. It's a real pain to deal
with a stack of outstanding patches with svn and merge against conflicts
from upstream.
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 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 embeded system that does not have
perl/etc, but does have a serial console with busybox.
---
Index: eeprom/decode-dimms.pl
===================================================================
--- eeprom/decode-dimms.pl (revision 5156)
+++ eeprom/decode-dimms.pl (working copy)
@@ -46,8 +46,8 @@
use strict;
use POSIX;
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 =~ s/\$\w+: (.*?) \$/$1/g;
@@ -1100,10 +1100,60 @@
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;
+
+ open F, '<', $_[0] or die "Unable to open: $_[0]";
+ while (<F>) {
+ my $ok = 1;
+
+ 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 or $ok = 0;
+ next if (!$ok && $header); # skip leading unparsed
lines
+
+ $ok or die "Unable to parse input";
+ $header = 0;
+
+ $addr = hex $1;
+ if ($repstart) {
+ @bytes[$repstart .. ($addr-1)] = ($bytes[$repstart-1])
x ($addr-$repstart);
+ $repstart = 0;
+ }
+ last unless defined $2;
+ foreach (split(/\s+/, $2)) {
+ if (/^(..)(..)$/) {
+ $bytes[$addr++] = hex($1);
+ $bytes[$addr++] = hex($2);
+ } else {
+ /^(..)$/;
+ $bytes[$addr++] = hex($1);
+ }
+ }
+ }
+ close F;
+ $header and die "Unable to parse any data from hexdump '$_[0]'";
+ return @bytes;
+}
+
sub readspd64 ($$) { # reads 64 bytes from SPD-EEPROM
my ($offset, $dimm_i) = @_;
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
sysopen(HANDLE, "/sys/bus/i2c/drivers/eeprom/$dimm_i/eeprom",
O_RDONLY)
or die "Cannot open
/sys/bus/i2c/drivers/eeprom/$dimm_i/eeprom";
@@ -1123,19 +1173,29 @@
}
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",
" -f, --format print nice html output\n",
" -b, --bodyonly don't print html header\n",
" (useful for postprocessing
the output)\n",
" -c, --checksum decode completely even if
checksum fails\n",
+ " -x, Read data from hexdump
files\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. It is better to use "hexdump -C", which is not ambiguous.
+EOF
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;
@@ -1155,21 +1215,23 @@
my $dimm_count = 0;
-my @dimm_list;
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 ) {
$_ = $dimm_list[$i];
if (($use_sysfs && /^\d+-\d+$/)
- || (!$use_sysfs && /^eeprom-/)) {
+ || (!$use_sysfs && /^eeprom-/)
+ || $use_hexdump) {
my @bytes = readspd64(0, $dimm_list[$i]);
my $dimm_checksum = 0;
$dimm_checksum += $bytes[$_] foreach (0 .. 62);
@@ -1179,15 +1241,18 @@
$dimm_count++;
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]" :
"/proc/sys/dev/sensors/$dimm_list[$i]");
print "</u></b>" 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)
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c