/[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 3918 - (show annotations) (download)
Thu Apr 5 02:49:21 2012 UTC (8 years, 4 months ago) by anssi
File size: 13251 byte(s)
display_driver_helper: cosmetics
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 # 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 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 # 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 IS_KMS=1
65 # radeon needs to be loaded before X server
66 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 # 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 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 # 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 check_xorg() {
208 local driver="$1"
209 local explicit_only="$2"
210
211 eval local xorg_drivers=\"\$XORG_$driver\"
212 [ -n "$xorg_drivers" ] || xorg_drivers="$driver"
213 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 # 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 }
250
251 # Load the driver for the specified modalias, if configured.
252 # Note: no /usr
253 load_driver() {
254 local modalias="$1"
255 local modulename
256 local load_default=1
257
258 for modulename in $(/sbin/modprobe -Rq "$modalias"); do
259 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 [ -z "$load_default" ] || /sbin/modprobe -b "$modalias"
287 }
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 for modulename in $(/sbin/modprobe -Rq "$modalias"); do
329 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 As --check-loaded, and consider ambiguous cases (e.g. nvidia where
388 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.28