This file is indexed.

/bin/check-missing-firmware is in ubiquity 18.04.14.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  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
#!/bin/sh
set -e
. /usr/share/debconf/confmodule

MISSING='/dev/.udev/firmware-missing /run/udev/firmware-missing'
DENIED=/tmp/missing-firmware-denied

if [ "x$1" = "x-n" ]; then
	NONINTERACTIVE=1
else
	NONINTERACTIVE=""
fi

IFACES="$@"

log () {
	logger -t check-missing-firmware "$@"
}

# Not all drivers register themselves if firmware is missing; in that
# case determine the module via the device's modalias.
get_module () {
	local devpath=$1

	if [ -d $devpath/driver ]; then
		# The real path of the destination of the driver/module
		# symlink should be something like "/sys/module/e100"
		basename $(readlink -f $devpath/driver/module) || true
	elif [ -e $devpath/modalias ]; then
		modalias="$(cat $devpath/modalias)"
		# Take the last module returned by modprobe
		modprobe --show-depends "$modalias" 2>/dev/null | \
			sed -n -e '$s#^.*/\([^.]*\)\.ko.*$#\1#p'
	fi
}

# Some modules only try to load firmware once brought up. So bring up and
# then down any interfaces specified by ethdetect.
upnics() {
	for iface in $IFACES; do
		log "taking network interface $iface up/down"
		ip link set "$iface" up || true
		ip link set "$iface" down || true
	done
}

# Checks if a given module is a nic module and has an interface that
# is up and has an IP address. Such modules should not be reloaded,
# to avoid taking down the network after it's been configured.
nic_is_configured() {
	module="$1"

	for iface in $(ip -o link show up | cut -d : -f 2); do
		dir="/sys/class/net/$iface/device/driver"
		if [ -e "$dir" ] && [ "$(basename "$(readlink "$dir")")" = "$module" ]; then
			if ip address show scope global dev "$iface" | grep -q 'scope global'; then
				return 0
			fi
		fi
	done

	return 1
}

get_fresh_dmesg() {
	dmesg_file=/tmp/dmesg.txt
	dmesg_ts=/tmp/dmesg-ts.txt

	# Get current dmesg:
	dmesg > $dmesg_file

	# Truncate if needed:
	if [ -f $dmesg_ts ]; then
		# Transform [foo] into \[foo\] to make it possible to search for
		# "^$tspattern" (-F for fixed string doesn't play well with ^ to
		# anchor the pattern on the left):
		tspattern=$(cat $dmesg_ts | sed 's,\[,\\[,;s,\],\\],')
		log "looking at dmesg again, restarting from $tspattern"

		# Find the line number for the first match, empty if not found:
		ln=$(grep -n "^$tspattern" $dmesg_file |sed 's/:.*//'|head -n 1)
		if [ ! -z "$ln" ]; then
			log "timestamp found, truncating dmesg accordingly"
			sed -i "1,$ln d" $dmesg_file
		else
			log "timestamp not found, using whole dmesg"
		fi
	else
		log "looking at dmesg for the first time"
	fi

	# Save the last timestamp:
	grep -o '^\[ *[0-9.]\+\]' $dmesg_file | tail -n 1 > $dmesg_ts
	log "saving timestamp for a later use: $(cat $dmesg_ts)"

	# Write and clean-up:
	cat $dmesg_file
	rm $dmesg_file
}

check_missing () {
	upnics

	# Give modules some time to request firmware.
	sleep 1
	
	modules=""
	files=""

	# The linux kernel and udev no longer let us know via
	# /dev/.udev/firmware-missing and /run/udev/firmware-missing
	# which firmware files the kernel drivers look for.  Check
	# dmesg instead.  See also bug #725714.
	fwlist=/tmp/check-missing-firmware-dmesg.list
	get_fresh_dmesg | sed -rn 's/^(\[[^]]*\] )?([^ ]+) [^ ]+: firmware: failed to load ([^ ]+) .*/\2 \3/p' > $fwlist
	while read module fwfile ; do
	    log "looking for firmware file $fwfile requested by $module"
	    if [ ! -e /lib/firmware/$fwfile ] ; then
		if grep -q "^$fwfile$" $DENIED 2>/dev/null; then
		    log "listed in $DENIED"
		    continue
		fi
		files="${files:+$files }$fwfile"
		modules="$module${modules:+ $modules}"
	    fi
	done < $fwlist

	# This block looking in $MISSING should be removed when
	# hw-detect no longer should support installing using older
	# udev and kernel versions.
	for missing_dir in $MISSING
	do
		if [ ! -d "$missing_dir" ]; then
			log "$missing_dir does not exist, skipping"
			continue
		fi
		for file in $(find $missing_dir -type l); do
			# decode firmware filename as encoded by
			# udev firmware.agent
			fwfile="$(basename $file | sed -e 's#\\x2f#/#g')"
			
			# strip probably nonexistant firmware subdirectory
			devpath="$(readlink $file | sed 's/\/firmware\/.*//')"
			# the symlink is supposed to point to the device in /sys
			if ! echo "$devpath" | grep -q '^/sys/'; then
				devpath="/sys$devpath"
			fi

			module=$(get_module "$devpath")
			if [ -z "$module" ]; then
				log "failed to determine module from $devpath"
				continue
			fi

			rm -f "$file"

			if grep -q "^$fwfile$" $DENIED 2>/dev/null; then
				continue
			fi
			
			files="$fwfile${files:+ $files}"

			if [ "$module" = usbcore ]; then
				# Special case for USB bus, which puts the
				# real module information in a subdir of
				# the devpath.
				for dir in $(find "$devpath" -maxdepth 1 -mindepth 1 -type d); do
					module=$(get_module "$dir")
					if [ -n "$module" ]; then
						modules="$module${modules:+ $modules}"
					fi
				done
			else
				modules="$module${modules:+ $modules}"
			fi
		done
	done

	if [ -n "$modules" ]; then
		log "missing firmware files ($files) for $modules"
		return 0
	else
		log "no missing firmware in loaded kernel modules"
		return 1
	fi
}

# If found, copy firmware file; preserve subdirs.
try_copy () {
	local fwfile=$1
	local sdir file f target

	sdir=$(dirname $fwfile | sed "s/^\.$//")
	file=$(basename $fwfile)
	for f in "/media/$fwfile" "/media/firmware/$fwfile" \
		 ${sdir:+"/media/$file" "/media/firmware/$file"}; do
		if [ -e "$f" ]; then
			target="/lib/firmware${sdir:+/$sdir}"
			log "copying loose file $file from '$(dirname $f)' to '$target'"
			mkdir -p "$target"
			rm -f "$target/$file"
			cp -aL "$f" "$target" || true
			break
		fi
	done
}

first_try=1
first_ask=1
ask_load_firmware () {
	if [ "$first_try" ]; then
		first_try=""
		return 0
	fi

	if [ "$NONINTERACTIVE" ]; then
		if [ ! "$first_ask" ]; then
			return 1
		else
			first_ask=""
			return 0
		fi
	fi

	db_subst hw-detect/load_firmware FILES "$files"
	if ! db_input high hw-detect/load_firmware; then
		if [ ! "$first_ask" ]; then
			exit 1;
		else
			first_ask=""
		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 () {
	udpkg -c "$1" \
		| grep '^\./lib/firmware/' \
		| sed -e 's!^\./lib/firmware/!!' \
		| grep -v '^$'
}

check_deb_arch () {
	arch=$(udpkg -f "$1" | grep '^Architecture:' | sed -e 's/Architecture: *//')
	[ "$arch" = all ] || [ "$arch" = "$(udpkg --print-architecture)" ]
}

# Remove non-accepted firmware package
remove_pkg() {
	pkgname="$1"
	# Remove all files listed in /var/lib/dpkg/info/$pkgname.md5sum
	for file in $(cut -d" " -f 2- /var/lib/dpkg/info/$pkgname.md5sum) ; do
		rm /$file
	done
}

install_firmware_pkg () {
	if echo "$1" | grep -q '\.deb$'; then
		# cache deb for installation into /target later
		mkdir -p /var/cache/firmware/
		cp -aL "$1" /var/cache/firmware/ || true
		filename="$(basename "$1")"
		pkgname="$(echo $filename |cut -d_ -f1)"
		udpkg --unpack "/var/cache/firmware/$filename"
		if [ -f /var/lib/dpkg/info/$pkgname.preinst ] ; then
			# Run preinst script to see if the firmware
			# license is accepted Exit code of preinst
			# decide if the package should be installed or
			# not.
			if /var/lib/dpkg/info/$pkgname.preinst ; then
				:
			else
				remove_pkg "$pkgname"
				rm "/var/cache/firmware/$filename"
			fi
		fi
	else
		udpkg --unpack "$1"
	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.
check_for_firmware() {
	echo "$files" | sed -e 's/ /\n/g' >/tmp/grepfor
	for filename in $@; 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
}

while check_missing && ask_load_firmware; do
	# first, check if needed firmware (u)debs are available on the
	# PXE initrd or the installation CD.
	if [ -d /firmware ]; then
		check_for_firmware /firmware/*.deb /firmware/*.udeb
	fi
	if [ -d /cdrom/firmware ]; then
		check_for_firmware /cdrom/firmware/*.deb /cdrom/firmware/*.udeb
	fi

	# second, look for loose firmware files on the media device.
	if mountmedia; then
		for file in $files; do
			try_copy "$file"
		done
		umount /media || true
	fi

	# last, look for firmware (u)debs on the media device
	if mountmedia driver; then
		check_for_firmware /media/*.deb /media/*.udeb /media/*.ude /media/firmware/*.deb /media/firmware/*.udeb /media/firmware/*.ude
		umount /media || true
	fi

	# remove and reload modules so they see the new firmware
	# Sort to only reload a given module once if it asks for more
	# than one firmware file (example iwlagn)
	for module in $(echo $modules | tr " " "\n" | sort -u); do
		if ! nic_is_configured $module; then
			log "removing and loading kernel module $module"
			modprobe -r $module || true
			modprobe -b $module || true
		fi
	done
done