"Fossies" - the Fresh Open Source Software Archive

Member "i2c-tools-4.3/eeprom/decode-vaio" (22 Jul 2021, 6528 Bytes) of package /linux/misc/i2c-tools-4.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Perl source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "decode-vaio": 4.1_vs_4.2.

    1 #!/usr/bin/perl -w
    2 #
    3 # Copyright (C) 2002-2020  Jean Delvare <jdelvare@suse.de>
    4 #
    5 #    This program is free software; you can redistribute it and/or modify
    6 #    it under the terms of the GNU General Public License as published by
    7 #    the Free Software Foundation; either version 2 of the License, or
    8 #    (at your option) any later version.
    9 #
   10 #    This program is distributed in the hope that it will be useful,
   11 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13 #    GNU General Public License for more details.
   14 #
   15 #    You should have received a copy of the GNU General Public License
   16 #    along with this program; if not, write to the Free Software
   17 #    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
   18 #    MA 02110-1301 USA.
   19 #
   20 # EEPROM data decoding for Sony Vaio laptops.
   21 #
   22 # The at24 or eeprom driver must be loaded. For kernels older than 2.6.0, the
   23 # eeprom driver can be found in the lm-sensors package.
   24 #
   25 # Please note that this is a guess-only work.  Sony support refused to help
   26 # me, so if someone can provide information, please contact me.
   27 # My knowledge is summarized on this page:
   28 # http://jdelvare.nerim.net/articles/vaio/eeprom.html
   29 #
   30 # It seems that if present, the EEPROM is always at 0x57.
   31 #
   32 # Models tested so far:
   33 #   PCG-F403     : No EEPROM
   34 #   PCG-F707     : No EEPROM
   35 #   PCG-GR114EK  : OK
   36 #   PCG-GR114SK  : OK
   37 #   PCG-GR214EP  : OK
   38 #   PCG-GRT955MP : OK
   39 #   PCG-GRX316G  : OK
   40 #   PCG-GRX570   : OK
   41 #   PCG-GRX600K  : OK
   42 #   PCG-U1       : OK
   43 #   PCG-Z600LEK  : No EEPROM
   44 #   PCG-Z600NE   : No EEPROM
   45 #   VGN-S260     : OK
   46 #   VGN-S4M/S    : OK
   47 #   VGN-TZ11MN/N : OK
   48 #
   49 # Thanks to Werner Heuser, Carsten Blume, Christian Gennerat, Joe Wreschnig,
   50 # Xavier Roche, Sebastien Lefevre, Lars Heer, Steve Dobson, Kent Hunt,
   51 # Timo Hoenig and others for their precious help.
   52 
   53 
   54 use strict;
   55 use Fcntl qw(:DEFAULT :seek);
   56 use File::Basename;
   57 use vars qw($sysfs $found);
   58 
   59 use constant VERSION    => "1.7";
   60 use constant ONLYROOT   => "Readable only by root";
   61 
   62 # From a sysfs device path and an attribute name, return the attribute
   63 # value, or undef (stolen from sensors-detect)
   64 sub sysfs_device_attribute
   65 {
   66     my ($device, $attr) = @_;
   67     my $value;
   68 
   69     open(local *FILE, "$device/$attr") or return "";
   70     $value = <FILE>;
   71     close(FILE);
   72     return unless defined $value;
   73 
   74     chomp($value);
   75     return $value;
   76 }
   77 
   78 # From a sysfs device path, return the driver name, or undef (stolen from
   79 # sensors-detect)
   80 sub sysfs_device_driver
   81 {
   82     my $device = shift;
   83 
   84     my $link = readlink("$device/driver");
   85     return unless defined $link;
   86     return basename($link);
   87 }
   88 
   89 sub print_item
   90 {
   91     my ($label,$value) = @_;
   92 
   93     printf("\%16s : \%s\n",$label,$value);
   94 }
   95 
   96 # Abstract reads so that other functions don't have to care wether
   97 # we need to use procfs or sysfs
   98 sub read_eeprom_bytes
   99 {
  100     my ($bus, $addr, $offset, $length) = @_;
  101     my $filename;
  102 
  103     if ($sysfs)
  104     {
  105         $filename = "/sys/bus/i2c/devices/$bus-00$addr/eeprom";
  106         sysopen(FH, $filename, O_RDONLY)
  107             or die "Can't open $filename";
  108         sysseek(FH, $offset, SEEK_SET)
  109             or die "Can't seek in $filename";
  110 
  111         my ($r, $bytes);
  112         $bytes = '';
  113         $offset = 0;
  114         while($length)
  115         {
  116             $r = sysread(FH, $bytes, $length, $offset);
  117             die "Can't read $filename"
  118                 unless defined($r);
  119             die "Unexpected EOF in $filename"
  120                 unless $r;
  121             $offset += $r;
  122             $length -= $r;
  123         }
  124         close(FH);
  125 
  126         return $bytes;
  127     }
  128     else
  129     {
  130         my $base = $offset & 0xf0;
  131         $offset -= $base;
  132         my $values = '';
  133         my $remains = $length + $offset;
  134 
  135         # Get all lines in a single string
  136         while ($remains > 0)
  137         {
  138             $filename = "/proc/sys/dev/sensors/eeprom-i2c-$bus-$addr/"
  139                       . sprintf('%02x', $base);
  140             open(FH, $filename)
  141                 or die "Can't open $filename";
  142             $values .= <FH>;
  143             close(FH);
  144             $remains -= 16;
  145             $base += 16;
  146         }
  147 
  148         # Store the useful part in an array
  149         my @bytes = split(/[ \n]/, $values);
  150         @bytes = @bytes[$offset..$offset+$length-1];
  151 
  152         # Back to a binary string
  153         return pack('C*', @bytes);
  154     }
  155 }
  156 
  157 sub decode_string
  158 {
  159     my ($bus, $addr, $offset, $length) = @_;
  160 
  161     my $string = read_eeprom_bytes($bus, $addr, $offset, $length);
  162     $string =~ s/\x00.*$//;
  163 
  164     return($string);
  165 }
  166 
  167 sub decode_hexa
  168 {
  169     my ($bus, $addr, $offset, $length) = @_;
  170 
  171     my @bytes = unpack('C*', read_eeprom_bytes($bus, $addr, $offset, $length));
  172     my $string='';
  173 
  174     for(my $i=0;$i<$length;$i++)
  175     {
  176         $string.=sprintf('%02X', shift(@bytes));
  177     }
  178 
  179     return($string);
  180 }
  181 
  182 sub decode_uuid
  183 {
  184     my ($bus,$addr,$base) = @_;
  185 
  186     my @bytes = unpack('C16', read_eeprom_bytes($bus, $addr, $base, 16));
  187     my $string='';
  188 
  189     for(my $i=0;$i<16;$i++)
  190     {
  191         $string.=sprintf('%02x',shift(@bytes));
  192         if(($i==3)||($i==5)||($i==7)||($i==9))
  193         {
  194             $string.='-';
  195         }
  196     }
  197 
  198     if ($string eq '00000000-0000-0000-0000-000000000000')
  199     {
  200         return(ONLYROOT);
  201     }
  202     else
  203     {
  204         return($string);
  205     }
  206 }
  207 
  208 sub vaio_decode
  209 {
  210     my ($bus,$addr) = @_;
  211 
  212     my $name = decode_string($bus, $addr, 128, 32);
  213     # Simple heuristic to skip false positives
  214     return 0 unless $name =~ m/^[A-Z-]{4}/;
  215 
  216     print_item('Machine Name', $name);
  217     my $serial = decode_string($bus, $addr, 192, 32);
  218     print_item('Serial Number', $serial ? $serial : ONLYROOT);
  219     print_item('UUID', decode_uuid($bus, $addr, 16));
  220     my $revision = decode_string($bus, $addr, 160, 10);
  221     print_item(length($revision) > 2 ? 'Service Tag' : 'Revision',
  222            $revision);
  223     print_item('Asset Tag', decode_string($bus, $addr, 170, 4).
  224                 decode_hexa($bus, $addr, 174, 12));
  225     print_item('OEM Data', decode_string($bus, $addr, 32, 16));
  226     print_item('Timestamp', decode_string($bus, $addr, 224, 18));
  227     return 1;
  228 }
  229 
  230 BEGIN
  231 {
  232     print("# Sony Vaio EEPROM Decoder version ".VERSION." by Jean Delvare\n\n");
  233 }
  234 
  235 END
  236 {
  237     print("\n");
  238 }
  239 
  240 for (my $i = 0, $found=0; $i <= 31 && !$found; $i++)
  241 {
  242     if (-r "/sys/bus/i2c/devices/$i-0057/eeprom")
  243     {
  244         my $driver = sysfs_device_driver("/sys/bus/i2c/devices/$i-0057");
  245         my $name = sysfs_device_attribute("/sys/bus/i2c/devices/$i-0057", "name");
  246         next unless ($driver eq "at24" || $driver eq "eeprom");
  247         next if ($driver eq "at24" && $name ne "24c02-vaio");
  248 
  249         $sysfs = 1;
  250         $found += vaio_decode($i, '57');
  251     }
  252     elsif (-r "/proc/sys/dev/sensors/eeprom-i2c-$i-57")
  253     {
  254         if (-r "/proc/sys/dev/sensors/eeprom-i2c-$i-57/data0-15")
  255         {
  256             print("Deprecated old interface found.  Please upgrade to lm_sensors 2.6.3 or greater.");
  257             exit;
  258         }
  259         else
  260         {
  261             $sysfs = 0;
  262             $found += vaio_decode($i, '57');
  263         }
  264     }
  265 }
  266 
  267 if (!$found)
  268 {
  269     print("Vaio EEPROM not found.  Please make sure that the at24 or eeprom module is loaded.\n");
  270 }