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

  ViewVC Help
Powered by ViewVC 1.1.30