b133cfb6120f777aba363b7a73eca6da6468d077
[bootcd.git] / conf_files / pl_hwinit
1 #!/usr/bin/python
2
3 import sys
4 import pypciscan
5 import pypcimap
6 import os
7 import time
8
9 loadedmodules = None
10
11 def modprobe(module, args = None):
12     if args: 
13         ret = os.system("/sbin/modprobe %s %s" % (module, args))
14     else:
15         ret = os.system("/sbin/modprobe %s" % module)
16     if os.WEXITSTATUS(ret) == 0:
17         globals()['loadedmodules'].write("%s\n" % module)
18         return True
19     else:
20         return False
21
22 def main(argv):
23     if len(argv) == 0:
24         kernel = os.uname()[2]
25     else:
26         kernel = argv[0]
27
28     if os.path.exists(kernel):
29         path = kernel
30     else:
31         path = "/lib/modules/%s/modules.pcimap" % kernel
32
33     pcimap = pypcimap.PCIMap(path)
34     print "pl_hwinit: loading applicable modules"
35     devices = pypciscan.get_devices()
36     storage_devices = 0
37     network_devices = 0
38     missing = []
39     globals()['loadedmodules'] = file('/tmp/loadedmodules', 'w')
40     for (slot, dev) in devices.iteritems():
41         modules = pcimap.get(dev)
42         base = (dev[4] & 0xff0000) >> 16
43         if len(modules) == 0:
44             if base == 0x01 or base == 0x02:
45                 # storage or network device, in that order
46                 missing.append((slot, dev))
47         else:
48             if base == 0x01:
49                 storage_devices += 1
50             elif base == 0x02:
51                 network_devices += 1
52
53             # FIXME: This needs improved logic in the case of multiple matching modules
54             for module in modules:
55                 print "pl_hwinit: found and loading module %s (%s)" % (module, slot)
56                 modprobe(module)
57
58     if network_devices == 0:
59         print "pl_hwinit: no supported network devices found!"
60         print "pl_hwinit: the following devices were found, but have no driver:"
61         print "pl_hwinit: ", "\npl_hwinit: ".join(missing)
62
63     # XXX: could check for storage devices too, but older kernels have a lot of that built-in
64
65     # sd_mod won't get loaded automatically
66     print "pl_hwinit: loading sd_mod"
67     modprobe("sd_mod")
68
69     # load usb_storage to support node conf files on flash disks
70     print "pl_hwinit: loading usb_storage"
71     modprobe("usb_storage")
72
73     print "pl_hwinit: loading floppy device driver"
74     modprobe("floppy","floppy=0,allowed_drive_mask")
75
76     # always wait a bit between loading the usb drivers, and checking /sys/
77     # for usb devices (this isn't necessarily for waiting for mass storage files,
78     # that is done below)
79     print "pl_hwinit: waiting for usb system to initialize."
80     time.sleep(10)
81
82     # sometimes, flash devices take a while to initialize. in fact, the kernel
83     # intentionally waits 5 seconds for a device to 'settle'. some take even longer
84     # to show up. if there are any mass storage devices on the system, try to
85     # delay until they come online, up to a max delay of 30s.
86
87     # the way this will be done is to look for files in /sys/devices that are named
88     # 'bInterfaceClass', these will be a list of the usb devices on the system, and
89     # their primary usb device interface class ids. The base directory these files 
90     # exist in will be the full path to the /sys/device entry for that device.
91     # for each mass storage devices (they have an interface class value of 08),
92     # we wait for a new symbolic link named 'driver' to exist in that directory,
93     # indicating the kernel loaded a driver for that device.
94
95     # usb interface class id for mass storage
96     INTERFACE_CLASS_MASS_STORAGE = "08"
97
98     # how long to wait in seconds before continuing on if devices
99     # aren't available
100     MAX_USB_WAIT_TIME = 30
101
102     # low long in seconds to wait between checks
103     PER_CHECK_USB_WAIT_TIME = 5
104
105
106     # find out if the device identified by the /sys dir has a module
107     # loaded for it. check for a symlink in the dir named driver.
108     def does_device_dir_have_driver(device):
109         return os.path.exists(os.path.join(device, "driver"))
110
111     def filter_and_add(list, directory, files):
112         if ("bInterfaceClass" in files and
113             int(file(os.path.join(directory, "bInterfaceClass")).read(), 16) == INTERFACE_CLASS_MASS_STORAGE):
114             list.append(directory)
115
116     wait_dev_list = []
117     os.path.walk("/sys/devices", filter_and_add, wait_dev_list)
118
119     if len(wait_dev_list) > 0:
120         print "pl_hwinit: found USB mass storage device(s). Attempting to wait"
121         print "pl_hwinit: up to %d seconds for them to come online." % MAX_USB_WAIT_TIME
122
123         total_wait_time = 0
124         success = False
125         while total_wait_time < MAX_USB_WAIT_TIME:    
126             total_wait_time += PER_CHECK_USB_WAIT_TIME
127
128             print "pl_hwinit: waiting %d seconds." % PER_CHECK_USB_WAIT_TIME
129             time.sleep(PER_CHECK_USB_WAIT_TIME)
130
131             all_devices_online = True
132             for device in wait_dev_list:
133                 if not does_device_dir_have_driver(device):
134                     all_devices_online = False
135
136             if all_devices_online:
137                 success = True
138                 print "pl_hwinit: looks like the devices are now online."
139                 break
140             else:
141                 print "pl_hwinit: not all devices online yet, waiting..."
142
143         if success:
144             print "pl_hwinit: Succesfully waited for USB mass storage devices"
145             print "pl_hwinit: to come online."
146         else:
147             print "pl_hwinit: One or more USB mass storage devices did not"
148             print "pl_hwinit: initialize in time. Continuing anyway."
149
150 if __name__ == "__main__":
151     main(sys.argv[1:])