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

  ViewVC Help
Powered by ViewVC 1.1.30