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
  
     | 
    
      #!/bin/sh
set -e
. /usr/share/debconf/confmodule
LOG=/tmp/missing-firmware
DENIED=/tmp/missing-firmware-denied
NL="
"
log () {
	logger -t check-missing-firmware "$@"
}
read_log () {
	# Give modules some time to request firmware.
	sleep 1
	
	modules=""
	files=""
	if [ -s "$LOG" ]; then
		mv $LOG $LOG.old
		OLDIFS="$IFS"
		IFS="$NL"
		for line in $(sort $LOG.old | uniq); do
			module="${line%% *}"
			file="${line#* }"
			[ -z "$module" ] || [ -z "$file" ] && continue
			if grep -q "^$file$" $DENIED 2>/dev/null; then
				continue
			fi
			modules="$module${modules:+ $modules}"
			files="$file${files:+ $files}"
		done
		IFS="$OLDIFS"
		rm -f $LOG.old
	fi
	if [ -n "$modules" ]; then
		log "missing firmware files ($files) for $modules"
		return 0
	else
		log "no missing firmware in $LOG"
		return 1
	fi
}
first=1
ask_load_firmware () {
	db_subst hw-detect/load_firmware FILES "$files"
	if ! db_input high hw-detect/load_firmware; then
		if [ ! "$first" ]; then
			exit 1;
		else
			first=""
		fi
	fi
	if ! db_go; then
		exit 10 # back up
	fi
	db_get hw-detect/load_firmware
	if [ "$RET" = true ]; then
		return 0
	else
		echo "$files" | tr ' ' '\n' >> $DENIED
		return 1
	fi
}
list_deb_firmware () {
	ar p "$1" data.tar.gz | tar zt \
		| grep '^\./lib/firmware/' \
		| sed -e 's!^\./lib/firmware/!!' \
		| grep -v '^$'
}
check_deb_arch () {
	arch=$(ar p "$1" control.tar.gz | tar zxO ./control | grep '^Architecture:' | sed -e 's/Architecture: *//')
	[ "$arch" = all ] || [ "$arch" = "$(udpkg --print-architecture)" ]
}
install_firmware_pkg () {
	if echo "$1" | grep -q '\.deb$'; then
		# cache deb for installation into /target later
		mkdir -p /var/cache/firmware/
		cp -a "$1" /var/cache/firmware/ || true
		udpkg --unpack "/var/cache/firmware/$(basename "$1")"
	else
		udpkg --unpack "$1"
	fi
}
while read_log && ask_load_firmware; do
	# first, look for loose firmware files on the media.
	if mountmedia; then
		for file in $files; do
			for f in "/media/$file" "/media/firmware/$file"; do
				if [ -e "$f" ]; then
					log "copying loose file $file"
					mkdir -p /lib/firmware
					rm -f "/lib/firmware/$file"
					cp -a "$f" /lib/firmware/ || true
					break
				fi
			done
		done
		umount /media || true
	fi
	# Try to load udebs (or debs) that contain the missing firmware.
	# This does not use anna because debs can have arbitrary
	# dependencies, which anna might try to install.
	if mountmedia driver; then
		echo "$files" | sed -e 's/ /\n/g' >/tmp/grepfor
		for filename in /media/*.deb /media/*.udeb /media/*.ude /media/firmware/*.deb /media/firmware/*.udeb /media/firmware/*.ude; do
			if [ -f "$filename" ]; then
				if check_deb_arch "$filename" && list_deb_firmware "$filename" | grep -qf /tmp/grepfor; then
					log "installing firmware package $filename"
					install_firmware_pkg "$filename" || true
				fi
			fi
		done
		rm -f /tmp/grepfor
		umount /media || true
	fi
	# remove and reload modules so they see the new firmware
	for module in $modules; do
		modprobe -r $module || true
		modprobe $module || true
	done
done
 
     |