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

  ViewVC Help
Powered by ViewVC 1.1.30