/[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 2244 - (hide annotations) (download)
Fri Dec 2 21:32:27 2011 UTC (12 years, 3 months ago) by anssi
File size: 13448 byte(s)
fix typo in a comment
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 anssi 2244 # radeon needs to be loaded before X server
61 anssi 912 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 anssi 1681 # implicit load allowed; only load if there is evidence that this is
238     # not a live cd or similar with automatic configuration occurring later
239     # in the boot process (which might configure a driver conflicting with
240     # the implicit driver, e.g. a proprietary one)
241     # TODO: Could this be replaced with a more robust check?
242     [ -e "/etc/X11/xorg.conf" ] || [ -e "/etc/sysconfig/harddrake2/kernels" ] ||
243     [ -e "/etc/sysconfig/harddrake2/xorg" ] || [ -e "/boot/grub/menu.lst" ]
244 anssi 912 }
245    
246     # Load the driver for the specified modalias, if configured.
247     # Note: no /usr
248     load_driver() {
249     local modulename
250     local load_default=1
251    
252     # NOTE: UPDATE when module-init-tools is upgraded to get better performance
253     # modprobe has -R option:
254     #for modulename in $(/home/anssi/module-init-tools-3.12/build/modprobe -Rq "$1"); do
255     # modprobe does not have -R option:
256     for mod in $(/sbin/modprobe -biqvn "$1"); do
257     [ "$mod" = "insmod" ] && continue
258     modulename="${mod##*/}"
259     modulename="${modulename%%.*}"
260    
261     check_driver "$modulename"
262     case $? in
263     1) # a driver which needs handling by this script matches
264     # the modalias, but was not configured - do not run
265     # the generic modprobe if no other drivers are
266     # configured either
267     load_default=
268     continue
269     ;;
270     2) continue
271     ;;
272     esac
273    
274     if [ -n "$IS_KMS" ]; then
275     grep -q "^$modulename " /proc/modules && return 0
276     echo "$modulename" > /dev/.late_kms 2>/dev/null
277     # If NEEDS_LOAD_NOW is not set and plymouth is running,
278     # skip loading the driver to avoid quitting plymouth.
279     # The driver will be loaded later by X server itself.
280     [ -z "$NEEDS_LOAD_NOW" ] && /bin/plymouth --ping 2>/dev/null && return 0
281     /bin/plymouth quit 2>/dev/null
282     fi
283     /sbin/modprobe -b "$modulename" && return 0
284     done
285    
286     # no specially handled modules were loaded, so load all modules normally
287     # unless $load_default was set above
288     [ -z "$load_default" ] || /sbin/modprobe -b "$1"
289     }
290    
291     is_kms_allowed() {
292     for driver in $KMS_DRIVERS; do
293     # Check all drivers for conflicts only.
294     check_xorg $driver 0 || return 1
295     done
296     return 0
297     }
298    
299     get_initrd_kms_drivers() {
300     local initrd="$1"
301    
302     local kms_drivers="$(echo "$KMS_DRIVERS" | tr " " "|")"
303     zcat "$initrd" | cpio -t --quiet | sed -nr "s,.*/($kms_drivers)\.ko.*$,\1,p"
304     }
305    
306     # Check that the initrd doesn't contain disabled modules
307     check_initrd() {
308     local initrd="$1"
309     local initrd_drivers="$(get_initrd_kms_drivers "$initrd")"
310     for driver in $initrd_drivers; do
311     check_driver "$driver" || return 1
312     done
313     for driver2 in $(get_active_kms_drivers); do
314     for driver in $initrd_drivers; do
315     [ "$driver" = "$driver2" ] && continue 2
316     done
317     # An enabled module for present hardware was not in initrd
318     return 1
319     done
320     return 0
321     }
322    
323     get_active_kms_drivers() {
324     local kms_drivers=
325     for device in $(grep -l 0x03 /sys/bus/pci/devices/0000\:0*/class); do
326     [ -e "$device" ] || continue
327     device="$(dirname $device)"
328     [ -f "$device/modalias" ] || continue
329     modalias="$(cat "$device/modalias")"
330     for mod in $(/sbin/modprobe --first-time -biqvn "$modalias" 2>&1); do
331     modulename="${mod##*/}"
332     modulename="${modulename%%.*}"
333     IS_KMS=
334     check_driver "$modulename" || continue
335     [ -n "$IS_KMS" ] && echo $modulename
336     done
337     done
338     }
339    
340     usage() {
341     cat <<EOF
342     Usage: $0 action [arguments]
343    
344     Known actions:
345    
346     --load MODALIAS
347     Load drivers matching MODALIAS, checking that they are enabled and
348     configured.
349    
350     --load-dkms-autoload MODNAME MODALIAS
351     Same as --load, but assume MODNAME is built and correct so that
352     checking dkms status is unnecessary.
353    
354     --is-disabled MODNAME
355     Checks whether the driver corresponding to MODNAME is disabled (e.g.
356     a conflicting driver is configured, etc.). Unknown MODNAMEs are
357     considered not disabled.
358    
359     --is-enabled-kms MODNAME
360     Checks whether the driver corresponding to MODNAME is enabled and
361     MODNAME is a known KMS module. Note that drivers may be enabled even
362     if there is no such hardware. This just checks that there are
363     no conflicting drivers in use etc.
364    
365     --is-kms-allowed
366     Checks whether it is ok to load KMS drivers in initrd. This returns
367     a failure when a conflicting driver is set up (vesa or a proprietary
368     one).
369    
370     --get-all-kms-drivers
371     Get a list of the known KMS drivers.
372    
373     --get-active-kms-drivers
374     Get a list of the known KMS drivers which are enabled and the hardware
375     is present.
376    
377     --get-initrd-kms-drivers INITRD
378     Get a list of the known KMS drivers in initrd INITRD.
379    
380     --check-dkms-status
381     Checks if there are no pending DKMS builds for the currently enabled
382     drivers.
383    
384     --check-loaded
385     Checks that there are no disabled drivers loaded.
386    
387     --check-speedboot
388     Does --check-dkms-status and --check-loaded.
389    
390     --check-loaded-strict
391     As --check-loaded, and consider ambigious cases (e.g. nvidia where
392     we can't detect if the loaded driver has the correct version) as
393     failure.
394    
395     --check-initrd INITRD
396     Check that INITRD doesn't contain disabled KMS drivers.
397     EOF
398     }
399    
400     # clear global variables
401    
402     # cache for check_gl()
403     GL_INODE=
404    
405     # cache for check_xorg()
406     XORG_DRIVERS=
407    
408     # The driver is a KMS enabled driver. This will cause the script to quit
409     # plymouth when a driver is loaded by --load and NEEDS_LOAD_NOW below is set.
410     # This is done as plymouth is still attached to the default framebuffer (the
411     # issues caused by not doing this don't seem to be fatal, though, but the
412     # display may be lost completely until plymouth eventually stops).
413     # There is no option in plymouth to "reload" a driver, it expects any KMS
414     # driver to be loaded be before starting it.
415     IS_KMS=
416    
417     # This KMS driver needs to be loaded before X server starts, so load it now
418     # even if we have to shut down plymouth (see above).
419     NEEDS_LOAD_NOW=
420    
421     # dkms module that was built when calling from DKMS
422     DKMS_AUTOLOAD_MODULE=
423    
424     # Set by check_loaded() when it can't be sure that the correct driver is loaded
425     # (e.g. in case of the multiple proprietary nvidia drivers which all identify as
426     # "nvidia" in loaded modules list).
427     UNSURE=
428    
429     case "$1" in
430     --load)
431     load_driver "$2"
432     ;;
433     --load-dkms-autoload)
434     DKMS_AUTOLOAD_MODULE="$2"
435     load_driver "$3"
436     ;;
437     --is-disabled)
438     check_driver "$2"
439     [ $? -eq 1 ]
440     # unknown (2) are not considered disabled :)
441     ;;
442     --is-enabled-kms)
443     check_driver "$2" && [ -n "$IS_KMS" ]
444     ;;
445     --is-kms-allowed)
446     is_kms_allowed
447     ;;
448     --check-dkms-status)
449     check_dkms_status
450     ;;
451     --get-all-kms-drivers)
452     echo $KMS_DRIVERS
453     ;;
454     --get-active-kms-drivers)
455     get_active_kms_drivers
456     ;;
457     --get-initrd-kms-drivers)
458     get_initrd_kms_drivers "$2"
459     ;;
460     --check-initrd)
461     check_initrd "$2"
462     ;;
463     --check-loaded)
464     check_loaded
465     ;;
466     --check-loaded-strict)
467     check_loaded && [ -z "$UNSURE" ]
468     ;;
469     --check-speedboot)
470     check_dkms_status && check_loaded
471     ;;
472     *)
473     usage
474     ;;
475     esac

  ViewVC Help
Powered by ViewVC 1.1.30