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

  ViewVC Help
Powered by ViewVC 1.1.30