1#!/bin/sh
2# This validates that the kernel will fall back to using the user helper
3# to load firmware it can't find on disk itself. We must request a firmware
4# that the kernel won't find, and any installed helper (e.g. udev) also
5# won't find so that we can do the load ourself manually.
6set -e
7
8modprobe test_firmware
9
10DIR=/sys/devices/virtual/misc/test_firmware
11
12OLD_TIMEOUT=$(cat /sys/class/firmware/timeout)
13
14FWPATH=$(mktemp -d)
15FW="$FWPATH/test-firmware.bin"
16
17test_finish()
18{
19	echo "$OLD_TIMEOUT" >/sys/class/firmware/timeout
20	rm -f "$FW"
21	rmdir "$FWPATH"
22}
23
24load_fw()
25{
26	local name="$1"
27	local file="$2"
28
29	# This will block until our load (below) has finished.
30	echo -n "$name" >"$DIR"/trigger_request &
31
32	# Give kernel a chance to react.
33	local timeout=10
34	while [ ! -e "$DIR"/"$name"/loading ]; do
35		sleep 0.1
36		timeout=$(( $timeout - 1 ))
37		if [ "$timeout" -eq 0 ]; then
38			echo "$0: firmware interface never appeared" >&2
39			exit 1
40		fi
41	done
42
43	echo 1 >"$DIR"/"$name"/loading
44	cat "$file" >"$DIR"/"$name"/data
45	echo 0 >"$DIR"/"$name"/loading
46
47	# Wait for request to finish.
48	wait
49}
50
51trap "test_finish" EXIT
52
53# This is an unlikely real-world firmware content. :)
54echo "ABCD0123" >"$FW"
55NAME=$(basename "$FW")
56
57# Test failure when doing nothing (timeout works).
58echo 1 >/sys/class/firmware/timeout
59echo -n "$NAME" >"$DIR"/trigger_request
60if diff -q "$FW" /dev/test_firmware >/dev/null ; then
61	echo "$0: firmware was not expected to match" >&2
62	exit 1
63else
64	echo "$0: timeout works"
65fi
66
67# Put timeout high enough for us to do work but not so long that failures
68# slow down this test too much.
69echo 4 >/sys/class/firmware/timeout
70
71# Load this script instead of the desired firmware.
72load_fw "$NAME" "$0"
73if diff -q "$FW" /dev/test_firmware >/dev/null ; then
74	echo "$0: firmware was not expected to match" >&2
75	exit 1
76else
77	echo "$0: firmware comparison works"
78fi
79
80# Do a proper load, which should work correctly.
81load_fw "$NAME" "$FW"
82if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
83	echo "$0: firmware was not loaded" >&2
84	exit 1
85else
86	echo "$0: user helper firmware loading works"
87fi
88
89exit 0
90