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