Changeset 5157

Show
Ignore:
Timestamp:
03/24/08 11:22:48 (8 months ago)
Author:
khali
Message:

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.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • i2c-tools/trunk/CHANGES

    r5152 r5157  
    77                Don't print anything by default if checksum fails 
    88                Decode all DDR2 SDRAM timing information 
     9                Add support for reading SPD data from hexdumps 
    910  decode-vaio: Private data might not be readable by non-root users 
    1011               Print the asset tag 
  • i2c-tools/trunk/eeprom/decode-dimms.pl

    r5156 r5157  
    4747use POSIX; 
    4848use Fcntl qw(:DEFAULT :seek); 
    49 use vars qw($opt_html $opt_body $opt_bodyonly $opt_igncheck $use_sysfs 
    50             @vendors %decode_callback $revision); 
     49use vars qw($opt_html $opt_body $opt_bodyonly $opt_igncheck $use_sysfs $use_hexdump 
     50            @vendors %decode_callback $revision @dimm_list); 
    5151 
    5252$revision = '$Revision$ ($Date$)'; 
     
    11011101} 
    11021102 
     1103# Read various hex dump style formats: hexdump, hexdump -C, i2cdump, eeprog 
     1104# note that normal 'hexdump' format on a little-endian system byte-swaps 
     1105# words, using hexdump -C is better. 
     1106sub read_hexdump ($) 
     1107{ 
     1108        my $addr = 0; 
     1109        my $repstart = 0; 
     1110        my @bytes; 
     1111        my $header = 1; 
     1112        my $word = 0; 
     1113 
     1114        open F, '<', $_[0] or die "Unable to open: $_[0]"; 
     1115        while (<F>) { 
     1116                chomp; 
     1117                if (/^\*$/) { 
     1118                        $repstart = $addr; 
     1119                        next; 
     1120                } 
     1121                /^(?:0000 )?([a-f\d]{2,8}):?\s+((:?[a-f\d]{4}\s*){8}|(:?[a-f\d]{2}\s*){16})/i || 
     1122                /^(?:0000 )?([a-f\d]{2,8}):?\s*$/i; 
     1123                next if (!defined $1 && $header);               # skip leading unparsed lines 
     1124 
     1125                defined $1 or die "Unable to parse input"; 
     1126                $header = 0; 
     1127 
     1128                $addr = hex $1; 
     1129                if ($repstart) { 
     1130                        @bytes[$repstart .. ($addr-1)] = 
     1131                                (@bytes[($repstart-16)..($repstart-1)]) x (($addr-$repstart)/16); 
     1132                        $repstart = 0; 
     1133                } 
     1134                last unless defined $2; 
     1135                foreach (split(/\s+/, $2)) { 
     1136                        if (/^(..)(..)$/) { 
     1137                                $word |= 1; 
     1138                                $bytes[$addr++] = hex($1); 
     1139                                $bytes[$addr++] = hex($2); 
     1140                        } else { 
     1141                                $bytes[$addr++] = hex($_); 
     1142                        } 
     1143                } 
     1144        } 
     1145        close F; 
     1146        $header and die "Unable to parse any data from hexdump '$_[0]'"; 
     1147        $word and printc "Warning: Assuming big-endian order 16-bit hex dump"; 
     1148        return @bytes; 
     1149} 
     1150 
    11031151sub readspd64 ($$) { # reads 64 bytes from SPD-EEPROM 
    11041152        my ($offset, $dimm_i) = @_; 
    11051153        my @bytes; 
    1106         if ($use_sysfs) { 
     1154        if ($use_hexdump) { 
     1155                @bytes = read_hexdump($dimm_i); 
     1156                return @bytes[$offset..($offset+63)]; 
     1157        } elsif ($use_sysfs) { 
    11071158                # Kernel 2.6 with sysfs 
    11081159                sysopen(HANDLE, "/sys/bus/i2c/drivers/eeprom/$dimm_i/eeprom", O_RDONLY) 
     
    11241175 
    11251176for (@ARGV) { 
    1126     if (/-h/) { 
    1127                 print "Usage: $0 [-c] [-f [-b]]\n", 
     1177    if (/^-?-h/) { 
     1178                print "Usage: $0 [-c] [-f [-b]] [-x file [files..]]\n", 
    11281179                        "       $0 -h\n\n", 
    11291180                        "  -f, --format            print nice html output\n", 
     
    11311182                        "                          (useful for postprocessing the output)\n", 
    11321183                        "  -c, --checksum          decode completely even if checksum fails\n", 
     1184                        "  -x,                     Read data from hexdump files\n", 
    11331185                        "  -h, --help              display this usage summary\n"; 
     1186                print <<"EOF"; 
     1187 
     1188Hexdumps can be the output from hexdump, hexdump -C, i2cdump, eeprog and 
     1189likely many other progams producing hex dumps of one kind or another.  Note 
     1190that the default output of "hexdump" will be byte-swapped on little-endian 
     1191systems and will therefore not be parsed correctly.  It is better to use 
     1192"hexdump -C", which is not ambiguous. 
     1193EOF 
    11341194                exit; 
    11351195    } 
    1136     $opt_html = 1 if (/-f/); 
    1137     $opt_bodyonly = 1 if (/-b/); 
    1138     $opt_igncheck = 1 if (/-c/); 
     1196    $opt_html = 1 if (/^-?-f/); 
     1197    $opt_bodyonly = 1 if (/^-?-b/); 
     1198    $opt_igncheck = 1 if (/^-?-c/); 
     1199    $use_hexdump = 1 if (/^-x/); 
     1200    push @dimm_list, $_ if ($use_hexdump && !/^-/); 
    11391201} 
    11401202$opt_body = $opt_html && ! $opt_bodyonly; 
     
    11561218 
    11571219my $dimm_count = 0; 
    1158 my @dimm_list; 
    11591220my $dir; 
    1160 if ($use_sysfs) { $dir = '/sys/bus/i2c/drivers/eeprom'; } 
    1161 else { $dir = '/proc/sys/dev/sensors'; } 
    1162 if (-d $dir) { 
    1163         @dimm_list = split(/\s+/, `ls $dir`); 
    1164 } elsif (! -d '/sys/module/eeprom') { 
    1165         print "No EEPROM found, are you sure the eeprom module is loaded?\n"; 
    1166         exit; 
     1221if (!$use_hexdump) { 
     1222        if ($use_sysfs) { $dir = '/sys/bus/i2c/drivers/eeprom'; } 
     1223        else { $dir = '/proc/sys/dev/sensors'; } 
     1224        if (-d $dir) { 
     1225                @dimm_list = split(/\s+/, `ls $dir`); 
     1226        } elsif (! -d '/sys/module/eeprom') { 
     1227                print "No EEPROM found, are you sure the eeprom module is loaded?\n"; 
     1228                exit; 
     1229        } 
    11671230} 
    11681231 
     
    11701233        $_ = $dimm_list[$i]; 
    11711234        if (($use_sysfs && /^\d+-\d+$/) 
    1172          || (!$use_sysfs && /^eeprom-/)) { 
     1235         || (!$use_sysfs && /^eeprom-/) 
     1236         || $use_hexdump) { 
    11731237                my @bytes = readspd64(0, $dimm_list[$i]); 
    11741238                my $dimm_checksum = 0; 
     
    11801244 
    11811245                print "<b><u>" if $opt_html; 
    1182                 printl2 "\n\nDecoding EEPROM", ($use_sysfs ? 
     1246                printl2 "\n\nDecoding EEPROM", 
     1247                        $use_hexdump ? $dimm_list[$i] : ($use_sysfs ? 
    11831248                        "/sys/bus/i2c/drivers/eeprom/$dimm_list[$i]" : 
    11841249                        "/proc/sys/dev/sensors/$dimm_list[$i]"); 
    11851250                print "</u></b>" if $opt_html; 
    11861251                print "<table border=1>\n" if $opt_html; 
    1187                 if (($use_sysfs && /^[^-]+-([^-]+)$/) 
    1188                  || (!$use_sysfs && /^[^-]+-[^-]+-[^-]+-([^-]+)$/)) { 
    1189                         my $dimm_num = $1 - 49; 
    1190                         printl "Guessing DIMM is in", "bank $dimm_num"; 
     1252                if (!$use_hexdump) { 
     1253                        if (($use_sysfs && /^[^-]+-([^-]+)$/) 
     1254                         || (!$use_sysfs && /^[^-]+-[^-]+-[^-]+-([^-]+)$/)) { 
     1255                                my $dimm_num = $1 - 49; 
     1256                                printl "Guessing DIMM is in", "bank $dimm_num"; 
     1257                        } 
    11911258                } 
    11921259