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