No more hwdata.
authorDaniel Hokka Zakrisson <dhokka@cs.princeton.edu>
Wed, 21 Nov 2007 03:28:59 +0000 (03:28 +0000)
committerDaniel Hokka Zakrisson <dhokka@cs.princeton.edu>
Wed, 21 Nov 2007 03:28:59 +0000 (03:28 +0000)
source/merge_hw_tables.py [deleted file]
source/systeminfo.py

diff --git a/source/merge_hw_tables.py b/source/merge_hw_tables.py
deleted file mode 100755 (executable)
index dfe3378..0000000
+++ /dev/null
@@ -1,332 +0,0 @@
-#!/usr/bin/python2
-
-# Copyright (c) 2003 Intel Corporation
-# All rights reserved.
-#
-# Copyright (c) 2004-2006 The Trustees of Princeton University
-# All rights reserved.
-
-
-"""
-The point of this small utility is to take a file in the format
-of /lib/modules/`uname -r`/modules.pcimap and /usr/share/hwdata/pcitable
-and output a condensed, more easily used format for module detection. This is
-done by first getting a list of all the built modules, then loading the
-pci ids for each of those modules from modules.pcimap, then finally merging
-in the contents of pcitable (for built modules only). The result should be
-a file with a pretty comprehensive mapping of pci ids to module names.
-
-The output is used by the PlanetLab boot cd (3.0+) and the pl_hwinit script
-to load all the applicable modules by scanning lspci output.
-
-
-
-Expected format of file modules.dep includes lines of:
-
-/full/module/path/mod.ko: <dependencies>
-
-Expected format of file modules.pcimap includes lines of:
-
-# pci_module vendor device subvendor subdevice class class_mask driver_data
-cciss 0x00000e11 0x0000b060 0x00000e11 0x00004070 0x00000000 0x00000000 0x0
-cciss 0x00000e11 0x0000b178 0x00000e11 0x00004070 0x00000000 0x00000000 0x0
-
-Expected format of file pcitable includes lines of:
-
-# ("%d\t%d\t%s\t"%s"\n", vendid, devid, moduleName, cardDescription)
-# or ("%d\t%d\t%d\t%d\t%s\t"%s"\n", vendid, devid, subvendid, subdevid, moduleNa
-# me, cardDescription)
-0x0e11  0x0508  "tmspci"        "Compaq|Netelligent 4/16 Token Ring"
-0x1000  0x0407  0x8086  0x0532  "megaraid"      "Storage RAID Controller SRCU42X"
-
-Lines listing a module name of ignore or unknown from pcitable are skipped
-
-
-
-Output format, for each line that matches the above lines:
-cciss 0e11:b060 0e11:b178
-
-"""
-
-import os, sys
-import string
-import StringIO
-
-PCI_ANY = 0xffffffffL
-
-def merge_files(modules_dep_path, modules_pcimap_path, pcitable_path):
-    """
-    merge the three files as described above, and return a dictionary.
-    keys are module names, value is a list of pci ids for that module,
-    in the form "0e11:b178"
-    """
-
-    try:
-        modulesdep_file= file(modules_dep_path,"r")
-    except IOError:
-        sys.stderr.write( "Unable to open modules.dep: %s\n" %
-                          modules_dep_path )
-        return
-
-    try:
-        pcimap_file= file(modules_pcimap_path,"r")
-    except IOError:
-        sys.stderr.write( "Unable to open modules.pcimap: %s\n" %
-                          modules_pcimap_path )
-        return
-
-    try:
-        pcitable_file= file(pcitable_path,"r")
-    except IOError:
-        sys.stderr.write( "Unable to open pcitable: %s\n" %
-                          pcitable_path )
-       pcitable_file=StringIO.StringIO()
-
-    # associative array to store all matches of module -> ['vendor:device',..]
-    # entries
-    all_modules= {}
-    all_pci_ids= {}
-
-    # first step, create an associative array of all the built modules
-    for line in modulesdep_file:
-        parts= string.split(line,":")
-        if len(parts) < 2:
-            continue
-
-        full_mod_path= parts[0]
-        parts= string.split(full_mod_path,"/")
-        module= parts[len(parts)-1]
-        module_len= len(module)
-        if module[module_len-3:] == ".ko":
-            module= module[:-3]
-            all_modules[module]= []
-
-    modulesdep_file.close()
-
-    # now, parse the pcimap and add devices
-    line_num= 0
-    for line in pcimap_file:
-        line_num= line_num+1
-
-        # skip blank lines, or lines that begin with # (comments)
-        line= string.strip(line)
-        if len(line) == 0:
-            continue
-
-        if line[0] == "#":
-            continue
-
-        line_parts= string.split(line)
-        if line_parts is None or len(line_parts) != 8:
-            sys.stderr.write( "Skipping line %d in pcimap " \
-                              "(incorrect format %s)\n" % (line_num,line) )
-            continue
-
-        # first two parts are always vendor / device id
-        module= line_parts[0]
-
-        # XXX In kernel versions <2.6.14, mptscsih is the actual
-        # module that should be loaded instead of mptbase.
-        if module == "mptbase":
-            module= "mptscsih"
-
-        try:
-            vendor_id= long(line_parts[1],16)
-        except ValueError, e:
-            sys.stderr.write( "Skipping line %d in %s " \
-                              "(incorrect vendor id format %s)\n" % (line_num,modules_pcimap_path,line_parts[1]))
-            continue
-
-        try:
-            device_id= long(line_parts[2],16)
-        except ValueError, e:
-            sys.stderr.write( "Skipping line %d in %s " \
-                              "(incorrect device id format %s)\n" % (line_num,modules_pcimap_path,line_parts[2]))
-            continue
-
-        try:
-            subvendor_id= long(line_parts[3],16)
-        except ValueError, e:
-            sys.stderr.write( "Skipping line %d in %s " \
-                              "(incorrect subvendor id format %s)\n" % (line_num,modules_pcimap_path,line_parts[3]))
-            continue
-
-        try:
-            subdevice_id= long(line_parts[4],16)
-        except ValueError, e:
-            sys.stderr.write( "Skipping line %d in %s " \
-                              "(incorrect subdevice id format %s)\n" % (line_num,modules_pcimap_path,line_parts[4]))
-            continue
-
-        full_id= (vendor_id, device_id, subvendor_id, subdevice_id)
-        if not all_modules.has_key(module):
-            # normally shouldn't get here, as the list is
-            # prepopulated with all the built modules
-
-            # XXX we probably shouldn't be doing this at all
-            all_modules[module] = [full_id]
-        else:
-            all_modules[module].append(full_id)
-            
-        if all_pci_ids.has_key(full_id):
-            # conflict as there are multiple modules that support
-            # particular pci device
-            all_pci_ids[full_id].append(module)
-        else:
-            all_pci_ids[full_id]= [module]
-
-    pcimap_file.close()
-
-    # parse pcitable, add any more ids for the devices
-    # We make the (potentially risky) assumption that pcitable contains
-    # only unique (vendor,device,subvendor,subdevice) entries.
-    line_num= 0
-    for line in pcitable_file:
-        line_num= line_num+1
-
-        # skip blank lines, or lines that begin with # (comments)
-        line= string.strip(line)
-        if len(line) == 0:
-            continue
-
-        if line[0] == "#":
-            continue
-
-        line_parts= string.split(line)
-        if line_parts is None or len(line_parts) <= 2:
-            sys.stderr.write( "Skipping line %d in pcitable " \
-                              "(incorrect format 1)\n" % line_num )
-            continue
-
-        # vendor id is always the first field, device the second. also,
-        # strip off first two chars (the 0x)
-        try:
-            vendor_id= long(line_parts[0],16)
-        except ValueError, e:
-            sys.stderr.write( "Skipping vendor_id %s in %s on line %d\n" \
-                              % (line_parts[0],pcitable_path,line_num))
-            continue
-
-        try:
-            device_id= long(line_parts[1],16)
-        except ValueError, e:
-            sys.stderr.write( "Skipping device %s in %s on line %d\n" \
-                              % (line_parts[1],pcitable_path,line_num))
-            continue
-
-        # if the first char of the third field is a double
-        # quote, the third field is a module, else if the first
-        # char of the third field is a 0 (zero), the fifth field is
-        # the module name. it would nice if there was any easy way
-        # to split a string on spaces, but recognize quoted strings,
-        # so they wouldn't be split up. that is the reason for this wierd check
-        if line_parts[2][0] == '"':
-            module= line_parts[2]
-
-            subvendor_id=PCI_ANY
-            subdevice_id=PCI_ANY
-        elif line_parts[2][0] == '0':
-            try:
-                module= line_parts[4]
-            except ValueError, e:
-                sys.stderr.write( "Skipping line %d in pcitable " \
-                                  "(incorrect format 2)\n" % line_num )
-                continue
-            try:
-                subvendor_id= long(line_parts[2],16)
-            except ValueError, e:
-                sys.stderr.write( "Skipping line %d in pcitable " \
-                                  "(incorrect format 2a)\n" % line_num )
-                continue
-            
-            try:
-                subdevice_id= long(line_parts[3],16)
-            except ValueError, e:
-                sys.stderr.write( "Skipping line %d in pcitable " \
-                                  "(incorrect format 2b)\n" % line_num )
-
-        else:
-            sys.stderr.write( "Skipping line %d in pcitable " \
-                              "(incorrect format 3)\n" % line_num )
-            continue
-
-        # remove the first and last char of module (quote marks)
-        module= module[1:]
-        module= module[:len(module)-1]
-
-        full_id= (vendor_id, device_id, subvendor_id, subdevice_id)
-
-        if not all_modules.has_key(module):
-            # Do not process any modules listed in pcitable for which
-            # we do not have a prebuilt module.
-            continue
-
-        if not full_id in all_modules[module]:
-            all_modules[module].append(full_id)
-
-        if all_pci_ids.has_key(full_id):
-            if not module in all_pci_ids[full_id]:
-                all_pci_ids[full_id].append(module)
-            
-            # check if there are duplicate mappings between modules
-            # and full_ids
-            if len(all_pci_ids[full_id])>1:
-                # collect the set of modules that are different than what
-                # is listed in the pcitables file
-                other_modules = []
-                for other_module in all_pci_ids[full_id]:
-                    if other_module != module:
-                        other_modules.append(other_module)
-
-                # remove full_id from the set of other modules in all_modules {}
-                for other_module in other_modules:
-                    all_modules[other_module].remove(full_id)
-
-                # ensure that there is only one full_id -> module 
-                all_pci_ids[full_id] = [module]
-
-        else:
-            all_pci_ids[full_id] = [module]
-                
-    pcitable_file.close()
-
-    return (all_pci_ids,all_modules)
-
-if __name__ == "__main__":
-    def usage():
-        print( "\nUsage:" )
-        print( "%s <modules.dep> <modules.pcimap> " \
-               "<pcitable> [<output>]" % sys.argv[0] )
-        print( "" )
-        
-    if len(sys.argv) < 4:
-        usage()
-        sys.exit(1)
-
-
-    if len(sys.argv) > 4:
-        output_file_name= sys.argv[4]
-        try:
-            output_file= file(output_file_name,"w")
-        except IOError:
-            sys.stderr.write( "Unable to open %s for writing.\n" % output_file )
-            sys.exit(1)
-    else:
-        output_file= sys.stdout
-
-
-    (all_pci_ids,all_modules)=merge_files( sys.argv[1],
-                                           sys.argv[2],
-                                           sys.argv[3] )
-    if all_modules is not None:
-        for module in all_modules.keys():
-            pci_ids = all_modules[module]
-            if len(pci_ids)>0:
-                output_file.write("%s" % module)
-                for pci_id in pci_ids:
-                    output_file.write(" %x:%x:%x:%x" % pci_id)
-                output_file.write(" \n")
-    else:
-        sys.stderr.write( "Unable to list modules.\n" )
-
-    output_file.close()
index 2f0ade6..58c2803 100755 (executable)
@@ -23,13 +23,13 @@ import string
 import sys
 import os
 import popen2
-import merge_hw_tables
 import re
 import errno
 import ModelOptions
+import pypciscan
+import pypcimap
 from Exceptions import *
 
-hwdatapath = "usr/share/hwdata"
 """
 a utility class for finding and returning information about
 block devices, memory, and other hardware on the system
@@ -53,14 +53,8 @@ LSPCI_CMD= "/sbin/lspci -nm"
 MODULE_CLASS_NETWORK= "network"
 MODULE_CLASS_SCSI= "scsi"
 
-PCI_CLASS_NETWORK_ETHERNET=0x0200L
-PCI_CLASS_STORAGE_SCSI=0x0100L
-PCI_CLASS_STORAGE_SATA=0x0106L
-PCI_CLASS_STORAGE_IDE=0x0101L
-PCI_CLASS_STORAGE_FLOPPY=0x0102L
-PCI_CLASS_STORAGE_IPI=0x0103L
-PCI_CLASS_STORAGE_RAID=0x0104L
-PCI_CLASS_STORAGE_OTHER=0x0180L
+PCI_BASE_CLASS_NETWORK=0x02L
+PCI_BASE_CLASS_STORAGE=0x01L
 
 PCI_ANY=0xffffffffL
 
@@ -224,10 +218,8 @@ def get_system_modules( vars = {}, log = sys.stderr):
     """
     Return a list of kernel modules that this system requires.
     This requires access to the installed system's root
-    directory, as the following files must exist and are used:
-    <install_root>/usr/share/hwdata/pcitable
+    directory, as the following file must exist and is used:
     <install_root>/lib/modules/(first entry if kernel_version unspecified)/modules.pcimap
-    <install_root>/lib/modules/(first entry if kernel version unspecified)/modules.dep
 
     If there are more than one kernels installed, and the kernel
     version is not specified, then only the first one in
@@ -271,27 +263,15 @@ def get_system_modules( vars = {}, log = sys.stderr):
 
     print( "Using kernel version %s" % kernel_version )
 
-    # test to make sure the three files we need are present
-    pcitable_path = "%s/%s/pcitable" % (SYSIMG_PATH,hwdatapath)
+    # test to make sure the file we need is present
     modules_pcimap_path = "%s/lib/modules/%s/modules.pcimap" % \
                           (SYSIMG_PATH,kernel_version)
-    modules_dep_path = "%s/lib/modules/%s/modules.dep" % \
-                       (SYSIMG_PATH,kernel_version)
-
-    for path in (pcitable_path,modules_pcimap_path,modules_dep_path):
-        if not os.access(path,os.R_OK):
-            print( "Unable to read %s" % path )
-            return
-
-    # now, with those three files, merge them all into one easy to
-    # use lookup table
-    (all_pci_ids, all_modules) = merge_hw_tables.merge_files( modules_dep_path,
-                                                              modules_pcimap_path,
-                                                              pcitable_path )
-    if all_modules is None:
-        print( "Unable to merge pci id tables." )
+    if not os.access(modules_pcimap_path,os.R_OK):
+        print( "Unable to read %s" % path )
         return
 
+    pcimap = pypcimap.PCIMap(modules_pcimap_path)
+
     # this is the actual data structure we return
     system_mods= {}
 
@@ -299,96 +279,30 @@ def get_system_modules( vars = {}, log = sys.stderr):
     network_mods= []
     scsi_mods= []
 
+    # XXX: this is really similar to what BootCD/conf_files/pl_hwinit does. merge?
+    pcidevs = pypciscan.get_devices()
 
-    # get all the system devices from lspci
-    lspci_prog= popen2.Popen3( LSPCI_CMD, 1 )
-    if lspci_prog is None:
-        print( "Unable to run %s with popen2.Popen3" % LSPCI_CMD )
-        return
-
-    returncode= lspci_prog.wait()
-    if returncode != 0:
-        print( "Running %s failed" % LSPCI_CMD )
-        return
-    else:
-        print( "Successfully ran %s" % LSPCI_CMD )
-
-    # for every lspci line, parse in the four tuple PCI id and the
-    # search for the corresponding driver from the dictionary
-    # generated by merge_hw_tables
-    for line in lspci_prog.fromchild:
-        # A sample line:
-        #
-        # 00:1f.1 "Class 0101" "8086" "2411" -r02 -p80 "8086" "2411"
-        #
-        # Remove '"', 'Class ', and anything beginning with '-'
-        # (usually revisions and prog-if flags) so that we can
-        # split on whitespace:
-        #
-        # 00:1f.1 0101 8086 2411 8086 2411
-        #
-        line = line.strip()
-        line = line.replace('"', '')
-        line = line.replace('Class ', '')
-        line = re.sub('-[^ ]*', '', line)
-
-        parts = line.split()
-        try:
-            if len(parts) < 4:
-                raise
-            classid = long(parts[1], 16)
-            vendorid = long(parts[2], 16)
-            deviceid = long(parts[3], 16)
-        except:
-            print "Invalid line:", line
-            continue
-
-        if classid not in (PCI_CLASS_NETWORK_ETHERNET,
-                           PCI_CLASS_STORAGE_SCSI,
-                           PCI_CLASS_STORAGE_SATA,
-                           PCI_CLASS_STORAGE_RAID,
-                           PCI_CLASS_STORAGE_OTHER,
-                           PCI_CLASS_STORAGE_IDE):
+    for (slot, dev) in pcidevs.iteritems():
+        base = (dev[4] & 0xff00) >> 8
+        if base not in (PCI_BASE_CLASS_STORAGE,
+                        PCI_BASE_CLASS_NETWORK):
             continue
 
-        # Device may have a subvendorid and subdeviceid
-        try:
-            subvendorid = long(parts[4], 16)
-            subdeviceid = long(parts[5], 16)
-        except:
-            subvendorid = PCI_ANY
-            subdeviceid = PCI_ANY
-
-        # search for driver that most closely matches the full_id
-        # to drivers that can handle any subvendor/subdevice
-        # version of the hardware.
-        full_ids = ((vendorid,deviceid,subvendorid,subdeviceid),
-                    (vendorid,deviceid,subvendorid,PCI_ANY),
-                    (vendorid,deviceid,PCI_ANY,PCI_ANY))
-
-        for full_id in full_ids:
-            module = all_pci_ids.get(full_id, None)
-            if module is not None:
-                if classid == PCI_CLASS_NETWORK_ETHERNET:
-                    network_mods.append(module[0])
-                elif classid in (PCI_CLASS_STORAGE_SCSI,
-                                 PCI_CLASS_STORAGE_SATA,
-                                 PCI_CLASS_STORAGE_RAID,
-                                 PCI_CLASS_STORAGE_OTHER,
-                                 PCI_CLASS_STORAGE_IDE):
-                    scsi_mods.append(module[0])
-
-                    # XXX ata_piix and ahci both claim 8086:2652 and 8086:2653,
-                    # and it is usually a non-visible BIOS option that decides
-                    # which is appropriate. Just load both.
-                    if vendorid == 0x8086 and (deviceid == 0x2652 or deviceid == 0x2653):
-                        if module[0] == "ahci":
-                            scsi_mods.append("ata_piix")
-                        elif module[0] == "ata_piix":
-                            scsi_mods.append("ahci")
-                else:
-                    print "not network or scsi: 0x%x" % classid
-                break
+        modules = pcimap.get(dev)
+        if len(modules) > 0:
+            if base == PCI_BASE_CLASS_NETWORK:
+                network_mods.append(modules[0])
+            elif base == PCI_BASE_CLASS_STORAGE:
+                scsi_mods.append(modules[0])
+
+                # XXX ata_piix and ahci both claim 8086:2652 and 8086:2653,
+                # and it is usually a non-visible BIOS option that decides
+                # which is appropriate. Just load both.
+                if dev[0] == 0x8086 and (dev[1] == 0x2652 or dev[1] == 0x2653):
+                    if modules[0] == "ahci":
+                        scsi_mods.append("ata_piix")
+                    elif modules[0] == "ata_piix":
+                        scsi_mods.append("ahci")
 
     system_mods[MODULE_CLASS_SCSI]= scsi_mods
     system_mods[MODULE_CLASS_NETWORK]= network_mods