root/i2c-tools/trunk/eeprom/decode-vaio.pl @ 5029

Revision 5029, 7.3 KB (checked in by khali, 6 years ago)

The timestamp is only 18-byte long.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#!/usr/bin/perl -w
2#
3# Copyright (C) 2002-2007 Jean Delvare <khali@linux-fr.org>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18#
19# Version 0.1  2002-02-06  Jean Delvare <khali@linux-fr.org>
20# Version 0.2  2002-02-16  Jean Delvare <khali@linux-fr.org>
21#  Fixed to work with the new, simplified /proc interface names of the eeprom
22#    driver (lm_sensors 2.6.3 and greater).
23#  Shifted data display by 4 columns left.
24# Version 0.3  2002-02-17  Jean Delvare <khali@linux-fr.org>
25#  Added UUID field at 0x10 (added decode_uuid).
26#  Merged decode_string and decode_string32.
27#  Added unknown field at 0x20.
28#  Moved header and footer to BEGIN and END, respectively.
29#  Reformated history to match those of the other decode scripts.
30#  Deleted decode_char (made useless by decode_string).
31#  Reordered field display, changed some labels.
32#  Added old /proc interface check.
33# Version 1.0  2002-11-15  Jean Delvare <khali@linux-fr.org>
34#  Gave the label "OEM Data" to the field at 0x20.
35#  Gave the label "Timestamp" to the field at 0xE0.
36#  Renamed "Model Number" to "Model Name".
37#  Added some documentation.
38# Version 1.1  2004-01-17  Jean Delvare <khali@linux-fr.org>
39#  Added support for Linux 2.5/2.6 (i.e. sysfs).
40# Version 1.2  2004-11-28  Jean Delvare <khali@linux-fr.org>
41#  Support bus number 0 to 4 instead of only 0.
42# Version 1.3  2005-01-18  Jean Delvare <khali@linux-fr.org>
43#  Revision might be a Service Tag.
44# Version 1.4  2006-09-20  Jean Delvare <khali@linux-fr.org>
45#  Detect and skip false positives (e.g. EDID EEPROMs).
46# Version 1.5  2007-11-19  Jean Delvare <khali@linux-fr.org>
47#  UUID and serial number might be hidden
48#  The model name is actually the first half of the asset tag
49#  The timestamp is only 18-byte long
50#
51# EEPROM data decoding for Sony Vaio laptops.
52#
53# The eeprom driver must be loaded. For kernels older than 2.6.0, the
54# eeprom driver can be found in the lm-sensors package.
55#
56# Please note that this is a guess-only work.  Sony support refused to help
57# me, so if someone can provide information, please contact me.
58# My knowledge is summarized on this page:
59# http://khali.linux-fr.org/vaio/eeprom.html
60#
61# It seems that if present, the EEPROM is always at 0x57.
62#
63# Models tested so far:
64#   PCG-F403     : No EEPROM
65#   PCG-F707     : No EEPROM
66#   PCG-GR114EK  : OK
67#   PCG-GR114SK  : OK
68#   PCG-GR214EP  : OK
69#   PCG-GRT955MP : OK
70#   PCG-GRX316G  : OK
71#   PCG-GRX570   : OK
72#   PCG-GRX600K  : OK
73#   PCG-U1       : OK
74#   PCG-Z600LEK  : No EEPROM
75#   PCG-Z600NE   : No EEPROM
76#   VGN-S260     : OK
77#   VGN-S4M/S    : OK
78#   VGN-TZ11MN/N : OK
79# Any feedback appreciated anyway.
80#
81# Thanks to Werner Heuser, Carsten Blume, Christian Gennerat, Joe Wreschnig,
82# Xavier Roche, Sebastien Lefevre, Lars Heer, Steve Dobson, Kent Hunt,
83# Timo Hoenig and others for their precious help.
84
85
86use strict;
87use Fcntl qw(:DEFAULT :seek);
88use vars qw($sysfs $found);
89
90use constant ONLYROOT   => "Readable only by root";
91
92sub print_item
93{
94        my ($label,$value) = @_;
95       
96        printf("\%16s : \%s\n",$label,$value);
97}
98
99# Abstract reads so that other functions don't have to care wether
100# we need to use procfs or sysfs
101sub read_eeprom_bytes
102{
103        my ($bus, $addr, $offset, $length) = @_;
104        my $filename;
105       
106        if ($sysfs)
107        {
108                $filename = "/sys/bus/i2c/devices/$bus-00$addr/eeprom";
109                sysopen(FH, $filename, O_RDONLY)
110                        or die "Can't open $filename";
111                sysseek(FH, $offset, SEEK_SET)
112                        or die "Can't seek in $filename";
113
114                my ($r, $bytes);
115                $bytes = '';
116                $offset = 0;
117                while($length)
118                {
119                        $r = sysread(FH, $bytes, $length, $offset);
120                        die "Can't read $filename"
121                                unless defined($r);
122                        die "Unexpected EOF in $filename"
123                                unless $r;
124                        $offset += $r;
125                        $length -= $r;
126                }
127                close(FH);
128               
129                return $bytes;
130        }
131        else
132        {
133                my $base = $offset & 0xf0;
134                $offset -= $base;
135                my $values = '';
136                my $remains = $length + $offset;
137               
138                # Get all lines in a single string
139                while ($remains > 0)
140                {
141                        $filename = "/proc/sys/dev/sensors/eeprom-i2c-$bus-$addr/"
142                                  . sprintf('%02x', $base);
143                        open(FH, $filename)
144                                or die "Can't open $filename";
145                        $values .= <FH>;
146                        close(FH);
147                        $remains -= 16;
148                        $base += 16;
149                }
150               
151                # Store the useful part in an array
152                my @bytes = split(/[ \n]/, $values);
153                @bytes = @bytes[$offset..$offset+$length-1];
154
155                # Back to a binary string
156                return pack('C*', @bytes);
157        }
158}
159
160sub decode_string
161{
162        my ($bus, $addr, $offset, $length) = @_;
163
164        my $string = read_eeprom_bytes($bus, $addr, $offset, $length);
165        $string =~ s/\x00.*$//;
166       
167        return($string);
168}
169
170sub decode_hexa
171{
172        my ($bus, $addr, $offset, $length) = @_;
173
174        my @bytes = unpack('C*', read_eeprom_bytes($bus, $addr, $offset, $length));
175        my $string='';
176
177        for(my $i=0;$i<$length;$i++)
178        {
179                $string.=sprintf('%02X', shift(@bytes));
180        }
181
182        return($string);
183}
184
185sub decode_uuid
186{
187        my ($bus,$addr,$base) = @_;
188
189        my @bytes = unpack('C16', read_eeprom_bytes($bus, $addr, $base, 16));
190        my $string='';
191
192        for(my $i=0;$i<16;$i++)
193        {
194                $string.=sprintf('%02x',shift(@bytes));
195                if(($i==3)||($i==5)||($i==7)||($i==9))
196                {
197                        $string.='-';
198                }
199        }
200
201        if ($string eq '00000000-0000-0000-0000-000000000000')
202        {
203                return(ONLYROOT);
204        }
205        else
206        {
207                return($string);
208        }
209}
210
211sub vaio_decode
212{
213        my ($bus,$addr) = @_;
214       
215        my $name = decode_string($bus, $addr, 128, 32);
216        # Simple heuristic to skip false positives
217        return 0 unless $name =~ m/^[A-Z-]{4}/;
218
219        print_item('Machine Name', $name);
220        my $serial = decode_string($bus, $addr, 192, 32);
221        print_item('Serial Number', $serial ? $serial : ONLYROOT);
222        print_item('UUID', decode_uuid($bus, $addr, 16));
223        my $revision = decode_string($bus, $addr, 160, 10);
224        print_item(length($revision) > 2 ? 'Service Tag' : 'Revision',
225                   $revision);
226        print_item('Asset Tag', decode_string($bus, $addr, 170, 4).
227                                decode_hexa($bus, $addr, 174, 12));
228        print_item('OEM Data', decode_string($bus, $addr, 32, 16));
229        print_item('Timestamp', decode_string($bus, $addr, 224, 18));
230        return 1;
231}
232
233BEGIN
234{
235        print("Sony Vaio EEPROM Decoder\n");
236        print("Copyright (C) 2002-2007  Jean Delvare\n");
237        print("Version 1.5\n\n");
238}
239
240END
241{
242        print("\n");
243}
244
245for (my $i = 0, $found=0; $i <= 4 && !$found; $i++)
246{
247        if (-r "/sys/bus/i2c/devices/$i-0057/eeprom")
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
267if (!$found)
268{
269        print("Vaio EEPROM not found.  Please make sure that the eeprom module is loaded.\n");
270        print("If you believe this is an error, please contact me <khali\@linux-fr.org>\n");
271        print("so that we may see how to fix the problem.\n");
272}
Note: See TracBrowser for help on using the browser.