[prev in list] [next in list] [prev in thread] [next in thread]
List: lm-sensors
Subject: Re: [lm-sensors] Sensors-detect with DMI information,
From: "Ivo Manca" <pinkel () gmail ! com>
Date: 2007-05-30 14:17:08
Message-ID: 00e501c7a2c5$366898b0$42ac2ac0 () pinkeltje
[Download RAW message or body]
Hey all,
It's been a while since I've posted the first patch and I've had no response
yet. Luckily, I was able to improve the script some more in the meantime, so
I would like to send in a new patch. Comments and flames are welcome ;)
The patch supports:
* Command line parameters
(--automatic, --manual, --version, --verbose, --help, --update)
* Looks up DMI information and tries to match this with a config file in
/usr/share/lmsensors/motherboards
* Ability to update /usr/share/lmsensors/motherboards with database (Note:
This database is currently a DUMMY and does not contain any usuable
information suitable for anything besides testing).
* Proccesses the config file if found.
New since last patch:
* Escaping of slashes in filenames.
* Check for updates before downloading the update
* Saves a dump of DMI information to file.
* Don't initialize DMI information if DMI detection is not enabled
* Displays annotated comments in configfiles
- Some code cleanup
- Added comments
Config files are parsed as following:
It looks in /usr/share/lmsensors/motherboards for a filename matching
system-manufacturer - baseboard-manufacturer - system-product-name -
baseboard-product-name - system-version - baseboard-version. (Without the
spaces ofcourse ;)). If it can't find this config, it will look for an
alternate revision: everything with a different version number. It lists
these config files and lets the user decide whether to load them or not.
If a configuration file is finally loaded, it looks through it for lines
starting with:
# modprobe
These modules will be (auto)loaded.
It also parses lines with:
# Comment: blablabla
And prints * blablabla. This is done (i.e.) to notify a user if a
configuration is found, but the motherboard has no hardware monitoring
capabilities.
=
I've also added a shellscript which can be added to the lmsensors
startupscript in /etc/init.d/. This script check for modified DMI
information (I.E. new motherboard) and then tries to autodetect the
motherboard using this information.
Because attachments seem to get filtered out when I send them to the list,
I've also uploaded them at:
Patch:
http://www.pinkelmans.nl/prive/sensors/sensors-detect-20070530.patch
Shellscript: http://www.pinkelmans.nl/prive/sensors/shell
Ivo Manca
----- Original Message -----
From: "Ivo Manca" <pinkel@gmail.com>
To: <lm-sensors@lm-sensors.org>
Cc: <J.W.R.deGoede@hhs.nl>; "Jasper Alias" <jasperalias@hotmail.com>; "Weg,
G. van der" <g.vanderweg@student.hhs.nl>; "Jean Delvare"
<khali@linux-fr.org>; <ejl@eberian.com>
Sent: Monday 14 May 2007 13:13
Subject: Sensors-detect with DMI information, requirements & first version:
Requestion comment
> Hey all,
>
> Please find attached the (patch for) first version of the updated
> sensors-detect. This patch adds support for looking up sensors
> configurations while using DMI information. It applies to the 3.0.0 branch
> of lmsensors.
>
> Information about the patch:
> * Adds command line parameters
> (--automatic, --manual, --version, --verbose, --help, --update)
> * Looks up DMI information and tries to match this with a config file in
> /usr/share/lmsensors/motherboards
> * Ability to update /usr/share/lmsensors/motherboards with database (Note:
> This database is currently a DUMMY and does not contain any usuable
> information suitable for anything besides testing).
> * Proccesses the config file if found.
>
> It seems like it's already near to a complete working version. Every
> comment
> will be appriciated.
> If you want to find a checklist with the implemented functions, please
> check: http://www.pinkelmans.nl/prive/sensors/Checklist.pdf
>
> Note 1: The script currentently does not yet escapes backslashes for
> filenames, this will be added soon.
> Note 2: To make the patch more readable, there are no spaces added to
> nearly
> every line inside the mainfunction of sensors-detect. Therefor the patched
> verion of sensors-detect itself might be hard to read. A patch with the
> added spaces (etc) will be submitted next week or so.
> Note 3: The ability to only download configurations suitable for the
> current
> architecture will be added if time permits.
>
> Requirements for sensors-detect (Ivo Manca):
> http://www.pinkelmans.nl/prive/sensors/sensors_detect-req.pdf
> Requirements for website (Jasper Alias):
> http://www.pinkelmans.nl/prive/sensors/website-req.pdf
> Please feel free to comment on these requirements or to ask us to
> eleberate
> them.
>
> Information about the sensors-detect discussion can be found:
> http://lists.lm-sensors.org/pipermail/lm-sensors/2007-March/thread.html#19332
> http://lists.lm-sensors.org/pipermail/lm-sensors/2007-March/thread.html#19008
> http://lists.lm-sensors.org/pipermail/lm-sensors/2007-February/thread.html#18932
>
> Ivo Manca
> Jasper Alias
> Gijs van der Weg
>
["shell" (application/octet-stream)]
["sensors-detect-20070530.patch" (application/octet-stream)]
--- sensors-detect-3.0.0 2007-05-09 15:06:41.609375000 +0200
+++ sensors-detect 2007-05-30 13:00:10.890625000 +0200
@@ -33,6 +33,9 @@
use Fcntl;
use POSIX;
use File::Basename;
+use File::Copy;
+use Getopt::Long;
+use LWP::Simple;
# We will call modprobe and i2cdetect, which typically live in either /sbin,
# /usr/sbin or /usr/local/bin. So make sure these are all in the PATH.
@@ -2117,7 +2120,7 @@
# AUTODETECTION #
#################
-use vars qw($modules_conf $dev_i2c $sysfs_root);
+use vars qw($modules_conf $dev_i2c $sysfs_root $verbose);
sub initialize_conf
{
@@ -5326,6 +5329,302 @@
return;
}
+###########
+# DMI #
+###########
+
+use vars qw(%dmi $libraryPath);
+
+sub initialize_dmi_data
+{
+ my $version;
+ my @items = (
+ 'system-manufacturer',
+ 'system-product-name',
+ 'system-version',
+ 'baseboard-manufacturer',
+ 'baseboard-product-name',
+ 'baseboard-version',
+ );
+
+ return 0 unless open(local *DMIDECODE, "dmidecode --version 2>/dev/null |");
+ $version = <DMIDECODE>;
+ close(DMIDECODE);
+ return 0 unless defined $version;
+
+ # We need at least version 2.7
+ chomp $version;
+ return 0 unless $version =~ m/^(\d+).(\d+)$/;
+ return 0 unless (($1 == 2 && $2 >= 7) || $1 > 2);
+
+ open(local *DMISTRINGS, ">/etc/dmistrings") or die "Sorry, can't create \
/etc/dmistrings ($!)"; +
+ foreach my $k (@items) {
+ next unless open(local *DMIDECODE, "dmidecode -s $k |");
+ $dmi{$k} = <DMIDECODE>;
+ close(DMIDECODE);
+ # Strip trailing white-space, discard empty field
+ $dmi{$k} =~ s/\s*$// if defined $dmi{$k};
+ delete $dmi{$k} if (!defined $dmi{$k} || $dmi{$k} eq '');
+ #write the DMI information to a file for later reference
+ print DMISTRINGS $dmi{$k};
+ }
+ return 1;
+}
+
+sub update_database
+{
+ my ($url,@headinfo,$modify_date_file,$modify_date_web,$file);
+
+ $url = "http://www.pinkelmans.nl/prive/sensors/latest.tar.gz";
+ $file = $libraryPath."latest.tar.gz";
+
+ print "\nChecking for updates...\n";
+
+ # Read the head to get the last-modified-date
+ @headinfo = head($url);
+ if (@headinfo) {
+ $modify_date_web = $headinfo[2];
+ } else {
+ print @headinfo . "Errors: Problems with the website\n";
+ return 0;
+ }
+
+ # check if library path exists, if not: create
+ if (not -d $libraryPath) {
+ my $dir;
+ my $accum="";
+ foreach $dir (split(/\//, $libraryPath)){
+ $accum = "$accum$dir/";
+ if(defined($dir) && $dir ne ""){
+ if(! -d "$accum"){
+ mkdir $accum;
+ print "Making dir: ".$accum."\n" if $verbose;
+ }
+ }
+ }
+ if (not -d $libraryPath) {
+ print "Error: Can not create directory: ".$libraryPath."\n";
+ print "Error details: " . $! . "\n" if $verbose;
+ }
+ }
+
+ # check if file exists localy, to check if there is a newer one available
+ if (-e $file) {
+ $modify_date_file = (stat($file))[9];
+ if ($modify_date_web <= $modify_date_file) {
+ print "No update available\n";
+ return 0;
+ }
+ }
+
+
+ print "Downloading tarball...";
+ print "\nFrom: ".$url." To: ".$file."\n" if $verbose;
+ my $response = getstore($url, $file);
+
+ # set modify date to the same date as the file on the website to get them in-sync;
+ utime $modify_date_web, $modify_date_web, $file;
+ if (is_success($response )) {
+ print "Extracting tarball...";
+ print "\nFrom: ".$file." To: ".$libraryPath." with: tar-xzf \n" if $verbose;
+ if (!system("tar -xzf ".$file." -C ".$libraryPath)) {
+ print "Extracting completed...Update progress completed!\n";
+ } else {
+ print "Error: failed to extract tarball!\n";
+ }
+ } else
+ {
+ print "Error: failed to download file!\n";
+ }
+}
+
+sub dmi_detection
+{
+ my $mode = $_[0];
+ my $update = 0;
+
+ # initialize the dmi data
+ if (!initialize_dmi_data()) {
+ print "Error! 'dmidecode' can not be found or loaded. Please make sure \n",
+ "it is installed. \n",
+ "Skipping DMI detection.\n\n";
+ return 0;
+ }
+
+ print $mode == 2 ? "Entering DMI Detection mode...\n" : "\n";
+
+ # check whether to update or not, based on automatic mode (mode==2), available \
local database and user input + $update = -1 if $mode == 2; # don't update if \
automatic mode is enabled + if (!$update) {
+ if (not -d $libraryPath) {
+ print "It seems that the database with the different motherboard \
configurations is\n". + "not available on your system. You needed to \
download and install this \n". + "database to continue.\n".
+ "Do you wish to download and install the database? (YES/no): ";
+ if (<STDIN> =~ /\s*[Nn]/) {
+ print "\nNo database available. Aborting.\n";
+ return 0;
+ } else {
+ $update = 1;
+ }
+ } else {
+ print "Before finding the apropriate config file, you can choose to update\n".
+ "your database with a database downloaded from internet. \n".
+ "Do you want to check for updates? (YES/no)";
+ $update = 1 unless (<STDIN> =~ /\s*[Nn]/);
+ }
+ }
+
+ if ($update == 1) {
+ update_database();
+ print "\n";
+ }
+
+ print_dmi_data() if $verbose;
+
+ return find_config_file($mode);
+}
+
+sub print_dmi_data
+{
+ print "This is the output of your DMI information: \n",
+ "# System Manufacturer: ", $dmi{'system-manufacturer'}, "\n",
+ "# System Productname: ", $dmi{'system-product-name'}, "\n",
+ "# System Version: ", $dmi{'system-version'}, "\n",
+ "# Baseboard Manufacturer: ", $dmi{'baseboard-manufacturer'}, "\n",
+ "# Baseboard Productname: ", $dmi{'baseboard-product-name'}, "\n",
+ "# Baseboard Version: ", $dmi{'baseboard-version'}, "\n\n";
+}
+
+sub find_config_file
+{
+ # find the config file corrensponding to the DMI information
+ my $mode = $_[0];
+ my $find_file = $dmi{'system-manufacturer'}. "-".$dmi{'baseboard-manufacturer'}. \
"-".$dmi{'system-product-name'}. "-".$dmi{'baseboard-product-name'}."-"; + my \
$find_version = $dmi{'system-version'}. "-".$dmi{'baseboard-version'}; +
+ # strip the character / (directory separator) from the dmi-info
+ $find_file =~ s/\//./g;
+ $find_version =~ s/\//./g;
+
+ $find_file = $libraryPath.$find_file;
+
+ my $config_file;
+
+ # search for config file matching revision
+ print "Looking for configfile '".$find_file.$find_version. "'\n" if $verbose;
+ if (-e $find_file.$find_version) {
+ $config_file = $find_file.$find_version;
+ } else {
+ print "Configfile not found \n" if $verbose;
+ if ($mode != 2) {
+ # search for alternative revisions and let the user decided wether to load it \
or not + print "Looking for alternative configfiles: '".$find_file."*'\n" if \
$verbose; + my @alternate_config_files;
+ my $file_name;
+ my $nr_alternate_config_files;
+ my $count;
+ while ($file_name = glob($find_file."*")) {
+ $file_name =~ s/$find_file//;
+ push(@alternate_config_files,$file_name);
+ }
+ $nr_alternate_config_files = scalar(@alternate_config_files);
+ if ($nr_alternate_config_files > 0) {
+ print "I was able to find ",$nr_alternate_config_files," alternate \
configurations after comparing\n", + "the information from the DMI table \
with the available configuration files.\n"; + print "These configurations \
match your motherboard manufacturer and model, \n". + "but are tested \
for a different revision. Your revision is: \n\n"; + print "* \
",$find_version,"\n\n"; + print "The available configrations are for the \
following revisions:\n\n"; + foreach $file_name(@alternate_config_files) {
+ $count++;
+ print$count,". ",$file_name,"\n";
+ }
+ print "\nPlease choose the configuration you want to load.\n",
+ "Note: These configurations are not tested for your specefic \
motherboard\n", + "model. Use them at your own risk.\n";
+ print "Enter 0 or hit return if you want to exit detection through DMI.\n";
+ print "Config file [0-",$nr_alternate_config_files,"]: ";
+ my $inp =<STDIN>;
+ print "\n";
+ if ($inp =~ /^[1-$nr_alternate_config_files]$/) {
+ $config_file = $find_file.$alternate_config_files[$inp-1];
+ }
+ }
+ }
+ }
+ if ($config_file) {
+ return load_config_file($config_file,$mode);
+ } else {
+ print "No configuration found.\n\n";
+ return 0;
+ }
+}
+
+sub load_config_file
+{
+ my $config_file = $_[0];
+ my $mode = $_[1];
+ my (@modules, $module, $modprobes,$comment);
+
+ print "Using config: ",$config_file,"\n\n";
+
+ # backup old config if automatic mode is enabled
+ if (!(-e "/etc/sensors.conf.sensorsdetect")) {
+ copy ("/etc/sensors.conf", "/etc/sensors.conf.sensorsdetect");
+ print "Backup of /etc/sensors.conf saved at /etc/sensors.conf.sensorsdetect\n";
+ }
+
+ # copy config to /etc/sensors.conf
+ copy ($config_file, "/etc/sensors.conf");
+
+ # parse config file
+ open FILE, "/etc/sensors.conf" or die "Can't open config file";
+ while(<FILE>) {
+ if ($_ =~ m/^# modprobe /) {
+ # modprobe found!
+ $_ =~ s/^# modprobe //;
+ $_ =~ s/\n//;
+ push(@modules,$_);
+ }
+ if ($_ =~ m/^# Comment: /) {
+ #comment found!
+ $_ =~ s/^# Comment: //;
+ $comment .= "* ".$_."\n";
+ }
+ }
+
+ # show the found comments first
+ print $comment;
+
+ # generate modprobes
+ $modprobes .= "# Drivers found by sensors-detect with DMI detection enabled\n";
+
+ # load modules and add to autoload
+ foreach $module(@modules) {
+ if (exists($modules_list{$module})) {
+ print "Module `$module' already loaded.\n";
+ } else {
+ print "Load `$module' (say NO if built into your kernel)? (YES/no): " unless \
($mode == 2); + unless ($mode != 2 && <STDIN> =~ /^\s*[Nn]/) {
+ if (system ("modprobe", $module)) {
+ print "Loading failed... skipping.\n";
+ $modprobes .= "# Warning: the required module $module is not currently \
installed\n". + "# on your system. For status of 2.6 kernel \
ports check\n". + "# http://www.lm-sensors.org/wiki/Devices. \
If driver is built\n". + "# into the kernel, or unavailable, \
comment out the following line.\n"; + } else {
+ print "Module loaded successfully.\n";
+ }
+ }
+ }
+ $modprobes .= "modprobe $module\n";
+ }
+ print "DMI detection succeeded and config file succesfully loaded!\n\n";
+ return (1,$modprobes);
+}
+
################
# MAIN PROGRAM #
################
@@ -5380,12 +5679,11 @@
# A second array, called
sub generate_modprobes
{
- my ($prefer_isa) = @_;
+ my ($prefer_isa,$modprobes) = @_;
my ($chip,$detection,$nr,$i,@optionlist,@probelist,$driver,$isa,$adap);
my $bmcsensors = 0;
my @adapters;
- my $modprobes = "";
my $configfile = "";
# These are always needed
@@ -5528,9 +5826,29 @@
}
+sub VersionMessage
+{
+ print "# sensors-detect revision $revision\n\n";
+ exit;
+}
+sub HelpMessage
+{
+ print "Usage: sensors-detect [OPTION]\n",
+ " -a --automatic Don't ask anything, use defaults\n",
+ " -?, --help Display this help\n",
+ " -m, --manual Only use old way of probing\n",
+ " -u --update Update the database, then quit\n",
+ " -v --verbose Display extra information useful for debugging\n",
+ " --version Display the program version\n",
+ "\n",
+ "Default mode is: use DMI detection first, fallback to old way of \
probing\n"; + exit;
+}
+
sub main
{
- my (@adapters,$res,$did_adapter_detection,$adapter);
+ my (@adapters,$res,$did_adapter_detection,$adapter,$modprobes,$configfile,$update,$inp);
+ my $dmi_success = 0;
# We won't go very far if not root
unless ($> == 0) {
@@ -5538,6 +5856,16 @@
exit -1;
}
+ # Parse the command line parameters
+ my $mode = 1; #0 = manual 1 = dmi, 2 = automatic
+ $libraryPath = "/usr/share/lmsensors/motherboards/";
+
+ my $result = GetOptions ("verbose|v"=> \$verbose, "update" => \$update, \
"automatic"=> sub {$mode = 2 },"manual"=> sub { $mode = 0 }, "help|?"=> sub { \
HelpMessage() },"version" => sub { VersionMessage() }); + if ($update) { # not an \
GetOptions sub. Verbose won't be passed if you specify "-u -v", when the update \
function is called in a sub. Now it will be passed. + update_database();
+ exit;
+ }
+
initialize_conf;
initialize_proc_pci;
initialize_modules_list;
@@ -5556,6 +5884,32 @@
unless kernel_version_at_least(2, 6, 0);
print "\n";
+ # dmi automaticly, interactive or disabled
+
+ if ($mode > 0) {
+ if ($mode == 2) { # start dmi detection if automatic mode is enabled
+ ($dmi_success, $modprobes) = dmi_detection($mode);
+ # create dmidecode information file, used by automatic startup script
+ } else {
+ print "We can start looking up the DMI table to find a config file. This\n",
+ "is the safest way to locate the available sensors.\n".
+ "Do you want to lookup the DMI table now? (YES/no): ";
+ $inp = <STDIN>;
+ if (not $inp =~ /\s*[Nn]/) { # start dmi detection if manual mode is enabled \
and user presses "yes" + ($dmi_success, $modprobes) = dmi_detection($mode);
+ # create dmidecode information file, used by automatic startup script
+ }
+ }
+ }
+
+ if ($dmi_success == 0) { # dmi detection not started or unsuccesful
+ if ($mode == 2) { # quit if automatic mode enabled
+ die "Detection using the DMI information failed. \n",
+ "Please update your database or use non-automatic mode for detection \n";
+ }
+
+ print "Detection using the DMI information failed. Switching to old mode. \n\n" \
unless ($mode == 0 || $inp =~ /\s*[Nn]/); +
print "We can start with probing for (PCI) I2C or SMBus adapters.\n";
print "Do you want to probe now? (YES/no): ";
@adapters = adapter_pci_detection
@@ -5615,7 +5969,7 @@
"If you found that the adapter hung after probing a certain address,\n",
"you can specify that address to remain unprobed.\n";
- my ($inp,@not_to_scan,$inp2);
+ my (@not_to_scan,$inp2);
# i2cdetect -l either cats /proc/bus/i2c or scans sysfs for the same information
open(local *INPUTFILE, "i2cdetect -l |") or die "Couldn't find i2cdetect \
program!!"; local $_;
@@ -5665,9 +6019,11 @@
}
print "\n";
+ } # end "DMI" mode to detect CPU sensors.
+
print "Some CPUs or memory controllers may also contain embedded sensors.\n";
- print "Do you want to scan for them? (YES/no): ";
- unless (<STDIN> =~ /^\s*n/i) {
+ print "Do you want to scan for them? (YES/no): " unless ($mode == 2);
+ unless ($mode != 2 && <STDIN> =~ /^\s*n/i) {
$| = 1;
foreach my $entry (@cpu_ids) {
scan_cpu($entry);
@@ -5675,7 +6031,9 @@
$| = 0;
}
print "\n";
-
+
+ if ($dmi_success == 0) # dmi detection not started or unsuccesful
+ {
if(! @chips_detected) {
print "Sorry, no sensors were detected.\n",
"Either your sensors are not supported, or they are connected to an\n",
@@ -5727,12 +6085,14 @@
}
print "\n";
- print "I will now generate the commands needed to load the required modules.\n".
- "Just press ENTER to continue: ";
- <STDIN>;
+ } # end "DMI" mode
+ ($modprobes, $configfile) = generate_modprobes(1,$modprobes); # 1 == prefer ISA
+
+ print "I will now generate the commands needed to load the required modules.\n";
+ print "Just press ENTER to continue: " unless ($mode == 2);
+ <STDIN> unless ($mode == 2);
print "\n";
- my ($modprobes, $configfile) = generate_modprobes 1; # 1 == prefer ISA
print "To make the sensors modules behave correctly, add these lines to\n".
"$modules_conf:\n\n";
print "#----cut here----\n".
@@ -5755,13 +6115,21 @@
my $have_sysconfig = -d '/etc/sysconfig';
printf "Do you want to \%s /etc/sysconfig/lm_sensors? (\%s): ",
(-e '/etc/sysconfig/lm_sensors' ? 'overwrite' : 'generate'),
- ($have_sysconfig ? 'YES/no' : 'yes/NO');
- $_ = <STDIN>;
+ ($have_sysconfig ? 'YES/no' : 'yes/NO') unless ($mode == 2);
+ $_ = $mode == 2 ? "" : <STDIN>;
+
if (($have_sysconfig and not m/^\s*n/i) or m/^\s*y/i) {
unless ($have_sysconfig) {
mkdir '/etc/sysconfig', 0777
or die "Sorry, can't create /etc/sysconfig ($!)";
}
+
+ if (($mode == 2) && (!(-e "/etc/sysconfig/lm_sensors.sensorsdetect"))) {
+ # backup the lmsensors sysconfig
+ copy ("/etc/sysconfig/lm_sensors","/etc/sysconfig/lm_sensors.sensorsdetect");
+ print "Backup of /etc/sysconfig/lm_sensors saved at \
/etc/sysconfig/lm_sensors.sensorsdetect\n\n"; + }
+
open(local *SYSCONFIG, ">/etc/sysconfig/lm_sensors")
or die "Sorry, can't create /etc/sysconfig/lm_sensors ($!)";
print SYSCONFIG <<'EOT';
@@ -5809,6 +6177,7 @@
}
print SYSCONFIG $sysconfig;
+ print "/etc/sysconfig/lm_senors is overwritten with the new config.\n";
print "Copy prog/init/lm_sensors.init to /etc/init.d/lm_sensors\n".
"for initialization at boot time.\n"
unless -f "/etc/init.d/lm_sensors";
_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic