/[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 2245 - (show annotations) (download)
Fri Dec 2 21:32:31 2011 UTC (12 years, 4 months ago) by anssi
File size: 13054 byte(s)
display_driver_helper: use modprobe --resolve-alias

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

  ViewVC Help
Powered by ViewVC 1.1.30