in generating the pci table lookup for hardware detection, we now
Aaron Klingaman [Mon, 6 Dec 2004 20:34:39 +0000 (20:34 +0000)]
merge in what we can from /usr/share/hwdata/pcitable. it is more out of date
that the dynamically generated modules.pcimap, but, it also seems to contain
some entries that are missing from the modules.

build.sh
scripts/rewrite-pcitable.py

index d71cd45..bc24406 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -167,7 +167,10 @@ function build_initrd()
 
     echo "building pcitable for hardware detection"
     pci_map_file=`find $CD_ROOT/lib/modules/ -name modules.pcimap | head -1`
-    ./scripts/rewrite-pcitable.py $pci_map_file $CD_ROOT/etc/pl_pcitable
+    module_dep_file=`find $CD_ROOT/lib/modules/ -name modules.dep | head -1`
+    pci_table=$CD_ROOT/usr/share/hwdata/pcitable
+    ./scripts/rewrite-pcitable.py $module_dep_file $pci_map_file $pci_table \
+       $CD_ROOT/etc/pl_pcitable
 
     dd if=/dev/zero of=$INITRD bs=1M count=$RAMDISK_SIZE
     mkfs.ext2 -F -m 0 -i $INITRD_BYTES_PER_INODE $INITRD
index c2dadb5..6ebc537 100755 (executable)
@@ -2,20 +2,46 @@
 
 """
 The point of this small utility is to take a file in the format
-of /lib/modules/`uname -r`/modules.pcimap and output a condensed, more
-easily used format for module detection
+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.
 
-Excepted format of file includes lines of:
+
+
+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
+
+If no pci ids are found for a particular module:
+
+sd_mod none:none
 """
 
 import os, sys
@@ -23,25 +49,47 @@ import string
 
 
 def usage():
-    print( "Usage:" )
-    print( "rewrite-pcitable.py <pcitable> [<output>]" )
+    print( "\nUsage:" )
+    print( "rewrite-pcitable.py <modules.dep> <modules.pcimap> " \
+           "<pcitable> [<output>]" )
     print( "" )
 
 
-if len(sys.argv) < 2:
+if len(sys.argv) < 4:
     usage()
     sys.exit(1)
 
 
-pcitable_file_name= sys.argv[1]
+# open modules.dep (for list of built modules)
+modulesdep_file_name= sys.argv[1]
 try:
-    pcitable_file= file(pcitable_file_name,"r")
+    modulesdep_file= file(modulesdep_file_name,"r")
+except IOError:
+    sys.stderr.write( "Unable to open modules.dep: %s\n" % modulesdep_file_name )
+    usage()
+    sys.exit(1)
+    
+# open modules.pcimap
+pcimap_file_name= sys.argv[2]
+try:
+    pcimap_file= file(pcimap_file_name,"r")
 except IOError:
-    sys.stderr.write( "Unable to open: %s\n" % pcitable_file_name )
+    sys.stderr.write( "Unable to open modules.pcimap: %s\n" % pcimap_file_name )
+    usage()
     sys.exit(1)
 
-if len(sys.argv) > 2:
-    output_file_name= sys.argv[2]
+# open pcitable
+pcitable_file_name= sys.argv[3]
+try:
+    pcitable_file= file(pcitable_file_name,"r")
+except IOError:
+    sys.stderr.write( "Unable to open pcitable: %s\n" % pcitable_file_name )
+    usage()
+    sys.exit(1)
+    
+# finally, if we are supposed to output to a file, open that too
+if len(sys.argv) > 4:
+    output_file_name= sys.argv[4]
     try:
         output_file= file(output_file_name,"w")
     except IOError:
@@ -51,13 +99,28 @@ else:
     output_file= sys.stdout
 
 
-line_num= 0
-
 # associative array to store all matches of module -> ['vendor:device',..]
 # entries
 all_modules= {}
 
-for line in pcitable_file:
+
+# first step, create an associative array of all the built modules
+for line in modulesdep_file_name:
+    parts= string.split(line,":")
+    if len(parts) < 2:
+        continue
+
+    full_mod_path= parts[0]
+    parts= string.split(full_mod_path,"/")
+    module_name= parts[len(parts)-1]
+    module_name_len= len(module_name)
+    if module_name[module_name_len-3:] == ".ko":
+        all_modules[module_name[:3]]= []
+
+
+# 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)
@@ -70,7 +133,8 @@ for line in pcitable_file:
 
     line_parts= string.split(line)
     if line_parts is None or len(line_parts) != 8:
-        sys.stderr.write( "Skipping line %d (incorrect format)\n" % line_num )
+        sys.stderr.write( "Skipping line %d in pcimap (incorrect format)\n" %
+                          line_num )
         continue
 
     # first two parts are always vendor / device id
@@ -81,14 +145,14 @@ for line in pcitable_file:
 
     # valid vendor and devices are 10 chars (0xXXXXXXXX) and begin with 0x
     if len(vendor_id) != 10 or len(device_id) != 10:
-        sys.stderr.write( "Skipping line %d (invalid vendor/device id length)\n"
-                          % line_num )
+        sys.stderr.write( "Skipping line %d in pcimap (invalid vendor/device " \
+                          "id length)\n" % line_num )
         continue
 
     if string.lower(vendor_id[:2]) != "0x" \
            or string.lower(device_id[:2]) != "0x":
-        sys.stderr.write( "Skipping line %d (invalid vendor/device id format)\n"
-                          % line_num )
+        sys.stderr.write( "Skipping line %d in pcimap (invalid vendor/device " \
+                          "id format)\n" % line_num )
         continue
 
     # cut down the ids, only need last 4 bytes
@@ -99,14 +163,77 @@ for line in pcitable_file:
     full_id= "%s:%s" % (vendor_id, device_id)
 
     if all_modules.has_key(module):
-        all_modules[module].append( full_id )
+        if full_id not in all_modules[module]:
+            all_modules[module].append( full_id )
     else:
+        # normally shouldn't get here, as the list is prepopulated with all
+        # the built modules
         all_modules[module]= [full_id,]
 
+
+# parse pcitable, add any more ids for the devices
+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) < 4:
+        sys.stderr.write( "Skipping line %d in pcitable (incorrect format)\n" %
+                          line_num )
+        continue
+
+    # vendor id is always the first field, device the second. also,
+    # strip off first two chars (the 0x)
+    vendor_id= string.lower(line_parts[0][2:])
+    device_id= string.lower(line_parts[1][2:])
+
+    full_id= "%s:%s" % (vendor_id, device_id)
+
+    # 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]
+    elif line_parts[2][0] == '0':
+        module= line_parts[4]
+    else:
+        sys.stderr.write( "Skipping line %d in pcitable (incorrect format)\n" %
+                          line_num )
+        continue
+
+    # remove the first and last char of module (quote marks)
+    module= module[1:]
+    module= module[:len(module)-1]
+
+    # now add it if we don't already have this module -> id mapping
+    if all_modules.has_key(module):
+        if full_id not in all_modules[module]:
+            all_modules[module].append( full_id )
+    else:
+        # don't add any modules from pcitable that we don't already know about
+        pass
+        
+
 for module in all_modules.keys():
-    devices= string.join( all_modules[module], " " )
-    output_file.write( "%s %s\n" % (module,devices) )
+    devices= all_modules[module]
+    if len(devices) > 0:
+        devices_str= string.join( all_modules[module], " " )
+        output_file.write( "%s %s\n" % (module,devices_str) )
 
     
 output_file.close()
 pcitable_file.close()
+pcimap_file.close()
+modulesdep_file.close()
+