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

  ViewVC Help
Powered by ViewVC 1.1.30