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

  ViewVC Help
Powered by ViewVC 1.1.30