You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

269 lines
7.2 KiB

#!/usr/bin/perl -w
#
# Copyright (C) 2002-2007 Jean Delvare <khali@linux-fr.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Version 0.1 2002-02-06 Jean Delvare <khali@linux-fr.org>
# Version 0.2 2002-02-16 Jean Delvare <khali@linux-fr.org>
# Fixed to work with the new, simplified /proc interface names of the eeprom
# driver (lm_sensors 2.6.3 and greater).
# Shifted data display by 4 columns left.
# Version 0.3 2002-02-17 Jean Delvare <khali@linux-fr.org>
# Added UUID field at 0x10 (added decode_uuid).
# Merged decode_string and decode_string32.
# Added unknown field at 0x20.
# Moved header and footer to BEGIN and END, respectively.
# Reformated history to match those of the other decode scripts.
# Deleted decode_char (made useless by decode_string).
# Reordered field display, changed some labels.
# Added old /proc interface check.
# Version 1.0 2002-11-15 Jean Delvare <khali@linux-fr.org>
# Gave the label "OEM Data" to the field at 0x20.
# Gave the label "Timestamp" to the field at 0xE0.
# Renamed "Model Number" to "Model Name".
# Added some documentation.
# Version 1.1 2004-01-17 Jean Delvare <khali@linux-fr.org>
# Added support for Linux 2.5/2.6 (i.e. sysfs).
# Version 1.2 2004-11-28 Jean Delvare <khali@linux-fr.org>
# Support bus number 0 to 4 instead of only 0.
# Version 1.3 2005-01-18 Jean Delvare <khali@linux-fr.org>
# Revision might be a Service Tag.
# Version 1.4 2006-09-20 Jean Delvare <khali@linux-fr.org>
# Detect and skip false positives (e.g. EDID EEPROMs).
# Version 1.5 2007-11-19 Jean Delvare <khali@linux-fr.org>
# UUID and serial number might be hidden
# The model name is actually the first half of the asset tag
#
# EEPROM data decoding for Sony Vaio laptops.
#
# The eeprom driver must be loaded. For kernels older than 2.6.0, the
# eeprom driver can be found in the lm-sensors package.
#
# Please note that this is a guess-only work. Sony support refused to help
# me, so if someone can provide information, please contact me.
# My knowledge is summarized on this page:
# http://khali.linux-fr.org/vaio/eeprom.html
#
# It seems that if present, the EEPROM is always at 0x57.
#
# Models tested so far:
# PCG-F403 : No EEPROM
# PCG-F707 : No EEPROM
# PCG-GR114EK : OK
# PCG-GR114SK : OK
# PCG-GR214EP : OK
# PCG-GRX316G : OK
# PCG-GRX570 : OK
# PCG-GRX600K : OK
# PCG-U1 : OK
# PCG-Z600LEK : No EEPROM
# PCG-Z600NE : No EEPROM
# VGN-S260 : OK
# VGN-S4M/S : OK
# Any feedback appreciated anyway.
#
# Thanks to Werner Heuser, Carsten Blume, Christian Gennerat, Joe Wreschnig,
# Xavier Roche, Sebastien Lefevre, Lars Heer, Steve Dobson, Kent Hunt and
# others for their precious help.
use strict;
use Fcntl qw(:DEFAULT :seek);
use vars qw($sysfs $found);
use constant ONLYROOT => "Readable only by root";
sub print_item
{
my ($label,$value) = @_;
printf("\%16s : \%s\n",$label,$value);
}
# Abstract reads so that other functions don't have to care wether
# we need to use procfs or sysfs
sub read_eeprom_bytes
{
my ($bus, $addr, $offset, $length) = @_;
my $filename;
if ($sysfs)
{
$filename = "/sys/bus/i2c/devices/$bus-00$addr/eeprom";
sysopen(FH, $filename, O_RDONLY)
or die "Can't open $filename";
sysseek(FH, $offset, SEEK_SET)
or die "Can't seek in $filename";
my ($r, $bytes);
$bytes = '';
$offset = 0;
while($length)
{
$r = sysread(FH, $bytes, $length, $offset);
die "Can't read $filename"
unless defined($r);
die "Unexpected EOF in $filename"
unless $r;
$offset += $r;
$length -= $r;
}
close(FH);
return $bytes;
}
else
{
my $base = $offset & 0xf0;
$offset -= $base;
my $values = '';
my $remains = $length + $offset;
# Get all lines in a single string
while ($remains > 0)
{
$filename = "/proc/sys/dev/sensors/eeprom-i2c-$bus-$addr/"
. sprintf('%02x', $base);
open(FH, $filename)
or die "Can't open $filename";
$values .= <FH>;
close(FH);
$remains -= 16;
$base += 16;
}
# Store the useful part in an array
my @bytes = split(/[ \n]/, $values);
@bytes = @bytes[$offset..$offset+$length-1];
# Back to a binary string
return pack('C*', @bytes);
}
}
sub decode_string
{
my ($bus, $addr, $offset, $length) = @_;
my $string = read_eeprom_bytes($bus, $addr, $offset, $length);
$string =~ s/\x00.*$//;
return($string);
}
sub decode_hexa
{
my ($bus, $addr, $offset, $length) = @_;
my @bytes = unpack('C*', read_eeprom_bytes($bus, $addr, $offset, $length));
my $string='';
for(my $i=0;$i<$length;$i++)
{
$string.=sprintf('%02X', shift(@bytes));
}
return($string);
}
sub decode_uuid
{
my ($bus,$addr,$base) = @_;
my @bytes = unpack('C16', read_eeprom_bytes($bus, $addr, $base, 16));
my $string='';
for(my $i=0;$i<16;$i++)
{
$string.=sprintf('%02x',shift(@bytes));
if(($i==3)||($i==5)||($i==7)||($i==9))
{
$string.='-';
}
}
if ($string eq '00000000-0000-0000-0000-000000000000')
{
return(ONLYROOT);
}
else
{
return($string);
}
}
sub vaio_decode
{
my ($bus,$addr) = @_;
my $name = decode_string($bus, $addr, 128, 32);
# Simple heuristic to skip false positives
return 0 unless $name =~ m/^[A-Z-]{4}/;
print_item('Machine Name', $name);
my $serial = decode_string($bus, $addr, 192, 32);
print_item('Serial Number', $serial ? $serial : ONLYROOT);
print_item('UUID', decode_uuid($bus, $addr, 16));
my $revision = decode_string($bus, $addr, 160, 10);
print_item(length($revision) > 2 ? 'Service Tag' : 'Revision',
$revision);
print_item('Asset Tag', decode_string($bus, $addr, 170, 4).
decode_hexa($bus, $addr, 174, 12));
print_item('OEM Data', decode_string($bus, $addr, 32, 16));
print_item('Timestamp', decode_string($bus, $addr, 224, 32));
return 1;
}
BEGIN
{
print("Sony Vaio EEPROM Decoder\n");
print("Copyright (C) 2002-2007 Jean Delvare\n");
print("Version 1.5\n\n");
}
END
{
print("\n");
}
for (my $i = 0, $found=0; $i <= 4 && !$found; $i++)
{
if (-r "/sys/bus/i2c/devices/$i-0057/eeprom")
{
$sysfs = 1;
$found += vaio_decode($i, '57');
}
elsif (-r "/proc/sys/dev/sensors/eeprom-i2c-$i-57")
{
if (-r "/proc/sys/dev/sensors/eeprom-i2c-$i-57/data0-15")
{
print("Deprecated old interface found. Please upgrade to lm_sensors 2.6.3 or greater.");
exit;
}
else
{
$sysfs = 0;
$found += vaio_decode($i, '57');
}
}
}
if (!$found)
{
print("Vaio EEPROM not found. Please make sure that the eeprom module is loaded.\n");
print("If you believe this is an error, please contact me <khali\@linux-fr.org>\n");
print("so that we may see how to fix the problem.\n");
}