File: check-missing-firmware.sh

package info (click to toggle)
hw-detect 1.71
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 1,140 kB
  • ctags: 64
  • sloc: sh: 1,153; makefile: 117; ansic: 12
file content (133 lines) | stat: -rwxr-xr-x 3,061 bytes parent folder | download
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