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

  ViewVC Help
Powered by ViewVC 1.1.30