GNU Linux-libre 4.19.245-gnu1
[releases.git] / tools / testing / selftests / firmware / fw_filesystem.sh
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # This validates that the kernel will load firmware out of its list of
4 # firmware locations on disk. Since the user helper does similar work,
5 # we reset the custom load directory to a location the user helper doesn't
6 # know so we can be sure we're not accidentally testing the user helper.
7 set -e
8
9 TEST_REQS_FW_SYSFS_FALLBACK="no"
10 TEST_REQS_FW_SET_CUSTOM_PATH="yes"
11 TEST_DIR=$(dirname $0)
12 source $TEST_DIR/fw_lib.sh
13
14 check_mods
15 check_setup
16 verify_reqs
17 setup_tmp_file
18
19 trap "test_finish" EXIT
20
21 if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
22         # Turn down the timeout so failures don't take so long.
23         echo 1 >/sys/class/firmware/timeout
24 fi
25
26 if printf '\000' >"$DIR"/trigger_request 2> /dev/null; then
27         echo "$0: empty filename should not succeed" >&2
28         exit 1
29 fi
30
31 if [ ! -e "$DIR"/trigger_async_request ]; then
32         echo "$0: empty filename: async trigger not present, ignoring test" >&2
33         exit $ksft_skip
34 else
35         if printf '\000' >"$DIR"/trigger_async_request 2> /dev/null; then
36                 echo "$0: empty filename should not succeed (async)" >&2
37                 exit 1
38         fi
39 fi
40
41 # Request a firmware that doesn't exist, it should fail.
42 if echo -n "nope-$NAME" >"$DIR"/trigger_request 2> /dev/null; then
43         echo "$0: firmware shouldn't have loaded" >&2
44         exit 1
45 fi
46 if diff -q "$FW" /dev/test_firmware >/dev/null ; then
47         echo "$0: firmware was not expected to match" >&2
48         exit 1
49 else
50         if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
51                 echo "$0: timeout works"
52         fi
53 fi
54
55 # This should succeed via kernel load or will fail after 1 second after
56 # being handed over to the user helper, which won't find the fw either.
57 if ! echo -n "$NAME" >"$DIR"/trigger_request ; then
58         echo "$0: could not trigger request" >&2
59         exit 1
60 fi
61
62 # Verify the contents are what we expect.
63 if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
64         echo "$0: firmware was not loaded" >&2
65         exit 1
66 else
67         echo "$0: filesystem loading works"
68 fi
69
70 # Try the asynchronous version too
71 if [ ! -e "$DIR"/trigger_async_request ]; then
72         echo "$0: firmware loading: async trigger not present, ignoring test" >&2
73         exit $ksft_skip
74 else
75         if ! echo -n "$NAME" >"$DIR"/trigger_async_request ; then
76                 echo "$0: could not trigger async request" >&2
77                 exit 1
78         fi
79
80         # Verify the contents are what we expect.
81         if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
82                 echo "$0: firmware was not loaded (async)" >&2
83                 exit 1
84         else
85                 echo "$0: async filesystem loading works"
86         fi
87 fi
88
89 ### Batched requests tests
90 test_config_present()
91 {
92         if [ ! -f $DIR/reset ]; then
93                 echo "Configuration triggers not present, ignoring test"
94                 exit $ksft_skip
95         fi
96 }
97
98 # Defaults :
99 #
100 # send_uevent: 1
101 # sync_direct: 0
102 # name: test-firmware.bin
103 # num_requests: 4
104 config_reset()
105 {
106         echo 1 >  $DIR/reset
107 }
108
109 release_all_firmware()
110 {
111         echo 1 >  $DIR/release_all_firmware
112 }
113
114 config_set_name()
115 {
116         echo -n $1 >  $DIR/config_name
117 }
118
119 config_set_sync_direct()
120 {
121         echo 1 >  $DIR/config_sync_direct
122 }
123
124 config_unset_sync_direct()
125 {
126         echo 0 >  $DIR/config_sync_direct
127 }
128
129 config_set_uevent()
130 {
131         echo 1 >  $DIR/config_send_uevent
132 }
133
134 config_unset_uevent()
135 {
136         echo 0 >  $DIR/config_send_uevent
137 }
138
139 config_trigger_sync()
140 {
141         echo -n 1 > $DIR/trigger_batched_requests 2>/dev/null
142 }
143
144 config_trigger_async()
145 {
146         echo -n 1 > $DIR/trigger_batched_requests_async 2> /dev/null
147 }
148
149 config_set_read_fw_idx()
150 {
151         echo -n $1 > $DIR/config_read_fw_idx 2> /dev/null
152 }
153
154 read_firmwares()
155 {
156         for i in $(seq 0 3); do
157                 config_set_read_fw_idx $i
158                 # Verify the contents are what we expect.
159                 # -Z required for now -- check for yourself, md5sum
160                 # on $FW and DIR/read_firmware will yield the same. Even
161                 # cmp agrees, so something is off.
162                 if ! diff -q -Z "$FW" $DIR/read_firmware 2>/dev/null ; then
163                         echo "request #$i: firmware was not loaded" >&2
164                         exit 1
165                 fi
166         done
167 }
168
169 read_firmwares_expect_nofile()
170 {
171         for i in $(seq 0 3); do
172                 config_set_read_fw_idx $i
173                 # Ensures contents differ
174                 if diff -q -Z "$FW" $DIR/read_firmware 2>/dev/null ; then
175                         echo "request $i: file was not expected to match" >&2
176                         exit 1
177                 fi
178         done
179 }
180
181 test_batched_request_firmware_nofile()
182 {
183         echo -n "Batched request_firmware() nofile try #$1: "
184         config_reset
185         config_set_name nope-test-firmware.bin
186         config_trigger_sync
187         read_firmwares_expect_nofile
188         release_all_firmware
189         echo "OK"
190 }
191
192 test_batched_request_firmware_direct_nofile()
193 {
194         echo -n "Batched request_firmware_direct() nofile try #$1: "
195         config_reset
196         config_set_name nope-test-firmware.bin
197         config_set_sync_direct
198         config_trigger_sync
199         release_all_firmware
200         echo "OK"
201 }
202
203 test_request_firmware_nowait_uevent_nofile()
204 {
205         echo -n "Batched request_firmware_nowait(uevent=true) nofile try #$1: "
206         config_reset
207         config_set_name nope-test-firmware.bin
208         config_trigger_async
209         release_all_firmware
210         echo "OK"
211 }
212
213 test_wait_and_cancel_custom_load()
214 {
215         if [ "$HAS_FW_LOADER_USER_HELPER" != "yes" ]; then
216                 return
217         fi
218         local timeout=10
219         name=$1
220         while [ ! -e "$DIR"/"$name"/loading ]; do
221                 sleep 0.1
222                 timeout=$(( $timeout - 1 ))
223                 if [ "$timeout" -eq 0 ]; then
224                         echo "firmware interface never appeared:" >&2
225                         echo "$DIR/$name/loading" >&2
226                         exit 1
227                 fi
228         done
229         echo -1 >"$DIR"/"$name"/loading
230 }
231
232 test_request_firmware_nowait_custom_nofile()
233 {
234         echo -n "Batched request_firmware_nowait(uevent=false) nofile try #$1: "
235         config_reset
236         config_unset_uevent
237         RANDOM_FILE_PATH=$(setup_random_file_fake)
238         RANDOM_FILE="$(basename $RANDOM_FILE_PATH)"
239         config_set_name $RANDOM_FILE
240         config_trigger_async &
241         test_wait_and_cancel_custom_load $RANDOM_FILE
242         wait
243         release_all_firmware
244         echo "OK"
245 }
246
247 test_batched_request_firmware()
248 {
249         echo -n "Batched request_firmware() try #$1: "
250         config_reset
251         config_trigger_sync
252         read_firmwares
253         release_all_firmware
254         echo "OK"
255 }
256
257 test_batched_request_firmware_direct()
258 {
259         echo -n "Batched request_firmware_direct() try #$1: "
260         config_reset
261         config_set_sync_direct
262         config_trigger_sync
263         release_all_firmware
264         echo "OK"
265 }
266
267 test_request_firmware_nowait_uevent()
268 {
269         echo -n "Batched request_firmware_nowait(uevent=true) try #$1: "
270         config_reset
271         config_trigger_async
272         release_all_firmware
273         echo "OK"
274 }
275
276 test_request_firmware_nowait_custom()
277 {
278         echo -n "Batched request_firmware_nowait(uevent=false) try #$1: "
279         config_reset
280         config_unset_uevent
281         RANDOM_FILE_PATH=$(setup_random_file)
282         RANDOM_FILE="$(basename $RANDOM_FILE_PATH)"
283         config_set_name $RANDOM_FILE
284         config_trigger_async
285         release_all_firmware
286         echo "OK"
287 }
288
289 # Only continue if batched request triggers are present on the
290 # test-firmware driver
291 test_config_present
292
293 # test with the file present
294 echo
295 echo "Testing with the file present..."
296 for i in $(seq 1 5); do
297         test_batched_request_firmware $i
298 done
299
300 for i in $(seq 1 5); do
301         test_batched_request_firmware_direct $i
302 done
303
304 for i in $(seq 1 5); do
305         test_request_firmware_nowait_uevent $i
306 done
307
308 for i in $(seq 1 5); do
309         test_request_firmware_nowait_custom $i
310 done
311
312 # Test for file not found, errors are expected, the failure would be
313 # a hung task, which would require a hard reset.
314 echo
315 echo "Testing with the file missing..."
316 for i in $(seq 1 5); do
317         test_batched_request_firmware_nofile $i
318 done
319
320 for i in $(seq 1 5); do
321         test_batched_request_firmware_direct_nofile $i
322 done
323
324 for i in $(seq 1 5); do
325         test_request_firmware_nowait_uevent_nofile $i
326 done
327
328 for i in $(seq 1 5); do
329         test_request_firmware_nowait_custom_nofile $i
330 done
331
332 exit 0