/[soft]/drakx-kbd-mouse-x11/trunk/tools/display_driver_helper
ViewVC logotype

Annotation of /drakx-kbd-mouse-x11/trunk/tools/display_driver_helper

Parent Directory Parent Directory | Revision Log Revision Log


Revision 961 - (hide annotations) (download)
Wed Apr 20 23:05:34 2011 UTC (12 years, 11 months ago) by anssi
File size: 12791 byte(s)
Try unloading unconfigured drivers in "display_driver_helper --check-loaded".
1 anssi 912 #!/bin/sh
2     #
3     # Display driver helper
4     #
5     # Copyright (c) 2010, 2011 Anssi Hannula <anssi.hannula@iki.fi>
6     #
7     # - Load drivers for specified modaliases, skipping disabled display drivers
8     # that would cause conflicts (KMS vs. vesa, KMS vs. proprietary).
9     # - Get information about enabled driver modules
10     # - Check that the loaded modules are correct
11     #
12     # Licensed under terms of GPLv2 or later.
13     #
14     # When updating, check:
15     # - the variables below
16     # - check_driver function
17     # - check_dkms_status function
18     #
19    
20 anssi 958 if [ -n "$DEBUG_DISPLAY_DRIVER_HELPER" ]; then
21     echo "$(date) $*" >> /dev/ddh_debug
22     exec 2>>/dev/ddh_debug
23     set -x
24     fi
25 anssi 912
26     export LC_ALL=C
27    
28     KMS_DRIVERS="i915 radeon nouveau"
29     # module names at run-time (hence nvidia instead of nvidia*):
30     KNOWN_MODULES="i915|radeon|nouveau|fglrx|nvidia"
31    
32     XORG_i915="intel"
33     CONFLICTS_i915=""
34    
35     XORG_nouveau="nouveau"
36     CONFLICTS_nouveau="nv nvidia"
37    
38     XORG_radeon="ati radeon"
39     CONFLICTS_radeon="fglrx"
40    
41     # Note: no /usr
42     # See end of script for descriptions of global variables.
43     check_driver() {
44     local name="$1"
45     case "$name" in
46     i915)
47     # implicitely loaded by X.org
48     check_xorg $name 0 || return 1
49     IS_KMS=1
50     ;;
51     radeon)
52     # implicitely loaded by X.org
53     check_xorg $name 0 || return 1
54     IS_KMS=1
55     # radeon needs to loaded before X server
56     NEEDS_LOAD_NOW=1
57     ;;
58     nouveau)
59     # these KMS drivers require an explicit directive in xorg.conf
60     check_xorg $name 1 || return 1
61     IS_KMS=1
62     ;;
63     fglrx)
64     check_xorg fglrx 1 || return 1
65     check_dkms fglrx || return 1
66     ;;
67     nvidia)
68     # manually installed driver or a call from check_loaded()
69     UNSURE=1
70     check_xorg nvidia 1 || return 1
71     ;;
72     nvidiafb)
73     # this is only reached if nvidiafb is manually unblacklisted
74     return 2
75     ;;
76     nvidia*)
77     [ "$name" = "nvidia_current" ] && name=nvidia-current
78     # there are multiple co-installable driver versions, so check
79     # the active alternative as well
80     check_gl /etc/$name/ld.so.conf || return 1
81     check_xorg nvidia 1 || return 1
82     check_dkms $name || return 1
83     ;;
84     *)
85     # unknown, will be loaded only if no known drivers were found
86     return 2
87     ;;
88     esac
89     return 0
90     }
91    
92     # Return success if there is no new pending DKMS build (needed to disallow
93     # speedboot on very early boot).
94     # Previously failed build or a missing module is counted as no pending build.
95     # Note: no /usr
96     check_dkms_status() {
97     [ -e /etc/alternatives/gl_conf ] || return 0
98     # return fast for non-DKMS
99     check_gl /etc/ld.so.conf.d/GL/standard.conf && return 0
100    
101     local active="$(ls -l /etc/alternatives/gl_conf | awk '{ print $NF }')"
102    
103     local modname=
104    
105     case $active in
106     /etc/nvidia*/ld.so.conf)
107     modname="nvidia${active#*nvidia}"
108     modname="${modname%/*}"
109     ;;
110     /etc/ld.so.conf.d/GL/ati.conf)
111     modname="fglrx"
112     ;;
113     *)
114     # Unknown DKMS-looking driver,
115     # allow speedboot.
116     return 0
117     ;;
118     esac
119     check_dkms "$modname" 1
120     }
121    
122     # Check if all loaded kernel modules have correct xorg.conf
123     check_loaded() {
124     for module in $(grep -oE "^($KNOWN_MODULES) " /proc/modules); do
125 anssi 961 # try to unload the driver in case it is not in use before bailing
126     check_driver "$module" || rmmod "$module" &>/dev/null || return 1
127 anssi 912 done
128     return 0
129     }
130    
131     # Check that specified DKMS driver is not queued for build for the current
132     # kernel. Used to check if we 1) should disable speedboot for this boot
133     # (--check-dkms-status), and 2) if should should load the currently
134     # existing driver (--load). Doing otherwise might cause us to load a wrong old
135     # version of the driver that had been installed using e.g. binary DKMS
136     # packages.
137     # Note: no /usr
138     check_dkms() {
139     local driver="$1"
140     local force="$2"
141    
142     # If called from DKMS itself or we are not in rc.sysinit anymore,
143     # there are no pending builds.
144     if [ -z "$force" ]; then
145     [ "$DKMS_AUTOLOAD_MODULE" = "$driver" ] && return 0
146     [ -z "$STARTUP" ] && [ ! -f "/dev/.in_sysinit" ] && return 0
147     fi
148    
149     local found=
150     local uname_r="$(uname -r)"
151    
152     for dir in /var/lib/dkms/$driver/*; do
153     [ -e "$dir" ] || return 0 # no module, no build; or no /var
154     [ -L "$dir" ] && continue # not a module version
155     found=1 # module version found
156     [ -e "$dir/$uname_r" ] && return 0
157     [ -e "/var/lib/dkms-binary/$driver/$(basename "$dir")/$uname_r" ] && return 0
158    
159     if [ -e "$dir/build/make.log" ]; then
160     # Build has failed for some kernel, check if it is this one.
161     # If so, there is no point in returning 1.
162     grep -q "^DKMS make\.log.* $uname_r " && return 0
163     fi
164     done
165    
166     # if module versions were found but none were built for this kernel, return 1
167     [ -n "$found" ] && return 1 || return 0
168     }
169    
170     # Note: no /usr
171     check_gl() {
172     local alt_inode="$(stat -L -c%i $1 2>/dev/null)"
173     [ -n "$alt_inode" ] || return 1
174     [ -n "$GL_INODE" ] || GL_INODE="$(stat -L -c%i /etc/alternatives/gl_conf 2>/dev/null)"
175     [ "$alt_inode" = "$GL_INODE" ] || return 1
176     return 0
177     }
178    
179     # Note: no /usr
180     get_xorg_drivers() {
181     if [ -z "$XORG_DRIVERS" ]; then
182     XORG_DRIVERS="$(cat /etc/X11/xorg.conf /etc/X11/xorg.conf.d/*.conf 2>/dev/null |
183     awk -F'"' -vORS=' ' -vIGNORECASE=1 '
184     /^[[:space:]]+*section[[:space:]]+"device"/ { device=1 }
185     /endsection/ { device=0 }
186     /^[[:space:]]*driver[[:space:]]*".*"/ { if (device) drivers[$2]=$2 }
187     END { for (driver in drivers) print driver }
188     ')"
189     [ -n "$XORG_DRIVERS" ] || XORG_DRIVERS="-"
190     fi
191     }
192    
193     # Note: no /usr
194     # parameter 1: xorg driver
195     # parameter 2: 1 the check if the driver is explicitely enabled
196     # 0 means that check only for conflicts
197     check_xorg() {
198     local driver="$1"
199     local explicit_only="$2"
200    
201     eval local xorg_drivers=\"\$XORG_$driver\"
202 anssi 959 [ -n "$xorg_drivers" ] || xorg_drivers="$driver"
203 anssi 912 eval local conflicts=\"\$CONFLICTS_$driver\"
204    
205     get_xorg_drivers
206    
207     conflict_found=
208     for enabled_driver in $XORG_DRIVERS; do
209     for xorg_driver in $xorg_drivers; do
210     [ "$enabled_driver" = "$xorg_driver" ] && return 0
211     done
212    
213     # if the X.org driver can be loaded implicitely, check that
214     # there are no conflicting drivers that override the driver
215     if [ "$explicit_only" = "0" -a -z "$conflict_found" ]; then
216     for conflict in vesa $conflicts; do
217     if [ "$enabled_driver" = "$conflict" ]; then
218     conflict_found=1
219     continue 2
220     # continue loop to check for an explicit load
221     fi
222     done
223     fi
224     done
225    
226     # in case of a conflict, do not load the module
227     [ -n "$conflict_found" ] && return 1
228    
229     # no driver is selected - don't load if explicit_only is 1
230     [ "$explicit_only" = "1" ] && return 1
231    
232     # implicit load allowed; still don't load if no xorg.conf (i.e. live cd)
233     [ -e "/etc/X11/xorg.conf" ]
234     }
235    
236     # Load the driver for the specified modalias, if configured.
237     # Note: no /usr
238     load_driver() {
239     local modulename
240     local load_default=1
241    
242     # NOTE: UPDATE when module-init-tools is upgraded to get better performance
243     # modprobe has -R option:
244     #for modulename in $(/home/anssi/module-init-tools-3.12/build/modprobe -Rq "$1"); do
245     # modprobe does not have -R option:
246     for mod in $(/sbin/modprobe -biqvn "$1"); do
247     [ "$mod" = "insmod" ] && continue
248     modulename="${mod##*/}"
249     modulename="${modulename%%.*}"
250    
251     check_driver "$modulename"
252     case $? in
253     1) # a driver which needs handling by this script matches
254     # the modalias, but was not configured - do not run
255     # the generic modprobe if no other drivers are
256     # configured either
257     load_default=
258     continue
259     ;;
260     2) continue
261     ;;
262     esac
263    
264     if [ -n "$IS_KMS" ]; then
265     grep -q "^$modulename " /proc/modules && return 0
266     echo "$modulename" > /dev/.late_kms 2>/dev/null
267     # If NEEDS_LOAD_NOW is not set and plymouth is running,
268     # skip loading the driver to avoid quitting plymouth.
269     # The driver will be loaded later by X server itself.
270     [ -z "$NEEDS_LOAD_NOW" ] && /bin/plymouth --ping 2>/dev/null && return 0
271     /bin/plymouth quit 2>/dev/null
272     fi
273     /sbin/modprobe -b "$modulename" && return 0
274     done
275    
276     # no specially handled modules were loaded, so load all modules normally
277     # unless $load_default was set above
278     [ -z "$load_default" ] || /sbin/modprobe -b "$1"
279     }
280    
281     is_kms_allowed() {
282     for driver in $KMS_DRIVERS; do
283     # Check all drivers for conflicts only.
284     check_xorg $driver 0 || return 1
285     done
286     return 0
287     }
288    
289     get_initrd_kms_drivers() {
290     local initrd="$1"
291    
292     local kms_drivers="$(echo "$KMS_DRIVERS" | tr " " "|")"
293     zcat "$initrd" | cpio -t --quiet | sed -nr "s,.*/($kms_drivers)\.ko.*$,\1,p"
294     }
295    
296     # Check that the initrd doesn't contain disabled modules
297     check_initrd() {
298     local initrd="$1"
299     local initrd_drivers="$(get_initrd_kms_drivers "$initrd")"
300     for driver in $initrd_drivers; do
301     check_driver "$driver" || return 1
302     done
303     for driver2 in $(get_active_kms_drivers); do
304     for driver in $initrd_drivers; do
305     [ "$driver" = "$driver2" ] && continue 2
306     done
307     # An enabled module for present hardware was not in initrd
308     return 1
309     done
310     return 0
311     }
312    
313     get_active_kms_drivers() {
314     local kms_drivers=
315     for device in $(grep -l 0x03 /sys/bus/pci/devices/0000\:0*/class); do
316     [ -e "$device" ] || continue
317     device="$(dirname $device)"
318     [ -f "$device/modalias" ] || continue
319     modalias="$(cat "$device/modalias")"
320     for mod in $(/sbin/modprobe --first-time -biqvn "$modalias" 2>&1); do
321     modulename="${mod##*/}"
322     modulename="${modulename%%.*}"
323     IS_KMS=
324     check_driver "$modulename" || continue
325     [ -n "$IS_KMS" ] && echo $modulename
326     done
327     done
328     }
329    
330     usage() {
331     cat <<EOF
332     Usage: $0 action [arguments]
333    
334     Known actions:
335    
336     --load MODALIAS
337     Load drivers matching MODALIAS, checking that they are enabled and
338     configured.
339    
340     --load-dkms-autoload MODNAME MODALIAS
341     Same as --load, but assume MODNAME is built and correct so that
342     checking dkms status is unnecessary.
343    
344     --is-disabled MODNAME
345     Checks whether the driver corresponding to MODNAME is disabled (e.g.
346     a conflicting driver is configured, etc.). Unknown MODNAMEs are
347     considered not disabled.
348    
349     --is-enabled-kms MODNAME
350     Checks whether the driver corresponding to MODNAME is enabled and
351     MODNAME is a known KMS module. Note that drivers may be enabled even
352     if there is no such hardware. This just checks that there are
353     no conflicting drivers in use etc.
354    
355     --is-kms-allowed
356     Checks whether it is ok to load KMS drivers in initrd. This returns
357     a failure when a conflicting driver is set up (vesa or a proprietary
358     one).
359    
360     --get-all-kms-drivers
361     Get a list of the known KMS drivers.
362    
363     --get-active-kms-drivers
364     Get a list of the known KMS drivers which are enabled and the hardware
365     is present.
366    
367     --get-initrd-kms-drivers INITRD
368     Get a list of the known KMS drivers in initrd INITRD.
369    
370     --check-dkms-status
371     Checks if there are no pending DKMS builds for the currently enabled
372     drivers.
373    
374     --check-loaded
375     Checks that there are no disabled drivers loaded.
376    
377     --check-speedboot
378     Does --check-dkms-status and --check-loaded.
379    
380     --check-loaded-strict
381     As --check-loaded, and consider ambigious cases (e.g. nvidia where
382     we can't detect if the loaded driver has the correct version) as
383     failure.
384    
385     --check-initrd INITRD
386     Check that INITRD doesn't contain disabled KMS drivers.
387     EOF
388     }
389    
390     # clear global variables
391    
392     # cache for check_gl()
393     GL_INODE=
394    
395     # cache for check_xorg()
396     XORG_DRIVERS=
397    
398     # The driver is a KMS enabled driver. This will cause the script to quit
399     # plymouth when a driver is loaded by --load and NEEDS_LOAD_NOW below is set.
400     # This is done as plymouth is still attached to the default framebuffer (the
401     # issues caused by not doing this don't seem to be fatal, though, but the
402     # display may be lost completely until plymouth eventually stops).
403     # There is no option in plymouth to "reload" a driver, it expects any KMS
404     # driver to be loaded be before starting it.
405     IS_KMS=
406    
407     # This KMS driver needs to be loaded before X server starts, so load it now
408     # even if we have to shut down plymouth (see above).
409     NEEDS_LOAD_NOW=
410    
411     # dkms module that was built when calling from DKMS
412     DKMS_AUTOLOAD_MODULE=
413    
414     # Set by check_loaded() when it can't be sure that the correct driver is loaded
415     # (e.g. in case of the multiple proprietary nvidia drivers which all identify as
416     # "nvidia" in loaded modules list).
417     UNSURE=
418    
419     case "$1" in
420     --load)
421     load_driver "$2"
422     ;;
423     --load-dkms-autoload)
424     DKMS_AUTOLOAD_MODULE="$2"
425     load_driver "$3"
426     ;;
427     --is-disabled)
428     check_driver "$2"
429     [ $? -eq 1 ]
430     # unknown (2) are not considered disabled :)
431     ;;
432     --is-enabled-kms)
433     check_driver "$2" && [ -n "$IS_KMS" ]
434     ;;
435     --is-kms-allowed)
436     is_kms_allowed
437     ;;
438     --check-dkms-status)
439     check_dkms_status
440     ;;
441     --get-all-kms-drivers)
442     echo $KMS_DRIVERS
443     ;;
444     --get-active-kms-drivers)
445     get_active_kms_drivers
446     ;;
447     --get-initrd-kms-drivers)
448     get_initrd_kms_drivers "$2"
449     ;;
450     --check-initrd)
451     check_initrd "$2"
452     ;;
453     --check-loaded)
454     check_loaded
455     ;;
456     --check-loaded-strict)
457     check_loaded && [ -z "$UNSURE" ]
458     ;;
459     --check-speedboot)
460     check_dkms_status && check_loaded
461     ;;
462     *)
463     usage
464     ;;
465     esac

  ViewVC Help
Powered by ViewVC 1.1.30