/[soft]/drakx-kbd-mouse-x11/trunk/tools/display_driver_helper
ViewVC logotype

Contents of /drakx-kbd-mouse-x11/trunk/tools/display_driver_helper

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.30