[lm-sensors] [RESEND][PATCH 1/3] prog/detect/sensors-detect: Add dmi-lookup support

Ivo Manca pinkel at gmail.com
Mon Jul 2 11:34:25 CEST 2007


Hey All,

Please find below a new version of my patch for sensors-detect. This patch 
fixes some issues not to be found on any of my system ;p.

Changelog:
* Applied to latest revision of sensors-detect (4533)
* Bugfix: Error with modprobing when spaces are added to configfile
* Bugfix: Error loading when DMI-info has spaces in
* Bugfix: Invalid alternate files found when DMI-info has spaces in it
* Bugfix: Error with ubuntu (and possibly other distributions) when 
`uname -i` is not supported

(Not sure if patch comes through correctly, uploaded a copy to: 
http://www.pinkelmans.nl/prive/sensors/sensors-detect-20070702.patch )

Signed-off-by: Ivo Manca <pinkel at gmail.com>
---

diff -urbN lm-sensors-3/prog/detect/sensors-detect 
lm-sensors.new/prog/detect/sensors-detect
--- lm-sensors-3/prog/detect/sensors-detect 2007-07-02 02:26:15.000000000 
+0200
+++ lm-sensors.new/prog/detect/sensors-detect 2007-07-02 13:28:21.000000000 
+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, which typically lives in either /sbin,
 # /usr/sbin or /usr/local/bin. So make sure these are all in the PATH.
@@ -5228,6 +5231,332 @@
  return;
 }

+###########
+# DMI #
+###########
+
+use vars qw(%dmi $libraryPath $verbose);
+
+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
+    $dmi{$k} =~ s/\s*$// if defined $dmi{$k};
+    #write the DMI information to a file for later reference
+    print DMISTRINGS $dmi{$k};
+   }
+   return 1;
+}
+
+sub update_database
+{
+  my 
($website,$url, at headinfo,$modify_date_file,$modify_date_web,$file,$architecture);
+
+  $website = "http://tom.ti.thrijswijk.nl/ali50478/DMI_site/tarball/";
+  $file = $libraryPath."latest.tar.gz";
+
+  print "\n";
+  print "Checking for updates...\n" if not $verbose;
+
+  # determine architecture
+  return 0 unless open(local *ARCH, "uname -i 2>/dev/null |");
+  $architecture = <ARCH>;
+  close(ARCH);
+  if ($architecture) {
+    chomp $architecture;
+
+    # try to get tarball for specific architecture first
+    # Read the head to get the last-modified-date
+    $url = $website.$architecture.".tar.gz";
+    print "Checking for updates at: ".$url."\n" if $verbose;
+    @headinfo = head($url);
+    if (@headinfo) {
+      $modify_date_web = $headinfo[2];
+    }
+  }
+  if (not @headinfo or not $architecture)
+  {
+    # fail back to generic tarball
+    $url = $website."latest.tar.gz";
+    print "Can't find architecture specific tarball. \nFallback to: 
".$url."\n" if $verbose;
+    @headinfo = head($url);
+    if (@headinfo) {
+      $modify_date_web = $headinfo[2];
+    } else {
+      print @headinfo . "Errors: Problems with the website\n";
+      return 0;
+    }
+  }
+
+  # 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;
+    }
+  }
+
+  # 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;
+    }
+  }
+
+  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 alternate 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 the old config if this hasn't been done before.
+  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//;
+      # strip whitespaces
+      $_ =~ s/\s+//g;
+      push(@modules,$_);
+    }
+    if ($_ =~ m/^# minimum-kernel-version /) {
+      $_ =~ s/^# minimum-kernel-version //;
+      $_ =~ /(\d+)\.(\d+)\.(\d+)(.*)/;
+      if (!kernel_version_at_least($1,$2,$3)) {
+        print "Error! Your motherboard's configuration is only supported 
with kernel version\n",
+              "$1.$2.$3 or higher while your kernel version is 
".$kernel_version[0].".".$kernel_version[1].".".$kernel_version[2]."\n";
+        return 0;
+     }
+    }
+    if ($_ =~ m/^# comment /) {
+      #comment found!
+      $_ =~ s/^# comment //;
+      $comment .= "* ".$_."\n";
+    }
+  }
+  # show the found comments first
+  print $comment if ($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 #
 ################
@@ -5282,11 +5611,10 @@
 # A second array, called
 sub generate_modprobes
 {
-  my ($prefer_isa) = @_;
+  my ($prefer_isa,$modprobes) = @_;

   my ($chip,$detection,$nr,$i, at optionlist, at probelist,$driver,$isa,$adap);
   my $ipmi = 0;
-  my $modprobes = "";
   my $configfile = "";

   # These are always needed
@@ -5422,9 +5750,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",
+        "  -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",
+        "  -?, --help            Display this help\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,$dmi_success);

   # We won't go very far if not root
   unless ($> == 0) {
@@ -5432,6 +5780,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;
@@ -5450,6 +5808,30 @@
     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);
+    } 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);
+      }
+    }
+  }
+
+  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
@@ -5556,10 +5938,11 @@
     close_ioports();
   }
   print "\n";
+  } # end "NO-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);
@@ -5568,6 +5951,8 @@
   }
   print "\n";

+  if (!$dmi_success) # 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",
@@ -5611,13 +5996,13 @@
     }
   }
   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".
@@ -5640,13 +6025,20 @@
   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';
@@ -5694,6 +6086,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"; 





More information about the lm-sensors mailing list