Codebase list hw-detect / 844323ee-2d0b-4221-a83a-62427d0c2819/main hw-detect.sh
844323ee-2d0b-4221-a83a-62427d0c2819/main

Tree @844323ee-2d0b-4221-a83a-62427d0c2819/main (Download .tar.gz)

hw-detect.sh @844323ee-2d0b-4221-a83a-62427d0c2819/mainraw · history · blame

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
#!/bin/sh

set -e
. /usr/share/debconf/confmodule
#set -x

if [ -z "$1" ]; then
	PROGRESSBAR=hw-detect/detect_progress_step
else
	PROGRESSBAR=$1
fi

NEWLINE="
"
MISSING_MODULES_LIST=""
SUBARCH="$(archdetect)"

finish_install=/usr/lib/finish-install.d/30hw-detect

LOAD_IDE=""
if db_get hw-detect/load-ide && [ "$RET" = true ]; then
	LOAD_IDE=1
fi

# Check for virtio devices
if [ -d /sys/bus/pci/devices ] && \
	grep -q 0x1af4 /sys/bus/pci/devices/*/vendor 2>/dev/null && \
	! grep -q ^virtio_ /proc/modules; then
	anna-install virtio-modules || true
fi

if [ -x /sbin/depmod ]; then
	depmod -a > /dev/null 2>&1 || true
fi

log () {
	logger -t hw-detect "$@"
}

is_not_loaded() {
	! ((cut -d" " -f1 /proc/modules | grep -q "^$1\$") || \
	   (cut -d" " -f1 /proc/modules | sed -e 's/_/-/g' | grep -q "^$1\$"))
}

is_available () {
	modprobe -qn "$1"
}

# Module as first parameter, description of device the second.
missing_module () {
	if ! in_list "$1" "$MISSING_MODULES_LIST"; then
		if [ -n "$MISSING_MODULES_LIST" ]; then
			MISSING_MODULES_LIST="$MISSING_MODULES_LIST, "
		fi
		MISSING_MODULES_LIST="$MISSING_MODULES_LIST$1 ($2)"
	fi
}

# The list can be delimited with spaces or spaces and commas.
in_list() {
	echo "$2" | grep -q "\(^\| \)$1\(,\| \|$\)"
}

snapshot_devs() {
	echo -n `grep : /proc/net/dev | cut -d':' -f1`
}

compare_devs() {
	local olddevs="$1"
	local devs="$2"
	local dev newdevs

	newdevs=
	for dev in $devs; do
		if ! echo " $olddevs " | grep -q " $dev "; then
			newdevs="${newdevs:+$newdevs }$dev"
		fi
	done
	echo "$newdevs"
}

load_module() {
	local module="$1"
	local cardname="$2"
	local devs=""
	local olddevs=""
	local newdev=""

	old=`cat /proc/sys/kernel/printk`
	echo 0 > /proc/sys/kernel/printk

	devs="$(snapshot_devs)"
	if log-output -t hw-detect modprobe -v "$module"; then
		olddevs="$devs"
		devs="$(snapshot_devs)"
		newdevs="$(compare_devs "$olddevs" "$devs")"

		# Make sure space is used as a delimiter.
		IFS_SAVE="$IFS"
		IFS=" "
		if [ -n "$newdevs" -a -n "$cardname" ]; then
			mkdir -p /etc/network
			for dev in $newdevs; do
				echo "${dev}:${cardname}" >> /etc/network/devnames
			done
		fi
		IFS="$IFS_SAVE"
	else   
		log "Error loading '$module'"
		if [ "$module" != floppy ] && [ "$module" != ide-floppy ] && \
		   [ "$module" != ide-cd ] && [ "$module" != ide-generic ]; then
			db_subst hw-detect/modprobe_error CMD_LINE_PARAM "modprobe -v $module"
			db_input medium hw-detect/modprobe_error || [ $? -eq 30 ]
			db_go
		fi
	fi

	echo $old > /proc/sys/kernel/printk
}

# Some pci chipsets are needed or there can be DMA or other problems.
get_ide_chipset_info() {
	for ide_module in $(find /lib/modules/*/kernel/drivers/ide/pci/ -type f 2>/dev/null); do
		if [ -e $ide_module ]; then
			baseidemod=$(echo $ide_module | sed 's/\.ko$//; s/.*\///')
			echo "$baseidemod:IDE chipset support"
		fi
	done
}

# Return list of lines formatted "module:Description"
get_detected_hw_info() {
	if [ "${SUBARCH%%/*}" = powerpc ]; then
		discover-mac-io
		if [ "$SUBARCH" = powerpc/chrp_rs6k ] || \
		   [ "$SUBARCH" = powerpc/chrp_ibm ]; then
			discover-ibm
		fi
	fi
	if [ "${SUBARCH%%/*}" = sparc ]; then
		discover-sbus
	fi
	if [ -d /sys/bus/usb ]; then
		echo "usb-storage:USB storage"
	fi
}

# NewWorld PowerMacs don't want floppy or ide-floppy, and on some models
# (e.g. G5s) the kernel hangs when loading the module.
get_floppy_info() {
	case $SUBARCH in
		powerpc/powermac_newworld) ;;
		*) echo "floppy:Linux Floppy" ;;
	esac
}

get_ide_floppy_info() {
	case $SUBARCH in
		powerpc/powermac_newworld) ;;
		*) echo "ide-floppy:Linux IDE floppy" ;;
	esac
}

# Manually load modules to enable things we can't detect.
# XXX: This isn't the best way to do this; we should autodetect.
# The order of these modules are important.
get_manual_hw_info() {
	if [ "$LOAD_IDE" ]; then
		get_floppy_info
		get_ide_chipset_info
		echo "ide-generic:Linux IDE support"
		get_ide_floppy_info
		echo "ide-disk:Linux ATA DISK"
		echo "ide-cd:Linux ATAPI CD-ROM"
	fi
}

# Should be greater than the number of kernel modules we can reasonably
# expect it will ever need to load.
MAX_STEPS=1000
OTHER_STEPS=4
# Use 1/10th of the progress bar for the non-module-load steps.
OTHER_STEPSIZE=$(expr $MAX_STEPS / 10 / $OTHER_STEPS)
db_progress START 0 $MAX_STEPS $PROGRESSBAR

db_progress INFO hw-detect/detect_progress_step

# TODO: Can possibly be removed if udev will load yenta_socket automatically
# Load yenta_socket, if hardware is available, for Cardbus cards.
if [ -d /sys/bus/pci/devices ] && \
	grep -q 0x060700 /sys/bus/pci/devices/*/class 2>/dev/null && \
	! grep -q ^yenta_socket /proc/modules; then
	db_subst hw-detect/load_progress_step CARDNAME "Cardbus bridge"
	db_subst hw-detect/load_progress_step MODULE "yenta_socket"
	db_progress INFO hw-detect/load_progress_step
	
	log "Detected Cardbus bridge, loading yenta_socket"
	load_module yenta_socket
	# Ugly hack, but what's the alternative?
	sleep 3 || true
fi

# Load the ethernet gadget network driver (g_ether) on S3C2410/S3C2440 (Openmoko GTA01/02)
if [ -d /sys/bus/platform/devices/s3c2440-usbgadget -o \
	-d /sys/bus/platform/devices/s3c2410-usbgadget ] ; then
	db_subst hw-detect/load_progress_step CARDNAME "S3C2410/S3C2440 SoC"
	db_subst hw-detect/load_progress_step MODULE "g_ether"
	db_progress INFO hw-detect/load_progress_step
	
	log "Detected S3C2410/S3C2440 SoC, loading g_ether"
	load_module g_ether
	register-module g_ether
fi

# Load xenbus_probe_frontend if we're running under the Xen hypervisor, so
# that it can deal with autoloading such things as xen-blkfront and
# xen-netfront.
if [ "$(cat /sys/hypervisor/type 2>/dev/null || true)" = xen ] && \
   [ ! -d /sys/bus/xen ]; then
	db_subst hw-detect/load_progress_step CARDNAME "Xen frontend"
	db_subst hw-detect/load_progress_step MODULE "xenbus_probe_frontend"
	db_progress INFO hw-detect/load_progress_step

	log "Detected Xen hypervisor, loading xenbus_probe_frontend"
	load_module xenbus_probe_frontend
	register-module -i xenbus_probe_frontend
fi

# If using real hotplug, re-run the rc scripts to pick up new modules.
# TODO: this just loads modules itself, rather than handing back a list
# Since we've just run depmod, new modules might be available, so we
# must trigger as well as settle.
update-dev >/dev/null

ALL_HW_INFO=$(get_detected_hw_info; get_manual_hw_info)
db_progress STEP $OTHER_STEPSIZE

# Remove modules that are already loaded or not available, and construct
# the list for the question.
LIST=""
PROCESSED=""
AVAIL_MODULES="$(find /lib/modules/$(uname -r)/ | sed 's!.*/!!' | cut -d . -f 1)"
LOADED_MODULES="$(cut -d " " -f 1 /proc/modules) $(cut -d " " -f 1 /proc/modules | sed -e 's/_/-/g')"
IFS_SAVE="$IFS"
IFS="$NEWLINE"
for device in $ALL_HW_INFO; do
	module="${device%%:*}"
	cardname="${device##*:}"
	if [ "$module" != "ignore" -a "$module" != "" ] &&
	   ! in_list "$module" "$LOADED_MODULES" &&
	   ! in_list "$module" "$PROCESSED"
	then
		if [ -z "$cardname" ]; then
			cardname="[Unknown]"
		fi
		
		if in_list "$module" "$AVAIL_MODULES"; then
			LIST="${LIST:+$LIST, }$module ($(echo "$cardname" | sed 's/,/ /g'))"
			PROCESSED="$PROCESSED $module"
		else
			missing_module "$module" "$cardname"
		fi
	fi
done
IFS="$IFS_SAVE"
db_progress STEP $OTHER_STEPSIZE

if [ "$LIST" ]; then
	# Ask which modules to install.
	db_subst hw-detect/select_modules list "$LIST"
	db_set hw-detect/select_modules "$LIST"
	db_input medium hw-detect/select_modules || true
	db_go || exit 10 # back up
	db_get hw-detect/select_modules
	LIST="$RET"
fi

list_to_lines() {
	echo "$LIST" | sed 's/, /\n/g'
}

# Work out amount to step per module load. expr rounds down, so 
# it may not get quite to 100%, but will at least never exceed it.
MODULE_STEPS=$(expr \( $MAX_STEPS - \( $OTHER_STEPS \* $OTHER_STEPSIZE \) \))
if [ "$LIST" ]; then
	MODULE_STEPSIZE=$(expr $MODULE_STEPS / $(list_to_lines | wc -l))
fi

IFS="$NEWLINE"

for device in $(list_to_lines); do
	module="${device%% *}"
	cardname="`echo $device | cut -d'(' -f2 | sed 's/)$//'`"
	# Restore IFS after extracting the fields.
	IFS="$IFS_SAVE"

	if [ -z "$module" ] ; then module="[Unknown]" ; fi
	if [ -z "$cardname" ] ; then cardname="[Unknown]" ; fi

	log "Detected module '$module' for '$cardname'"

	if is_not_loaded "$module"; then
		db_subst hw-detect/load_progress_step CARDNAME "$cardname"
		db_subst hw-detect/load_progress_step MODULE "$module"
		db_progress INFO hw-detect/load_progress_step
		if [ "$cardname" = "[Unknown]" ]; then
			load_module "$module"
		else
			load_module "$module" "$cardname"
		fi
	fi

	db_progress STEP $MODULE_STEPSIZE
	IFS="$NEWLINE"
done
IFS="$IFS_SAVE"

if [ -z "$LIST" ]; then
	db_progress STEP $MODULE_STEPS
fi

# Load ide-generic and check if that results in new block devices.
# If so, make sure it is added to the initrd for the installed system.
# Note: this may need to be done for more systems than just systems
# that have an ISA bus, but that seems like a good start; it could also
# be done unconditionally.
if [ -z "$LOAD_IDE" ] && is_not_loaded ide-generic && \
   [ -e /sys/bus/isa ] && is_available ide-generic; then
	update-dev --settle >/dev/null
	blockdev_count=$(ls /sys/block | wc -w)

	log "ISA bus detected; loading module 'ide-generic'"
	load_module ide-generic
	update-dev --settle >/dev/null
	if [ $(ls /sys/block | wc -w) -gt $blockdev_count ]; then
		log "New devices detected after loading ide-generic"

		# This will tell initramfs-tools to load ide-generic
		kopts=
		if db_get debian-installer/add-kernel-opts && [ "$RET" ]; then
			kopts="$RET"
		fi
		if ! echo "$kopt" | grep -Eq "(^| )all_generic_ide(=1|)( |$)"; then
			db_set debian-installer/add-kernel-opts \
				"${kopts:+$kopts }all_generic_ide=1"
		fi
	fi
fi

if ! is_not_loaded ohci1394 || ! is_not_loaded firewire-ohci; then
	# if firewire was found, try to enable firewire cd support
	if is_not_loaded sbp2 && is_not_loaded firewire-sbp2 && \
	    is_available scsi_mod; then
	    	sbp2module=
		if is_available firewire-sbp2; then
			sbp2module=firewire-sbp2
		elif is_available sbp2; then
			sbp2module=sbp2
		fi
		if [ -n "$sbp2module" ]; then
			db_subst hw-detect/load_progress_step CARDNAME "FireWire CDROM support"
			db_subst hw-detect/load_progress_step MODULE "$sbp2module"
			db_progress INFO hw-detect/load_progress_step
			load_module "$sbp2module"
			register-module "$sbp2module"
		else
			missing_module firewire-sbp2 "FireWire CDROM"
		fi
	fi
	db_progress STEP $OTHER_STEPSIZE

	# also try to enable firewire ethernet (The right way to do this is
	# really to catch the hotplug events from the kernel.)
	if is_not_loaded eth1394; then
		if is_available eth1394; then
			db_subst hw-detect/load_progress_step CARDNAME "FireWire ethernet support"
			db_subst hw-detect/load_progress_step MODULE "eth1394"
			db_progress INFO hw-detect/load_progress_step
			load_module eth1394 "FireWire ethernet"
			# do not call register-module; udev/hotplug will load it
			# on the installed system
		else
			missing_module eth1394 "FireWire ethernet"
		fi
	fi
fi

apply_pcmcia_resource_opts() {
	local config_opts=/etc/pcmcia/config.opts
	
	# Idempotency
	if ! [ -f ${config_opts}.orig ]; then
		cp $config_opts ${config_opts}.orig
	fi
	cp ${config_opts}.orig $config_opts

	local mode=""
	local rmode=""
	local type=""
	local value=""
	while [ -n "$1" ] && [ -n "$2" ] && [ -n "$3" ]; do
		if [ "$1" = exclude ]; then
			mode=exclude
			rmode=include
			shift
		elif [ "$1" = include ]; then
			mode=include
			rmode=exclude
			shift
		fi
		type="$1"
		shift
		value="$1"
		shift
		
		if grep -q "^$rmode $type $value\$" $config_opts; then
			sed "s/^$rmode $type $value\$/$mode $type $value/" \
				$config_opts >${config_opts}.new
			mv ${config_opts}.new $config_opts
		else
			echo "$mode $type $value" >>$config_opts
		fi
	done
}

# get pcmcia running if possible
PCMCIA_INIT=/etc/init.d/pcmciautils
if [ -x "$PCMCIA_INIT" ]; then
	if is_not_loaded pcmcia_core; then
		db_input low hw-detect/pcmcia_resources || true
		db_go || true

		if db_get hw-detect/pcmcia_resources && [ "$RET" ]; then
			apply_pcmcia_resource_opts $RET
		fi
		# cdebconf doesn't set seen flags, so this would normally be
		# asked again on subsequent hw-detect runs, which is
		# annoying.
		db_fset hw-detect/pcmcia_resources seen true || true

		db_progress INFO hw-detect/pcmcia_step
		$PCMCIA_INIT start 2>&1 | log
		db_progress STEP $OTHER_STEPSIZE
	fi
fi

have_pcmcia=0
if ls /sys/class/pcmcia_socket/* >/dev/null 2>&1; then
	if db_get hw-detect/start_pcmcia && [ "$RET" = false ]; then
		have_pcmcia=0
	else
		have_pcmcia=1
	fi
fi

# find Cardbus network cards
cardbus_check_netdev()
{
	local socket="$1"
	local netdev="$2"
	if [ -L "$netdev/device" ] && \
		[ -d "$socket/device/$(basename "$(readlink "$netdev/device")")" ]; then
		echo "$(basename "$netdev")" >> /etc/network/devhotplug
	fi
}

# Try to do this only once..
if [ "$have_pcmcia" -eq 1 ] && \
   ! grep -q pcmciautils /var/lib/apt-install/queue 2>/dev/null; then
	log "Detected PCMCIA, installing pcmciautils."
	apt-install pcmciautils || true

	for socket in /sys/class/pcmcia_socket/*; do
		for netdev in /sys/class/net/*; do
			cardbus_check_netdev "$socket" "$netdev"
		done
	done

	if db_get hw-detect/pcmcia_resources && [ -n "$RET" ]; then
		echo "mkdir /target/etc/pcmcia 2>/dev/null || true" \
			>>$finish_install
		echo "cp /etc/pcmcia/config.opts /target/etc/pcmcia/config.opts" \
			>>$finish_install
	fi
fi

# Install udev into target
apt-install udev || true

# Install pciutils/usbutils
if [ -d /sys/bus/pci ]; then
	apt-install pciutils || true
fi

if [ -d /sys/bus/usb ]; then
	apt-install usbutils || true
fi

# If hardware has support for pmu, install pbbuttonsd
if [ -d /sys/class/misc/pmu/ ]; then
	apt-install pbbuttonsd || true
fi

# Install eject?
if [ -n "$(list-devices cd; list-devices maybe-usb-floppy)" ]; then
	apt-install eject || true
fi

db_progress SET $MAX_STEPS
db_progress STOP

if [ -n "$MISSING_MODULES_LIST" ]; then
	log "Missing modules '$MISSING_MODULES_LIST"
fi

if [ "$CHECK_MISSING_FIRMWARE" != 0 ]; then
	check-missing-firmware
else
	log "skipping check-missing-firmware as requested by the caller"
fi

sysfs-update-devnames

# Let userspace /dev tools rescan the devices
update-dev --settle >/dev/null

exit 0