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

  ViewVC Help
Powered by ViewVC 1.1.30