| @@ -1,125 +1,211 @@ | | | @@ -1,125 +1,211 @@ |
1 | $NetBSD: patch-decode-dimms,v 1.16 2019/10/03 18:42:26 pgoyette Exp $ | | 1 | $NetBSD: patch-decode-dimms,v 1.17 2019/10/08 17:11:45 pgoyette Exp $ |
2 | | | 2 | |
3 | Add NetBSD-specific ability to use spdmem(4)'s sysctl values as | | 3 | Add NetBSD-specific ability to use spdmem(4)'s sysctl values as |
4 | input. Remove attempts to use linux-specific data sources. | | 4 | input. Remove attempts to use linux-specific data sources. |
5 | | | 5 | |
6 | --- eeprom/decode-dimms.orig 2019-10-03 10:53:17.810726776 -0700 | | 6 | --- eeprom/decode-dimms.orig 2019-10-08 10:01:39.370148879 -0700 |
7 | +++ eeprom/decode-dimms 2019-10-03 11:02:03.877954987 -0700 | | 7 | +++ eeprom/decode-dimms 2019-10-08 09:57:14.231699228 -0700 |
8 | @@ -45,8 +45,9 @@ | | 8 | @@ -45,8 +45,9 @@ |
9 | use Fcntl qw(:DEFAULT :seek); | | 9 | use Fcntl qw(:DEFAULT :seek); |
10 | use File::Basename; | | 10 | use File::Basename; |
11 | use vars qw($opt_html $opt_bodyonly $opt_side_by_side $opt_merge | | 11 | use vars qw($opt_html $opt_bodyonly $opt_side_by_side $opt_merge |
12 | - $opt_igncheck $use_sysfs $use_hexdump $sbs_col_width | | 12 | - $opt_igncheck $use_sysfs $use_hexdump $sbs_col_width |
13 | - @vendors %decode_callback @dimm $current %hexdump_cache); | | 13 | - @vendors %decode_callback @dimm $current %hexdump_cache); |
14 | + $opt_igncheck $use_sysctl $use_sysfs $use_hexdump $sbs_col_width | | 14 | + $opt_igncheck $use_sysctl $use_hexdump $sbs_col_width |
15 | + @vendors %decode_callback @dimm $current %hexdump_cache | | 15 | + @vendors %decode_callback @dimm $current %hexdump_cache |
16 | + %sysctl_cache); | | 16 | + %sysctl_cache); |
17 | | | 17 | |
18 | use constant LITTLEENDIAN => "little-endian"; | | 18 | use constant LITTLEENDIAN => "little-endian"; |
19 | use constant BIGENDIAN => "big-endian"; | | 19 | use constant BIGENDIAN => "big-endian"; |
20 | @@ -419,6 +420,7 @@ | | 20 | @@ -418,7 +419,7 @@ |
| | | 21 | "Thermaltake Technology Co Ltd", "Shenzhen O'Yang Maile Technology Ltd", "UPMEM"] |
21 | ); | | 22 | ); |
22 | | | 23 | |
23 | $use_sysfs = -d '/sys/bus'; | | 24 | -$use_sysfs = -d '/sys/bus'; |
24 | +$use_sysctl = 0; | | 25 | +$use_sysctl = 0; |
25 | | | 26 | |
26 | # We consider that no data was written to this area of the SPD EEPROM if | | 27 | # We consider that no data was written to this area of the SPD EEPROM if |
27 | # all bytes read 0x00 or all bytes read 0xff | | 28 | # all bytes read 0x00 or all bytes read 0xff |
28 | @@ -2357,6 +2359,26 @@ | | 29 | @@ -2357,6 +2358,26 @@ |
29 | } | | 30 | } |
30 | } | | 31 | } |
31 | | | 32 | |
32 | +# read data from a NetBSD (or equivalent) sysctl variable | | 33 | +# read data from a NetBSD (or equivalent) sysctl variable |
33 | + | | 34 | + |
34 | +sub read_sysctl($) | | 35 | +sub read_sysctl($) |
35 | +{ | | 36 | +{ |
36 | + | | 37 | + |
37 | + # Look in the cache first | | 38 | + # Look in the cache first |
38 | + return @{$sysctl_cache{$_[0]}} if exists $sysctl_cache{$_[0]}; | | 39 | + return @{$sysctl_cache{$_[0]}} if exists $sysctl_cache{$_[0]}; |
39 | + | | 40 | + |
40 | + my $sysctl_var = sprintf("hw.%s.spd_data", $_[0]); | | 41 | + my $sysctl_var = sprintf("hw.%s.spd_data", $_[0]); |
41 | + open(PIPE, "-|", "sysctl -r $sysctl_var") | | 42 | + open(PIPE, "-|", "sysctl -r $sysctl_var") |
42 | + or die "Cannot read sysctl variable $sysctl_var"; | | 43 | + or die "Cannot read sysctl variable $sysctl_var"; |
43 | + sysread(PIPE, my $eeprom, 512); # XXX Assumed maximum size! XXX | | 44 | + sysread(PIPE, my $eeprom, 512); # XXX Assumed maximum size! XXX |
44 | + close PIPE or die "sysctl returned $?"; | | 45 | + close PIPE or die "sysctl returned $?"; |
45 | + my @bytes = unpack("C*", $eeprom); | | 46 | + my @bytes = unpack("C*", $eeprom); |
46 | + | | 47 | + |
47 | + # Cache the data for later use | | 48 | + # Cache the data for later use |
48 | + $sysctl_cache{$_[0]} = \@bytes; | | 49 | + $sysctl_cache{$_[0]} = \@bytes; |
49 | + return @bytes; | | 50 | + return @bytes; |
50 | +} | | 51 | +} |
51 | + | | 52 | + |
52 | # Read bytes from SPD-EEPROM | | 53 | # Read bytes from SPD-EEPROM |
53 | # Note: offset must be a multiple of 16! | | 54 | # Note: offset must be a multiple of 16! |
54 | sub readspd($$$) | | 55 | sub readspd($$$) |
55 | @@ -2370,6 +2392,13 @@ | | 56 | @@ -2370,20 +2391,13 @@ |
56 | $size = @bytes - $offset; | | 57 | $size = @bytes - $offset; |
57 | } | | 58 | } |
58 | return @bytes[$offset..($offset + $size - 1)]; | | 59 | return @bytes[$offset..($offset + $size - 1)]; |
| | | 60 | - } elsif ($use_sysfs) { |
| | | 61 | - # Kernel 2.6 with sysfs |
| | | 62 | - sysopen(HANDLE, "$dimm_i/eeprom", O_RDONLY) |
| | | 63 | - or die "Cannot open $dimm_i/eeprom"; |
| | | 64 | - binmode HANDLE; |
| | | 65 | - sysseek(HANDLE, $offset, SEEK_SET) |
| | | 66 | - or die "Cannot seek $dimm_i/eeprom"; |
| | | 67 | - $read = sysread(HANDLE, my $eeprom, $size) |
| | | 68 | - or die "Cannot read $dimm_i/eeprom"; |
| | | 69 | - close HANDLE; |
| | | 70 | - if ($read < $size) { |
| | | 71 | - print STDERR "WARNING: $dimm_i/eeprom is smaller than expected\n"; |
59 | + } elsif ($use_sysctl) { | | 72 | + } elsif ($use_sysctl) { |
60 | + @bytes = read_sysctl($dimm_i); | | 73 | + @bytes = read_sysctl($dimm_i); |
61 | + if (@bytes < $offset + $size) { | | 74 | + if (@bytes < $offset + $size) { |
62 | + print STDERR "WARNING: sysctl for $dimm_i is truncated\n"; | | 75 | + print STDERR "WARNING: sysctl for $dimm_i is truncated\n"; |
63 | + $size = @bytes - $offset; | | 76 | + $size = @bytes - $offset; |
64 | + } | | 77 | } |
| | | 78 | - @bytes = unpack("C*", $eeprom); |
65 | + return return @bytes[$offset..($offset + $size - 1)]; | | 79 | + return return @bytes[$offset..($offset + $size - 1)]; |
66 | } elsif ($use_sysfs) { | | 80 | } else { |
67 | # Kernel 2.6 with sysfs | | 81 | # Kernel 2.4 with procfs |
68 | sysopen(HANDLE, "$dimm_i/eeprom", O_RDONLY) | | 82 | for my $i (0 .. ($size-1)/16) { |
69 | @@ -2449,7 +2478,7 @@ | | 83 | @@ -2449,7 +2463,7 @@ |
70 | # Parse command-line | | 84 | # Parse command-line |
71 | foreach (@ARGV) { | | 85 | foreach (@ARGV) { |
72 | if ($_ eq '-h' || $_ eq '--help') { | | 86 | if ($_ eq '-h' || $_ eq '--help') { |
73 | - print "Usage: $0 [-c] [-f [-b]] [-x|-X file [files..]]\n", | | 87 | - print "Usage: $0 [-c] [-f [-b]] [-x|-X file [files..]]\n", |
74 | + print "Usage: $0 [-c] [-f [-b]] [-x|-X|-s file [files..]]\n", | | 88 | + print "Usage: $0 [-c] [-f [-b]] [-x|-X|-s file [files..]]\n", |
75 | " $0 -h\n\n", | | 89 | " $0 -h\n\n", |
76 | " -f, --format Print nice html output\n", | | 90 | " -f, --format Print nice html output\n", |
77 | " -b, --bodyonly Don't print html header\n", | | 91 | " -b, --bodyonly Don't print html header\n", |
78 | @@ -2463,6 +2492,8 @@ | | 92 | @@ -2463,6 +2477,8 @@ |
79 | " -x, Read data from hexdump files\n", | | 93 | " -x, Read data from hexdump files\n", |
80 | " -X, Same as -x except treat multibyte hex\n", | | 94 | " -X, Same as -x except treat multibyte hex\n", |
81 | " data as little endian\n", | | 95 | " data as little endian\n", |
82 | + " -s, Use NetBSD-compatible sysctl(8) to obtain\n", | | 96 | + " -s, Use NetBSD-compatible sysctl(8) to obtain\n", |
83 | + " EEPROM data\n", | | 97 | + " EEPROM data\n", |
84 | " -h, --help Display this usage summary\n"; | | 98 | " -h, --help Display this usage summary\n"; |
85 | print <<"EOF"; | | 99 | print <<"EOF"; |
86 | | | 100 | |
87 | @@ -2507,13 +2538,20 @@ | | 101 | @@ -2507,85 +2523,25 @@ |
88 | $use_hexdump = LITTLEENDIAN; | | 102 | $use_hexdump = LITTLEENDIAN; |
89 | next; | | 103 | next; |
90 | } | | 104 | } |
91 | + if ($_ eq '-s') { | | 105 | + if ($_ eq '-s') { |
92 | + if (-x "/sbin/sysctl") { | | 106 | + if (-x "/sbin/sysctl") { |
93 | + $use_sysctl = 1; | | 107 | + $use_sysctl = 1; |
94 | + } else { die "No /sbin/sysctl available for -s"; } | | 108 | + } else { die "No /sbin/sysctl available for -s"; } |
95 | + next; | | 109 | + next; |
96 | + } | | 110 | + } |
97 | | | 111 | |
98 | if (m/^-/) { | | 112 | if (m/^-/) { |
99 | print STDERR "Unrecognized option $_\n"; | | 113 | print STDERR "Unrecognized option $_\n"; |
100 | exit; | | 114 | exit; |
101 | } | | 115 | } |
102 | | | 116 | |
103 | - push @dimm, { eeprom => basename($_), file => $_ } if $use_hexdump; | | 117 | - push @dimm, { eeprom => basename($_), file => $_ } if $use_hexdump; |
104 | + push @dimm, { eeprom => basename($_), file => $_ } | | 118 | + push @dimm, { eeprom => basename($_), file => $_ } |
105 | + if ($use_sysctl || $use_hexdump); | | 119 | + if ($use_sysctl || $use_hexdump); |
106 | } | | 120 | } |
107 | | | 121 | |
108 | # Default values | | 122 | # Default values |
109 | @@ -2598,7 +2636,6 @@ | | 123 | $opt_merge = 1 unless defined $opt_merge; |
| | | 124 | |
| | | 125 | -# From a sysfs device path and an attribute name, return the attribute |
| | | 126 | -# value, or undef (stolen from sensors-detect) |
| | | 127 | -sub sysfs_device_attribute |
| | | 128 | -{ |
| | | 129 | - my ($device, $attr) = @_; |
| | | 130 | - my $value; |
| | | 131 | - |
| | | 132 | - open(local *FILE, "$device/$attr") or return ""; |
| | | 133 | - $value = <FILE>; |
| | | 134 | - close(FILE); |
| | | 135 | - return unless defined $value; |
| | | 136 | - |
| | | 137 | - chomp($value); |
| | | 138 | - return $value; |
| | | 139 | -} |
| | | 140 | - |
| | | 141 | -sub get_dimm_list |
| | | 142 | -{ |
| | | 143 | - my (@drivers, $driver, $dir, $opened, $file, @files); |
| | | 144 | - |
| | | 145 | - if ($use_sysfs) { |
| | | 146 | - @drivers = ('eeprom', |
| | | 147 | - 'at24', |
| | | 148 | - 'ee1004'); # DDR4 |
| | | 149 | - } else { |
| | | 150 | - @drivers = ('eeprom'); |
| | | 151 | - $dir = '/proc/sys/dev/sensors'; |
| | | 152 | - } |
| | | 153 | - |
| | | 154 | - foreach $driver (@drivers) { |
| | | 155 | - if ($use_sysfs) { |
| | | 156 | - $dir = "/sys/bus/i2c/drivers/$driver"; |
| | | 157 | - } |
| | | 158 | - |
| | | 159 | - next unless opendir(local *DIR, $dir); |
| | | 160 | - $opened++; |
| | | 161 | - while (defined($file = readdir(DIR))) { |
| | | 162 | - if ($use_sysfs) { |
| | | 163 | - # We look for I2C devices like 0-0050 or 2-0051 |
| | | 164 | - next unless $file =~ /^\d+-[\da-f]+$/i; |
| | | 165 | - next unless -d "$dir/$file"; |
| | | 166 | - |
| | | 167 | - # Device name must be eeprom (driver eeprom) |
| | | 168 | - # spd (driver at24) or ee1004 (driver ee1004) |
| | | 169 | - my $attr = sysfs_device_attribute("$dir/$file", "name"); |
| | | 170 | - next unless defined $attr && |
| | | 171 | - ($attr eq "eeprom" || |
| | | 172 | - $attr eq "spd" || |
| | | 173 | - $attr eq "ee1004"); # DDR4 |
| | | 174 | - } else { |
| | | 175 | - next unless $file =~ /^eeprom-/; |
| | | 176 | - } |
| | | 177 | - push @files, { eeprom => "$file", |
| | | 178 | - file => "$dir/$file", |
| | | 179 | - driver => "$driver" }; |
| | | 180 | - } |
| | | 181 | - close(DIR); |
| | | 182 | - } |
| | | 183 | - |
| | | 184 | - if (!$opened) { |
| | | 185 | - print STDERR "No EEPROM found, try loading the eeprom, at24 or ee1004 module\n"; |
| | | 186 | - exit; |
| | | 187 | - } |
| | | 188 | - |
| | | 189 | - return sort { $a->{file} cmp $b->{file} } @files; |
| | | 190 | -} |
| | | 191 | - |
| | | 192 | # @dimm is a list of hashes. There's one hash for each EEPROM we found. |
| | | 193 | # Each hash has the following keys: |
| | | 194 | # * eeprom: Name of the eeprom data file |
| | | 195 | @@ -2598,7 +2554,6 @@ |
110 | # * chk_spd: The checksum or CRC value found in the EEPROM | | 196 | # * chk_spd: The checksum or CRC value found in the EEPROM |
111 | # * chk_calc: The checksum or CRC computed from the EEPROM data | | 197 | # * chk_calc: The checksum or CRC computed from the EEPROM data |
112 | # Keys are added over time. | | 198 | # Keys are added over time. |
113 | -@dimm = get_dimm_list() unless $use_hexdump; | | 199 | -@dimm = get_dimm_list() unless $use_hexdump; |
114 | | | 200 | |
115 | for my $i (0 .. $#dimm) { | | 201 | for my $i (0 .. $#dimm) { |
116 | my @bytes = readspd(0, 128, $dimm[$i]->{file}); | | 202 | my @bytes = readspd(0, 128, $dimm[$i]->{file}); |
117 | @@ -2650,7 +2687,7 @@ | | 203 | @@ -2650,7 +2605,7 @@ |
118 | printl("Decoding EEPROM", $dimm[$current]->{eeprom}); | | 204 | printl("Decoding EEPROM", $dimm[$current]->{eeprom}); |
119 | } | | 205 | } |
120 | | | 206 | |
121 | - if (!$use_hexdump) { | | 207 | - if (!$use_hexdump) { |
122 | + if (!$use_hexdump && !$use_sysctl) { | | 208 | + if (!$use_hexdump && !$use_sysctl) { |
123 | if ($dimm[$current]->{file} =~ /-([\da-f]+)$/i) { | | 209 | if ($dimm[$current]->{file} =~ /-([\da-f]+)$/i) { |
124 | my $dimm_num = hex($1) - 0x50 + 1; | | 210 | my $dimm_num = hex($1) - 0x50 + 1; |
125 | if ($dimm_num >= 1 && $dimm_num <= 8) { | | 211 | if ($dimm_num >= 1 && $dimm_num <= 8) { |