Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1#!/bin/sh
2# This validates that the kernel will fall back to using the fallback mechanism
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
61load_fw_cancel()
62{
63 local name="$1"
64 local file="$2"
65
66 # This will block until our load (below) has finished.
67 echo -n "$name" >"$DIR"/trigger_request 2>/dev/null &
68
69 # Give kernel a chance to react.
70 local timeout=10
71 while [ ! -e "$DIR"/"$name"/loading ]; do
72 sleep 0.1
73 timeout=$(( $timeout - 1 ))
74 if [ "$timeout" -eq 0 ]; then
75 echo "$0: firmware interface never appeared" >&2
76 exit 1
77 fi
78 done
79
80 echo -1 >"$DIR"/"$name"/loading
81
82 # Wait for request to finish.
83 wait
84}
85
86load_fw_custom()
87{
88 local name="$1"
89 local file="$2"
90
91 echo -n "$name" >"$DIR"/trigger_custom_fallback 2>/dev/null &
92
93 # Give kernel a chance to react.
94 local timeout=10
95 while [ ! -e "$DIR"/"$name"/loading ]; do
96 sleep 0.1
97 timeout=$(( $timeout - 1 ))
98 if [ "$timeout" -eq 0 ]; then
99 echo "$0: firmware interface never appeared" >&2
100 exit 1
101 fi
102 done
103
104 echo 1 >"$DIR"/"$name"/loading
105 cat "$file" >"$DIR"/"$name"/data
106 echo 0 >"$DIR"/"$name"/loading
107
108 # Wait for request to finish.
109 wait
110}
111
112
113load_fw_custom_cancel()
114{
115 local name="$1"
116 local file="$2"
117
118 echo -n "$name" >"$DIR"/trigger_custom_fallback 2>/dev/null &
119
120 # Give kernel a chance to react.
121 local timeout=10
122 while [ ! -e "$DIR"/"$name"/loading ]; do
123 sleep 0.1
124 timeout=$(( $timeout - 1 ))
125 if [ "$timeout" -eq 0 ]; then
126 echo "$0: firmware interface never appeared" >&2
127 exit 1
128 fi
129 done
130
131 echo -1 >"$DIR"/"$name"/loading
132
133 # Wait for request to finish.
134 wait
135}
136
137
138trap "test_finish" EXIT
139
140# This is an unlikely real-world firmware content. :)
141echo "ABCD0123" >"$FW"
142NAME=$(basename "$FW")
143
144DEVPATH="$DIR"/"nope-$NAME"/loading
145
146# Test failure when doing nothing (timeout works).
147echo -n 2 >/sys/class/firmware/timeout
148echo -n "nope-$NAME" >"$DIR"/trigger_request 2>/dev/null &
149
150# Give the kernel some time to load the loading file, must be less
151# than the timeout above.
152sleep 1
153if [ ! -f $DEVPATH ]; then
154 echo "$0: fallback mechanism immediately cancelled"
155 echo ""
156 echo "The file never appeared: $DEVPATH"
157 echo ""
158 echo "This might be a distribution udev rule setup by your distribution"
159 echo "to immediately cancel all fallback requests, this must be"
160 echo "removed before running these tests. To confirm look for"
161 echo "a firmware rule like /lib/udev/rules.d/50-firmware.rules"
162 echo "and see if you have something like this:"
163 echo ""
164 echo "SUBSYSTEM==\"firmware\", ACTION==\"add\", ATTR{loading}=\"-1\""
165 echo ""
166 echo "If you do remove this file or comment out this line before"
167 echo "proceeding with these tests."
168 exit 1
169fi
170
171if diff -q "$FW" /dev/test_firmware >/dev/null ; then
172 echo "$0: firmware was not expected to match" >&2
173 exit 1
174else
175 echo "$0: timeout works"
176fi
177
178# Put timeout high enough for us to do work but not so long that failures
179# slow down this test too much.
180echo 4 >/sys/class/firmware/timeout
181
182# Load this script instead of the desired firmware.
183load_fw "$NAME" "$0"
184if diff -q "$FW" /dev/test_firmware >/dev/null ; then
185 echo "$0: firmware was not expected to match" >&2
186 exit 1
187else
188 echo "$0: firmware comparison works"
189fi
190
191# Do a proper load, which should work correctly.
192load_fw "$NAME" "$FW"
193if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
194 echo "$0: firmware was not loaded" >&2
195 exit 1
196else
197 echo "$0: fallback mechanism works"
198fi
199
200load_fw_cancel "nope-$NAME" "$FW"
201if diff -q "$FW" /dev/test_firmware >/dev/null ; then
202 echo "$0: firmware was expected to be cancelled" >&2
203 exit 1
204else
205 echo "$0: cancelling fallback mechanism works"
206fi
207
208load_fw_custom "$NAME" "$FW"
209if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
210 echo "$0: firmware was not loaded" >&2
211 exit 1
212else
213 echo "$0: custom fallback loading mechanism works"
214fi
215
216load_fw_custom_cancel "nope-$NAME" "$FW"
217if diff -q "$FW" /dev/test_firmware >/dev/null ; then
218 echo "$0: firmware was expected to be cancelled" >&2
219 exit 1
220else
221 echo "$0: cancelling custom fallback mechanism works"
222fi
223
224exit 0