/[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 3924 - (show 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 #!/bin/sh
2 #
3 # Display driver helper
4 #
5 # Copyright (c) 2010, 2011, 2012 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 # Note that drivers not known by this script are handled normally, i.e.
13 # loaded automatically as udev normally would've.
14 #
15 # 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 # DEBUG_DISPLAY_DRIVER_HELPER=yes
24
25 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
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 # 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 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 # 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
71 IS_KMS=1
72 # radeon KMS needs to be loaded before X server
73 NEEDS_LOAD_NOW=1
74
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 ;;
107 nouveau)
108 # implicitely loaded by X.org
109 check_xorg $name 0 || return 1
110 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 # 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 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 # 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 check_xorg() {
247 local driver="$1"
248 local explicit_only="$2"
249
250 eval local xorg_drivers=\"\$XORG_$driver\"
251 [ -n "$xorg_drivers" ] || xorg_drivers="$driver"
252 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 # 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 }
289
290 # Load the driver for the specified modalias, if configured.
291 # Note: no /usr
292 load_driver() {
293 local modalias="$1"
294 local modulename
295 local load_default=1
296
297 for modulename in $(/sbin/modprobe -Rq "$modalias"); do
298 check_driver "$modulename" "$modalias"
299 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 /sbin/modprobe -b "$modulename" $MODOPTIONS && return 0
321 done
322
323 # no specially handled modules were loaded, so load all modules normally
324 # unless $load_default was set above
325 [ -z "$load_default" ] || /sbin/modprobe -b "$modalias"
326 }
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
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 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 get_hw_display_modaliases() {
360 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 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 for modulename in $(/sbin/modprobe -Rq "$modalias"); do
372 IS_KMS=
373 check_driver "$modulename" "$modalias" || continue
374 [ -n "$IS_KMS" ] && echo $modulename
375 done
376 done
377 }
378
379 setup_boot_kms() {
380 perl -I/usr/lib/libDrakX -MXconfig::various -e 'Xconfig::various::setup_kms()'
381 }
382
383 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 As --check-loaded, and consider ambiguous cases (e.g. nvidia where
435 we can't detect if the loaded driver has the correct version) as
436 failure.
437
438 --setup-boot-kms
439 Set or unset the 'nokmsboot' option as necessary.
440 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 # Extra module options - used to disable radeon modesetting when no firmware
473 # is present and it is needed.
474 MODOPTIONS=
475
476 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 --setup-boot-kms)
517 setup_boot_kms
518 ;;
519 *)
520 usage
521 ;;
522 esac

  ViewVC Help
Powered by ViewVC 1.1.30