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
12# CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/
13# These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that
14# as an indicator for CONFIG_FW_LOADER_USER_HELPER.
15HAS_FW_LOADER_USER_HELPER=$(if [ -d /sys/class/firmware/ ]; then echo yes; else echo no; fi)
16
17if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
18       OLD_TIMEOUT=$(cat /sys/class/firmware/timeout)
19else
20	echo "usermode helper disabled so ignoring test"
21	exit 0
22fi
23
24FWPATH=$(mktemp -d)
25FW="$FWPATH/test-firmware.bin"
26
27test_finish()
28{
29	echo "$OLD_TIMEOUT" >/sys/class/firmware/timeout
30	rm -f "$FW"
31	rmdir "$FWPATH"
32}
33
34load_fw()
35{
36	local name="$1"
37	local file="$2"
38
39	# This will block until our load (below) has finished.
40	echo -n "$name" >"$DIR"/trigger_request &
41
42	# Give kernel a chance to react.
43	local timeout=10
44	while [ ! -e "$DIR"/"$name"/loading ]; do
45		sleep 0.1
46		timeout=$(( $timeout - 1 ))
47		if [ "$timeout" -eq 0 ]; then
48			echo "$0: firmware interface never appeared" >&2
49			exit 1
50		fi
51	done
52
53	echo 1 >"$DIR"/"$name"/loading
54	cat "$file" >"$DIR"/"$name"/data
55	echo 0 >"$DIR"/"$name"/loading
56
57	# Wait for request to finish.
58	wait
59}
60
61trap "test_finish" EXIT
62
63# This is an unlikely real-world firmware content. :)
64echo "ABCD0123" >"$FW"
65NAME=$(basename "$FW")
66
67# Test failure when doing nothing (timeout works).
68echo 1 >/sys/class/firmware/timeout
69echo -n "$NAME" >"$DIR"/trigger_request
70if diff -q "$FW" /dev/test_firmware >/dev/null ; then
71	echo "$0: firmware was not expected to match" >&2
72	exit 1
73else
74	echo "$0: timeout works"
75fi
76
77# Put timeout high enough for us to do work but not so long that failures
78# slow down this test too much.
79echo 4 >/sys/class/firmware/timeout
80
81# Load this script instead of the desired firmware.
82load_fw "$NAME" "$0"
83if diff -q "$FW" /dev/test_firmware >/dev/null ; then
84	echo "$0: firmware was not expected to match" >&2
85	exit 1
86else
87	echo "$0: firmware comparison works"
88fi
89
90# Do a proper load, which should work correctly.
91load_fw "$NAME" "$FW"
92if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
93	echo "$0: firmware was not loaded" >&2
94	exit 1
95else
96	echo "$0: user helper firmware loading works"
97fi
98
99exit 0
100